diff --git a/tests/e2e/hcp_tuning_config_test.go b/tests/e2e/hcp_tuning_config_test.go new file mode 100644 index 0000000000..674a0a0ae7 --- /dev/null +++ b/tests/e2e/hcp_tuning_config_test.go @@ -0,0 +1,115 @@ +package e2e + +import ( + "fmt" + "os" + "strings" + + . "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("Create Tuning Config", 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("Check hosted cluster") + hosted, err := clusterService.IsHostedCPCluster(clusterID) + Expect(err).ToNot(HaveOccurred()) + if !hosted { + Skip("Tuning Configs are only supported on Hosted clusters") + } + }) + + AfterEach(func() { + By("Clean remaining resources") + err := rosaClient.CleanResources(clusterID) + Expect(err).ToNot(HaveOccurred()) + }) + + It("tuning config can be created/updated/deleted to hosted cluster - [id:63164]", + labels.Critical, labels.NonClassicCluster, + func() { + tuningConfigService := rosaClient.TuningConfig + tuningConfigName_1 := common.GenerateRandomName("tuned01", 2) + tuningConfigName_2 := common.GenerateRandomName("tuned02", 2) + + tuningConfigPayload_1 := `{ + "profile": [ + { + "data": "[main]\nsummary=Custom OpenShift profile\ninclude=openshift-node\n\n[sysctl]\nvm.dirty_ratio=\"25\"\n", + "name": "%s-profile" + } + ], + "recommend": [ + { + "priority": 10, + "profile": "%s-profile" + } + ] + }` + tuningConfigPayload_2 := `{ + "profile": [ + { + "data": "[main]\nsummary=Custom OpenShift profile\ninclude=openshift-node\n\n[sysctl]\nvm.dirty_ratio=\"65\"\n", + "name": "%s-profile" + } + ], + "recommend": [ + { + "priority": 20, + "profile": "%s-profile" + } + ] + }` + By("Create tuning configs to the cluster") + resp, err := tuningConfigService.CreateTuningConfig(clusterID, tuningConfigName_1, fmt.Sprintf(tuningConfigPayload_1, tuningConfigName_1, tuningConfigName_1)) + 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'", tuningConfigName_1, clusterID))) + resp, err = tuningConfigService.CreateTuningConfig(clusterID, tuningConfigName_2, fmt.Sprintf(tuningConfigPayload_1, tuningConfigName_2, tuningConfigName_2)) + 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'", tuningConfigName_2, clusterID))) + + By("List all tuning configs") + tuningConfigList, err := tuningConfigService.ListTuningConfigsAndReflect(clusterID) + Expect(err).ToNot(HaveOccurred()) + Expect(tuningConfigList.IsPresent(tuningConfigName_1)).To(BeTrue(), "the tuningconfig %s is not in output", tuningConfigName_1) + Expect(tuningConfigList.IsPresent(tuningConfigName_2)).To(BeTrue(), "the tuningconfig %s is not in output", tuningConfigName_2) + + By("Update a tuning config of the cluster") + specPath, err := common.CreateTempFileWithContent(fmt.Sprintf(tuningConfigPayload_2, tuningConfigName_2, tuningConfigName_2)) + defer os.Remove(specPath) + Expect(err).ToNot(HaveOccurred()) + _, err = tuningConfigService.EditTuningConfig(clusterID, tuningConfigName_2, "--spec-path", specPath) + Expect(err).ToNot(HaveOccurred()) + + By("Describe the updated tuning config") + output, err := tuningConfigService.DescribeTuningConfigAndReflect(clusterID, tuningConfigName_2) + Expect(err).ToNot(HaveOccurred()) + tuningConfigPayload_2 = strings.ReplaceAll(tuningConfigPayload_2, "\t", " ") + Expect(output.Spec).To(Equal(fmt.Sprintf(tuningConfigPayload_2, tuningConfigName_2, tuningConfigName_2))) + Expect(output.Name).To(Equal(tuningConfigName_2)) + + By("Delete the tuning config") + _, err = tuningConfigService.DeleteTuningConfig(clusterID, tuningConfigName_2) + Expect(err).ToNot(HaveOccurred()) + + By("List the tuning configs and check deleted tuning config should not be present]") + tuningConfigList, err = tuningConfigService.ListTuningConfigsAndReflect(clusterID) + Expect(err).ToNot(HaveOccurred()) + Expect(tuningConfigList.IsPresent(tuningConfigName_1)).To(BeTrue(), "the tuningconfig %s is not in output", tuningConfigName_1) + Expect(tuningConfigList.IsPresent(tuningConfigName_2)).To(BeFalse(), "the tuningconfig %s is in the output", tuningConfigName_2) + }) +}) diff --git a/tests/e2e/test_rosacli_iam_roles.go b/tests/e2e/test_rosacli_iam_roles.go index f8e4bda3bc..160417353a 100644 --- a/tests/e2e/test_rosacli_iam_roles.go +++ b/tests/e2e/test_rosacli_iam_roles.go @@ -874,4 +874,130 @@ var _ = Describe("Edit IAM", foundUserRole = userRoleList.UserRole(userrolePrefix, ocmAccountUsername) Expect(foundUserRole.Linded).To(Equal("No")) }) + + It("create/delete hypershift account roles with managed policies - [id:61322]", + labels.Critical, + func() { + defer func() { + By("Cleanup created account-roles in the test case") + if len(accountRolePrefixesNeedCleanup) > 0 { + for _, v := range accountRolePrefixesNeedCleanup { + _, err := ocmResourceService.DeleteAccountRole("--mode", "auto", + "--prefix", v, + "-y") + + Expect(err).To(BeNil()) + } + } + }() + + var ( + rolePrefixStable = "prefixS" + rolePrefixCandidate = "prefixC" + rolePrefixClassic = "prefixClassic" + versionStable = "4.13" + versionCandidate = "4.14" + path = "/fd/sd/" + ) + + By("Get the AWS Account Id") + rosaClient.Runner.JsonFormat() + + whoamiOutput, err := ocmResourceService.Whoami() + Expect(err).To(BeNil()) + rosaClient.Runner.UnsetFormat() + whoamiData := ocmResourceService.ReflectAccountsInfo(whoamiOutput) + AWSAccountID := whoamiData.AWSAccountID + + By("Create account-roles of hosted-cp in stable channel") + output, err := ocmResourceService.CreateAccountRole("--mode", "auto", + "--prefix", rolePrefixStable, + "--path", path, + "--permissions-boundary", permissionsBoundaryArn, + "--force-policy-creation", "--version", versionStable, + "--channel-group", "stable", + "--hosted-cp", + "-y") + Expect(err).To(BeNil()) + + accountRolePrefixesNeedCleanup = append(accountRolePrefixesNeedCleanup, rolePrefixStable) + textData := rosaClient.Parser.TextData.Input(output).Parse().Tip() + Expect(textData).ToNot(ContainSubstring("Creating classic account roles")) + Expect(textData).To(ContainSubstring("Creating hosted CP account roles")) + Expect(textData).To(ContainSubstring("WARN: Setting `version` flag for hosted CP managed policies has no effect, any supported ROSA version can be installed with managed policies")) + Expect(textData).To(ContainSubstring(fmt.Sprintf("Created role '%s-HCP-ROSA-Installer-Role'", rolePrefixStable))) + Expect(textData).To(ContainSubstring(fmt.Sprintf("Created role '%s-HCP-ROSA-Support-Role'", rolePrefixStable))) + Expect(textData).To(ContainSubstring(fmt.Sprintf("Created role '%s-HCP-ROSA-Worker-Role'", rolePrefixStable))) + + By("Create account-roles of hosted-cp in candidate channel") + output, err = ocmResourceService.CreateAccountRole("--mode", "auto", + "--prefix", rolePrefixCandidate, + "--path", path, + "--permissions-boundary", permissionsBoundaryArn, + "--version", versionCandidate, + "--channel-group", "candidate", + "--hosted-cp", + "-y") + Expect(err).To(BeNil()) + + accountRolePrefixesNeedCleanup = append(accountRolePrefixesNeedCleanup, rolePrefixCandidate) + textData = rosaClient.Parser.TextData.Input(output).Parse().Tip() + Expect(textData).ToNot(ContainSubstring("Creating classic account roles")) + Expect(textData).To(ContainSubstring("Creating hosted CP account roles")) + Expect(textData).To(ContainSubstring("WARN: Setting `version` flag for hosted CP managed policies has no effect, any supported ROSA version can be installed with managed policies")) + Expect(textData).To(ContainSubstring(fmt.Sprintf("Created role '%s-HCP-ROSA-Installer-Role'", rolePrefixCandidate))) + Expect(textData).To(ContainSubstring(fmt.Sprintf("Created role '%s-HCP-ROSA-Support-Role'", rolePrefixCandidate))) + Expect(textData).To(ContainSubstring(fmt.Sprintf("Created role '%s-HCP-ROSA-Worker-Role'", rolePrefixCandidate))) + + By("List the acount roles ") + accountRoleList, _, err := ocmResourceService.ListAccountRole() + Expect(err).To(BeNil()) + + By("Get the stable/candidate account roles that are created above") + accountRoleSetStable := accountRoleList.AccountRoles(rolePrefixStable) + accountRoleSetCandidate := accountRoleList.AccountRoles(rolePrefixCandidate) + + selectedRoleStable := accountRoleSetStable[rand.Intn(len(accountRoleSetStable))] + selectedRoleCandidate := accountRoleSetCandidate[rand.Intn(len(accountRoleSetCandidate))] + + By("Check 3 roles are created for hosted CP account roles") + Expect(len(accountRoleSetStable)).To(Equal(3)) + Expect(len(accountRoleSetCandidate)).To(Equal(3)) + + By("Check the roles are AWS managed, and path and version flag works correctly") + Expect(selectedRoleStable.AWSManaged).To(Equal("Yes")) + Expect(selectedRoleStable.RoleArn).To(Equal(fmt.Sprintf("arn:aws:iam::%s:role%s%s-HCP-ROSA-%s", AWSAccountID, path, rolePrefixStable, rosacli.RoleTypeSuffixMap[selectedRoleStable.RoleType]))) + Expect(selectedRoleStable.OpenshiftVersion).To(Equal(versionStable)) + Expect(selectedRoleCandidate.AWSManaged).To(Equal("Yes")) + Expect(selectedRoleCandidate.RoleArn).To(Equal(fmt.Sprintf("arn:aws:iam::%s:role%s%s-HCP-ROSA-%s", AWSAccountID, path, rolePrefixCandidate, rosacli.RoleTypeSuffixMap[selectedRoleCandidate.RoleType]))) + Expect(selectedRoleCandidate.OpenshiftVersion).To(Equal(versionCandidate)) + + By("Delete the hypershift account roles in auto mode") + output, err = ocmResourceService.DeleteAccountRole("--mode", "auto", + "--prefix", rolePrefixStable, + "--hosted-cp", + "-y", + ) + + Expect(err).To(BeNil()) + textData = rosaClient.Parser.TextData.Input(output).Parse().Tip() + Expect(textData).To(ContainSubstring("Successfully deleted the hosted CP account roles")) + + By("Create a classic account role") + _, err = ocmResourceService.CreateAccountRole("--mode", "auto", + "--prefix", rolePrefixClassic, + "--classic", + "-y") + Expect(err).To(BeNil()) + accountRolePrefixesNeedCleanup = append(accountRolePrefixesNeedCleanup, rolePrefixClassic) + + By("Try to delete classic account-role with --hosted-cp flag") + output, err = ocmResourceService.DeleteAccountRole("--mode", "auto", + "--prefix", rolePrefixClassic, + "--hosted-cp", + "-y") + Expect(err).ToNot(HaveOccurred()) + textData = rosaClient.Parser.TextData.Input(output).Parse().Tip() + Expect(textData).To(ContainSubstring("WARN: There are no hosted CP account roles to be deleted")) + }) }) diff --git a/tests/utils/exec/rosacli/tuning_config_service.go b/tests/utils/exec/rosacli/tuning_config_service.go index c4e094fd00..458e23c62e 100644 --- a/tests/utils/exec/rosacli/tuning_config_service.go +++ b/tests/utils/exec/rosacli/tuning_config_service.go @@ -3,6 +3,7 @@ package rosacli import ( "bytes" "os" + "strings" "gopkg.in/yaml.v3" @@ -119,6 +120,18 @@ func (tcs *tuningConfigService) ListTuningConfigsAndReflect(clusterID string) (* return tcs.ReflectTuningConfigList(output) } +// Check the tuningConfig with the name exists in the tuningConfigList +func (tuningConfigs TuningConfigList) IsPresent(tcName string) (existed bool) { + existed = false + for _, tuningConfig := range tuningConfigs.TuningConfigs { + if tuningConfig.Name == tcName { + existed = true + break + } + } + return +} + func (tcs *tuningConfigService) DescribeTuningConfig(clusterID string, tcID string) (bytes.Buffer, error) { describe := tcs.client.Runner. Cmd("describe", "tuning-configs", tcID). @@ -138,7 +151,11 @@ func (tcs *tuningConfigService) DescribeTuningConfigAndReflect(clusterID string, func (tcs *tuningConfigService) ReflectTuningConfigDescription(result bytes.Buffer) (res *TuningConfigDescription, err error) { var data []byte res = &TuningConfigDescription{} - theMap, err := tcs.client.Parser.TextData.Input(result).Parse().YamlToMap() + // Apply transformation to avoid issue with getting of Spec Content + theMap, err := tcs.client.Parser.TextData.Input(result).Parse().TransformOutput(func(str string) (newStr string) { + newStr = strings.Replace(str, "Spec:", "Spec: |\n ", 1) + return + }).YamlToMap() if err != nil { return }