github.com/redhat-appstudio/e2e-tests@v0.0.0-20240520140907-9709f6f59323/tests/integration-service/integration.go (about)

     1  package integration
     2  
     3  import (
     4  	"fmt"
     5  	"time"
     6  
     7  	"github.com/konflux-ci/operator-toolkit/metadata"
     8  
     9  	"github.com/devfile/library/v2/pkg/util"
    10  	"github.com/redhat-appstudio/e2e-tests/pkg/clients/has"
    11  	"github.com/redhat-appstudio/e2e-tests/pkg/framework"
    12  	"github.com/redhat-appstudio/e2e-tests/pkg/utils"
    13  	pipeline "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
    14  	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
    15  
    16  	integrationv1beta1 "github.com/konflux-ci/integration-service/api/v1beta1"
    17  	intgteststat "github.com/konflux-ci/integration-service/pkg/integrationteststatus"
    18  
    19  	appstudioApi "github.com/redhat-appstudio/application-api/api/v1alpha1"
    20  
    21  	. "github.com/onsi/ginkgo/v2"
    22  	. "github.com/onsi/gomega"
    23  )
    24  
    25  var _ = framework.IntegrationServiceSuiteDescribe("Integration Service E2E tests", Label("integration-service", "HACBS"), func() {
    26  	defer GinkgoRecover()
    27  
    28  	var f *framework.Framework
    29  	var err error
    30  
    31  	var applicationName, componentName, testNamespace string
    32  	var integrationTestScenario *integrationv1beta1.IntegrationTestScenario
    33  	var newIntegrationTestScenario *integrationv1beta1.IntegrationTestScenario
    34  	var timeout, interval time.Duration
    35  	var originalComponent *appstudioApi.Component
    36  	var pipelineRun *pipeline.PipelineRun
    37  	var snapshot *appstudioApi.Snapshot
    38  	var snapshotPush *appstudioApi.Snapshot
    39  	AfterEach(framework.ReportFailure(&f))
    40  
    41  	Describe("with happy path for general flow of Integration service", Ordered, func() {
    42  		BeforeAll(func() {
    43  			// Initialize the tests controllers
    44  			f, err = framework.NewFramework(utils.GetGeneratedNamespace("integration1"))
    45  			Expect(err).NotTo(HaveOccurred())
    46  			testNamespace = f.UserNamespace
    47  
    48  			applicationName = createApp(*f, testNamespace)
    49  			componentName, originalComponent = createComponent(*f, testNamespace, applicationName)
    50  			integrationTestScenario, err = f.AsKubeAdmin.IntegrationController.CreateIntegrationTestScenario("", applicationName, testNamespace, gitURL, revision, pathInRepoPass)
    51  			Expect(err).ShouldNot(HaveOccurred())
    52  		})
    53  
    54  		AfterAll(func() {
    55  			if !CurrentSpecReport().Failed() {
    56  				cleanup(*f, testNamespace, applicationName, componentName)
    57  
    58  				Expect(f.AsKubeAdmin.IntegrationController.DeleteSnapshot(snapshotPush, testNamespace)).To(Succeed())
    59  			}
    60  		})
    61  
    62  		When("a new Component is created", func() {
    63  			It("triggers a build PipelineRun", Label("integration-service"), func() {
    64  				pipelineRun, err = f.AsKubeDeveloper.IntegrationController.GetBuildPipelineRun(componentName, applicationName, testNamespace, false, "")
    65  				Expect(err).ShouldNot(HaveOccurred())
    66  			})
    67  
    68  			It("verifies if the build PipelineRun contains the finalizer", Label("integration-service"), func() {
    69  				Eventually(func() error {
    70  					pipelineRun, err = f.AsKubeDeveloper.IntegrationController.GetBuildPipelineRun(componentName, applicationName, testNamespace, false, "")
    71  					Expect(err).ShouldNot(HaveOccurred())
    72  					if !controllerutil.ContainsFinalizer(pipelineRun, pipelinerunFinalizerByIntegrationService) {
    73  						return fmt.Errorf("build pipelineRun %s/%s doesn't contain the finalizer: %s yet", pipelineRun.GetNamespace(), pipelineRun.GetName(), pipelinerunFinalizerByIntegrationService)
    74  					}
    75  					return nil
    76  				}, 1*time.Minute, 1*time.Second).Should(Succeed(), "timeout when waiting for finalizer to be added")
    77  			})
    78  
    79  			It("waits for build PipelineRun to succeed", Label("integration-service"), func() {
    80  				Expect(pipelineRun.Annotations[snapshotAnnotation]).To(Equal(""))
    81  				Expect(f.AsKubeDeveloper.HasController.WaitForComponentPipelineToBeFinished(originalComponent, "",
    82  					f.AsKubeAdmin.TektonController, &has.RetryOptions{Retries: 2, Always: true}, pipelineRun)).To(Succeed())
    83  			})
    84  		})
    85  
    86  		When("the build pipelineRun run succeeded", func() {
    87  			It("checks if the BuildPipelineRun have the annotation of chains signed", func() {
    88  				Expect(f.AsKubeDeveloper.IntegrationController.WaitForBuildPipelineRunToGetAnnotated(testNamespace, applicationName, componentName, chainsSignedAnnotation)).To(Succeed())
    89  			})
    90  
    91  			It("checks if the Snapshot is created", func() {
    92  				snapshot, err = f.AsKubeDeveloper.IntegrationController.WaitForSnapshotToGetCreated("", "", componentName, testNamespace)
    93  				Expect(err).ShouldNot(HaveOccurred())
    94  			})
    95  
    96  			It("checks if the Build PipelineRun got annotated with Snapshot name", func() {
    97  				Expect(f.AsKubeDeveloper.IntegrationController.WaitForBuildPipelineRunToGetAnnotated(testNamespace, applicationName, componentName, snapshotAnnotation)).To(Succeed())
    98  			})
    99  
   100  			It("verifies that the finalizer has been removed from the build pipelinerun", func() {
   101  				timeout := "60s"
   102  				interval := "1s"
   103  				Eventually(func() error {
   104  					pipelineRun, err = f.AsKubeDeveloper.IntegrationController.GetBuildPipelineRun(componentName, applicationName, testNamespace, false, "")
   105  					Expect(err).ShouldNot(HaveOccurred())
   106  					if controllerutil.ContainsFinalizer(pipelineRun, pipelinerunFinalizerByIntegrationService) {
   107  						return fmt.Errorf("build pipelineRun %s/%s still contains the finalizer: %s", pipelineRun.GetNamespace(), pipelineRun.GetName(), pipelinerunFinalizerByIntegrationService)
   108  					}
   109  					return nil
   110  				}, timeout, interval).Should(Succeed(), "timeout when waiting for finalizer to be removed")
   111  			})
   112  
   113  			It("checks if all of the integrationPipelineRuns passed", Label("slow"), func() {
   114  				Expect(f.AsKubeDeveloper.IntegrationController.WaitForAllIntegrationPipelinesToBeFinished(testNamespace, applicationName, snapshot)).To(Succeed())
   115  			})
   116  
   117  			It("checks if the passed status of integration test is reported in the Snapshot", func() {
   118  				timeout = time.Second * 240
   119  				interval = time.Second * 5
   120  				Eventually(func() error {
   121  					snapshot, err = f.AsKubeAdmin.IntegrationController.GetSnapshot(snapshot.Name, "", "", testNamespace)
   122  					Expect(err).ShouldNot(HaveOccurred())
   123  
   124  					statusDetail, err := f.AsKubeDeveloper.IntegrationController.GetIntegrationTestStatusDetailFromSnapshot(snapshot, integrationTestScenario.Name)
   125  					Expect(err).ToNot(HaveOccurred())
   126  
   127  					if statusDetail.Status != intgteststat.IntegrationTestStatusTestPassed {
   128  						return fmt.Errorf("test status for scenario: %s, doesn't have expected value %s, within the snapshot: %s", integrationTestScenario.Name, intgteststat.IntegrationTestStatusTestPassed, snapshot.Name)
   129  					}
   130  					return nil
   131  				}, timeout, interval).Should(Succeed())
   132  			})
   133  
   134  			It("checks if the finalizer was removed from all of the related Integration pipelineRuns", func() {
   135  				Expect(f.AsKubeDeveloper.IntegrationController.WaitForFinalizerToGetRemovedFromAllIntegrationPipelineRuns(testNamespace, applicationName, snapshot)).To(Succeed())
   136  			})
   137  		})
   138  
   139  		It("creates a ReleasePlan", func() {
   140  			_, err = f.AsKubeAdmin.ReleaseController.CreateReleasePlan(autoReleasePlan, testNamespace, applicationName, targetReleaseNamespace, "", nil)
   141  			Expect(err).ShouldNot(HaveOccurred())
   142  			testScenarios, err := f.AsKubeAdmin.IntegrationController.GetIntegrationTestScenarios(applicationName, testNamespace)
   143  			Expect(err).ShouldNot(HaveOccurred())
   144  			for _, testScenario := range *testScenarios {
   145  				GinkgoWriter.Printf("IntegrationTestScenario %s is found\n", testScenario.Name)
   146  			}
   147  		})
   148  
   149  		It("creates an snapshot of push event", func() {
   150  			sampleImage := "quay.io/redhat-appstudio/sample-image@sha256:841328df1b9f8c4087adbdcfec6cc99ac8308805dea83f6d415d6fb8d40227c1"
   151  			snapshotPush, err = f.AsKubeAdmin.IntegrationController.CreateSnapshotWithImage(componentName, applicationName, testNamespace, sampleImage)
   152  			Expect(err).ShouldNot(HaveOccurred())
   153  		})
   154  
   155  		When("An snapshot of push event is created", func() {
   156  			It("checks if all of the integrationPipelineRuns created by push event passed", Label("slow"), func() {
   157  				Expect(f.AsKubeAdmin.IntegrationController.WaitForAllIntegrationPipelinesToBeFinished(testNamespace, applicationName, snapshotPush)).To(Succeed(), "Error when waiting for one of the integration pipelines to finish in %s namespace", testNamespace)
   158  			})
   159  
   160  			It("checks if the global candidate is updated after push event", func() {
   161  				timeout = time.Second * 600
   162  				interval = time.Second * 10
   163  				Eventually(func() error {
   164  					snapshotPush, err = f.AsKubeAdmin.IntegrationController.GetSnapshot(snapshotPush.Name, "", "", testNamespace)
   165  					Expect(err).ShouldNot(HaveOccurred())
   166  
   167  					if f.AsKubeAdmin.CommonController.HaveTestsSucceeded(snapshotPush) {
   168  						component, err := f.AsKubeAdmin.HasController.GetComponentByApplicationName(applicationName, testNamespace)
   169  						Expect(err).ShouldNot(HaveOccurred())
   170  						Expect(component.Spec.ContainerImage).ToNot(Equal(originalComponent.Spec.ContainerImage))
   171  						return nil
   172  					}
   173  					return fmt.Errorf("tests haven't succeeded yet for snapshot %s/%s", snapshotPush.GetNamespace(), snapshotPush.GetName())
   174  				}, timeout, interval).Should(Succeed(), fmt.Sprintf("time out when waiting for updating the global candidate in %s namespace", testNamespace))
   175  			})
   176  
   177  			It("checks if a Release is created successfully", func() {
   178  				timeout = time.Second * 60
   179  				interval = time.Second * 5
   180  				Eventually(func() error {
   181  					_, err := f.AsKubeAdmin.ReleaseController.GetReleases(testNamespace)
   182  					return err
   183  				}, timeout, interval).Should(Succeed(), fmt.Sprintf("time out when waiting for release created for snapshot %s/%s", snapshotPush.GetNamespace(), snapshotPush.GetName()))
   184  			})
   185  		})
   186  	})
   187  
   188  	Describe("with an integration test fail", Ordered, func() {
   189  		BeforeAll(func() {
   190  			// Initialize the tests controllers
   191  			f, err = framework.NewFramework(utils.GetGeneratedNamespace("integration2"))
   192  			Expect(err).NotTo(HaveOccurred())
   193  			testNamespace = f.UserNamespace
   194  
   195  			applicationName = createApp(*f, testNamespace)
   196  			componentName, originalComponent = createComponent(*f, testNamespace, applicationName)
   197  
   198  			integrationTestScenario, err = f.AsKubeAdmin.IntegrationController.CreateIntegrationTestScenario("", applicationName, testNamespace, gitURL, revision, pathInRepoFail)
   199  			Expect(err).ShouldNot(HaveOccurred())
   200  		})
   201  
   202  		AfterAll(func() {
   203  			if !CurrentSpecReport().Failed() {
   204  				cleanup(*f, testNamespace, applicationName, componentName)
   205  
   206  			}
   207  		})
   208  
   209  		It("triggers a build PipelineRun", Label("integration-service"), func() {
   210  			pipelineRun, err = f.AsKubeDeveloper.IntegrationController.GetBuildPipelineRun(componentName, applicationName, testNamespace, false, "")
   211  			Expect(pipelineRun.Annotations[snapshotAnnotation]).To(Equal(""))
   212  			Expect(f.AsKubeDeveloper.HasController.WaitForComponentPipelineToBeFinished(originalComponent, "", f.AsKubeAdmin.TektonController,
   213  				&has.RetryOptions{Retries: 2, Always: true}, pipelineRun)).To(Succeed())
   214  
   215  		})
   216  
   217  		It("checks if the BuildPipelineRun have the annotation of chains signed", func() {
   218  			Expect(f.AsKubeDeveloper.IntegrationController.WaitForBuildPipelineRunToGetAnnotated(testNamespace, applicationName, componentName, chainsSignedAnnotation)).To(Succeed())
   219  		})
   220  
   221  		It("checks if the Snapshot is created", func() {
   222  			snapshot, err = f.AsKubeDeveloper.IntegrationController.WaitForSnapshotToGetCreated("", pipelineRun.Name, componentName, testNamespace)
   223  			Expect(err).ShouldNot(HaveOccurred())
   224  		})
   225  
   226  		It("checks if the Build PipelineRun got annotated with Snapshot name", func() {
   227  			Expect(f.AsKubeDeveloper.IntegrationController.WaitForBuildPipelineRunToGetAnnotated(testNamespace, applicationName, componentName, snapshotAnnotation)).To(Succeed())
   228  		})
   229  
   230  		It("checks if all of the integrationPipelineRuns finished", Label("slow"), func() {
   231  			Expect(f.AsKubeDeveloper.IntegrationController.WaitForAllIntegrationPipelinesToBeFinished(testNamespace, applicationName, snapshot)).To(Succeed())
   232  		})
   233  
   234  		It("checks if the failed status of integration test is reported in the Snapshot", func() {
   235  			Eventually(func() error {
   236  				snapshot, err = f.AsKubeAdmin.IntegrationController.GetSnapshot(snapshot.Name, "", "", testNamespace)
   237  				Expect(err).ShouldNot(HaveOccurred())
   238  
   239  				statusDetail, err := f.AsKubeDeveloper.IntegrationController.GetIntegrationTestStatusDetailFromSnapshot(snapshot, integrationTestScenario.Name)
   240  				Expect(err).ToNot(HaveOccurred())
   241  
   242  				if statusDetail.Status != intgteststat.IntegrationTestStatusTestFail {
   243  					return fmt.Errorf("test status doesn't have expected value %s", intgteststat.IntegrationTestStatusTestFail)
   244  				}
   245  				return nil
   246  			}, timeout, interval).Should(Succeed())
   247  		})
   248  
   249  		It("checks if snapshot is marked as failed", FlakeAttempts(3), func() {
   250  			snapshot, err = f.AsKubeAdmin.IntegrationController.GetSnapshot(snapshot.Name, "", "", testNamespace)
   251  			Expect(err).ShouldNot(HaveOccurred())
   252  			Expect(f.AsKubeAdmin.CommonController.HaveTestsSucceeded(snapshot)).To(BeFalse(), "expected tests to fail for snapshot %s/%s", snapshot.GetNamespace(), snapshot.GetName())
   253  		})
   254  
   255  		It("checks if the finalizer was removed from all of the related Integration pipelineRuns", func() {
   256  			Expect(f.AsKubeDeveloper.IntegrationController.WaitForFinalizerToGetRemovedFromAllIntegrationPipelineRuns(testNamespace, applicationName, snapshot)).To(Succeed())
   257  		})
   258  
   259  		It("creates a new IntegrationTestScenario", func() {
   260  			newIntegrationTestScenario, err = f.AsKubeAdmin.IntegrationController.CreateIntegrationTestScenario("", applicationName, testNamespace, gitURL, revision, pathInRepoPass)
   261  			Expect(err).ShouldNot(HaveOccurred())
   262  		})
   263  
   264  		It("updates the Snapshot with the re-run label for the new scenario", FlakeAttempts(3), func() {
   265  			updatedSnapshot := snapshot.DeepCopy()
   266  			err := metadata.AddLabels(updatedSnapshot, map[string]string{snapshotRerunLabel: newIntegrationTestScenario.Name})
   267  			Expect(err).ShouldNot(HaveOccurred())
   268  			Expect(f.AsKubeAdmin.IntegrationController.PatchSnapshot(snapshot, updatedSnapshot)).Should(Succeed())
   269  			Expect(metadata.GetLabelsWithPrefix(updatedSnapshot, snapshotRerunLabel)).NotTo(BeEmpty())
   270  		})
   271  
   272  		When("An snapshot is updated with a re-run label for a given scenario", func() {
   273  			It("checks if the new integration pipelineRun started", Label("slow"), func() {
   274  				reRunPipelineRun, err := f.AsKubeDeveloper.IntegrationController.WaitForIntegrationPipelineToGetStarted(newIntegrationTestScenario.Name, snapshot.Name, testNamespace)
   275  				Expect(err).ShouldNot(HaveOccurred())
   276  				Expect(reRunPipelineRun).ShouldNot(BeNil())
   277  			})
   278  
   279  			It("checks if the re-run label was removed from the Snapshot", func() {
   280  				Eventually(func() error {
   281  					snapshot, err = f.AsKubeAdmin.IntegrationController.GetSnapshot(snapshot.Name, "", "", testNamespace)
   282  					if err != nil {
   283  						return fmt.Errorf("encountered error while getting Snapshot %s/%s: %w", snapshot.Name, snapshot.Namespace, err)
   284  					}
   285  
   286  					if metadata.HasLabel(snapshot, snapshotRerunLabel) {
   287  						return fmt.Errorf("the Snapshot %s/%s shouldn't contain the %s label", snapshot.Name, snapshot.Namespace, snapshotRerunLabel)
   288  					}
   289  					return nil
   290  				}, timeout, interval).Should(Succeed())
   291  			})
   292  
   293  			It("checks if all integration pipelineRuns finished successfully", Label("slow"), func() {
   294  				Expect(f.AsKubeDeveloper.IntegrationController.WaitForAllIntegrationPipelinesToBeFinished(testNamespace, applicationName, snapshot)).To(Succeed())
   295  			})
   296  
   297  			It("checks if the name of the re-triggered pipelinerun is reported in the Snapshot", FlakeAttempts(3), func() {
   298  				Eventually(func(g Gomega) {
   299  					snapshot, err = f.AsKubeAdmin.IntegrationController.GetSnapshot(snapshot.Name, "", "", testNamespace)
   300  					g.Expect(err).ShouldNot(HaveOccurred())
   301  
   302  					statusDetail, err := f.AsKubeDeveloper.IntegrationController.GetIntegrationTestStatusDetailFromSnapshot(snapshot, newIntegrationTestScenario.Name)
   303  					g.Expect(err).ToNot(HaveOccurred())
   304  					g.Expect(statusDetail).NotTo(BeNil())
   305  
   306  					integrationPipelineRun, err := f.AsKubeDeveloper.IntegrationController.GetIntegrationPipelineRun(newIntegrationTestScenario.Name, snapshot.Name, testNamespace)
   307  					g.Expect(err).ToNot(HaveOccurred())
   308  					g.Expect(integrationPipelineRun).NotTo(BeNil())
   309  
   310  					g.Expect(statusDetail.TestPipelineRunName).To(Equal(integrationPipelineRun.Name))
   311  				}, timeout, interval).Should(Succeed())
   312  			})
   313  
   314  			It("checks if snapshot is still marked as failed", func() {
   315  				snapshot, err = f.AsKubeAdmin.IntegrationController.GetSnapshot(snapshot.Name, "", "", testNamespace)
   316  				Expect(err).ShouldNot(HaveOccurred())
   317  				Expect(f.AsKubeAdmin.CommonController.HaveTestsSucceeded(snapshot)).To(BeFalse(), "expected tests to fail for snapshot %s/%s", snapshot.GetNamespace(), snapshot.GetName())
   318  			})
   319  
   320  		})
   321  
   322  		It("creates an snapshot of push event", func() {
   323  			sampleImage := "quay.io/redhat-appstudio/sample-image@sha256:841328df1b9f8c4087adbdcfec6cc99ac8308805dea83f6d415d6fb8d40227c1"
   324  			snapshotPush, err = f.AsKubeAdmin.IntegrationController.CreateSnapshotWithImage(componentName, applicationName, testNamespace, sampleImage)
   325  			Expect(err).ShouldNot(HaveOccurred())
   326  		})
   327  
   328  		When("An snapshot of push event is created", func() {
   329  			It("checks no Release CRs are created", func() {
   330  				releases, err := f.AsKubeAdmin.ReleaseController.GetReleases(testNamespace)
   331  				Expect(err).NotTo(HaveOccurred(), "Error when fetching the Releases")
   332  				Expect(releases.Items).To(BeEmpty(), "Expected no Release CRs to be present, but found some")
   333  			})
   334  
   335  			It("checks if the global candidate is not updated", func() {
   336  				// give some time to do eventual updates in component
   337  				time.Sleep(60 * time.Second)
   338  
   339  				component, err := f.AsKubeAdmin.HasController.GetComponentByApplicationName(applicationName, testNamespace)
   340  				Expect(err).ShouldNot(HaveOccurred())
   341  
   342  				// global candidate is not updated
   343  				Expect(component.Spec.ContainerImage).To(Equal(originalComponent.Spec.ContainerImage))
   344  			})
   345  		})
   346  	})
   347  })
   348  
   349  func createApp(f framework.Framework, testNamespace string) string {
   350  	applicationName := fmt.Sprintf("integ-app-%s", util.GenerateRandomString(4))
   351  
   352  	_, err := f.AsKubeAdmin.HasController.CreateApplication(applicationName, testNamespace)
   353  	Expect(err).NotTo(HaveOccurred())
   354  
   355  	return applicationName
   356  }
   357  
   358  func createComponent(f framework.Framework, testNamespace, applicationName string) (string, *appstudioApi.Component) {
   359  	var originalComponent *appstudioApi.Component
   360  
   361  	componentName := fmt.Sprintf("integration-suite-test-component-git-source-%s", util.GenerateRandomString(6))
   362  	// Create a component with Git Source URL being defined
   363  	// using cdq since git ref is not known
   364  	cdq, err := f.AsKubeAdmin.HasController.CreateComponentDetectionQuery(componentName, testNamespace, componentRepoURL, "", "", "", false)
   365  	Expect(err).NotTo(HaveOccurred())
   366  	Expect(cdq.Status.ComponentDetected).To(HaveLen(1), "Expected length of the detected Components was not 1")
   367  
   368  	for _, compDetected := range cdq.Status.ComponentDetected {
   369  		originalComponent, err = f.AsKubeAdmin.HasController.CreateComponent(compDetected.ComponentStub, testNamespace, "", "", applicationName, true, map[string]string{})
   370  		Expect(err).NotTo(HaveOccurred())
   371  		Expect(originalComponent).NotTo(BeNil())
   372  		componentName = originalComponent.Name
   373  	}
   374  
   375  	return componentName, originalComponent
   376  }
   377  
   378  func cleanup(f framework.Framework, testNamespace, applicationName, componentName string) {
   379  	if !CurrentSpecReport().Failed() {
   380  		Expect(f.AsKubeAdmin.HasController.DeleteApplication(applicationName, testNamespace, false)).To(Succeed())
   381  		Expect(f.AsKubeAdmin.HasController.DeleteComponent(componentName, testNamespace, false)).To(Succeed())
   382  		integrationTestScenarios, err := f.AsKubeAdmin.IntegrationController.GetIntegrationTestScenarios(applicationName, testNamespace)
   383  		Expect(err).ShouldNot(HaveOccurred())
   384  
   385  		for _, testScenario := range *integrationTestScenarios {
   386  			Expect(f.AsKubeAdmin.IntegrationController.DeleteIntegrationTestScenario(&testScenario, testNamespace)).To(Succeed())
   387  		}
   388  		Expect(f.SandboxController.DeleteUserSignup(f.UserName)).To(BeTrue())
   389  	}
   390  }