Merge pull request #2165 from JoshVanL/0.11-cli-migration
Adds CLI migration tool with docs on how to use it
This commit is contained in:
commit
d3a418642e
@ -2,8 +2,6 @@
|
||||
Upgrading from v0.10 to v0.11
|
||||
=============================
|
||||
|
||||
** NOTE: THIS UPGRADE GUIDE IS PROVISIONAL AND MAY NOT BE COMPLETE WHILST THE v0.11 RELEASE SERIES IS IN ALPHA**
|
||||
|
||||
The v0.11 release marks the removal of the v1alpha1 API that was used in
|
||||
previous versions of cert-manager, as well as our API group changing to be
|
||||
``cert-manager.io`` instead of ``certmanager.k8s.io``.
|
||||
@ -23,7 +21,7 @@ This upgrade should be performed in a few steps:
|
||||
1) Back up existing cert-manager resources, as per the
|
||||
:doc:`backup and restore guide <../backup-restore-crds>`.
|
||||
|
||||
2) Uninstall cert-manager (by running ``kubectl delete -f`` or ``helm delete --purge``)
|
||||
2) :doc: `Uninstall cert-manager`<../uninstalling/index>`.
|
||||
|
||||
3) Ensure the old cert-manager CRD resources have also been deleted: ``kubectl get crd | grep certmanager.k8s.io``
|
||||
|
||||
@ -47,7 +45,19 @@ you will need to update them to reflect the new API group.
|
||||
|
||||
A full table of annotations, including the old and new equivalents:
|
||||
|
||||
.. TODO: create a table mapping old annotations to new
|
||||
| Old Annotation | New Annotation |
|
||||
|----------------------------------------------|-------------------------------------------|
|
||||
| certmanager.k8s.io/acme-http01-edit-in-place | acme.cert-manager.io/http01-edit-in-place |
|
||||
| certmanager.k8s.io/acme-http01-ingress-class | acme.cert-manager.io/http01-ingress-class |
|
||||
| certmanager.k8s.io/issuer | cert-manager.io/issuer |
|
||||
| certmanager.k8s.io/cluster-issuer | cert-manager.io/cluster-issuer |
|
||||
| certmanager.k8s.io/acme-challenge-type | DEPRECATED |
|
||||
| certmanager.k8s.io/acme-dns01-provider | DEPRECATED |
|
||||
| certmanager.k8s.io/alt-names | cert-manager.io/alt-names |
|
||||
| certmanager.k8s.io/ip-sans | cert-manager.io/ip-sans |
|
||||
| certmanager.k8s.io/common-name | cert-manager.io/common-name |
|
||||
| certmanager.k8s.io/issuer-name | cert-manager.io/issuer-name |
|
||||
| certmanager.k8s.io/issuer-kind | cert-manager.io/issuer-kind |
|
||||
|
||||
You can use the following bash magic to print a list of Ingress resources that
|
||||
still contain an old annotation:
|
||||
@ -62,5 +72,25 @@ still contain an old annotation:
|
||||
Ingress resource "demo/testcrt contains old annotations: (certmanager.k8s.io/cluster-issuer)"
|
||||
Ingress resource "example/ingress-resource contains old annotations: (certmanager.k8s.io/cluster-issuer)"
|
||||
|
||||
In order to help with this migration, the following CLI tool will automatically
|
||||
migrate these annotations for you. Note that it *will not* make any changes to
|
||||
your cluster for you.
|
||||
|
||||
.. code-block:: shell
|
||||
|
||||
# Firstly, download the binary for your given platform
|
||||
$ wget -O api-migration https://github.com/jetstack/cert-manager/releases/download/v0.11.0/api-migration-linux
|
||||
# or for Darwin
|
||||
$ wget -O api-migration https://github.com/jetstack/cert-manager/releases/download/v0.11.0/api-migration-darwin
|
||||
|
||||
# Mark the binary as executable and run the binary against your cluster
|
||||
$ chmod +x api-migration && ./api-migration --kubeconfig /path/to/my/kubeconfig.yaml
|
||||
|
||||
# Follow the CLI ouput and check for the difference that has been made in files
|
||||
$ diff ingress.yaml ingress-migrated.yaml
|
||||
|
||||
# Finally, once the new ingress resources have been reviewed, apply the manifests
|
||||
$ kubectl apply -f ingress-migrated.yaml --kubeconfig /path/to/my/kubeconfig.yaml
|
||||
|
||||
You should make sure to update _all_ Ingress resources to ensure that your
|
||||
certificates continue to be kept up to date.
|
||||
|
||||
@ -296,6 +296,7 @@ filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [
|
||||
":package-srcs",
|
||||
"//hack/api-migration:all-srcs",
|
||||
"//hack/bin:all-srcs",
|
||||
"//hack/boilerplate:all-srcs",
|
||||
"//hack/build:all-srcs",
|
||||
|
||||
38
hack/api-migration/BUILD.bazel
Normal file
38
hack/api-migration/BUILD.bazel
Normal file
@ -0,0 +1,38 @@
|
||||
load("@io_bazel_rules_go//go:def.bzl", "go_binary", "go_library")
|
||||
|
||||
go_library(
|
||||
name = "go_default_library",
|
||||
srcs = ["main.go"],
|
||||
importpath = "github.com/jetstack/cert-manager/hack/api-migration",
|
||||
visibility = ["//visibility:private"],
|
||||
deps = [
|
||||
"@com_github_spf13_cobra//:go_default_library",
|
||||
"@io_k8s_api//extensions/v1beta1:go_default_library",
|
||||
"@io_k8s_apimachinery//pkg/apis/meta/v1:go_default_library",
|
||||
"@io_k8s_apimachinery//pkg/runtime/serializer/json:go_default_library",
|
||||
"@io_k8s_client_go//kubernetes:go_default_library",
|
||||
"@io_k8s_client_go//kubernetes/scheme:go_default_library",
|
||||
"@io_k8s_client_go//plugin/pkg/client/auth:go_default_library",
|
||||
"@io_k8s_client_go//tools/clientcmd:go_default_library",
|
||||
],
|
||||
)
|
||||
|
||||
go_binary(
|
||||
name = "api-migration",
|
||||
embed = [":go_default_library"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "package-srcs",
|
||||
srcs = glob(["**"]),
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:private"],
|
||||
)
|
||||
|
||||
filegroup(
|
||||
name = "all-srcs",
|
||||
srcs = [":package-srcs"],
|
||||
tags = ["automanaged"],
|
||||
visibility = ["//visibility:public"],
|
||||
)
|
||||
220
hack/api-migration/main.go
Normal file
220
hack/api-migration/main.go
Normal file
@ -0,0 +1,220 @@
|
||||
/*
|
||||
Copyright 2019 The Jetstack cert-manager contributors.
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
*/
|
||||
|
||||
package main
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"os/exec"
|
||||
"strings"
|
||||
|
||||
"github.com/spf13/cobra"
|
||||
networkingv1beta "k8s.io/api/extensions/v1beta1"
|
||||
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
|
||||
"k8s.io/apimachinery/pkg/runtime/serializer/json"
|
||||
"k8s.io/client-go/kubernetes"
|
||||
"k8s.io/client-go/kubernetes/scheme"
|
||||
"k8s.io/client-go/tools/clientcmd"
|
||||
|
||||
// This package is required to be imported to register all client
|
||||
// plugins.
|
||||
_ "k8s.io/client-go/plugin/pkg/client/auth"
|
||||
)
|
||||
|
||||
const (
|
||||
oldGroupName = "certmanager.k8s.io"
|
||||
)
|
||||
|
||||
var (
|
||||
kubeconfig string
|
||||
origFile string
|
||||
newFile string
|
||||
migrations = map[string]string{
|
||||
"certmanager.k8s.io/acme-http01-edit-in-place": "acme.cert-manager.io/http01-edit-in-place",
|
||||
"certmanager.k8s.io/acme-http01-ingress-class": "acme.cert-manager.io/http01-ingress-class",
|
||||
|
||||
"certmanager.k8s.io/issuer": "cert-manager.io/issuer",
|
||||
"certmanager.k8s.io/cluster-issuer": "cert-manager.io/cluster-issuer",
|
||||
"certmanager.k8s.io/alt-names": "cert-manager.io/alt-names",
|
||||
"certmanager.k8s.io/ip-sans": "cert-manager.io/ip-sans",
|
||||
"certmanager.k8s.io/common-name": "cert-manager.io/common-name",
|
||||
"certmanager.k8s.io/issuer-name": "cert-manager.io/issuer-name",
|
||||
"certmanager.k8s.io/issuer-kind": "cert-manager.io/issuer-kind",
|
||||
"certmanager.k8s.io/certificate-name": "cert-manager.io/certificate-name",
|
||||
}
|
||||
|
||||
deprecations = []string{
|
||||
"certmanager.k8s.io/acme-challenge-type",
|
||||
"certmanager.k8s.io/acme-dns01-provider",
|
||||
}
|
||||
)
|
||||
|
||||
var cmd = &cobra.Command{
|
||||
Use: "cert-manager-api-migration",
|
||||
Long: "A tool to download Ingress resources and convert cert-manager annotations from certmanager.k8s.io to cert-manager.io. This tool will not modify resources in the API server.",
|
||||
RunE: func(cmd *cobra.Command, args []string) error {
|
||||
if len(kubeconfig) == 0 {
|
||||
kubeconfig = os.Getenv("KUBECONFIG")
|
||||
}
|
||||
|
||||
if len(kubeconfig) == 0 {
|
||||
return errors.New("flag --kubeconfig or environment variable $KUBECONFIG must be set")
|
||||
}
|
||||
|
||||
client, err := clientSet(kubeconfig)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ingList, err := client.ExtensionsV1beta1().Ingresses("").List(metav1.ListOptions{})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
ingStr, err := writeIngressToFile(ingList, origFile)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("written current ingresses to file %q\n", origFile)
|
||||
fmt.Printf("searching ingress resources for occurrences of old API annotations...\n")
|
||||
|
||||
for oldA, newA := range migrations {
|
||||
count := strings.Count(ingStr, oldA)
|
||||
if count == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("found %d instances of %q\tmigrating to %q\n", count, oldA, newA)
|
||||
|
||||
ingStr = strings.ReplaceAll(ingStr, oldA, newA)
|
||||
}
|
||||
|
||||
for _, d := range deprecations {
|
||||
count := strings.Count(ingStr, d)
|
||||
if count == 0 {
|
||||
continue
|
||||
}
|
||||
|
||||
fmt.Printf("found %d instances of %q\tthis field is DEPRECATED and will be deleted\n", count, d)
|
||||
|
||||
lines := strings.Split(ingStr, "\n")
|
||||
|
||||
for i, line := range lines {
|
||||
if strings.Contains(line, d) {
|
||||
lines = append(lines[:i], lines[i+1:]...)
|
||||
}
|
||||
}
|
||||
|
||||
ingStr = strings.Join(lines, "\n")
|
||||
}
|
||||
|
||||
count := strings.Count(ingStr, oldGroupName)
|
||||
if count > 0 {
|
||||
fmt.Fprintf(os.Stderr,
|
||||
"found %d more instances of the group %q with unrecognised paths\n", count, oldGroupName)
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(newFile, []byte(ingStr), 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("wrote new ingresses to file %q\n", newFile)
|
||||
|
||||
var buff bytes.Buffer
|
||||
diffFile := fmt.Sprintf("%s.%s.diff", origFile, newFile)
|
||||
eCmd := exec.Command("diff", origFile, newFile)
|
||||
eCmd.Stdout = &buff
|
||||
|
||||
if err := eCmd.Run(); err != nil {
|
||||
if exitErr, ok := err.(*exec.ExitError); !ok || exitErr.ExitCode() != 1 {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(diffFile, buff.Bytes(), 0644); err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
fmt.Printf("wrote diff to file %q\n", diffFile)
|
||||
|
||||
fmt.Printf("\nPlease check for any missing or incorrect annotations in your newly generated ingress manifests.\n")
|
||||
fmt.Printf("You should now check the diff of the two files to determine what has changed - either by inspecting the diff file %q, or running the command yourself:\n\n",
|
||||
diffFile)
|
||||
fmt.Printf("$ diff %s %s\n", origFile, newFile)
|
||||
|
||||
return nil
|
||||
},
|
||||
}
|
||||
|
||||
func writeIngressToFile(ingList *networkingv1beta.IngressList, path string) (string, error) {
|
||||
s := json.NewYAMLSerializer(json.DefaultMetaFactory, scheme.Scheme,
|
||||
scheme.Scheme)
|
||||
|
||||
var buff bytes.Buffer
|
||||
|
||||
for _, ing := range ingList.Items {
|
||||
ing.Kind = "Ingress"
|
||||
ing.APIVersion = "extensions/v1beta1"
|
||||
|
||||
if err := s.Encode(&ing, &buff); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
if _, err := buff.WriteString("---\n"); err != nil {
|
||||
return "", err
|
||||
}
|
||||
}
|
||||
|
||||
if err := ioutil.WriteFile(path, buff.Bytes(), 0644); err != nil {
|
||||
return "", err
|
||||
}
|
||||
|
||||
return buff.String(), nil
|
||||
}
|
||||
|
||||
func main() {
|
||||
cmd.PersistentFlags().StringVarP(&kubeconfig, "kubeconfig", "k", "", "Path location to Kubeconfig")
|
||||
cmd.PersistentFlags().StringVarP(&origFile, "original-file", "o", "ingress.yaml", "File path to store the current list of Ingress resources")
|
||||
cmd.PersistentFlags().StringVarP(&newFile, "new-file", "n", "ingress-migrated.yaml", "File path to store the migrated Ingress resources")
|
||||
|
||||
if err := cmd.Execute(); err != nil {
|
||||
fmt.Fprint(os.Stderr, err.Error())
|
||||
}
|
||||
}
|
||||
|
||||
func clientSet(kubeconfig string) (*kubernetes.Clientset, error) {
|
||||
kubeconfigBytes, err := ioutil.ReadFile(kubeconfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
restConfig, err := clientcmd.RESTConfigFromKubeConfig(kubeconfigBytes)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
clientset, err := kubernetes.NewForConfig(restConfig)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return clientset, nil
|
||||
}
|
||||
Loading…
Reference in New Issue
Block a user