From 4aa658b1ff158452d4987c1727985357c33a1fe2 Mon Sep 17 00:00:00 2001 From: James Munnelly Date: Thu, 9 Jul 2020 11:53:11 +0100 Subject: [PATCH] Persist installed cert-manager version as a label on created resources --- cmd/clusterctl/client/cluster/cert_manager.go | 25 +++++++++++++++++++ .../client/cluster/cert_manager_test.go | 25 +++++++++++++++++++ 2 files changed, 50 insertions(+) diff --git a/cmd/clusterctl/client/cluster/cert_manager.go b/cmd/clusterctl/client/cluster/cert_manager.go index 597a904bfd52..91cd66cc0870 100644 --- a/cmd/clusterctl/client/cluster/cert_manager.go +++ b/cmd/clusterctl/client/cluster/cert_manager.go @@ -33,6 +33,17 @@ import ( utilyaml "sigs.k8s.io/cluster-api/util/yaml" ) +var ( + // This is declared as a variable mapping a version number to the hash of the + // embedded cert-manager.yaml file. + // The hash is used to ensure that when the cert-manager.yaml file is updated, + // the version number marker here is _also_ updated. + // If the cert-manager.yaml asset is modified, this line **MUST** be updated + // accordingly else future upgrades of the cert-manager component will not + // be possible, as there'll be no record of the version installed. + embeddedCertManagerManifestVersion = map[string]string{"v0.15.2": "56bd9851567be27698114a73625594a9"} +) + const ( embeddedCertManagerManifestPath = "cmd/clusterctl/config/assets/cert-manager.yaml" embeddedCertManagerTestResourcesManifestPath = "cmd/clusterctl/config/assets/cert-manager-test-resources.yaml" @@ -199,6 +210,9 @@ func (cm *certManagerClient) createObj(o unstructured.Unstructured) error { labels = map[string]string{} } labels[clusterctlv1.ClusterctlCoreLabelName] = "cert-manager" + // persist the version number of stored resources to make a + // future enhancement to add upgrade support possible. + labels["certmanager.clusterctl.cluster.x-k8s.io/version"] = embeddedCertManagerVersion() o.SetLabels(labels) if err = c.Create(ctx, &o); err != nil { @@ -265,3 +279,14 @@ func (cm *certManagerClient) waitForAPIReady(ctx context.Context, retry bool) er return nil } + +func embeddedCertManagerVersion() string { + if len(embeddedCertManagerManifestVersion) != 1 { + panic("embeddedCertManagerManifestVersion MUST only have one entry") + } + for version := range embeddedCertManagerManifestVersion { + return version + } + // unreachable + return "" +} diff --git a/cmd/clusterctl/client/cluster/cert_manager_test.go b/cmd/clusterctl/client/cluster/cert_manager_test.go index d495f967de22..1ce5bb683efd 100644 --- a/cmd/clusterctl/client/cluster/cert_manager_test.go +++ b/cmd/clusterctl/client/cluster/cert_manager_test.go @@ -17,6 +17,8 @@ limitations under the License. package cluster import ( + "crypto/md5" + "fmt" "testing" "time" @@ -25,10 +27,33 @@ import ( "k8s.io/apimachinery/pkg/apis/meta/v1/unstructured" "k8s.io/apimachinery/pkg/util/wait" "sigs.k8s.io/cluster-api/cmd/clusterctl/client/config" + manifests "sigs.k8s.io/cluster-api/cmd/clusterctl/config" "sigs.k8s.io/cluster-api/cmd/clusterctl/internal/scheme" "sigs.k8s.io/cluster-api/cmd/clusterctl/internal/test" ) +func Test_VersionMarkerUpToDate(t *testing.T) { + if len(embeddedCertManagerManifestVersion) != 1 { + t.Fatal("embeddedCertManagerManifestVersion map MUST only contain one item") + } + + // As we know this map only contains a single element, this is an easy + // way to extract both the key and value of the only element in the map. + var _, hash string + for _, hash = range embeddedCertManagerManifestVersion { + } + + yaml, err := manifests.Asset(embeddedCertManagerTestResourcesManifestPath) + if err != nil { + t.Fatalf("Failed to get cert-manager.yaml asset data: %v", err) + } + + actualHash := fmt.Sprintf("%x", md5.Sum(yaml)) + if actualHash != hash { + t.Errorf("The cert-manager.yaml asset data has changed, but the version marker embeddedCertManagerManifestVersion has not been updated. Expected hash to be: %s", actualHash) + } +} + func Test_certManagerClient_getManifestObjects(t *testing.T) { tests := []struct {