From 1a480030b41c6d505226acfa3f905c926e141922 Mon Sep 17 00:00:00 2001 From: shysank Date: Mon, 11 Oct 2021 11:12:00 -0700 Subject: [PATCH 1/3] add v1alpha3 -> v1beta1 upgrade test Co-authored-by: sonasingh46 --- test/e2e/capi_test.go | 34 ++- test/e2e/config/azure-dev.yaml | 149 +++++++---- .../v1alpha3/cluster-template-prow.yaml | 243 ++++++++++++++++++ test/e2e/data/shared/v1alpha3/metadata.yaml | 9 + .../shared/v1alpha3_provider/metadata.yaml | 13 + 5 files changed, 391 insertions(+), 57 deletions(-) create mode 100644 test/e2e/data/infrastructure-azure/v1alpha3/cluster-template-prow.yaml create mode 100644 test/e2e/data/shared/v1alpha3/metadata.yaml create mode 100644 test/e2e/data/shared/v1alpha3_provider/metadata.yaml diff --git a/test/e2e/capi_test.go b/test/e2e/capi_test.go index 30287dfd7b7..53bdbb5a4e8 100644 --- a/test/e2e/capi_test.go +++ b/test/e2e/capi_test.go @@ -20,13 +20,13 @@ package e2e import ( "context" + "encoding/base64" "fmt" - "os" - . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" corev1 "k8s.io/api/core/v1" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" + "os" e2e_namespace "sigs.k8s.io/cluster-api-provider-azure/test/e2e/kubernetes/namespace" clusterctl "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" capi_e2e "sigs.k8s.io/cluster-api/test/e2e" @@ -228,4 +228,34 @@ var _ = Describe("Running the Cluster API E2E tests", func() { } }) }) + + if os.Getenv("LOCAL_ONLY") != "true" { + Context("upgrade from v1alpha3 to v1beta1, and scale workload clusters created in v1alpha3", func() { + BeforeEach(func() { + // Unset resource group and vnet env variables, since we capi test creates 2 clusters, + // and will result in both the clusters using the same vnet and resource group. + Expect(os.Unsetenv(AzureResourceGroup)).To(Succeed()) + Expect(os.Unsetenv(AzureVNetName)).To(Succeed()) + + // Set base64 encoded values for v1alpha3 cluster. + Expect(os.Setenv("AZURE_CLIENT_ID_B64", base64.StdEncoding.EncodeToString([]byte(os.Getenv(AzureClientId))))).To(Succeed()) + Expect(os.Setenv("AZURE_CLIENT_SECRET_B64", base64.StdEncoding.EncodeToString([]byte(os.Getenv(AzureClientSecret))))).To(Succeed()) + Expect(os.Setenv("AZURE_SUBSCRIPTION_ID_B64", base64.StdEncoding.EncodeToString([]byte(os.Getenv("AZURE_SUBSCRIPTION_ID"))))).To(Succeed()) + Expect(os.Setenv("AZURE_TENANT_ID_B64", base64.StdEncoding.EncodeToString([]byte(os.Getenv("AZURE_TENANT_ID"))))).To(Succeed()) + + // Unset windows specific variables + Expect(os.Unsetenv("WINDOWS_WORKER_MACHINE_COUNT")).To(Succeed()) + Expect(os.Unsetenv("K8S_FEATURE_GATES")).To(Succeed()) + }) + capi_e2e.ClusterctlUpgradeSpec(ctx, func() capi_e2e.ClusterctlUpgradeSpecInput { + return capi_e2e.ClusterctlUpgradeSpecInput{ + E2EConfig: e2eConfig, + ClusterctlConfigPath: clusterctlConfigPath, + BootstrapClusterProxy: bootstrapClusterProxy, + ArtifactFolder: artifactFolder, + SkipCleanup: skipCleanup, + } + }) + }) + } }) diff --git a/test/e2e/config/azure-dev.yaml b/test/e2e/config/azure-dev.yaml index b3a79385ba0..b1a01c85f31 100644 --- a/test/e2e/config/azure-dev.yaml +++ b/test/e2e/config/azure-dev.yaml @@ -8,6 +8,15 @@ providers: - name: cluster-api type: CoreProvider versions: + - name: v0.3.23 # latest published release in the v1alpha3 series; this is used for v1alpha3 --> v1beta1 clusterctl upgrades test only. + value: https://github.com/kubernetes-sigs/cluster-api/releases/download/v0.3.23/core-components.yaml + type: url + contract: v1alpha3 + files: + - sourcePath: "../data/shared/v1alpha3/metadata.yaml" + replacements: + - old: "imagePullPolicy: Always" + new: "imagePullPolicy: IfNotPresent" - name: v1.0.0 value: https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.0.0/core-components.yaml type: url @@ -16,11 +25,20 @@ providers: replacements: - old: "imagePullPolicy: Always" new: "imagePullPolicy: IfNotPresent" - - old: "--leader-elect" - new: "--leader-elect=false" + + - name: kubeadm type: BootstrapProvider versions: + - name: v0.3.23 # latest published release in the v1alpha3 series; this is used for v1alpha3 --> v1beta1 clusterctl upgrades test only. + value: https://github.com/kubernetes-sigs/cluster-api/releases/download/v0.3.23/bootstrap-components.yaml + type: url + contract: v1alpha3 + files: + - sourcePath: "../data/shared/v1alpha3/metadata.yaml" + replacements: + - old: "imagePullPolicy: Always" + new: "imagePullPolicy: IfNotPresent" - name: v1.0.0 value: https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.0.0/bootstrap-components.yaml type: url @@ -29,11 +47,19 @@ providers: replacements: - old: "imagePullPolicy: Always" new: "imagePullPolicy: IfNotPresent" - - old: "--leader-elect" - new: "--leader-elect=false" + - name: kubeadm type: ControlPlaneProvider versions: + - name: v0.3.23 # latest published release in the v1alpha3 series; this is used for v1alpha3 --> v1beta1 clusterctl upgrades test only. + value: https://github.com/kubernetes-sigs/cluster-api/releases/download/v0.3.23/control-plane-components.yaml + type: url + contract: v1alpha3 + files: + - sourcePath: "../data/shared/v1alpha3/metadata.yaml" + replacements: + - old: "imagePullPolicy: Always" + new: "imagePullPolicy: IfNotPresent" - name: v1.0.0 value: https://github.com/kubernetes-sigs/cluster-api/releases/download/v1.0.0/control-plane-components.yaml type: url @@ -42,66 +68,74 @@ providers: replacements: - old: "imagePullPolicy: Always" new: "imagePullPolicy: IfNotPresent" - - old: "--leader-elect" - new: "--leader-elect=false" + - name: azure type: InfrastructureProvider versions: - - name: v1.0.0 + - name: v0.4.15 # latest published release in the v1alpha3 series; this is used for v1alpha3 --> v1beta1 clusterctl upgrades test only. + value: https://github.com/kubernetes-sigs/cluster-api-provider-azure/releases/download/v0.4.15/infrastructure-components.yaml + type: url + contract: v1alpha3 + files: + - sourcePath: "../data/shared/v1alpha3_provider/metadata.yaml" + - sourcePath: "../data/infrastructure-azure/v1alpha3/cluster-template-prow.yaml" + targetName: "cluster-template.yaml" + replacements: + - old: "imagePullPolicy: Always" + new: "imagePullPolicy: IfNotPresent" + - name: v1.0.99 # next; use manifest from source files value: "${PWD}/config/default" files: - sourcePath: "../data/shared/v1beta1_provider/metadata.yaml" + - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow.yaml" + targetName: "cluster-template.yaml" + - sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template.yaml" + targetName: "cluster-template-management.yaml" + - sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-kcp-adoption.yaml" + targetName: "cluster-template-kcp-adoption.yaml" + - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-ipv6.yaml" + targetName: "cluster-template-ipv6.yaml" + - sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-md-remediation.yaml" + targetName: "cluster-template-md-remediation.yaml" + - sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-kcp-remediation.yaml" + targetName: "cluster-template-kcp-remediation.yaml" + - sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-kcp-scale-in.yaml" + targetName: "cluster-template-kcp-scale-in.yaml" + - sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-node-drain.yaml" + targetName: "cluster-template-node-drain.yaml" + - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-machine-pool.yaml" + targetName: "cluster-template-machine-pool.yaml" + - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-nvidia-gpu.yaml" + targetName: "cluster-template-nvidia-gpu.yaml" + - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-private.yaml" + targetName: "cluster-template-private.yaml" + - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-ci-version.yaml" + targetName: "cluster-template-conformance-ci-artifacts.yaml" + - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-ci-version-windows.yaml" + targetName: "cluster-template-conformance-ci-artifacts-windows.yaml" + - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-ci-version-windows-containerd-2022.yaml" + targetName: "cluster-template-conformance-ci-artifacts-windows-containerd-2022.yaml" + - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-ci-version.yaml" + targetName: "cluster-template-conformance-ci-artifacts-windows-containerd.yaml" + - sourcePath: "${PWD}/templates/test/dev/cluster-template-custom-builds.yaml" + targetName: "cluster-template-conformance-presubmit-artifacts.yaml" + - sourcePath: "${PWD}/templates/test/dev/cluster-template-custom-builds.yaml" + targetName: "cluster-template-conformance-presubmit-artifacts-windows-containerd.yaml" + - sourcePath: "${PWD}/templates/test/dev/cluster-template-custom-builds-windows.yaml" + targetName: "cluster-template-conformance-presubmit-artifacts-windows.yaml" + - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-windows.yaml" + targetName: "cluster-template-windows.yaml" + - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-machine-pool-windows.yaml" + targetName: "cluster-template-machine-pool-windows.yaml" + - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-external-cloud-provider.yaml" + targetName: "cluster-template-external-cloud-provider.yaml" + - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-aks-multi-tenancy.yaml" + targetName: "cluster-template-aks-multi-tenancy.yaml" + - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-custom-vnet.yaml" + targetName: "cluster-template-custom-vnet.yaml" replacements: - old: "--v=0" new: "--v=2" - files: - - sourcePath: "../data/shared/v1beta1/metadata.yaml" - - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow.yaml" - targetName: "cluster-template.yaml" - - sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template.yaml" - targetName: "cluster-template-management.yaml" - - sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-kcp-adoption.yaml" - targetName: "cluster-template-kcp-adoption.yaml" - - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-ipv6.yaml" - targetName: "cluster-template-ipv6.yaml" - - sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-md-remediation.yaml" - targetName: "cluster-template-md-remediation.yaml" - - sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-kcp-remediation.yaml" - targetName: "cluster-template-kcp-remediation.yaml" - - sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-kcp-scale-in.yaml" - targetName: "cluster-template-kcp-scale-in.yaml" - - sourcePath: "../data/infrastructure-azure/v1beta1/cluster-template-node-drain.yaml" - targetName: "cluster-template-node-drain.yaml" - - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-machine-pool.yaml" - targetName: "cluster-template-machine-pool.yaml" - - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-nvidia-gpu.yaml" - targetName: "cluster-template-nvidia-gpu.yaml" - - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-private.yaml" - targetName: "cluster-template-private.yaml" - - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-ci-version.yaml" - targetName: "cluster-template-conformance-ci-artifacts.yaml" - - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-ci-version-windows.yaml" - targetName: "cluster-template-conformance-ci-artifacts-windows.yaml" - - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-ci-version-windows-containerd-2022.yaml" - targetName: "cluster-template-conformance-ci-artifacts-windows-containerd-2022.yaml" - - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-ci-version.yaml" - targetName: "cluster-template-conformance-ci-artifacts-windows-containerd.yaml" - - sourcePath: "${PWD}/templates/test/dev/cluster-template-custom-builds.yaml" - targetName: "cluster-template-conformance-presubmit-artifacts.yaml" - - sourcePath: "${PWD}/templates/test/dev/cluster-template-custom-builds.yaml" - targetName: "cluster-template-conformance-presubmit-artifacts-windows-containerd.yaml" - - sourcePath: "${PWD}/templates/test/dev/cluster-template-custom-builds-windows.yaml" - targetName: "cluster-template-conformance-presubmit-artifacts-windows.yaml" - - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-windows.yaml" - targetName: "cluster-template-windows.yaml" - - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-machine-pool-windows.yaml" - targetName: "cluster-template-machine-pool-windows.yaml" - - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-external-cloud-provider.yaml" - targetName: "cluster-template-external-cloud-provider.yaml" - - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-aks-multi-tenancy.yaml" - targetName: "cluster-template-aks-multi-tenancy.yaml" - - sourcePath: "${PWD}/templates/test/ci/cluster-template-prow-custom-vnet.yaml" - targetName: "cluster-template-custom-vnet.yaml" variables: KUBERNETES_VERSION: "${KUBERNETES_VERSION:-v1.22.1}" @@ -125,6 +159,11 @@ variables: CLUSTER_IDENTITY_NAME: "cluster-identity" NODE_DRAIN_TIMEOUT: "60s" CI_VERSION: "" + # NOTE: INIT_WITH_BINARY and INIT_WITH_KUBERNETES_VERSION are only used by the clusterctl upgrade test to initialize + # the management cluster to be upgraded. + INIT_WITH_BINARY: "https://github.com/kubernetes-sigs/cluster-api/releases/download/v0.3.23/clusterctl-{OS}-{ARCH}" + INIT_WITH_PROVIDERS_CONTRACT: "v1alpha3" + INIT_WITH_KUBERNETES_VERSION: "v1.21.2" intervals: default/wait-controllers: ["3m", "10s"] diff --git a/test/e2e/data/infrastructure-azure/v1alpha3/cluster-template-prow.yaml b/test/e2e/data/infrastructure-azure/v1alpha3/cluster-template-prow.yaml new file mode 100644 index 00000000000..5e44a7ecc6d --- /dev/null +++ b/test/e2e/data/infrastructure-azure/v1alpha3/cluster-template-prow.yaml @@ -0,0 +1,243 @@ +apiVersion: cluster.x-k8s.io/v1alpha3 +kind: Cluster +metadata: + labels: + cni: ${CLUSTER_NAME}-crs-0 + name: ${CLUSTER_NAME} + namespace: default +spec: + clusterNetwork: + pods: + cidrBlocks: + - 192.168.0.0/16 + controlPlaneRef: + apiVersion: controlplane.cluster.x-k8s.io/v1alpha3 + kind: KubeadmControlPlane + name: ${CLUSTER_NAME}-control-plane + infrastructureRef: + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 + kind: AzureCluster + name: ${CLUSTER_NAME} +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AzureCluster +metadata: + name: ${CLUSTER_NAME} + namespace: default +spec: + additionalTags: + creationTimestamp: ${TIMESTAMP} + jobName: ${JOB_NAME} + location: ${AZURE_LOCATION} + networkSpec: + vnet: + name: ${AZURE_VNET_NAME:=${CLUSTER_NAME}-vnet} + resourceGroup: ${AZURE_RESOURCE_GROUP:=${CLUSTER_NAME}} + subscriptionID: ${AZURE_SUBSCRIPTION_ID} +--- +apiVersion: controlplane.cluster.x-k8s.io/v1alpha3 +kind: KubeadmControlPlane +metadata: + name: ${CLUSTER_NAME}-control-plane + namespace: default +spec: + infrastructureTemplate: + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 + kind: AzureMachineTemplate + name: ${CLUSTER_NAME}-control-plane + kubeadmConfigSpec: + clusterConfiguration: + apiServer: + extraArgs: + cloud-config: /etc/kubernetes/azure.json + cloud-provider: azure + extraVolumes: + - hostPath: /etc/kubernetes/azure.json + mountPath: /etc/kubernetes/azure.json + name: cloud-config + readOnly: true + timeoutForControlPlane: 20m + controllerManager: + extraArgs: + allocate-node-cidrs: "false" + cloud-config: /etc/kubernetes/azure.json + cloud-provider: azure + cluster-name: ${CLUSTER_NAME} + v: "4" + extraVolumes: + - hostPath: /etc/kubernetes/azure.json + mountPath: /etc/kubernetes/azure.json + name: cloud-config + readOnly: true + etcd: + local: + dataDir: /var/lib/etcddisk/etcd + diskSetup: + filesystems: + - device: /dev/disk/azure/scsi1/lun0 + extraOpts: + - -E + - lazy_itable_init=1,lazy_journal_init=1 + filesystem: ext4 + label: etcd_disk + - device: ephemeral0.1 + filesystem: ext4 + label: ephemeral0 + replaceFS: ntfs + partitions: + - device: /dev/disk/azure/scsi1/lun0 + layout: true + overwrite: false + tableType: gpt + files: + - contentFrom: + secret: + key: control-plane-azure.json + name: ${CLUSTER_NAME}-control-plane-azure-json + owner: root:root + path: /etc/kubernetes/azure.json + permissions: "0644" + initConfiguration: + nodeRegistration: + kubeletExtraArgs: + cloud-config: /etc/kubernetes/azure.json + cloud-provider: azure + name: '{{ ds.meta_data["local_hostname"] }}' + joinConfiguration: + nodeRegistration: + kubeletExtraArgs: + cloud-config: /etc/kubernetes/azure.json + cloud-provider: azure + name: '{{ ds.meta_data["local_hostname"] }}' + mounts: + - - LABEL=etcd_disk + - /var/lib/etcddisk + useExperimentalRetryJoin: true + replicas: ${CONTROL_PLANE_MACHINE_COUNT} + version: ${KUBERNETES_VERSION} +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AzureMachineTemplate +metadata: + name: ${CLUSTER_NAME}-control-plane + namespace: default +spec: + template: + spec: + dataDisks: + - diskSizeGB: 256 + lun: 0 + nameSuffix: etcddisk + location: ${AZURE_LOCATION} + osDisk: + diskSizeGB: 128 + managedDisk: + storageAccountType: Premium_LRS + osType: Linux + sshPublicKey: ${AZURE_SSH_PUBLIC_KEY_B64:=""} + vmSize: ${AZURE_CONTROL_PLANE_MACHINE_TYPE} +--- +apiVersion: cluster.x-k8s.io/v1alpha3 +kind: MachineDeployment +metadata: + name: ${CLUSTER_NAME}-md-0 + namespace: default +spec: + clusterName: ${CLUSTER_NAME} + replicas: ${WORKER_MACHINE_COUNT} + selector: + matchLabels: null + template: + metadata: + labels: + nodepool: pool1 + spec: + bootstrap: + configRef: + apiVersion: bootstrap.cluster.x-k8s.io/v1alpha3 + kind: KubeadmConfigTemplate + name: ${CLUSTER_NAME}-md-0 + clusterName: ${CLUSTER_NAME} + infrastructureRef: + apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 + kind: AzureMachineTemplate + name: ${CLUSTER_NAME}-md-0 + version: ${KUBERNETES_VERSION} +--- +apiVersion: infrastructure.cluster.x-k8s.io/v1alpha3 +kind: AzureMachineTemplate +metadata: + name: ${CLUSTER_NAME}-md-0 + namespace: default +spec: + template: + spec: + location: ${AZURE_LOCATION} + osDisk: + diskSizeGB: 128 + managedDisk: + storageAccountType: Premium_LRS + osType: Linux + sshPublicKey: ${AZURE_SSH_PUBLIC_KEY_B64:=""} + vmSize: ${AZURE_NODE_MACHINE_TYPE} +--- +apiVersion: bootstrap.cluster.x-k8s.io/v1alpha3 +kind: KubeadmConfigTemplate +metadata: + name: ${CLUSTER_NAME}-md-0 + namespace: default +spec: + template: + spec: + files: + - contentFrom: + secret: + key: worker-node-azure.json + name: ${CLUSTER_NAME}-md-0-azure-json + owner: root:root + path: /etc/kubernetes/azure.json + permissions: "0644" + joinConfiguration: + nodeRegistration: + kubeletExtraArgs: + cloud-config: /etc/kubernetes/azure.json + cloud-provider: azure + name: '{{ ds.meta_data["local_hostname"] }}' + useExperimentalRetryJoin: true +--- +apiVersion: cluster.x-k8s.io/v1alpha3 +kind: MachineHealthCheck +metadata: + name: ${CLUSTER_NAME}-mhc-0 + namespace: default +spec: + clusterName: ${CLUSTER_NAME} + maxUnhealthy: 100% + selector: + matchLabels: + nodepool: pool1 + unhealthyConditions: + - status: "True" + timeout: 30s + type: E2ENodeUnhealthy +--- +apiVersion: v1 +data: ${CNI_RESOURCES} +kind: ConfigMap +metadata: + name: cni-${CLUSTER_NAME}-crs-0 + namespace: default +--- +apiVersion: addons.cluster.x-k8s.io/v1alpha3 +kind: ClusterResourceSet +metadata: + name: ${CLUSTER_NAME}-crs-0 + namespace: default +spec: + clusterSelector: + matchLabels: + cni: ${CLUSTER_NAME}-crs-0 + resources: + - kind: ConfigMap + name: cni-${CLUSTER_NAME}-crs-0 + strategy: ApplyOnce diff --git a/test/e2e/data/shared/v1alpha3/metadata.yaml b/test/e2e/data/shared/v1alpha3/metadata.yaml new file mode 100644 index 00000000000..f79552caf79 --- /dev/null +++ b/test/e2e/data/shared/v1alpha3/metadata.yaml @@ -0,0 +1,9 @@ +apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 +kind: Metadata +releaseSeries: + - major: 0 + minor: 3 + contract: v1alpha3 + - major: 0 + minor: 2 + contract: v1alpha2 diff --git a/test/e2e/data/shared/v1alpha3_provider/metadata.yaml b/test/e2e/data/shared/v1alpha3_provider/metadata.yaml new file mode 100644 index 00000000000..87fcec6aca8 --- /dev/null +++ b/test/e2e/data/shared/v1alpha3_provider/metadata.yaml @@ -0,0 +1,13 @@ +# maps release series of major.minor to cluster-api contract version +# the contract version may change between minor or major versions, but *not* +# between patch versions. +# +# update this file only when a new major or minor version is released +apiVersion: clusterctl.cluster.x-k8s.io/v1alpha3 +releaseSeries: + - major: 0 + minor: 3 + contract: v1alpha2 + - major: 0 + minor: 4 + contract: v1alpha3 From 4de6ecdc65283e3e10ff2dbbc06cc5cdd12d3d2e Mon Sep 17 00:00:00 2001 From: shysank Date: Thu, 21 Oct 2021 12:54:01 -0700 Subject: [PATCH 2/3] fix default mismatch during v1alpha3 -> v1beta1 upgrade --- api/v1beta1/azurecluster_webhook.go | 18 ++++++++++++++---- api/v1beta1/azuremachinetemplate_webhook.go | 20 ++++++++++++++++---- 2 files changed, 30 insertions(+), 8 deletions(-) diff --git a/api/v1beta1/azurecluster_webhook.go b/api/v1beta1/azurecluster_webhook.go index 44829a7317d..f3b5b0c6d81 100644 --- a/api/v1beta1/azurecluster_webhook.go +++ b/api/v1beta1/azurecluster_webhook.go @@ -85,10 +85,20 @@ func (c *AzureCluster) ValidateUpdate(oldRaw runtime.Object) error { } if !reflect.DeepEqual(c.Spec.AzureEnvironment, old.Spec.AzureEnvironment) { - allErrs = append(allErrs, - field.Invalid(field.NewPath("spec", "AzureEnvironment"), - c.Spec.AzureEnvironment, "field is immutable"), - ) + // The equality failure could be because of default mismatch between v1alpha3 and v1beta1. This happens because + // the new object `r` will have run through the default webhooks but the old object `old` would not have so. + // This means if the old object was in v1alpha3, it would not get the new defaults set in v1beta1 resulting + // in object inequality. To workaround this, we set the v1beta1 defaults here so that the old object also gets + // the new defaults. + old.setAzureEnvironmentDefault() + + // if it's still not equal, return error. + if !reflect.DeepEqual(c.Spec.AzureEnvironment, old.Spec.AzureEnvironment) { + allErrs = append(allErrs, + field.Invalid(field.NewPath("spec", "AzureEnvironment"), + c.Spec.AzureEnvironment, "field is immutable"), + ) + } } if !reflect.DeepEqual(c.Spec.NetworkSpec.PrivateDNSZoneName, old.Spec.NetworkSpec.PrivateDNSZoneName) { diff --git a/api/v1beta1/azuremachinetemplate_webhook.go b/api/v1beta1/azuremachinetemplate_webhook.go index 27e8647848b..a19819b1649 100644 --- a/api/v1beta1/azuremachinetemplate_webhook.go +++ b/api/v1beta1/azuremachinetemplate_webhook.go @@ -64,9 +64,19 @@ func (r *AzureMachineTemplate) ValidateUpdate(oldRaw runtime.Object) error { old := oldRaw.(*AzureMachineTemplate) if !reflect.DeepEqual(r.Spec.Template.Spec, old.Spec.Template.Spec) { - allErrs = append(allErrs, - field.Invalid(field.NewPath("AzureMachineTemplate", "spec", "template", "spec"), r, AzureMachineTemplateImmutableMsg), - ) + // The equality failure could be because of default mismatch between v1alpha3 and v1beta1. This happens because + // the new object `r` will have run through the default webhooks but the old object `old` would not have so. + // This means if the old object was in v1alpha3, it would not get the new defaults set in v1beta1 resulting + // in object inequality. To workaround this, we set the v1beta1 defaults here so that the old object also gets + // the new defaults. + old.Default() + + // if it's still not equal, return error. + if !reflect.DeepEqual(r.Spec.Template.Spec, old.Spec.Template.Spec) { + allErrs = append(allErrs, + field.Invalid(field.NewPath("AzureMachineTemplate", "spec", "template", "spec"), r, AzureMachineTemplateImmutableMsg), + ) + } } if len(allErrs) == 0 { @@ -83,5 +93,7 @@ func (r *AzureMachineTemplate) ValidateDelete() error { // Default implements webhookutil.defaulter so a webhook will be registered for the type. func (r *AzureMachineTemplate) Default() { machinetemplatelog.Info("default", "name", r.Name) - r.Spec.Template.Spec.SetDefaults(machinetemplatelog) + r.Spec.Template.Spec.SetDefaultCachingType() + r.Spec.Template.Spec.SetDataDisksDefaults() + r.Spec.Template.Spec.SetIdentityDefaults() } From aefd581bf254fc3fc7e6789e99a3042b61aebc0d Mon Sep 17 00:00:00 2001 From: shysank Date: Thu, 21 Oct 2021 12:54:25 -0700 Subject: [PATCH 3/3] add test for default mismatch --- api/v1beta1/azurecluster_webhook_test.go | 10 +++++ .../azuremachinetemplate_webhook_test.go | 43 +++++++++++++++++++ 2 files changed, 53 insertions(+) diff --git a/api/v1beta1/azurecluster_webhook_test.go b/api/v1beta1/azurecluster_webhook_test.go index d95a153688e..3014825043f 100644 --- a/api/v1beta1/azurecluster_webhook_test.go +++ b/api/v1beta1/azurecluster_webhook_test.go @@ -234,6 +234,16 @@ func TestAzureCluster_ValidateUpdate(t *testing.T) { }, wantErr: true, }, + { + name: "azurecluster azureEnvironment default mismatch", + oldCluster: createValidCluster(), + cluster: func() *AzureCluster { + cluster := createValidCluster() + cluster.Spec.AzureEnvironment = "AzurePublicCloud" + return cluster + }(), + wantErr: false, + }, { name: "control plane outbound lb is immutable", oldCluster: &AzureCluster{ diff --git a/api/v1beta1/azuremachinetemplate_webhook_test.go b/api/v1beta1/azuremachinetemplate_webhook_test.go index d9240dc462d..596929ed498 100644 --- a/api/v1beta1/azuremachinetemplate_webhook_test.go +++ b/api/v1beta1/azuremachinetemplate_webhook_test.go @@ -226,6 +226,49 @@ func TestAzureMachineTemplate_ValidateUpdate(t *testing.T) { }, wantErr: false, }, + { + name: "AzureMachineTemplate with default mismatch", + oldTemplate: &AzureMachineTemplate{ + Spec: AzureMachineTemplateSpec{ + Template: AzureMachineTemplateResource{ + Spec: AzureMachineSpec{ + VMSize: "size", + FailureDomain: &failureDomain, + OSDisk: OSDisk{ + OSType: "type", + DiskSizeGB: to.Int32Ptr(11), + CachingType: "", + }, + DataDisks: []DataDisk{}, + SSHPublicKey: "", + }, + }, + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "OldTemplate", + }, + }, + template: &AzureMachineTemplate{ + Spec: AzureMachineTemplateSpec{ + Template: AzureMachineTemplateResource{ + Spec: AzureMachineSpec{ + VMSize: "size", + FailureDomain: &failureDomain, + OSDisk: OSDisk{ + OSType: "type", + DiskSizeGB: to.Int32Ptr(11), + CachingType: "None", + }, + DataDisks: []DataDisk{}, + }, + }, + }, + ObjectMeta: metav1.ObjectMeta{ + Name: "NewTemplate", + }, + }, + wantErr: false, + }, } for _, amt := range tests {