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  })