sigs.k8s.io/cluster-api-provider-azure@v1.14.3/test/e2e/capi_test.go (about) 1 //go:build e2e 2 // +build e2e 3 4 /* 5 Copyright 2020 The Kubernetes Authors. 6 7 Licensed under the Apache License, Version 2.0 (the "License"); 8 you may not use this file except in compliance with the License. 9 You may obtain a copy of the License at 10 11 http://www.apache.org/licenses/LICENSE-2.0 12 13 Unless required by applicable law or agreed to in writing, software 14 distributed under the License is distributed on an "AS IS" BASIS, 15 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 See the License for the specific language governing permissions and 17 limitations under the License. 18 */ 19 20 package e2e 21 22 import ( 23 "context" 24 "fmt" 25 "os" 26 "time" 27 28 . "github.com/onsi/ginkgo/v2" 29 . "github.com/onsi/gomega" 30 corev1 "k8s.io/api/core/v1" 31 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" 32 "k8s.io/utils/ptr" 33 e2e_namespace "sigs.k8s.io/cluster-api-provider-azure/test/e2e/kubernetes/namespace" 34 clusterctlv1 "sigs.k8s.io/cluster-api/cmd/clusterctl/api/v1alpha3" 35 capi_e2e "sigs.k8s.io/cluster-api/test/e2e" 36 "sigs.k8s.io/cluster-api/test/framework" 37 "sigs.k8s.io/cluster-api/test/framework/clusterctl" 38 "sigs.k8s.io/cluster-api/util" 39 ) 40 41 const ( 42 IdentitySecretName = "cluster-identity-secret" 43 ) 44 45 var _ = Describe("Running the Cluster API E2E tests", func() { 46 var ( 47 ctx = context.TODO() 48 identityNamespace *corev1.Namespace 49 specTimes = map[string]time.Time{} 50 err error 51 ) 52 BeforeEach(func() { 53 Expect(e2eConfig.Variables).To(HaveKey(capi_e2e.CNIPath)) 54 rgName := fmt.Sprintf("capz-e2e-%s", util.RandomString(6)) 55 Expect(os.Setenv(AzureResourceGroup, rgName)).To(Succeed()) 56 Expect(os.Setenv(AzureVNetName, fmt.Sprintf("%s-vnet", rgName))).To(Succeed()) 57 58 Expect(e2eConfig.Variables).To(HaveKey(capi_e2e.KubernetesVersionUpgradeFrom)) 59 Expect(os.Setenv("WINDOWS_WORKER_MACHINE_COUNT", "2")).To(Succeed()) 60 61 clientset := bootstrapClusterProxy.GetClientSet() 62 Expect(clientset).NotTo(BeNil()) 63 ns := fmt.Sprintf("capz-e2e-identity-%s", util.RandomString(6)) 64 65 identityNamespace, err = e2e_namespace.Create(ctx, clientset, ns, map[string]string{}) 66 Expect(err).NotTo(HaveOccurred()) 67 68 spClientSecret := os.Getenv(AzureClientSecret) 69 secret := &corev1.Secret{ 70 ObjectMeta: metav1.ObjectMeta{ 71 Name: IdentitySecretName, 72 Namespace: identityNamespace.Name, 73 Labels: map[string]string{ 74 clusterctlv1.ClusterctlMoveHierarchyLabel: "true", 75 }, 76 }, 77 Type: corev1.SecretTypeOpaque, 78 Data: map[string][]byte{"clientSecret": []byte(spClientSecret)}, 79 } 80 err = bootstrapClusterProxy.GetClient().Create(ctx, secret) 81 Expect(err).NotTo(HaveOccurred()) 82 83 identityName := e2eConfig.GetVariable(ClusterIdentityName) 84 Expect(os.Setenv(ClusterIdentityName, identityName)).To(Succeed()) 85 Expect(os.Setenv(ClusterIdentitySecretName, IdentitySecretName)).To(Succeed()) 86 Expect(os.Setenv(ClusterIdentitySecretNamespace, identityNamespace.Name)).To(Succeed()) 87 88 logCheckpoint(specTimes) 89 }) 90 91 AfterEach(func() { 92 CheckTestBeforeCleanup() 93 redactLogs() 94 95 Expect(os.Unsetenv(AzureResourceGroup)).To(Succeed()) 96 Expect(os.Unsetenv(AzureVNetName)).To(Succeed()) 97 Expect(os.Unsetenv(ClusterIdentityName)).To(Succeed()) 98 Expect(os.Unsetenv(ClusterIdentitySecretName)).To(Succeed()) 99 Expect(os.Unsetenv(ClusterIdentitySecretNamespace)).To(Succeed()) 100 101 logCheckpoint(specTimes) 102 }) 103 104 Context("Running the quick-start spec", func() { 105 capi_e2e.QuickStartSpec(context.TODO(), func() capi_e2e.QuickStartSpecInput { 106 return capi_e2e.QuickStartSpecInput{ 107 E2EConfig: e2eConfig, 108 ClusterctlConfigPath: clusterctlConfigPath, 109 BootstrapClusterProxy: bootstrapClusterProxy, 110 ArtifactFolder: artifactFolder, 111 SkipCleanup: skipCleanup, 112 ControlPlaneWaiters: clusterctl.ControlPlaneWaiters{ 113 WaitForControlPlaneInitialized: EnsureControlPlaneInitializedNoAddons, 114 }, 115 } 116 }) 117 }) 118 119 Context("Running the MachineDeployment rollout spec", func() { 120 capi_e2e.MachineDeploymentRolloutSpec(context.TODO(), func() capi_e2e.MachineDeploymentRolloutSpecInput { 121 return capi_e2e.MachineDeploymentRolloutSpecInput{ 122 E2EConfig: e2eConfig, 123 ClusterctlConfigPath: clusterctlConfigPath, 124 BootstrapClusterProxy: bootstrapClusterProxy, 125 ArtifactFolder: artifactFolder, 126 SkipCleanup: skipCleanup, 127 ControlPlaneWaiters: clusterctl.ControlPlaneWaiters{ 128 WaitForControlPlaneInitialized: EnsureControlPlaneInitializedNoAddons, 129 }, 130 } 131 }) 132 }) 133 134 if os.Getenv("USE_LOCAL_KIND_REGISTRY") != "true" { 135 Context("Running the self-hosted spec", func() { 136 SelfHostedSpec(context.TODO(), func() SelfHostedSpecInput { 137 return SelfHostedSpecInput{ 138 E2EConfig: e2eConfig, 139 ClusterctlConfigPath: clusterctlConfigPath, 140 BootstrapClusterProxy: bootstrapClusterProxy, 141 ArtifactFolder: artifactFolder, 142 SkipCleanup: skipCleanup, 143 ControlPlaneWaiters: clusterctl.ControlPlaneWaiters{ 144 WaitForControlPlaneInitialized: EnsureControlPlaneInitializedNoAddons, 145 }, 146 } 147 }) 148 }) 149 } 150 151 // TODO: Add test using KCPRemediationSpec 152 Context("Should successfully remediate unhealthy worker machines with MachineHealthCheck", func() { 153 capi_e2e.MachineDeploymentRemediationSpec(context.TODO(), func() capi_e2e.MachineDeploymentRemediationSpecInput { 154 return capi_e2e.MachineDeploymentRemediationSpecInput{ 155 E2EConfig: e2eConfig, 156 ClusterctlConfigPath: clusterctlConfigPath, 157 BootstrapClusterProxy: bootstrapClusterProxy, 158 ArtifactFolder: artifactFolder, 159 SkipCleanup: skipCleanup, 160 ControlPlaneWaiters: clusterctl.ControlPlaneWaiters{ 161 WaitForControlPlaneInitialized: EnsureControlPlaneInitializedNoAddons, 162 }, 163 } 164 }) 165 }) 166 167 Context("Should successfully exercise machine pools", func() { 168 capi_e2e.MachinePoolSpec(context.TODO(), func() capi_e2e.MachinePoolInput { 169 return capi_e2e.MachinePoolInput{ 170 E2EConfig: e2eConfig, 171 ClusterctlConfigPath: clusterctlConfigPath, 172 BootstrapClusterProxy: bootstrapClusterProxy, 173 ArtifactFolder: artifactFolder, 174 SkipCleanup: skipCleanup, 175 ControlPlaneWaiters: clusterctl.ControlPlaneWaiters{ 176 WaitForControlPlaneInitialized: EnsureControlPlaneInitializedNoAddons, 177 }, 178 } 179 }) 180 }) 181 182 Context("Should successfully scale out and scale in a MachineDeployment", func() { 183 capi_e2e.MachineDeploymentScaleSpec(context.TODO(), func() capi_e2e.MachineDeploymentScaleSpecInput { 184 return capi_e2e.MachineDeploymentScaleSpecInput{ 185 E2EConfig: e2eConfig, 186 ClusterctlConfigPath: clusterctlConfigPath, 187 BootstrapClusterProxy: bootstrapClusterProxy, 188 ArtifactFolder: artifactFolder, 189 SkipCleanup: skipCleanup, 190 ControlPlaneWaiters: clusterctl.ControlPlaneWaiters{ 191 WaitForControlPlaneInitialized: EnsureControlPlaneInitializedNoAddons, 192 }, 193 } 194 }) 195 }) 196 197 Context("Should successfully set and use node drain timeout", func() { 198 capi_e2e.NodeDrainTimeoutSpec(context.TODO(), func() capi_e2e.NodeDrainTimeoutSpecInput { 199 return capi_e2e.NodeDrainTimeoutSpecInput{ 200 E2EConfig: e2eConfig, 201 ClusterctlConfigPath: clusterctlConfigPath, 202 BootstrapClusterProxy: bootstrapClusterProxy, 203 ArtifactFolder: artifactFolder, 204 SkipCleanup: skipCleanup, 205 ControlPlaneWaiters: clusterctl.ControlPlaneWaiters{ 206 WaitForControlPlaneInitialized: EnsureControlPlaneInitializedNoAddons, 207 }, 208 } 209 }) 210 }) 211 212 if os.Getenv("USE_LOCAL_KIND_REGISTRY") != "true" { 213 Context("API Version Upgrade", func() { 214 BeforeEach(func() { 215 // Unset resource group and vnet env variables, since the upgrade test creates 2 clusters, 216 // and will result in both the clusters using the same vnet and resource group. 217 Expect(os.Unsetenv(AzureResourceGroup)).To(Succeed()) 218 Expect(os.Unsetenv(AzureVNetName)).To(Succeed()) 219 220 // Unset windows specific variables 221 Expect(os.Unsetenv("WINDOWS_WORKER_MACHINE_COUNT")).To(Succeed()) 222 223 Expect(os.Setenv("K8S_FEATURE_GATES", "WindowsHostProcessContainers=true")).To(Succeed()) 224 }) 225 226 Context("upgrade from an old version of v1beta1 to current, and scale workload clusters created in the old version", func() { 227 capi_e2e.ClusterctlUpgradeSpec(ctx, func() capi_e2e.ClusterctlUpgradeSpecInput { 228 return capi_e2e.ClusterctlUpgradeSpecInput{ 229 E2EConfig: e2eConfig, 230 ClusterctlConfigPath: clusterctlConfigPath, 231 BootstrapClusterProxy: bootstrapClusterProxy, 232 ArtifactFolder: artifactFolder, 233 SkipCleanup: skipCleanup, 234 PreInit: getPreInitFunc(ctx), 235 InitWithProvidersContract: "v1beta1", 236 ControlPlaneWaiters: clusterctl.ControlPlaneWaiters{ 237 WaitForControlPlaneInitialized: EnsureControlPlaneInitialized, 238 }, 239 InitWithKubernetesVersion: e2eConfig.GetVariable(KubernetesVersionAPIUpgradeFrom), 240 InitWithBinary: fmt.Sprintf("https://github.com/kubernetes-sigs/cluster-api/releases/download/%s/clusterctl-{OS}-{ARCH}", e2eConfig.GetVariable(OldCAPIUpgradeVersion)), 241 InitWithCoreProvider: "cluster-api:" + e2eConfig.GetVariable(OldCAPIUpgradeVersion), 242 InitWithBootstrapProviders: []string{"kubeadm:" + e2eConfig.GetVariable(OldCAPIUpgradeVersion)}, 243 InitWithControlPlaneProviders: []string{"kubeadm:" + e2eConfig.GetVariable(OldCAPIUpgradeVersion)}, 244 InitWithInfrastructureProviders: []string{"azure:" + e2eConfig.GetVariable(OldProviderUpgradeVersion)}, 245 InitWithAddonProviders: []string{"helm:" + e2eConfig.GetVariable(OldAddonProviderUpgradeVersion)}, 246 } 247 }) 248 }) 249 250 Context("upgrade from the latest version of v1beta1 to current, and scale workload clusters created in the old version", func() { 251 capi_e2e.ClusterctlUpgradeSpec(ctx, func() capi_e2e.ClusterctlUpgradeSpecInput { 252 return capi_e2e.ClusterctlUpgradeSpecInput{ 253 E2EConfig: e2eConfig, 254 ClusterctlConfigPath: clusterctlConfigPath, 255 BootstrapClusterProxy: bootstrapClusterProxy, 256 ArtifactFolder: artifactFolder, 257 SkipCleanup: skipCleanup, 258 PreInit: getPreInitFunc(ctx), 259 InitWithProvidersContract: "v1beta1", 260 ControlPlaneWaiters: clusterctl.ControlPlaneWaiters{ 261 WaitForControlPlaneInitialized: EnsureControlPlaneInitialized, 262 }, 263 InitWithKubernetesVersion: e2eConfig.GetVariable(KubernetesVersionAPIUpgradeFrom), 264 InitWithBinary: fmt.Sprintf("https://github.com/kubernetes-sigs/cluster-api/releases/download/%s/clusterctl-{OS}-{ARCH}", e2eConfig.GetVariable(LatestCAPIUpgradeVersion)), 265 InitWithCoreProvider: "cluster-api:" + e2eConfig.GetVariable(LatestCAPIUpgradeVersion), 266 InitWithBootstrapProviders: []string{"kubeadm:" + e2eConfig.GetVariable(LatestCAPIUpgradeVersion)}, 267 InitWithControlPlaneProviders: []string{"kubeadm:" + e2eConfig.GetVariable(LatestCAPIUpgradeVersion)}, 268 InitWithInfrastructureProviders: []string{"azure:" + e2eConfig.GetVariable(LatestProviderUpgradeVersion)}, 269 InitWithAddonProviders: []string{"helm:" + e2eConfig.GetVariable(LatestAddonProviderUpgradeVersion)}, 270 } 271 }) 272 }) 273 }) 274 } 275 276 Context("Running the workload cluster upgrade spec [K8s-Upgrade]", func() { 277 capi_e2e.ClusterUpgradeConformanceSpec(ctx, func() capi_e2e.ClusterUpgradeConformanceSpecInput { 278 return capi_e2e.ClusterUpgradeConformanceSpecInput{ 279 E2EConfig: e2eConfig, 280 ClusterctlConfigPath: clusterctlConfigPath, 281 BootstrapClusterProxy: bootstrapClusterProxy, 282 ArtifactFolder: artifactFolder, 283 SkipCleanup: skipCleanup, 284 SkipConformanceTests: true, 285 ControlPlaneWaiters: clusterctl.ControlPlaneWaiters{ 286 WaitForControlPlaneInitialized: EnsureControlPlaneInitialized, 287 }, 288 } 289 }) 290 }) 291 292 Context("Running KCP upgrade in a HA cluster [K8s-Upgrade]", func() { 293 capi_e2e.ClusterUpgradeConformanceSpec(context.TODO(), func() capi_e2e.ClusterUpgradeConformanceSpecInput { 294 return capi_e2e.ClusterUpgradeConformanceSpecInput{ 295 E2EConfig: e2eConfig, 296 ClusterctlConfigPath: clusterctlConfigPath, 297 BootstrapClusterProxy: bootstrapClusterProxy, 298 ArtifactFolder: artifactFolder, 299 ControlPlaneMachineCount: ptr.To[int64](3), 300 WorkerMachineCount: ptr.To[int64](0), 301 SkipCleanup: skipCleanup, 302 SkipConformanceTests: true, 303 ControlPlaneWaiters: clusterctl.ControlPlaneWaiters{ 304 WaitForControlPlaneInitialized: EnsureControlPlaneInitialized, 305 }, 306 } 307 }) 308 }) 309 310 Context("Running KCP upgrade in a HA cluster using scale in rollout [K8s-Upgrade]", func() { 311 capi_e2e.ClusterUpgradeConformanceSpec(context.TODO(), func() capi_e2e.ClusterUpgradeConformanceSpecInput { 312 return capi_e2e.ClusterUpgradeConformanceSpecInput{ 313 E2EConfig: e2eConfig, 314 ClusterctlConfigPath: clusterctlConfigPath, 315 BootstrapClusterProxy: bootstrapClusterProxy, 316 ArtifactFolder: artifactFolder, 317 ControlPlaneMachineCount: ptr.To[int64](3), 318 WorkerMachineCount: ptr.To[int64](0), 319 SkipCleanup: skipCleanup, 320 SkipConformanceTests: true, 321 Flavor: ptr.To("kcp-scale-in"), 322 ControlPlaneWaiters: clusterctl.ControlPlaneWaiters{ 323 WaitForControlPlaneInitialized: EnsureControlPlaneInitialized, 324 }, 325 } 326 }) 327 }) 328 }) 329 330 func getPreInitFunc(ctx context.Context) func(proxy framework.ClusterProxy) { 331 return func(clusterProxy framework.ClusterProxy) { 332 spClientSecret := os.Getenv(AzureClientSecret) 333 secret := &corev1.Secret{ 334 ObjectMeta: metav1.ObjectMeta{ 335 Name: IdentitySecretName, 336 Namespace: "default", 337 Labels: map[string]string{ 338 clusterctlv1.ClusterctlMoveHierarchyLabel: "true", 339 }, 340 }, 341 Type: corev1.SecretTypeOpaque, 342 Data: map[string][]byte{"clientSecret": []byte(spClientSecret)}, 343 } 344 err := clusterProxy.GetClient().Create(ctx, secret) 345 Expect(err).NotTo(HaveOccurred()) 346 347 identityName := e2eConfig.GetVariable(ClusterIdentityName) 348 Expect(os.Setenv(ClusterIdentityName, identityName)).To(Succeed()) 349 Expect(os.Setenv(ClusterIdentitySecretName, IdentitySecretName)).To(Succeed()) 350 Expect(os.Setenv(ClusterIdentitySecretNamespace, "default")).To(Succeed()) 351 } 352 }