From fae39bb525df140d992449582326731fdf98223e Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Tue, 8 Oct 2019 16:09:57 +0100 Subject: [PATCH 1/3] Adds CLI migration tool with docs on how to use it Signed-off-by: JoshVanL --- docs/tasks/upgrading/upgrading-0.10-0.11.rst | 32 ++- hack/BUILD.bazel | 1 + hack/api-migration/BUILD.bazel | 38 ++++ hack/api-migration/main.go | 203 +++++++++++++++++++ 4 files changed, 273 insertions(+), 1 deletion(-) create mode 100644 hack/api-migration/BUILD.bazel create mode 100644 hack/api-migration/main.go diff --git a/docs/tasks/upgrading/upgrading-0.10-0.11.rst b/docs/tasks/upgrading/upgrading-0.10-0.11.rst index c3263d70a..8e2f3e6fe 100644 --- a/docs/tasks/upgrading/upgrading-0.10-0.11.rst +++ b/docs/tasks/upgrading/upgrading-0.10-0.11.rst @@ -47,7 +47,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 | DEPRECIATED | +| certmanager.k8s.io/acme-dns01-provider | DEPRECIATED | +| 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 +74,23 @@ 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 + $ TODO: Add link + + # Mark the binary as executable and run the binary against your cluster + $ chmod +x api-migration && ./api-migration --kubeconfig /path/to/my/kubeconfig + + # Follow the CLI ouput and check for the difference that has been made in files + $ vim -d ingress.yaml ingress-migrated.yaml + + # Finally, once the new ingress resources have been reviewed, apply the manifests + $ kubectl apply -f ingress-migrated --kubeconfig /path/to/my/kubeconfig + You should make sure to update _all_ Ingress resources to ensure that your certificates continue to be kept up to date. diff --git a/hack/BUILD.bazel b/hack/BUILD.bazel index 6db028ad7..d5599e8a4 100644 --- a/hack/BUILD.bazel +++ b/hack/BUILD.bazel @@ -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", diff --git a/hack/api-migration/BUILD.bazel b/hack/api-migration/BUILD.bazel new file mode 100644 index 000000000..69a626183 --- /dev/null +++ b/hack/api-migration/BUILD.bazel @@ -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//networking/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"], +) diff --git a/hack/api-migration/main.go b/hack/api-migration/main.go new file mode 100644 index 000000000..e55c0d4ed --- /dev/null +++ b/hack/api-migration/main.go @@ -0,0 +1,203 @@ +/* +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" + "strings" + + "github.com/spf13/cobra" + networkingv1beta "k8s.io/api/networking/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", + } + + depreciations = []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.NetworkingV1beta1().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 depreciations { + count := strings.Count(ingStr, d) + if count == 0 { + continue + } + + fmt.Printf("found %d instances of %q\tthis field is DEPRECIATED 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("written new ingresses to file %q\n", newFile) + fmt.Printf("\nPlease check for any missing or wrong annotations in your newly generated ingress manifests.\n") + fmt.Printf("You are encouraged to check the diff of the two files to determine what has changed (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 { + _, err := buff.WriteString("apiVersion: networking.k8s.io/v1beta1\nkind: Ingress\n") + if err != nil { + return "", err + } + + if err := s.Encode(&ing, &buff); err != nil { + return "", err + } + + _, err = buff.WriteString("---\n") + if 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 +} From 345385fcfcf2ad80cfdab40a4a0add7fe2172d44 Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Tue, 8 Oct 2019 17:17:54 +0100 Subject: [PATCH 2/3] Fix up migration output and its docs Signed-off-by: JoshVanL --- docs/tasks/upgrading/upgrading-0.10-0.11.rst | 10 ++-- hack/api-migration/BUILD.bazel | 2 +- hack/api-migration/main.go | 49 +++++++++++++------- 3 files changed, 39 insertions(+), 22 deletions(-) diff --git a/docs/tasks/upgrading/upgrading-0.10-0.11.rst b/docs/tasks/upgrading/upgrading-0.10-0.11.rst index 8e2f3e6fe..0e04470a0 100644 --- a/docs/tasks/upgrading/upgrading-0.10-0.11.rst +++ b/docs/tasks/upgrading/upgrading-0.10-0.11.rst @@ -53,8 +53,8 @@ A full table of annotations, including the old and new equivalents: | 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 | DEPRECIATED | -| certmanager.k8s.io/acme-dns01-provider | DEPRECIATED | +| 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 | @@ -84,13 +84,13 @@ your cluster for you. $ TODO: Add link # Mark the binary as executable and run the binary against your cluster - $ chmod +x api-migration && ./api-migration --kubeconfig /path/to/my/kubeconfig + $ 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 - $ vim -d ingress.yaml ingress-migrated.yaml + $ diff ingress.yaml ingress-migrated.yaml # Finally, once the new ingress resources have been reviewed, apply the manifests - $ kubectl apply -f ingress-migrated --kubeconfig /path/to/my/kubeconfig + $ kubectl apply -f ingress-migrated --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. diff --git a/hack/api-migration/BUILD.bazel b/hack/api-migration/BUILD.bazel index 69a626183..693207fc2 100644 --- a/hack/api-migration/BUILD.bazel +++ b/hack/api-migration/BUILD.bazel @@ -7,7 +7,7 @@ go_library( visibility = ["//visibility:private"], deps = [ "@com_github_spf13_cobra//:go_default_library", - "@io_k8s_api//networking/v1beta1: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", diff --git a/hack/api-migration/main.go b/hack/api-migration/main.go index e55c0d4ed..6be79294b 100644 --- a/hack/api-migration/main.go +++ b/hack/api-migration/main.go @@ -22,15 +22,17 @@ import ( "fmt" "io/ioutil" "os" + "os/exec" "strings" "github.com/spf13/cobra" - networkingv1beta "k8s.io/api/networking/v1beta1" + 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" @@ -58,7 +60,7 @@ var ( "certmanager.k8s.io/certificate-name": "cert-manager.io/certificate-name", } - depreciations = []string{ + deprecations = []string{ "certmanager.k8s.io/acme-challenge-type", "certmanager.k8s.io/acme-dns01-provider", } @@ -81,7 +83,7 @@ var cmd = &cobra.Command{ return err } - ingList, err := client.NetworkingV1beta1().Ingresses("").List(metav1.ListOptions{}) + ingList, err := client.ExtensionsV1beta1().Ingresses("").List(metav1.ListOptions{}) if err != nil { return err } @@ -105,13 +107,13 @@ var cmd = &cobra.Command{ ingStr = strings.ReplaceAll(ingStr, oldA, newA) } - for _, d := range depreciations { + for _, d := range deprecations { count := strings.Count(ingStr, d) if count == 0 { continue } - fmt.Printf("found %d instances of %q\tthis field is DEPRECIATED and will be deleted\n", count, d) + fmt.Printf("found %d instances of %q\tthis field is DEPRECATED and will be deleted\n", count, d) lines := strings.Split(ingStr, "\n") @@ -134,10 +136,29 @@ var cmd = &cobra.Command{ return err } - fmt.Printf("written new ingresses to file %q\n", newFile) - fmt.Printf("\nPlease check for any missing or wrong annotations in your newly generated ingress manifests.\n") - fmt.Printf("You are encouraged to check the diff of the two files to determine what has changed (diff %s %s).\n", - origFile, newFile) + 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 }, @@ -150,17 +171,14 @@ func writeIngressToFile(ingList *networkingv1beta.IngressList, path string) (str var buff bytes.Buffer for _, ing := range ingList.Items { - _, err := buff.WriteString("apiVersion: networking.k8s.io/v1beta1\nkind: Ingress\n") - if err != nil { - return "", err - } + ing.Kind = "Ingress" + ing.APIVersion = "extensions/v1beta1" if err := s.Encode(&ing, &buff); err != nil { return "", err } - _, err = buff.WriteString("---\n") - if err != nil { + if _, err := buff.WriteString("---\n"); err != nil { return "", err } } @@ -173,7 +191,6 @@ func writeIngressToFile(ingList *networkingv1beta.IngressList, path string) (str } 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") From af8d844a70bf0d0929e8dc1e3ff6c31dcc7129f2 Mon Sep 17 00:00:00 2001 From: JoshVanL Date: Tue, 8 Oct 2019 18:16:34 +0100 Subject: [PATCH 3/3] Links uninstall docs, adds predicted links and minor fix Signed-off-by: JoshVanL --- docs/tasks/upgrading/upgrading-0.10-0.11.rst | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docs/tasks/upgrading/upgrading-0.10-0.11.rst b/docs/tasks/upgrading/upgrading-0.10-0.11.rst index 0e04470a0..4ea5072b9 100644 --- a/docs/tasks/upgrading/upgrading-0.10-0.11.rst +++ b/docs/tasks/upgrading/upgrading-0.10-0.11.rst @@ -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`` @@ -75,13 +73,15 @@ still contain an old annotation: 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 +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 - $ TODO: Add link + $ 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 @@ -90,7 +90,7 @@ your cluster for you. $ diff ingress.yaml ingress-migrated.yaml # Finally, once the new ingress resources have been reviewed, apply the manifests - $ kubectl apply -f ingress-migrated --kubeconfig /path/to/my/kubeconfig.yaml + $ 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.