github.com/redhat-appstudio/e2e-tests@v0.0.0-20230619105049-9a422b2094d7/tests/e2e-demos/e2e-demo.go (about) 1 package e2e 2 3 import ( 4 "fmt" 5 "time" 6 7 . "github.com/onsi/ginkgo/v2" 8 . "github.com/onsi/gomega" 9 appservice "github.com/redhat-appstudio/application-api/api/v1alpha1" 10 "github.com/redhat-appstudio/e2e-tests/pkg/constants" 11 "github.com/redhat-appstudio/e2e-tests/pkg/framework" 12 "github.com/redhat-appstudio/e2e-tests/pkg/utils" 13 e2eConfig "github.com/redhat-appstudio/e2e-tests/tests/e2e-demos/config" 14 "github.com/spf13/viper" 15 appsv1 "k8s.io/api/apps/v1" 16 v1 "k8s.io/api/core/v1" 17 "k8s.io/apimachinery/pkg/api/errors" 18 "k8s.io/utils/pointer" 19 ) 20 21 const ( 22 // Environment name used for e2e-tests demos 23 EnvironmentName string = "development" 24 25 // Secret Name created by spi to interact with github 26 SPIGithubSecretName string = "e2e-github-secret" 27 28 // Environment name used for e2e-tests demos 29 SPIQuaySecretName string = "e2e-quay-secret" 30 ) 31 32 var _ = framework.E2ESuiteDescribe(Label("e2e-demo"), func() { 33 defer GinkgoRecover() 34 var outputContainerImage = "" 35 var timeout, interval time.Duration 36 var namespace string 37 38 // Initialize the application struct 39 application := &appservice.Application{} 40 component := &appservice.Component{} 41 snapshot := &appservice.Snapshot{} 42 env := &appservice.Environment{} 43 fw := &framework.Framework{} 44 45 // Initialize the e2e demo configuration 46 configTestFile := viper.GetString("config-suites") 47 GinkgoWriter.Printf("Starting e2e-demo test suites from config: %s\n", configTestFile) 48 49 configTest, err := e2eConfig.LoadTestGeneratorConfig(configTestFile) 50 Expect(err).NotTo(HaveOccurred()) 51 52 for _, appTest := range configTest.Tests { 53 appTest := appTest 54 55 Describe(appTest.Name, Ordered, func() { 56 BeforeAll(func() { 57 if appTest.Skip { 58 Skip(fmt.Sprintf("test skipped %s", appTest.Name)) 59 } 60 61 // Initialize the tests controllers 62 fw, err = framework.NewFramework(utils.GetGeneratedNamespace("e2e-demos")) 63 Expect(err).NotTo(HaveOccurred()) 64 namespace = fw.UserNamespace 65 Expect(namespace).NotTo(BeEmpty()) 66 67 // collect SPI ResourceQuota metrics (temporary) 68 err := fw.AsKubeAdmin.CommonController.GetResourceQuotaInfo("e2e-demo", namespace, "appstudio-crds-spi") 69 Expect(err).NotTo(HaveOccurred()) 70 71 suiteConfig, _ := GinkgoConfiguration() 72 GinkgoWriter.Printf("Parallel processes: %d\n", suiteConfig.ParallelTotal) 73 GinkgoWriter.Printf("Running on namespace: %s\n", namespace) 74 GinkgoWriter.Printf("User: %s\n", fw.UserName) 75 76 githubCredentials := `{"access_token":"` + utils.GetEnv(constants.GITHUB_TOKEN_ENV, "") + `"}` 77 78 _ = 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) 79 }) 80 81 // Remove all resources created by the tests 82 AfterAll(func() { 83 // collect SPI ResourceQuota metrics (temporary) 84 err := fw.AsKubeAdmin.CommonController.GetResourceQuotaInfo("e2e-demo", namespace, "appstudio-crds-spi") 85 Expect(err).NotTo(HaveOccurred()) 86 87 if !CurrentSpecReport().Failed() { 88 Expect(fw.AsKubeDeveloper.HasController.DeleteAllComponentsInASpecificNamespace(namespace, 30*time.Second)).To(Succeed()) 89 Expect(fw.AsKubeAdmin.HasController.DeleteAllApplicationsInASpecificNamespace(namespace, 30*time.Second)).To(Succeed()) 90 Expect(fw.AsKubeAdmin.HasController.DeleteAllSnapshotEnvBindingsInASpecificNamespace(namespace, 30*time.Second)).To(Succeed()) 91 Expect(fw.AsKubeAdmin.ReleaseController.DeleteAllSnapshotsInASpecificNamespace(namespace, 30*time.Second)).To(Succeed()) 92 Expect(fw.AsKubeAdmin.GitOpsController.DeleteAllEnvironmentsInASpecificNamespace(namespace, 30*time.Second)).To(Succeed()) 93 Expect(fw.AsKubeAdmin.TektonController.DeleteAllPipelineRunsInASpecificNamespace(namespace)).To(Succeed()) 94 Expect(fw.AsKubeAdmin.GitOpsController.DeleteAllGitOpsDeploymentInASpecificNamespace(namespace, 30*time.Second)).To(Succeed()) 95 Expect(fw.SandboxController.DeleteUserSignup(fw.UserName)).NotTo(BeFalse()) 96 } 97 }) 98 99 // Create an application in a specific namespace 100 It("creates an application", func() { 101 GinkgoWriter.Printf("Parallel process %d\n", GinkgoParallelProcess()) 102 createdApplication, err := fw.AsKubeDeveloper.HasController.CreateHasApplication(appTest.ApplicationName, namespace) 103 Expect(err).NotTo(HaveOccurred()) 104 Expect(createdApplication.Spec.DisplayName).To(Equal(appTest.ApplicationName)) 105 Expect(createdApplication.Namespace).To(Equal(namespace)) 106 }) 107 108 // Check the application health and check if a devfile was generated in the status 109 It("checks if application is healthy", func() { 110 Eventually(func() string { 111 appstudioApp, err := fw.AsKubeDeveloper.HasController.GetHasApplication(appTest.ApplicationName, namespace) 112 Expect(err).NotTo(HaveOccurred()) 113 application = appstudioApp 114 115 return application.Status.Devfile 116 }, 3*time.Minute, 100*time.Millisecond).Should(Not(BeEmpty()), "Error creating gitOps repository") 117 118 Eventually(func() bool { 119 gitOpsRepository := utils.ObtainGitOpsRepositoryName(application.Status.Devfile) 120 121 return fw.AsKubeDeveloper.CommonController.Github.CheckIfRepositoryExist(gitOpsRepository) 122 }, 5*time.Minute, 1*time.Second).Should(BeTrue(), "Has controller didn't create gitops repository") 123 }) 124 125 // Create an environment in a specific namespace 126 It("creates an environment", func() { 127 env, err = fw.AsKubeDeveloper.IntegrationController.CreateEnvironment(namespace, EnvironmentName) 128 Expect(err).NotTo(HaveOccurred()) 129 }) 130 131 for _, componentTest := range appTest.Components { 132 componentTest := componentTest 133 cdq := &appservice.ComponentDetectionQuery{} 134 if componentTest.Type == "private" { 135 It("injects manually SPI token", func() { 136 // Inject spi tokens to work with private components 137 if componentTest.ContainerSource != "" { 138 // More info about manual token upload for quay.io here: https://github.com/redhat-appstudio/service-provider-integration-operator/pull/115 139 oauthCredentials := `{"access_token":"` + utils.GetEnv(constants.QUAY_OAUTH_TOKEN_ENV, "") + `", "username":"` + utils.GetEnv(constants.QUAY_OAUTH_USER_ENV, "") + `"}` 140 141 _ = fw.AsKubeAdmin.SPIController.InjectManualSPIToken(namespace, componentTest.ContainerSource, oauthCredentials, v1.SecretTypeDockerConfigJson, SPIQuaySecretName) 142 } 143 }) 144 } 145 146 It("creates componentdetectionquery", func() { 147 if componentTest.Type == "private" { 148 cdq, err = fw.AsKubeDeveloper.HasController.CreateComponentDetectionQuery(componentTest.Name, namespace, componentTest.GitSourceUrl, componentTest.GitSourceRevision, componentTest.GitSourceContext, SPIGithubSecretName, false) 149 Expect(err).NotTo(HaveOccurred()) 150 Expect(len(cdq.Status.ComponentDetected)).To(Equal(1), "Expected length of the detected Components was not 1") 151 152 } else { 153 cdq, err = fw.AsKubeDeveloper.HasController.CreateComponentDetectionQuery(componentTest.Name, namespace, componentTest.GitSourceUrl, componentTest.GitSourceRevision, componentTest.GitSourceContext, "", false) 154 Expect(err).NotTo(HaveOccurred()) 155 Expect(len(cdq.Status.ComponentDetected)).To(Equal(1), "Expected length of the detected Components was not 1") 156 } 157 }) 158 159 // Components for now can be imported from gitUrl, container image or a devfile 160 if componentTest.ContainerSource != "" { 161 It(fmt.Sprintf("creates component %s from %s container source", componentTest.Name, componentTest.Type), func() { 162 component, err = fw.AsKubeDeveloper.HasController.CreateComponent(application.Name, componentTest.Name, namespace, "", "", componentTest.ContainerSource, outputContainerImage, SPIQuaySecretName, true) 163 Expect(err).NotTo(HaveOccurred()) 164 }) 165 } else if componentTest.GitSourceUrl != "" { 166 It(fmt.Sprintf("creates component %s from %s git source %s", componentTest.Name, componentTest.Type, componentTest.GitSourceUrl), func() { 167 for _, compDetected := range cdq.Status.ComponentDetected { 168 if componentTest.Type == "private" { 169 component, err = fw.AsKubeDeveloper.HasController.CreateComponentFromStub(compDetected, namespace, "", SPIGithubSecretName, appTest.ApplicationName) 170 Expect(err).NotTo(HaveOccurred()) 171 } else if componentTest.Type == "public" { 172 component, err = fw.AsKubeDeveloper.HasController.CreateComponentFromStub(compDetected, namespace, "", "", appTest.ApplicationName) 173 Expect(err).NotTo(HaveOccurred()) 174 } 175 } 176 }) 177 178 } else { 179 defer GinkgoRecover() 180 Fail("Please Provide a valid test sample") 181 } 182 183 // Start to watch the pipeline until is finished 184 It(fmt.Sprintf("waits %s component %s pipeline to be finished", componentTest.Type, componentTest.Name), func() { 185 if componentTest.ContainerSource != "" { 186 Skip(fmt.Sprintf("component %s was imported from quay.io/docker.io source. Skipping pipelinerun check.", componentTest.Name)) 187 } 188 component, err = fw.AsKubeAdmin.HasController.GetHasComponent(component.Name, namespace) 189 Expect(err).ShouldNot(HaveOccurred(), "failed to get component: %v", err) 190 191 Expect(fw.AsKubeAdmin.HasController.WaitForComponentPipelineToBeFinished(component, "", 2)).To(Succeed()) 192 }) 193 194 It("finds the snapshot and checks if it is marked as successful", func() { 195 timeout = time.Second * 600 196 interval = time.Second * 10 197 198 Eventually(func() bool { 199 snapshot, err = fw.AsKubeAdmin.IntegrationController.GetSnapshot("", "", component.Name, namespace) 200 if err != nil { 201 GinkgoWriter.Println("snapshot has not been found yet") 202 return false 203 } 204 return fw.AsKubeAdmin.IntegrationController.HaveTestsSucceeded(snapshot) 205 206 }, timeout, interval).Should(BeTrue(), fmt.Sprintf("time out when trying to check if the snapshot %s is marked as successful", snapshot.Name)) 207 }) 208 209 It("checks if a snapshot environment binding is created successfully", func() { 210 Eventually(func() bool { 211 if fw.AsKubeAdmin.IntegrationController.HaveTestsSucceeded(snapshot) { 212 envbinding, err := fw.AsKubeAdmin.IntegrationController.GetSnapshotEnvironmentBinding(application.Name, namespace, env) 213 if err != nil { 214 GinkgoWriter.Println("SnapshotEnvironmentBinding has not been found yet") 215 return false 216 } 217 GinkgoWriter.Printf("The SnapshotEnvironmentBinding %s is created\n", envbinding.Name) 218 return true 219 } 220 return false 221 }, timeout, interval).Should(BeTrue(), fmt.Sprintf("time out when trying to check if SnapshotEnvironmentBinding is created (snapshot: %s, env: %s)", snapshot.Name, env.Name)) 222 }) 223 224 // Deploy the component using gitops 225 It(fmt.Sprintf("deploys component %s using gitops", component.Name), func() { 226 if componentTest.SkipDeploymentCheck { 227 Skip("component deployment skipped.") 228 } 229 var deployment *appsv1.Deployment 230 Eventually(func() bool { 231 deployment, err = fw.AsKubeDeveloper.CommonController.GetDeployment(component.Name, namespace) 232 return err == nil 233 }, 25*time.Minute, 10*time.Second).Should(BeTrue(), fmt.Sprintf("Component deployment did not exist: %+v", deployment)) 234 Expect(err).NotTo(HaveOccurred()) 235 }) 236 237 // Check for the health of the deployed component 238 It(fmt.Sprintf("deployed component %s becomes ready", component.Name), func() { 239 if componentTest.SkipDeploymentCheck { 240 Skip("component deployment skipped.") 241 } 242 var deployment *appsv1.Deployment 243 Eventually(func() bool { 244 deployment, err = fw.AsKubeDeveloper.CommonController.GetDeployment(component.Name, namespace) 245 if err != nil && !errors.IsNotFound(err) { 246 return false 247 } 248 if deployment.Status.AvailableReplicas == 1 { 249 GinkgoWriter.Printf("Deployment %s is ready\n", deployment.Name) 250 return true 251 } 252 253 return false 254 }, 25*time.Minute, 10*time.Second).Should(BeTrue(), fmt.Sprintf("Component deployment didn't become ready: %+v", deployment)) 255 Expect(err).NotTo(HaveOccurred()) 256 }) 257 258 It(fmt.Sprintf("checks if component %s health", component.Name), func() { 259 if componentTest.SkipDeploymentCheck { 260 Skip("component deployment skipped.") 261 } 262 Eventually(func() bool { 263 gitOpsRoute, err := fw.AsKubeDeveloper.CommonController.GetOpenshiftRouteByComponentName(component.Name, namespace) 264 Expect(err).NotTo(HaveOccurred()) 265 err = fw.AsKubeDeveloper.GitOpsController.CheckGitOpsEndpoint(gitOpsRoute, componentTest.HealthEndpoint) 266 if err != nil { 267 GinkgoWriter.Printf("Failed to request component endpoint: %+v\n retrying...\n", err) 268 } 269 return true 270 }, 5*time.Minute, 10*time.Second).Should(BeTrue()) 271 }) 272 273 if componentTest.K8sSpec != (e2eConfig.K8sSpec{}) && componentTest.K8sSpec.Replicas > 1 { 274 It(fmt.Sprintf("scales component %s replicas", component.Name), Pending, func() { 275 component, err := fw.AsKubeDeveloper.HasController.GetHasComponent(component.Name, namespace) 276 Expect(err).NotTo(HaveOccurred()) 277 _, err = fw.AsKubeDeveloper.HasController.ScaleComponentReplicas(component, pointer.Int(componentTest.K8sSpec.Replicas)) 278 Expect(err).NotTo(HaveOccurred()) 279 280 Eventually(func() bool { 281 deployment, _ := fw.AsKubeDeveloper.CommonController.GetDeployment(component.Name, namespace) 282 if err != nil && !errors.IsNotFound(err) { 283 return false 284 } 285 if int(deployment.Status.AvailableReplicas) == componentTest.K8sSpec.Replicas { 286 GinkgoWriter.Printf("Replicas scaled to %s\n", componentTest.K8sSpec.Replicas) 287 return true 288 } 289 290 return false 291 }, 5*time.Minute, 10*time.Second).Should(BeTrue(), "Component deployment didn't get scaled to desired replicas") 292 Expect(err).NotTo(HaveOccurred()) 293 }) 294 } 295 } 296 }) 297 } 298 })