github.com/redhat-appstudio/e2e-tests@v0.0.0-20230619105049-9a422b2094d7/tests/e2e-demos/multi-component.go (about) 1 package e2e 2 3 import ( 4 "fmt" 5 "strings" 6 "time" 7 8 . "github.com/onsi/ginkgo/v2" 9 . "github.com/onsi/gomega" 10 appservice "github.com/redhat-appstudio/application-api/api/v1alpha1" 11 "github.com/redhat-appstudio/e2e-tests/pkg/constants" 12 "github.com/redhat-appstudio/e2e-tests/pkg/framework" 13 "github.com/redhat-appstudio/e2e-tests/pkg/utils" 14 "github.com/redhat-appstudio/e2e-tests/tests/e2e-demos/config" 15 v1 "k8s.io/api/core/v1" 16 "k8s.io/apimachinery/pkg/api/errors" 17 ) 18 19 // All multiple components scenarios are supported in the next jira: https://issues.redhat.com/browse/DEVHAS-305 20 const ( 21 MultiComponentWithoutDockerFileAndDevfile = "multi-component scenario with components without devfile or dockerfile" 22 MultiComponentWithAllSupportedImportScenarios = "multi-component scenario with all supported import components" 23 MultiComponentWithDevfileAndDockerfile = "multi-component scenario with components with devfile or dockerfile or both" 24 MultiComponentWithUnsupportedRuntime = "multi-component scenario with a component with a supported runtime and another unsuported" 25 ) 26 27 var runtimeSupported = []string{"Dockerfile", "Node.js", "Go", "Quarkus", "Python", "JavaScript", "springboot"} 28 29 const ( 30 multiComponentTestNamespace string = "multi-comp-e2e" 31 ) 32 33 var _ = framework.E2ESuiteDescribe(Label("e2e-demo", "multi-component"), func() { 34 defer GinkgoRecover() 35 36 var fw *framework.Framework 37 var err error 38 var namespace string 39 40 // Initialize the application struct 41 application := &appservice.Application{} 42 cdq := &appservice.ComponentDetectionQuery{} 43 componentList := []*appservice.Component{} 44 env := &appservice.Environment{} 45 46 // https://github.com/redhat-appstudio-qe/rhtap-three-component-scenarios.git 47 var testSpecification = config.WorkflowSpec{ 48 Tests: []config.TestSpec{ 49 { 50 Name: MultiComponentWithoutDockerFileAndDevfile, 51 ApplicationName: "mc-quality-dashboard", 52 // We need to skip for now deployment checks of quality dashboard until RHTAP support secrets 53 Components: []config.ComponentSpec{ 54 { 55 Name: "mc-withdockerfile-withoutdevfile", 56 SkipDeploymentCheck: true, 57 Type: "public", 58 GitSourceUrl: "https://github.com/redhat-appstudio/quality-dashboard.git", 59 }, 60 }, 61 }, 62 { 63 Name: MultiComponentWithDevfileAndDockerfile, 64 ApplicationName: "mc-two-scenarios", 65 Components: []config.ComponentSpec{ 66 { 67 Name: "mc-two-scenarios", 68 SkipDeploymentCheck: false, 69 Type: "public", 70 GitSourceUrl: "https://github.com/redhat-appstudio-qe/rhtap-devfile-multi-component.git", 71 }, 72 }, 73 }, 74 { 75 Name: MultiComponentWithAllSupportedImportScenarios, 76 ApplicationName: "mc-three-scenarios", 77 Components: []config.ComponentSpec{ 78 { 79 Name: "mc-three-scenarios", 80 Type: "public", 81 SkipDeploymentCheck: false, 82 GitSourceUrl: "https://github.com/redhat-appstudio-qe/rhtap-three-component-scenarios.git", 83 }, 84 }, 85 }, 86 { 87 Name: MultiComponentWithUnsupportedRuntime, 88 ApplicationName: "mc-unsupported-runtime", 89 Components: []config.ComponentSpec{ 90 { 91 Name: "mc-unsuported-runtime", 92 Type: "public", 93 SkipDeploymentCheck: false, 94 GitSourceUrl: "https://github.com/redhat-appstudio-qe/rhtap-mc-unsuported-runtime.git", 95 }, 96 }, 97 }, 98 }, 99 } 100 101 for _, suite := range testSpecification.Tests { 102 Describe(suite.Name, Ordered, func() { 103 suite := suite 104 BeforeAll(func() { 105 if suite.Skip { 106 Skip(fmt.Sprintf("test skipped %s", suite.Name)) 107 } 108 109 // Initialize the tests controllers 110 fw, err = framework.NewFramework(utils.GetGeneratedNamespace(multiComponentTestNamespace)) 111 Expect(err).NotTo(HaveOccurred()) 112 namespace = fw.UserNamespace 113 Expect(namespace).NotTo(BeEmpty()) 114 115 // collect SPI ResourceQuota metrics (temporary) 116 err := fw.AsKubeAdmin.CommonController.GetResourceQuotaInfo("multi-component", namespace, "appstudio-crds-spi") 117 Expect(err).NotTo(HaveOccurred()) 118 119 suiteConfig, _ := GinkgoConfiguration() 120 GinkgoWriter.Printf("Parallel processes: %d\n", suiteConfig.ParallelTotal) 121 GinkgoWriter.Printf("Running on namespace: %s\n", namespace) 122 GinkgoWriter.Printf("User: %s\n", fw.UserName) 123 124 githubCredentials := `{"access_token":"` + utils.GetEnv(constants.GITHUB_TOKEN_ENV, "") + `"}` 125 126 _ = fw.AsKubeDeveloper.SPIController.InjectManualSPIToken(namespace, fmt.Sprintf("https://github.com/%s", utils.GetEnv(constants.GITHUB_E2E_ORGANIZATION_ENV, "redhat-appstudio-qe")), githubCredentials, v1.SecretTypeBasicAuth, SPIGithubSecretName) 127 128 }) 129 130 // Remove all resources created by the tests 131 AfterAll(func() { 132 // collect SPI ResourceQuota metrics (temporary) 133 err := fw.AsKubeAdmin.CommonController.GetResourceQuotaInfo("multi-component", namespace, "appstudio-crds-spi") 134 Expect(err).NotTo(HaveOccurred()) 135 136 if !CurrentSpecReport().Failed() { 137 Expect(fw.AsKubeDeveloper.HasController.DeleteAllComponentsInASpecificNamespace(namespace, 30*time.Second)).To(Succeed()) 138 Expect(fw.AsKubeAdmin.HasController.DeleteAllApplicationsInASpecificNamespace(namespace, 30*time.Second)).To(Succeed()) 139 Expect(fw.AsKubeAdmin.HasController.DeleteAllSnapshotEnvBindingsInASpecificNamespace(namespace, 30*time.Second)).To(Succeed()) 140 Expect(fw.AsKubeAdmin.ReleaseController.DeleteAllSnapshotsInASpecificNamespace(namespace, 30*time.Second)).To(Succeed()) 141 Expect(fw.AsKubeAdmin.GitOpsController.DeleteAllEnvironmentsInASpecificNamespace(namespace, 30*time.Second)).To(Succeed()) 142 Expect(fw.AsKubeAdmin.TektonController.DeleteAllPipelineRunsInASpecificNamespace(namespace)).To(Succeed()) 143 Expect(fw.AsKubeAdmin.GitOpsController.DeleteAllGitOpsDeploymentInASpecificNamespace(namespace, 30*time.Second)).To(Succeed()) 144 Expect(fw.SandboxController.DeleteUserSignup(fw.UserName)).NotTo(BeFalse()) 145 } 146 }) 147 148 // Create an application in a specific namespace 149 It(fmt.Sprintf("create application %s", suite.ApplicationName), func() { 150 GinkgoWriter.Printf("Parallel process %d\n", GinkgoParallelProcess()) 151 application, err := fw.AsKubeDeveloper.HasController.CreateHasApplication(suite.ApplicationName, namespace) 152 Expect(err).NotTo(HaveOccurred()) 153 Expect(application.Spec.DisplayName).To(Equal(suite.ApplicationName)) 154 Expect(application.Namespace).To(Equal(namespace)) 155 }) 156 157 // Check the application health and check if a devfile was generated in the status 158 It(fmt.Sprintf("checks if application %s is healthy", suite.ApplicationName), func() { 159 Eventually(func() string { 160 appstudioApp, err := fw.AsKubeDeveloper.HasController.GetHasApplication(suite.ApplicationName, namespace) 161 Expect(err).NotTo(HaveOccurred()) 162 application = appstudioApp 163 164 return application.Status.Devfile 165 }, 3*time.Minute, 100*time.Millisecond).Should(Not(BeEmpty()), "Error creating gitOps repository") 166 167 Eventually(func() bool { 168 gitOpsRepository := utils.ObtainGitOpsRepositoryName(application.Status.Devfile) 169 170 return fw.AsKubeDeveloper.CommonController.Github.CheckIfRepositoryExist(gitOpsRepository) 171 }, 5*time.Minute, 1*time.Second).Should(BeTrue(), "Has controller didn't create gitops repository") 172 }) 173 174 for _, testComponent := range suite.Components { 175 testComponent := testComponent 176 177 It(fmt.Sprintf("creates ComponentDetectionQuery for application %s", suite.ApplicationName), func() { 178 cdq, err = fw.AsKubeDeveloper.HasController.CreateComponentDetectionQuery( 179 testComponent.Name, 180 namespace, 181 testComponent.GitSourceUrl, 182 testComponent.GitSourceRevision, 183 testComponent.GitSourceContext, 184 "", 185 false, 186 ) 187 Expect(err).NotTo(HaveOccurred()) 188 Expect(cdq.Name).To(Equal(testComponent.Name)) 189 }) 190 191 It("check if components have supported languages by AppStudio", func() { 192 if suite.Name == MultiComponentWithUnsupportedRuntime { 193 // Validate that the completed CDQ only has detected 1 component and not also the unsupported component 194 Expect(len(cdq.Status.ComponentDetected)).To(Equal(1), "cdq also detect unsupported component") 195 } 196 for _, component := range cdq.Status.ComponentDetected { 197 Expect(utils.Contains(runtimeSupported, component.ProjectType), "unsupported runtime used for multi component tests") 198 199 } 200 }) 201 202 // Create an environment in a specific namespace 203 It(fmt.Sprintf("creates environment %s", EnvironmentName), func() { 204 env, err = fw.AsKubeDeveloper.IntegrationController.CreateEnvironment(namespace, EnvironmentName) 205 Expect(err).NotTo(HaveOccurred()) 206 }) 207 208 It(fmt.Sprintf("creates multiple components in application %s", suite.ApplicationName), func() { 209 for _, component := range cdq.Status.ComponentDetected { 210 // Skip https://github.com/redhat-appstudio/quality-dashboard/tree/main/frontend because takes to much to much ton push to quay.io and analyze sbom due huge image and is make 211 // ci to be slow 212 if !strings.Contains(component.ComponentStub.ComponentName, "frontend-quality") { 213 c, err := fw.AsKubeDeveloper.HasController.CreateComponentFromStub(component, namespace, "", SPIGithubSecretName, application.Name) 214 Expect(err).NotTo(HaveOccurred()) 215 Expect(c.Name).To(Equal(component.ComponentStub.ComponentName)) 216 Expect(utils.Contains(runtimeSupported, component.ProjectType), "unsupported runtime used for multi component tests") 217 218 componentList = append(componentList, c) 219 } 220 } 221 }) 222 223 It(fmt.Sprintf("waits application %s components pipelines to be finished", suite.ApplicationName), func() { 224 for _, component := range componentList { 225 Expect(fw.AsKubeAdmin.HasController.WaitForComponentPipelineToBeFinished(component, "", 2)).To(Succeed()) 226 } 227 }) 228 229 It(fmt.Sprintf("finds the application %s components snapshots and checks if it is marked as successfully", suite.ApplicationName), func() { 230 timeout := time.Second * 600 231 interval := time.Second * 10 232 233 for _, component := range componentList { 234 var componentSnapshot *appservice.Snapshot 235 236 Eventually(func() bool { 237 componentSnapshot, err = fw.AsKubeDeveloper.IntegrationController.GetSnapshot("", "", component.Name, namespace) 238 if err != nil { 239 GinkgoWriter.Printf("cannot get the Snapshot: %v\n", err) 240 return false 241 } 242 243 return fw.AsKubeDeveloper.IntegrationController.HaveTestsSucceeded(componentSnapshot) 244 }, timeout, interval).Should(BeTrue(), "time out when trying to either check if the snapshot is created or is marked as successful") 245 246 Eventually(func() bool { 247 if fw.AsKubeDeveloper.IntegrationController.HaveTestsSucceeded(componentSnapshot) { 248 envbinding, err := fw.AsKubeDeveloper.IntegrationController.GetSnapshotEnvironmentBinding(application.Name, namespace, env) 249 if err != nil { 250 GinkgoWriter.Printf("cannot get the SnapshotEnvironmentBinding: %v\n", err) 251 return false 252 } 253 GinkgoWriter.Printf("The SnapshotEnvironmentBinding %s is found\n", envbinding.Name) 254 return true 255 } 256 257 componentSnapshot, err = fw.AsKubeDeveloper.IntegrationController.GetSnapshot("", "", component.Name, namespace) 258 if err != nil { 259 GinkgoWriter.Printf("cannot get the Snapshot: %v\n", err) 260 return false 261 } 262 return false 263 }, timeout, interval).Should(BeTrue(), "time out when waiting for snapshoot environment binding") 264 } 265 }) 266 267 It("checks if multiple components are deployed", func() { 268 if testComponent.SkipDeploymentCheck { 269 Skip("component deployment skipped.") 270 } 271 for _, component := range componentList { 272 Eventually(func() bool { 273 componentDeployment, err := fw.AsKubeDeveloper.CommonController.GetDeployment(component.Name, namespace) 274 if err != nil && !errors.IsNotFound(err) { 275 return false 276 } 277 278 if componentDeployment.Status.AvailableReplicas == 1 { 279 return true 280 } 281 return false 282 }) 283 284 } 285 }) 286 287 It("checks if multicomponents routes exists", func() { 288 if testComponent.SkipDeploymentCheck { 289 Skip("component deployment skipped.") 290 } 291 for _, component := range componentList { 292 Eventually(func() bool { 293 if _, err := fw.AsKubeDeveloper.CommonController.GetOpenshiftRoute(component.Name, namespace); err != nil { 294 return false 295 } 296 return true 297 }) 298 } 299 }) 300 } 301 }) 302 } 303 })