From 16821c01921d58cc19b53ac819501928c083623c Mon Sep 17 00:00:00 2001 From: radtriste Date: Fri, 6 Sep 2024 15:24:38 +0200 Subject: [PATCH] OCM-9774 | ci: Automate ids:54413,56783,56786,63169,63174,76056 - https://issues.redhat.com/browse/OCM-9774 - https://issues.redhat.com/browse/OCM-10962 - https://issues.redhat.com/browse/OCM-10999 --- tests/e2e/classic_tuning_config_test.go | 55 ++++++ tests/e2e/hcp_machine_pool_test.go | 167 ++++++++++++++++++ tests/e2e/hcp_tuning_config_test.go | 151 +++++++++++++++- tests/e2e/test_rosacli_cluster.go | 85 +++++++-- tests/e2e/test_rosacli_node_pool.go | 8 +- tests/utils/config/cluster_command.go | 12 +- .../utils/exec/rosacli/machinepool_service.go | 6 +- .../exec/rosacli/tuning_config_service.go | 21 ++- 8 files changed, 466 insertions(+), 39 deletions(-) create mode 100644 tests/e2e/classic_tuning_config_test.go diff --git a/tests/e2e/classic_tuning_config_test.go b/tests/e2e/classic_tuning_config_test.go new file mode 100644 index 0000000000..8ca8bcc6f5 --- /dev/null +++ b/tests/e2e/classic_tuning_config_test.go @@ -0,0 +1,55 @@ +package e2e + +import ( + "encoding/json" + + . "github.com/onsi/ginkgo/v2" + . "github.com/onsi/gomega" + + "github.com/openshift/rosa/tests/ci/labels" + "github.com/openshift/rosa/tests/utils/common" + "github.com/openshift/rosa/tests/utils/exec/rosacli" +) + +var _ = Describe("Tuning Config(s) on Classic cluster", labels.Feature.TuningConfigs, func() { + + var rosaClient *rosacli.Client + var clusterService rosacli.ClusterService + + BeforeEach(func() { + Expect(clusterID).ToNot(BeEmpty(), "Cluster ID is empty, please export the env variable CLUSTER_ID") + rosaClient = rosacli.NewClient() + clusterService = rosaClient.Cluster + + By("Skip testing if the cluster is not a Classic cluster") + hosted, err := clusterService.IsHostedCPCluster(clusterID) + Expect(err).ToNot(HaveOccurred()) + if hosted { + SkipNotClassic() + } + }) + + AfterEach(func() { + By("Clean remaining resources") + err := rosaClient.CleanResources(clusterID) + Expect(err).ToNot(HaveOccurred()) + }) + + It("is not supported - [id:76056]", + labels.Medium, labels.Runtime.Day2, + func() { + tuningConfigService := rosaClient.TuningConfig + tcName := common.GenerateRandomName("tuned01", 2) + tcSpec := rosacli.NewTuningConfigSpecRootStub(tcName, 25, 10) + + By("Create tuning config should fail") + tcJSON, err := json.Marshal(tcSpec) + Expect(err).ToNot(HaveOccurred()) + _, err = tuningConfigService.CreateTuningConfigFromSpecContent( + clusterID, + tcName, + string(tcJSON)) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("This command is only supported for Hosted Control Planes")) + }) +}) diff --git a/tests/e2e/hcp_machine_pool_test.go b/tests/e2e/hcp_machine_pool_test.go index 1c75d44973..316a407e83 100644 --- a/tests/e2e/hcp_machine_pool_test.go +++ b/tests/e2e/hcp_machine_pool_test.go @@ -370,6 +370,7 @@ var _ = Describe("HCP Machine Pool", labels.Feature.Machinepool, func() { "-y", ) expectErrMsg := "The number of machine pool min-replicas needs to be a non-negative integer" + Expect(err).To(HaveOccurred()) Expect(err.Error()).Should(ContainSubstring(expectErrMsg)) By("Scale up a machine pool max replica too large") @@ -379,6 +380,7 @@ var _ = Describe("HCP Machine Pool", labels.Feature.Machinepool, func() { "-y", ) expectErrMsg = "exceeds the maximum allowed" + Expect(err).To(HaveOccurred()) Expect(err.Error()).Should(ContainSubstring(expectErrMsg)) By("Scale a machine pool min replica > max replica") @@ -388,6 +390,7 @@ var _ = Describe("HCP Machine Pool", labels.Feature.Machinepool, func() { "-y", ) expectErrMsg = "min-replicas needs to be less than the number of machine pool max-replicas" + Expect(err).To(HaveOccurred()) Expect(err.Error()).Should(ContainSubstring(expectErrMsg)) By("Scale down a machine pool min replica to -1") @@ -397,6 +400,7 @@ var _ = Describe("HCP Machine Pool", labels.Feature.Machinepool, func() { "-y", ) expectErrMsg = "Min replicas must be a non-negative number when autoscaling is set" + Expect(err).To(HaveOccurred()) Expect(err.Error()).Should(ContainSubstring(expectErrMsg)) By("Scale a machine pool with min replica and max replica a char") @@ -406,7 +410,170 @@ var _ = Describe("HCP Machine Pool", labels.Feature.Machinepool, func() { "-y", ) expectErrMsg = "invalid syntax" + Expect(err).To(HaveOccurred()) Expect(err.Error()).Should(ContainSubstring(expectErrMsg)) }) }) + + Describe("Validate machinepool", func() { + It("creation - [id:56786]", labels.Medium, labels.Runtime.Day2, func() { + By("with negative replicas number") + _, err := machinePoolService.CreateMachinePool(clusterID, "anything", "--replicas", "-9") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("Replicas must be a non-negative integer")) + + By("with replicas > 180") + _, err = machinePoolService.CreateMachinePool(clusterID, "anything", "--replicas", "181") + Expect(err).To(HaveOccurred()) + Expect(err.Error()). + Should( + ContainSubstring("Replicas+Autoscaling.Min: The total number of compute nodes for a single cluster")) + Expect(err.Error()).Should(ContainSubstring("exceeds the maximum allowed: 180")) + + By("with invalid name") + _, err = machinePoolService.CreateMachinePool(clusterID, "anything%^#@", "--replicas", "2") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("Expected a valid name for the machine pool")) + + By("with replicas and enable-autoscaling at the same time") + _, err = machinePoolService.CreateMachinePool( + clusterID, + "anything", + "--replicas", "2", + "--enable-autoscaling", + "--min-replicas", "3", + "--max-replicas", "3") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("Replicas can't be set when autoscaling is enabled")) + + By("with min-replicas larger than max-replicas") + _, err = machinePoolService.CreateMachinePool( + clusterID, + "anything", + "--enable-autoscaling", + "--min-replicas", "6", + "--max-replicas", "3") + Expect(err).To(HaveOccurred()) + Expect(err.Error()). + Should( + ContainSubstring("Invalid autoscaling range: 6 - 3. 'min_replica' must be less than or equal to 'max_replica'")) + + By("with min-replicas and max-replicas but without enable-autoscaling") + _, err = machinePoolService.CreateMachinePool( + clusterID, + "anything", + "--min-replicas", "3", + "--max-replicas", "3") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("Autoscaling must be enabled in order to set min and max replicas")) + + By("with max-replicas > 180") + _, err = machinePoolService.CreateMachinePool( + clusterID, + "anything", + "--enable-autoscaling", + "--min-replicas", "3", + "--max-replicas", "181") + Expect(err).To(HaveOccurred()) + Expect(err.Error()). + Should( + ContainSubstring("Replicas+Autoscaling.Max: The total number of compute nodes for a single cluster")) + Expect(err.Error()).Should(ContainSubstring("exceeds the maximum allowed: 180")) + + By("with wrong instance-type") + _, err = machinePoolService.CreateMachinePool(clusterID, "anything", "--replicas", "2", "--instance-type", "wrong") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("Expected a valid instance type")) + + By("with non existing subnet") + _, err = machinePoolService.CreateMachinePool(clusterID, "anything", "--replicas", "2", "--subnet", "subnet-xxx") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("The subnet ID 'subnet-xxx' does not exist")) + + By("with subnet not in VPC") + vpcPrefix := common.TrimNameByLength("c56786", 20) + vpc, err := vpc_client.PrepareVPC(vpcPrefix, profile.Region, constants.DefaultVPCCIDRValue, false, "") + Expect(err).ToNot(HaveOccurred()) + defer vpc.DeleteVPCChain(true) + zones, err := vpc.AWSClient.ListAvaliableZonesForRegion(profile.Region, "availability-zone") + Expect(err).ToNot(HaveOccurred()) + subnet, err := vpc.CreateSubnet(zones[0]) + Expect(err).ToNot(HaveOccurred()) + _, err = machinePoolService.CreateMachinePool(clusterID, "anything", "--replicas", "2", "--subnet", subnet.ID) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("found but expected on VPC")) + + By("with label no key") + _, err = machinePoolService.CreateMachinePool(clusterID, "anything", "--replicas", "2", "--labels", "v") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("Expected key=value format for labels")) + + By("with taint no key") + _, err = machinePoolService.CreateMachinePool(clusterID, "anything", "--replicas", "2", "--taints", "v") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("Expected key=value:scheduleType format for taints. Got 'v'")) + + By("with taint no schedule type") + _, err = machinePoolService.CreateMachinePool(clusterID, "anything", "--replicas", "2", "--taints", "k=v") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("Expected key=value:scheduleType format for taints. Got 'k=v'")) + + By("with taint empty schedule type") + _, err = machinePoolService.CreateMachinePool(clusterID, "anything", "--replicas", "2", "--taints", "k=v:") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("Expected a not empty effect")) + + By("with auto-repair wrong value") + _, err = machinePoolService.CreateMachinePool(clusterID, "anything", "--replicas", "2", "--autorepair=v") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("strconv.ParseBool: parsing \"v\": invalid syntax")) + + By("with unsupported version") + _, err = machinePoolService.CreateMachinePool(clusterID, "anything", "--replicas", "2", "--version", "4.12.1") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("Expected a valid OpenShift version")) + + By("with unsupported flag") + _, err = machinePoolService.CreateMachinePool(clusterID, "anything", "--replicas", "2", "--multi-availability-zone") + Expect(err).To(HaveOccurred()) + Expect(err.Error()). + Should( + ContainSubstring("Setting `multi-availability-zone` flag is not supported for HCP clusters")) + }) + + It("deletion - [id:56783]", labels.Medium, labels.Runtime.Day2, func() { + By("with no machinepool id") + _, err := machinePoolService.DeleteMachinePool(clusterID, "") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("You need to specify a machine pool name")) + + By("with non existing machinepool id") + _, err = machinePoolService.DeleteMachinePool(clusterID, "anything") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("Machine pool 'anything' does not exist")) + + By("with invalid machinepool id") + _, err = machinePoolService.DeleteMachinePool(clusterID, "anything%^") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("Expected a valid identifier for the machine pool")) + + By("with unknown flag --interactive") + _, err = machinePoolService.DeleteMachinePool(clusterID, "anything", "--interactive") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).Should(ContainSubstring("unknown flag: --interactive")) + + if !profile.ClusterConfig.MultiAZ { + By("Delete last remaining machinepool") + _, err = machinePoolService.DeleteMachinePool(clusterID, constants.DefaultHostedWorkerPool) + Expect(err).To(HaveOccurred()) + Expect(err.Error()). + Should( + ContainSubstring( + fmt.Sprintf("Failed to delete machine pool '%s' on hosted cluster", constants.DefaultHostedWorkerPool))) + Expect(err.Error()). + Should( + ContainSubstring("The last node pool can not be deleted from a cluster")) + } + }) + }) }) diff --git a/tests/e2e/hcp_tuning_config_test.go b/tests/e2e/hcp_tuning_config_test.go index b8d1bfe92b..3bfc98a436 100644 --- a/tests/e2e/hcp_tuning_config_test.go +++ b/tests/e2e/hcp_tuning_config_test.go @@ -15,7 +15,7 @@ import ( "github.com/openshift/rosa/tests/utils/exec/rosacli" ) -var _ = Describe("Create Tuning Config", labels.Feature.TuningConfigs, func() { +var _ = Describe("Tuning Config(s)", labels.Feature.TuningConfigs, func() { var rosaClient *rosacli.Client var clusterService rosacli.ClusterService @@ -39,7 +39,7 @@ var _ = Describe("Create Tuning Config", labels.Feature.TuningConfigs, func() { Expect(err).ToNot(HaveOccurred()) }) - It("tuning config can be created/updated/deleted to hosted cluster - [id:63164]", + It("can be created/updated/deleted to hosted cluster - [id:63164]", labels.Critical, labels.Runtime.Day2, func() { tuningConfigService := rosaClient.TuningConfig @@ -56,7 +56,7 @@ var _ = Describe("Create Tuning Config", labels.Feature.TuningConfigs, func() { By("Create tuning configs to the cluster") tc1JSON, err := json.Marshal(tc1Spec) Expect(err).ToNot(HaveOccurred()) - resp, err := tuningConfigService.CreateTuningConfig( + resp, err := tuningConfigService.CreateTuningConfigFromSpecContent( clusterID, tc1Name, string(tc1JSON)) @@ -68,7 +68,7 @@ var _ = Describe("Create Tuning Config", labels.Feature.TuningConfigs, func() { tc2YAML, err := yaml.Marshal(tc2Spec) Expect(err).ToNot(HaveOccurred()) - resp, err = tuningConfigService.CreateTuningConfig( + resp, err = tuningConfigService.CreateTuningConfigFromSpecContent( clusterID, tc2Name, string(tc2YAML)) @@ -81,10 +81,11 @@ var _ = Describe("Create Tuning Config", labels.Feature.TuningConfigs, func() { By("List all tuning configs") tuningConfigList, err := tuningConfigService.ListTuningConfigsAndReflect(clusterID) Expect(err).ToNot(HaveOccurred()) + expectDescriptionTemplate := "the tuningconfig %s is not in output" Expect(tuningConfigList.IsPresent(tc1Name)). - To(BeTrue(), "the tuningconfig %s is not in output", tc1Name) + To(BeTrue(), expectDescriptionTemplate, tc1Name) Expect(tuningConfigList.IsPresent(tc2Name)). - To(BeTrue(), "the tuningconfig %s is not in output", tc2Name) + To(BeTrue(), expectDescriptionTemplate, tc2Name) By("Update a tuning config of the cluster") tc2Spec.Profile[0].Data = rosacli.NewTuningConfigSpecProfileData(secondVMDirtyRatio) @@ -123,4 +124,142 @@ var _ = Describe("Create Tuning Config", labels.Feature.TuningConfigs, func() { Expect(tuningConfigList.IsPresent(tc2Name)). To(BeFalse(), "the tuningconfig %s is in the output", tc2Name) }) + + It("can validate creation - [id:63169]", + labels.Medium, labels.Runtime.Day2, + func() { + tuningConfigService := rosaClient.TuningConfig + + By("Create tuning config") + tcName := common.GenerateRandomName("c63169", 2) + firstPriority := 10 + firstVMDirtyRatio := 25 + tcSpec := rosacli.NewTuningConfigSpecRootStub(tcName, firstVMDirtyRatio, firstPriority) + tcSpecJSON, err := json.Marshal(tcSpec) + Expect(err).ToNot(HaveOccurred()) + resp, err := tuningConfigService.CreateTuningConfigFromSpecContent( + clusterID, + tcName, + string(tcSpecJSON)) + Expect(err).ToNot(HaveOccurred()) + textData := rosaClient.Parser.TextData.Input(resp).Parse().Tip() + Expect(textData). + To(ContainSubstring( + fmt.Sprintf("Tuning config '%s' has been created on cluster '%s'", tcName, clusterID))) + + By("Create another tuning config with same name") + _, err = tuningConfigService.CreateTuningConfigFromSpecContent( + clusterID, + tcName, + string(tcSpecJSON)) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("A tuning config with name '%s'", tcName))) + Expect(err.Error()).To(ContainSubstring(fmt.Sprintf("already exists for cluster '%s'", clusterID))) + + By("Create tuning config with no name") + _, err = tuningConfigService.CreateTuningConfigFromSpecContent( + clusterID, + "", + string(tcSpecJSON)) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("Expected a valid name")) + + By("Create tuning config with no spec") + _, err = tuningConfigService.CreateTuningConfigFromSpecContent( + clusterID, + common.GenerateRandomName("c63169", 2), + "") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("Attribute 'spec' must be set")) + + By("Create tuning config with invalid name") + _, err = tuningConfigService.CreateTuningConfigFromSpecContent( + clusterID, + "c63169%^", + string(tcSpecJSON)) + Expect(err).To(HaveOccurred()) + Expect(err.Error()). + To( + ContainSubstring("Name 'c63169%^' is not valid. The name must be a lowercase RFC 1123 subdomain")) + + By("Create tuning config with invalid spec file") + _, err = tuningConfigService.CreateTuningConfigFromSpecFile( + clusterID, + common.GenerateRandomName("c63169", 2), + "wrong_file") + Expect(err).To(HaveOccurred()) + Expect(err.Error()). + To( + ContainSubstring("Expected a valid TuneD spec file: open wrong_file: no such file or directory")) + + By("Create tuning config with invalid spec content") + _, err = tuningConfigService.CreateTuningConfigFromSpecContent( + clusterID, + common.GenerateRandomName("c63169", 2), + "Spec%^") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("Expected a valid TuneD spec file: error unmarshaling")) + + By("Create more than 100 tuning configs") + tcs, err := tuningConfigService.ListTuningConfigsAndReflect(clusterID) + Expect(err).ToNot(HaveOccurred()) + maxTcNb := 100 - len(tcs.TuningConfigs) + for i := 1; i <= maxTcNb; i++ { + _, err = tuningConfigService.CreateTuningConfigFromSpecContent( + clusterID, + common.GenerateRandomName(fmt.Sprintf("c63169%d", i), 2), + string(tcSpecJSON)) + Expect(err).ToNot(HaveOccurred()) + } + _, err = tuningConfigService.CreateTuningConfigFromSpecContent( + clusterID, + common.GenerateRandomName("c63169", 2), + string(tcSpecJSON)) + Expect(err).To(HaveOccurred()) + Expect(err.Error()). + To( + ContainSubstring("Maximum number of TuningConfigs per cluster reached. " + + "Maximum allowed is '100'. Current count is '100'.")) + }) + + It("can validate update - [id:63174]", + labels.Medium, labels.Runtime.Day2, + func() { + tuningConfigService := rosaClient.TuningConfig + + By("Create tuning config") + tcName := common.GenerateRandomName("c63174", 2) + firstPriority := 10 + firstVMDirtyRatio := 25 + tcSpec := rosacli.NewTuningConfigSpecRootStub(tcName, firstVMDirtyRatio, firstPriority) + tcSpecJSON, err := json.Marshal(tcSpec) + Expect(err).ToNot(HaveOccurred()) + resp, err := tuningConfigService.CreateTuningConfigFromSpecContent( + clusterID, + tcName, + string(tcSpecJSON)) + Expect(err).ToNot(HaveOccurred()) + textData := rosaClient.Parser.TextData.Input(resp).Parse().Tip() + Expect(textData). + To(ContainSubstring( + fmt.Sprintf("Tuning config '%s' has been created on cluster '%s'", tcName, clusterID))) + + By("Update tuning config with incorrect name") + _, err = tuningConfigService.EditTuningConfig(clusterID, "wrong_name") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("Tuning config 'wrong_name' does not exist")) + + By("Update tuning config with incorrect spec file") + _, err = tuningConfigService.EditTuningConfig(clusterID, tcName, "--spec-path", "wrong_file") + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("Expected a valid spec file: open wrong_file: no such file or directory")) + + By("Update tuning config with incorrect spec content") + specPath, err := common.CreateTempFileWithContent("Spec%^") + defer os.Remove(specPath) + Expect(err).ToNot(HaveOccurred()) + _, err = tuningConfigService.EditTuningConfig(clusterID, tcName, "--spec-path", specPath) + Expect(err).To(HaveOccurred()) + Expect(err.Error()).To(ContainSubstring("Expected a valid spec file: error unmarshaling")) + }) }) diff --git a/tests/e2e/test_rosacli_cluster.go b/tests/e2e/test_rosacli_cluster.go index ae12d09a0c..855051aa38 100644 --- a/tests/e2e/test_rosacli_cluster.go +++ b/tests/e2e/test_rosacli_cluster.go @@ -1120,7 +1120,7 @@ var _ = Describe("Classic cluster creation validation", }) It("Validate --worker-mp-labels option for ROSA cluster creation - [id:71329]", - labels.Medium, labels.Runtime.Day1Supplemental, + labels.Medium, labels.Runtime.Day1Negative, func() { var ( clusterName = "cluster-71329" @@ -1740,7 +1740,7 @@ var _ = Describe("Classic cluster deletion validation", }) It("to validate the ROSA cluster deletion will work via rosacli - [id:38778]", - labels.Medium, labels.Runtime.Day1Supplemental, + labels.Medium, labels.Runtime.Day1Negative, func() { clusterService := rosaClient.Cluster notExistID := "no-exist-cluster-id" @@ -2696,7 +2696,7 @@ var _ = Describe("Create cluster with existing operator-roles prefix which roles ) Expect(err).To(BeNil()) - By("Create another cluster with the same operator-roless-prefix") + By("Create another cluster with the same operator-roles-prefix") clusterName := "test-45742b" out, err, _ := clusterService.Create( clusterName, "--sts", @@ -3255,22 +3255,30 @@ var _ = Describe("HCP cluster creation supplemental testing", }) AfterEach(func() { - By("Delete cluster") - rosaClient.Runner.UnsetArgs() - _, err := clusterService.DeleteCluster(clusterID, "-y") - Expect(err).To(BeNil()) + if clusterID != "" { + By("Delete cluster by id") + rosaClient.Runner.UnsetArgs() + _, err := clusterService.DeleteCluster(clusterID, "-y") + Expect(err).To(BeNil()) - rosaClient.Runner.UnsetArgs() - err = clusterService.WaitClusterDeleted(clusterID, 3, 30) - Expect(err).To(BeNil()) + rosaClient.Runner.UnsetArgs() + err = clusterService.WaitClusterDeleted(clusterID, 3, 30) + Expect(err).To(BeNil()) - By("Delete operator-roles") - _, err = ocmResourceService.DeleteOperatorRoles( - "-c", clusterID, - "--mode", "auto", - "-y", - ) - Expect(err).To(BeNil()) + By("Delete operator-roles") + _, err = ocmResourceService.DeleteOperatorRoles( + "-c", clusterID, + "--mode", "auto", + "-y", + ) + Expect(err).To(BeNil()) + } else { + // At least try to delete testing cluster + By("Delete cluster by name") + rosaClient.Runner.UnsetArgs() + _, err := clusterService.DeleteCluster(testingClusterName, "-y") + Expect(err).To(BeNil()) + } By("Clean resource") errs := profilehandler.DestroyResourceByProfile(customProfile, rosaClient) @@ -3306,6 +3314,49 @@ var _ = Describe("HCP cluster creation supplemental testing", clusterID = clusterList.ClusterByName(testingClusterName).ID Expect(clusterID).ToNot(BeNil()) }) + + It("Check single AZ hosted cluster can be created - [id:54413]", + labels.Critical, labels.Runtime.Day1Supplemental, + func() { + testingClusterName = common.GenerateRandomName("c54413", 2) + flags, err := profilehandler.GenerateClusterCreateFlags(customProfile, rosaClient) + Expect(err).ToNot(HaveOccurred()) + + command := "rosa create cluster --cluster-name " + testingClusterName + " " + strings.Join(flags, " ") + rosalCommand := config.GenerateCommand(command) + if rosalCommand.CheckFlagExist("--multi-az") { + rosalCommand.DeleteFlag("--multi-az", false) + } + if rosalCommand.CheckFlagExist("--subnet-ids") { + subnets := strings.Split(rosalCommand.GetFlagValue("--subnet-ids", true), ",") + var newSubnets []string + if customProfile.ClusterConfig.Private && customProfile.ClusterConfig.PrivateLink { + newSubnets = append(newSubnets, subnets[0]) + } else { + index := len(subnets) / 2 + newSubnets = append(newSubnets, subnets[0], subnets[index]) + } + flags := map[string]string{} + flags["--subnet-ids"] = strings.Join(newSubnets, ",") + rosalCommand.ReplaceFlagValue(flags) + } + + stdout, err := rosaClient.Runner.RunCMD(strings.Split(rosalCommand.GetFullCommand(), " ")) + Expect(err).To(BeNil()) + Expect(stdout.String()).To(ContainSubstring(fmt.Sprintf("Cluster '%s' has been created", testingClusterName))) + + By("Retrieve cluster ID") + rosaClient.Runner.UnsetArgs() + clusterListout, err := clusterService.List() + Expect(err).To(BeNil()) + clusterList, err := clusterService.ReflectClusterList(clusterListout) + Expect(err).To(BeNil()) + clusterID = clusterList.ClusterByName(testingClusterName).ID + + By("Wait for Cluster") + err = clusterService.WaitClusterStatus(clusterID, constants.Ready, 3, 60) + Expect(err).To(BeNil(), "It met error or timeout when waiting cluster to ready status") + }) }) var _ = Describe("Sts cluster creation supplemental testing", labels.Feature.Cluster, diff --git a/tests/e2e/test_rosacli_node_pool.go b/tests/e2e/test_rosacli_node_pool.go index cf64d55b0a..723e1b80c7 100644 --- a/tests/e2e/test_rosacli_node_pool.go +++ b/tests/e2e/test_rosacli_node_pool.go @@ -332,7 +332,7 @@ var _ = Describe("Edit nodepool", By("Prepare tuning configs") tc1JSON, err := json.Marshal(tc1Spec) Expect(err).ToNot(HaveOccurred()) - _, err = tuningConfigService.CreateTuningConfig( + _, err = tuningConfigService.CreateTuningConfigFromSpecContent( clusterID, tuningConfig1Name, string(tc1JSON)) @@ -340,7 +340,7 @@ var _ = Describe("Edit nodepool", tc2JSON, err := json.Marshal(tc2Spec) Expect(err).ToNot(HaveOccurred()) - _, err = tuningConfigService.CreateTuningConfig( + _, err = tuningConfigService.CreateTuningConfigFromSpecContent( clusterID, tuningConfig2Name, string(tc2JSON)) @@ -348,7 +348,7 @@ var _ = Describe("Edit nodepool", tc3JSON, err := json.Marshal(tc3Spec) Expect(err).ToNot(HaveOccurred()) - _, err = tuningConfigService.CreateTuningConfig( + _, err = tuningConfigService.CreateTuningConfigFromSpecContent( clusterID, tuningConfig3Name, string(tc3JSON)) @@ -399,7 +399,7 @@ var _ = Describe("Edit nodepool", By("Prepare tuning configs") tcJSON, err := json.Marshal(tcSpec) Expect(err).ToNot(HaveOccurred()) - _, err = tuningConfigService.CreateTuningConfig( + _, err = tuningConfigService.CreateTuningConfigFromSpecContent( clusterID, tuningConfigName, string(tcJSON)) diff --git a/tests/utils/config/cluster_command.go b/tests/utils/config/cluster_command.go index 22b78df6c7..f2dd919327 100644 --- a/tests/utils/config/cluster_command.go +++ b/tests/utils/config/cluster_command.go @@ -8,10 +8,10 @@ import ( type Command interface { GetFullCommand() string - GetFlagValue(flag string, flagWithVaue bool) string + GetFlagValue(flag string, flagWithValue bool) string AddFlags(flags ...string) ReplaceFlagValue(flags map[string]string) - DeleteFlag(flag string, flagWithVaue bool) error + DeleteFlag(flag string, flagWithValue bool) error CheckFlagExist(flag string) bool } @@ -53,11 +53,11 @@ func (c *command) ReplaceFlagValue(flags map[string]string) { } // a function to delete any flag in the command -func (c *command) DeleteFlag(flag string, flagWithVaue bool) error { +func (c *command) DeleteFlag(flag string, flagWithValue bool) error { elements := strings.Split(c.cmd, " ") for i, e := range elements { if e == flag { - if flagWithVaue { + if flagWithValue { elements = append(elements[:i], elements[i+2:]...) } else { elements = append(elements[:i], elements[i+1:]...) @@ -70,11 +70,11 @@ func (c *command) DeleteFlag(flag string, flagWithVaue bool) error { } // Get the value of a flag from the command -func (c *command) GetFlagValue(flag string, flagWithVaue bool) string { +func (c *command) GetFlagValue(flag string, flagWithValue bool) string { elements := strings.Split(c.cmd, " ") for i, e := range elements { if e == flag { - if flagWithVaue { + if flagWithValue { return elements[i+1] } else { return "" diff --git a/tests/utils/exec/rosacli/machinepool_service.go b/tests/utils/exec/rosacli/machinepool_service.go index cdda6019fd..5357e61e2c 100644 --- a/tests/utils/exec/rosacli/machinepool_service.go +++ b/tests/utils/exec/rosacli/machinepool_service.go @@ -25,7 +25,7 @@ type MachinePoolService interface { DescribeMachinePool(clusterID string, mpID string) (bytes.Buffer, error) CreateMachinePool(clusterID string, name string, flags ...string) (bytes.Buffer, error) EditMachinePool(clusterID string, machinePoolName string, flags ...string) (bytes.Buffer, error) - DeleteMachinePool(clusterID string, machinePoolName string) (bytes.Buffer, error) + DeleteMachinePool(clusterID string, machinePoolName string, flags ...string) (bytes.Buffer, error) ReflectMachinePoolList(result bytes.Buffer) (mpl MachinePoolList, err error) ReflectMachinePoolDescription(result bytes.Buffer) (*MachinePoolDescription, error) @@ -190,10 +190,10 @@ func (m *machinepoolService) DescribeAndReflectMachinePool( // Delete MachinePool func (m *machinepoolService) DeleteMachinePool( - clusterID string, machinePoolName string) (output bytes.Buffer, err error) { + clusterID string, machinePoolName string, flags ...string) (output bytes.Buffer, err error) { output, err = m.client.Runner. Cmd("delete", "machinepool"). - CmdFlags("-c", clusterID, machinePoolName, "-y"). + CmdFlags(append(flags, "-c", clusterID, machinePoolName, "-y")...). Run() if err == nil { m.machinePools[clusterID] = common.RemoveFromStringSlice(m.machinePools[clusterID], machinePoolName) diff --git a/tests/utils/exec/rosacli/tuning_config_service.go b/tests/utils/exec/rosacli/tuning_config_service.go index c04c81e701..b7a11a2e0e 100644 --- a/tests/utils/exec/rosacli/tuning_config_service.go +++ b/tests/utils/exec/rosacli/tuning_config_service.go @@ -15,7 +15,16 @@ import ( type TuningConfigService interface { ResourcesCleaner - CreateTuningConfig(clusterID string, tcName string, specContent string, flags ...string) (bytes.Buffer, error) + CreateTuningConfigFromSpecFile( + clusterID string, + tcName string, + specFile string, + flags ...string) (bytes.Buffer, error) + CreateTuningConfigFromSpecContent( + clusterID string, + tcName string, + specContent string, + flags ...string) (bytes.Buffer, error) EditTuningConfig(clusterID string, tcName string, flags ...string) (bytes.Buffer, error) DeleteTuningConfig(clusterID string, tcName string) (bytes.Buffer, error) @@ -97,7 +106,7 @@ func NewTuningConfigSpecProfileData(vmDirtyRatio int) string { vmDirtyRatio) } -func (tcs *tuningConfigService) CreateTuningConfig( +func (tcs *tuningConfigService) CreateTuningConfigFromSpecContent( clusterID string, tcName string, specContent string, flags ...string) (output bytes.Buffer, err error) { Logger.Debugf("Create tc %s with content %s", tcName, specContent) specPath, err := common.CreateTempFileWithContent(specContent) @@ -105,9 +114,15 @@ func (tcs *tuningConfigService) CreateTuningConfig( if err != nil { return *bytes.NewBufferString(""), err } + output, err = tcs.CreateTuningConfigFromSpecFile(clusterID, tcName, specPath, flags...) + return +} + +func (tcs *tuningConfigService) CreateTuningConfigFromSpecFile( + clusterID string, tcName string, specFile string, flags ...string) (output bytes.Buffer, err error) { output, err = tcs.client.Runner. Cmd("create", "tuning-config"). - CmdFlags(append(flags, "-c", clusterID, "--name", tcName, "--spec-path", specPath)...). + CmdFlags(append(flags, "-c", clusterID, "--name", tcName, "--spec-path", specFile)...). Run() if err == nil { tcs.tuningConfigs[clusterID] = append(tcs.tuningConfigs[clusterID], tcName)