diff --git a/test/e2e/cluster_topology_scale_in_test.go b/test/e2e/cluster_topology_scale_in_test.go new file mode 100644 index 0000000000..10211946d3 --- /dev/null +++ b/test/e2e/cluster_topology_scale_in_test.go @@ -0,0 +1,189 @@ +//go:build e2e + +/* +Copyright 2024 Nutanix + +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 e2e + +import ( + "context" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + corev1 "k8s.io/api/core/v1" + clusterv1 "sigs.k8s.io/cluster-api/api/v1beta1" +) + +var _ = Describe("When scaling in cluster with topology ", Label("clusterclass", "cluster-topology-scale-in"), func() { + const specName = "cluster-with-topology-scale-in-workflow" + const flavor = "topology" + + var ( + namespace *corev1.Namespace + clusterName string + cluster *clusterv1.Cluster + cancelWatches context.CancelFunc + testHelper testHelperInterface + nutanixE2ETest *NutanixE2ETest + ) + + BeforeEach(func() { + testHelper = newTestHelper(e2eConfig) + Expect(bootstrapClusterProxy).NotTo(BeNil(), "BootstrapClusterProxy can't be nil") + namespace, cancelWatches = setupSpecNamespace(ctx, specName, bootstrapClusterProxy, artifactFolder) + Expect(namespace).NotTo(BeNil()) + nutanixE2ETest = NewNutanixE2ETest( + WithE2ETestSpecName(specName), + WithE2ETestHelper(testHelper), + WithE2ETestConfig(e2eConfig), + WithE2ETestBootstrapClusterProxy(bootstrapClusterProxy), + WithE2ETestArtifactFolder(artifactFolder), + WithE2ETestClusterctlConfigPath(clusterctlConfigPath), + WithE2ETestClusterTemplateFlavor(flavor), + WithE2ETestNamespace(namespace), + ) + }) + + AfterEach(func() { + dumpSpecResourcesAndCleanup(ctx, specName, bootstrapClusterProxy, artifactFolder, namespace, cancelWatches, cluster, e2eConfig.GetIntervals, skipCleanup) + }) + + var scaleOutWorkflow = func(targetKubeVer, targetImageName string, fromCPNodeCount, fromWorkerNodeCount, toCPNodeCount, toWorkerNodeCount int) { + By("Creating a workload cluster with topology") + clusterTopologyConfig := NewClusterTopologyConfig( + WithName(clusterName), + WithKubernetesVersion(targetKubeVer), + WithControlPlaneCount(fromCPNodeCount), + WithWorkerNodeCount(fromWorkerNodeCount), + WithControlPlaneMachineTemplateImage(targetImageName), + WithWorkerMachineTemplateImage(targetImageName), + ) + + clusterResources, err := nutanixE2ETest.CreateCluster(ctx, clusterTopologyConfig) + Expect(err).ToNot(HaveOccurred()) + + // Set test specific variable so that cluster can be cleaned up after reach test + cluster = clusterResources.Cluster + + By("Waiting until nodes are ready") + nutanixE2ETest.WaitForNodesReady(ctx, targetKubeVer, clusterResources) + + clusterTopologyConfig = NewClusterTopologyConfig( + WithName(clusterName), + WithKubernetesVersion(targetKubeVer), + WithControlPlaneCount(toCPNodeCount), + WithWorkerNodeCount(toWorkerNodeCount), + WithControlPlaneMachineTemplateImage(targetImageName), + WithWorkerMachineTemplateImage(targetImageName), + ) + + clusterResources, err = nutanixE2ETest.UpgradeCluster(ctx, clusterTopologyConfig) + Expect(err).ToNot(HaveOccurred()) + + By("Waiting for control-plane machines to have the upgraded Kubernetes version") + nutanixE2ETest.WaitForControlPlaneMachinesToBeUpgraded(ctx, clusterTopologyConfig, clusterResources) + + By("Waiting for machine deployment machines to have the upgraded Kubernetes version") + nutanixE2ETest.WaitForMachineDeploymentMachinesToBeUpgraded(ctx, clusterTopologyConfig, clusterResources) + + By("Waiting until nodes are ready") + nutanixE2ETest.WaitForNodesReady(ctx, targetKubeVer, clusterResources) + + By("PASSED!") + } + + It("Scale in a cluster with topology from 3 CP node to 1 CP nodes with Kube127", func() { + clusterName = testHelper.generateTestClusterName(specName) + Expect(clusterName).NotTo(BeNil()) + + kube127 := testHelper.getVariableFromE2eConfig("KUBERNETES_VERSION_v1_27") + kube127Image := testHelper.getVariableFromE2eConfig("NUTANIX_MACHINE_TEMPLATE_IMAGE_NAME_v1_27") + scaleOutWorkflow(kube127, kube127Image, 3, 1, 1, 1) + }) + + It("Scale in a cluster with topology from 3 Worker node to 1 Worker nodes with Kube127", func() { + clusterName = testHelper.generateTestClusterName(specName) + Expect(clusterName).NotTo(BeNil()) + + kube127 := testHelper.getVariableFromE2eConfig("KUBERNETES_VERSION_v1_27") + kube127Image := testHelper.getVariableFromE2eConfig("NUTANIX_MACHINE_TEMPLATE_IMAGE_NAME_v1_27") + scaleOutWorkflow(kube127, kube127Image, 1, 3, 1, 1) + }) + + It("Scale in a cluster with topology from 3 CP and Worker node to 1 CP and Worker nodes with Kube127", func() { + clusterName = testHelper.generateTestClusterName(specName) + Expect(clusterName).NotTo(BeNil()) + + kube127 := testHelper.getVariableFromE2eConfig("KUBERNETES_VERSION_v1_27") + kube127Image := testHelper.getVariableFromE2eConfig("NUTANIX_MACHINE_TEMPLATE_IMAGE_NAME_v1_27") + scaleOutWorkflow(kube127, kube127Image, 3, 3, 1, 1) + }) + + It("Scale in a cluster with topology from 3 CP node to 1 CP nodes with Kube128", func() { + clusterName = testHelper.generateTestClusterName(specName) + Expect(clusterName).NotTo(BeNil()) + + kube128 := testHelper.getVariableFromE2eConfig("KUBERNETES_VERSION_v1_28") + kube128Image := testHelper.getVariableFromE2eConfig("NUTANIX_MACHINE_TEMPLATE_IMAGE_NAME_v1_28") + scaleOutWorkflow(kube128, kube128Image, 3, 1, 1, 1) + }) + + It("Scale in a cluster with topology from 3 Worker node to 1 Worker nodes with Kube128", func() { + clusterName = testHelper.generateTestClusterName(specName) + Expect(clusterName).NotTo(BeNil()) + + kube128 := testHelper.getVariableFromE2eConfig("KUBERNETES_VERSION_v1_28") + kube128Image := testHelper.getVariableFromE2eConfig("NUTANIX_MACHINE_TEMPLATE_IMAGE_NAME_v1_28") + scaleOutWorkflow(kube128, kube128Image, 1, 3, 1, 1) + }) + + It("Scale in a cluster with topology from 3 CP and Worker node to 1 CP and Worker nodes with Kube128", func() { + clusterName = testHelper.generateTestClusterName(specName) + Expect(clusterName).NotTo(BeNil()) + + kube128 := testHelper.getVariableFromE2eConfig("KUBERNETES_VERSION_v1_28") + kube128Image := testHelper.getVariableFromE2eConfig("NUTANIX_MACHINE_TEMPLATE_IMAGE_NAME_v1_28") + scaleOutWorkflow(kube128, kube128Image, 3, 3, 1, 1) + }) + + It("Scale in a cluster with topology from 3 CP node to 1 CP nodes with Kube129", func() { + clusterName = testHelper.generateTestClusterName(specName) + Expect(clusterName).NotTo(BeNil()) + + kube129 := testHelper.getVariableFromE2eConfig("KUBERNETES_VERSION_v1_29") + kube129Image := testHelper.getVariableFromE2eConfig("NUTANIX_MACHINE_TEMPLATE_IMAGE_NAME_v1_29") + scaleOutWorkflow(kube129, kube129Image, 3, 1, 1, 1) + }) + + It("Scale in a cluster with topology from 3 Worker node to 1 Worker nodes with Kube129", func() { + clusterName = testHelper.generateTestClusterName(specName) + Expect(clusterName).NotTo(BeNil()) + + kube129 := testHelper.getVariableFromE2eConfig("KUBERNETES_VERSION_v1_29") + kube129Image := testHelper.getVariableFromE2eConfig("NUTANIX_MACHINE_TEMPLATE_IMAGE_NAME_v1_29") + scaleOutWorkflow(kube129, kube129Image, 1, 3, 1, 1) + }) + + It("Scale in a cluster with topology from 3 CP and Worker node to 1 CP and Worker nodes with Kube129", func() { + clusterName = testHelper.generateTestClusterName(specName) + Expect(clusterName).NotTo(BeNil()) + + kube129 := testHelper.getVariableFromE2eConfig("KUBERNETES_VERSION_v1_29") + kube129Image := testHelper.getVariableFromE2eConfig("NUTANIX_MACHINE_TEMPLATE_IMAGE_NAME_v1_29") + scaleOutWorkflow(kube129, kube129Image, 3, 3, 1, 1) + }) + +})