github.com/redhat-appstudio/e2e-tests@v0.0.0-20240520140907-9709f6f59323/tests/release/pipelines/fbc_release.go (about)

     1  package pipelines
     2  
     3  import (
     4  	"encoding/json"
     5  	"fmt"
     6  	"time"
     7  
     8  	"github.com/devfile/library/v2/pkg/util"
     9  	ecp "github.com/enterprise-contract/enterprise-contract-controller/api/v1alpha1"
    10  	. "github.com/onsi/ginkgo/v2"
    11  	. "github.com/onsi/gomega"
    12  	appservice "github.com/redhat-appstudio/application-api/api/v1alpha1"
    13  	"github.com/redhat-appstudio/e2e-tests/pkg/clients/has"
    14  	"github.com/redhat-appstudio/e2e-tests/pkg/constants"
    15  	"github.com/redhat-appstudio/e2e-tests/pkg/framework"
    16  	"github.com/redhat-appstudio/e2e-tests/pkg/utils"
    17  	"github.com/redhat-appstudio/e2e-tests/pkg/utils/tekton"
    18  	releasecommon "github.com/redhat-appstudio/e2e-tests/tests/release"
    19  	releaseapi "github.com/redhat-appstudio/release-service/api/v1alpha1"
    20  	tektonutils "github.com/redhat-appstudio/release-service/tekton/utils"
    21  	tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
    22  	"k8s.io/apimachinery/pkg/runtime"
    23  )
    24  
    25  const (
    26  	fbcServiceAccountName   = "release-service-account"
    27  	fbcSourceGitURL         = "https://github.com/redhat-appstudio-qe/fbc-sample-repo"
    28  	targetPort              = 50051
    29  	relSvcCatalogPathInRepo = "pipelines/fbc-release/fbc-release.yaml"
    30  )
    31  
    32  var snapshot *appservice.Snapshot
    33  var releaseCR *releaseapi.Release
    34  var releasePr, buildPr *tektonv1.PipelineRun
    35  var err error
    36  var devWorkspace = utils.GetEnv(constants.RELEASE_DEV_WORKSPACE_ENV, constants.DevReleaseTeam)
    37  var managedWorkspace = utils.GetEnv(constants.RELEASE_MANAGED_WORKSPACE_ENV, constants.ManagedReleaseTeam)
    38  var devFw *framework.Framework
    39  var mFw *framework.Framework
    40  var managedFw *framework.Framework
    41  
    42  var _ = framework.ReleasePipelinesSuiteDescribe("FBC e2e-tests", Label("release-pipelines", "fbc-tests"), func() {
    43  	defer GinkgoRecover()
    44  
    45  	var devNamespace = devWorkspace + "-tenant"
    46  	var managedNamespace = managedWorkspace + "-tenant"
    47  
    48  	var issueId = "bz12345"
    49  	var productName = "preGA-product"
    50  	var productVersion = "v2"
    51  	var fbcApplicationName = "fbc-pipelines-app-" + util.GenerateRandomString(4)
    52  	var fbcHotfixAppName = "fbc-hotfix-app-" + util.GenerateRandomString(4)
    53  	var fbcPreGAAppName = "fbc-prega-app-" + util.GenerateRandomString(4)
    54  	var fbcComponentName = "fbc-pipelines-comp-" + util.GenerateRandomString(4)
    55  	var fbcHotfixCompName = "fbc-hotfix-comp-" + util.GenerateRandomString(4)
    56  	var fbcPreGACompName = "fbc-prega-comp-" + util.GenerateRandomString(4)
    57  	var fbcReleasePlanName = "fbc-pipelines-rp-" + util.GenerateRandomString(4)
    58  	var fbcHotfixRPName = "fbc-hotfix-rp-" + util.GenerateRandomString(4)
    59  	var fbcPreGARPName = "fbc-prega-rp-" + util.GenerateRandomString(4)
    60  	var fbcReleasePlanAdmissionName = "fbc-pipelines-rpa-" + util.GenerateRandomString(4)
    61  	var fbcHotfixRPAName = "fbc-hotfix-rpa-" + util.GenerateRandomString(4)
    62  	var fbcPreGARPAName = "fbc-prega-rpa-" + util.GenerateRandomString(4)
    63  	var fbcEnterpriseContractPolicyName = "fbc-pipelines-policy-" + util.GenerateRandomString(4)
    64  	var fbcHotfixECPolicyName = "fbc-hotfix-policy-" + util.GenerateRandomString(4)
    65  	var fbcPreGAECPolicyName = "fbc-prega-policy-" + util.GenerateRandomString(4)
    66  
    67  	AfterEach(framework.ReportFailure(&devFw))
    68  
    69  	Describe("with FBC happy path", Label("fbcHappyPath"), func() {
    70  		var component *appservice.Component
    71  		BeforeAll(func() {
    72  			devFw = releasecommon.NewFramework(devWorkspace)
    73  			managedFw = releasecommon.NewFramework(managedWorkspace)
    74  
    75  			managedNamespace = managedFw.UserNamespace
    76  
    77  			// Linking the build secret to the pipeline service account in dev namespace.
    78  			err = devFw.AsKubeAdmin.CommonController.LinkSecretToServiceAccount(devNamespace, releasecommon.HacbsReleaseTestsTokenSecret, constants.DefaultPipelineServiceAccount, true)
    79  			Expect(err).ToNot(HaveOccurred())
    80  
    81  			_, err = devFw.AsKubeDeveloper.HasController.CreateApplication(fbcApplicationName, devNamespace)
    82  			Expect(err).NotTo(HaveOccurred())
    83  			GinkgoWriter.Println("Created application :", fbcApplicationName)
    84  
    85  			_, err = devFw.AsKubeDeveloper.ReleaseController.CreateReleasePlan(fbcReleasePlanName, devNamespace, fbcApplicationName, managedNamespace, "true", nil)
    86  			Expect(err).NotTo(HaveOccurred())
    87  
    88  			createFBCReleasePlanAdmission(fbcReleasePlanAdmissionName, *managedFw, devNamespace, managedNamespace, fbcApplicationName, fbcEnterpriseContractPolicyName, relSvcCatalogPathInRepo, "false", "", "", "", "")
    89  			component = releasecommon.CreateComponentByCDQ(*devFw, devNamespace, managedNamespace, fbcApplicationName, fbcComponentName, fbcSourceGitURL)
    90  			createFBCEnterpriseContractPolicy(fbcEnterpriseContractPolicyName, *managedFw, devNamespace, managedNamespace)
    91  
    92  		})
    93  
    94  		AfterAll(func() {
    95  			devFw = releasecommon.NewFramework(devWorkspace)
    96  			managedFw = releasecommon.NewFramework(managedWorkspace)
    97  			Expect(devFw.AsKubeDeveloper.HasController.DeleteApplication(fbcApplicationName, devNamespace, false)).NotTo(HaveOccurred())
    98  			Expect(managedFw.AsKubeDeveloper.TektonController.DeleteEnterpriseContractPolicy(fbcEnterpriseContractPolicyName, managedNamespace, false)).NotTo(HaveOccurred())
    99  			Expect(managedFw.AsKubeDeveloper.ReleaseController.DeleteReleasePlanAdmission(fbcReleasePlanAdmissionName, managedNamespace, false)).NotTo(HaveOccurred())
   100  		})
   101  
   102  		var _ = Describe("Post-release verification", func() {
   103  			It("verifies that a build PipelineRun is created in dev namespace and succeeds", func() {
   104  				assertBuildPipelineRunCreated(*devFw, devNamespace, managedNamespace, fbcApplicationName, component)
   105  			})
   106  
   107  			It("verifies the fbc release pipelinerun is running and succeeds", func() {
   108  				assertReleasePipelineRunSucceeded(*devFw, *managedFw, devNamespace, managedNamespace, fbcApplicationName, component)
   109  			})
   110  
   111  			It("verifies release CR completed and set succeeded.", func() {
   112  				assertReleaseCRSucceeded(*devFw, devNamespace, managedNamespace, fbcApplicationName, component)
   113  			})
   114  		})
   115  	})
   116  
   117  	Describe("with FBC hotfix process", Label("fbcHotfix"), func() {
   118  		var component *appservice.Component
   119  
   120  		BeforeAll(func() {
   121  			devFw = releasecommon.NewFramework(devWorkspace)
   122  			managedFw = releasecommon.NewFramework(managedWorkspace)
   123  
   124  			_, err = devFw.AsKubeDeveloper.HasController.CreateApplication(fbcHotfixAppName, devNamespace)
   125  			Expect(err).NotTo(HaveOccurred())
   126  			GinkgoWriter.Println("Created application :", fbcHotfixAppName)
   127  
   128  			_, err = devFw.AsKubeDeveloper.ReleaseController.CreateReleasePlan(fbcHotfixRPName, devNamespace, fbcHotfixAppName, managedNamespace, "true", nil)
   129  			Expect(err).NotTo(HaveOccurred())
   130  
   131  			createFBCReleasePlanAdmission(fbcHotfixRPAName, *managedFw, devNamespace, managedNamespace, fbcHotfixAppName, fbcHotfixECPolicyName, relSvcCatalogPathInRepo, "true", issueId, "false", "", "")
   132  			component = releasecommon.CreateComponentByCDQ(*devFw, devNamespace, managedNamespace, fbcHotfixAppName, fbcHotfixCompName, fbcSourceGitURL)
   133  			createFBCEnterpriseContractPolicy(fbcHotfixECPolicyName, *managedFw, devNamespace, managedNamespace)
   134  		})
   135  
   136  		AfterAll(func() {
   137  			devFw = releasecommon.NewFramework(devWorkspace)
   138  			managedFw = releasecommon.NewFramework(managedWorkspace)
   139  			Expect(devFw.AsKubeDeveloper.HasController.DeleteApplication(fbcHotfixAppName, devNamespace, false)).NotTo(HaveOccurred())
   140  			Expect(managedFw.AsKubeDeveloper.TektonController.DeleteEnterpriseContractPolicy(fbcHotfixECPolicyName, managedNamespace, false)).NotTo(HaveOccurred())
   141  			Expect(managedFw.AsKubeDeveloper.ReleaseController.DeleteReleasePlanAdmission(fbcHotfixRPAName, managedNamespace, false)).NotTo(HaveOccurred())
   142  		})
   143  
   144  		var _ = Describe("FBC hotfix post-release verification", func() {
   145  			It("verifies that a build PipelineRun is created in dev namespace and succeeds", func() {
   146  				assertBuildPipelineRunCreated(*devFw, devNamespace, managedNamespace, fbcHotfixAppName, component)
   147  			})
   148  
   149  			It("verifies the fbc release pipelinerun is running and succeeds", func() {
   150  				assertReleasePipelineRunSucceeded(*devFw, *managedFw, devNamespace, managedNamespace, fbcHotfixAppName, component)
   151  			})
   152  
   153  			It("verifies release CR completed and set succeeded.", func() {
   154  				assertReleaseCRSucceeded(*devFw, devNamespace, managedNamespace, fbcHotfixAppName, component)
   155  			})
   156  		})
   157  	})
   158  
   159  	Describe("with FBC pre-GA process", Label("fbcPreGA"), func() {
   160  		var component *appservice.Component
   161  
   162  		BeforeAll(func() {
   163  			devFw = releasecommon.NewFramework(devWorkspace)
   164  			managedFw = releasecommon.NewFramework(managedWorkspace)
   165  
   166  			_, err = devFw.AsKubeDeveloper.HasController.CreateApplication(fbcPreGAAppName, devNamespace)
   167  			Expect(err).NotTo(HaveOccurred())
   168  			GinkgoWriter.Println("Created application :", fbcPreGAAppName)
   169  
   170  			_, err = devFw.AsKubeDeveloper.ReleaseController.CreateReleasePlan(fbcPreGARPName, devNamespace, fbcPreGAAppName, managedNamespace, "true", nil)
   171  			Expect(err).NotTo(HaveOccurred())
   172  
   173  			createFBCReleasePlanAdmission(fbcPreGARPAName, *managedFw, devNamespace, managedNamespace, fbcPreGAAppName, fbcPreGAECPolicyName, relSvcCatalogPathInRepo, "false", issueId, "true", productName, productVersion)
   174  			component = releasecommon.CreateComponentByCDQ(*devFw, devNamespace, managedNamespace, fbcPreGAAppName, fbcPreGACompName, fbcSourceGitURL)
   175  			createFBCEnterpriseContractPolicy(fbcPreGAECPolicyName, *managedFw, devNamespace, managedNamespace)
   176  		})
   177  
   178  		AfterAll(func() {
   179  			devFw = releasecommon.NewFramework(devWorkspace)
   180  			managedFw = releasecommon.NewFramework(managedWorkspace)
   181  			if !CurrentSpecReport().Failed() {
   182  				Expect(devFw.AsKubeDeveloper.HasController.DeleteApplication(fbcPreGAAppName, devNamespace, false)).NotTo(HaveOccurred())
   183  				Expect(managedFw.AsKubeDeveloper.TektonController.DeleteEnterpriseContractPolicy(fbcPreGAECPolicyName, managedNamespace, false)).NotTo(HaveOccurred())
   184  				Expect(managedFw.AsKubeDeveloper.ReleaseController.DeleteReleasePlanAdmission(fbcPreGARPAName, managedNamespace, false)).NotTo(HaveOccurred())
   185  			}
   186  		})
   187  
   188  		var _ = Describe("FBC pre-GA post-release verification", func() {
   189  			It("verifies that a build PipelineRun is created in dev namespace and succeeds", func() {
   190  				assertBuildPipelineRunCreated(*devFw, devNamespace, managedNamespace, fbcPreGAAppName, component)
   191  			})
   192  
   193  			It("verifies the fbc release pipelinerun is running and succeeds", func() {
   194  				assertReleasePipelineRunSucceeded(*devFw, *managedFw, devNamespace, managedNamespace, fbcPreGAAppName, component)
   195  			})
   196  
   197  			It("verifies release CR completed and set succeeded.", func() {
   198  				assertReleaseCRSucceeded(*devFw, devNamespace, managedNamespace, fbcPreGAAppName, component)
   199  			})
   200  		})
   201  	})
   202  })
   203  
   204  func assertBuildPipelineRunCreated(devFw framework.Framework, devNamespace, managedNamespace, fbcAppName string, component *appservice.Component) {
   205  	dFw := releasecommon.NewFramework(devWorkspace)
   206  	devFw = *dFw
   207  	// Create a ticker that ticks every 3 minutes
   208  	ticker := time.NewTicker(3 * time.Minute)
   209  	// Schedule the stop of the ticker after 10 minutes
   210  	time.AfterFunc(10*time.Minute, func() {
   211  		ticker.Stop()
   212  		fmt.Println("Stopped executing every 3 minutes.")
   213  	})
   214  	// Run a goroutine to handle the ticker ticks
   215  	go func() {
   216  		for range ticker.C {
   217  			dFw = releasecommon.NewFramework(devWorkspace)
   218  			devFw = *dFw
   219  		}
   220  	}()
   221  	Expect(devFw.AsKubeDeveloper.HasController.WaitForComponentPipelineToBeFinished(component, "", devFw.AsKubeDeveloper.TektonController, &has.RetryOptions{Retries: 3, Always: true}, nil)).To(Succeed())
   222  	buildPr, err = devFw.AsKubeDeveloper.HasController.GetComponentPipelineRun(component.Name, fbcAppName, devNamespace, "")
   223  	Expect(err).ShouldNot(HaveOccurred())
   224  }
   225  
   226  func assertReleasePipelineRunSucceeded(devFw, managedFw framework.Framework, devNamespace, managedNamespace, fbcAppName string, component *appservice.Component) {
   227  	Eventually(func() error {
   228  		snapshot, err = devFw.AsKubeDeveloper.IntegrationController.GetSnapshot("", buildPr.Name, "", devNamespace)
   229  		if err != nil {
   230  			return err
   231  		}
   232  		GinkgoWriter.Println("snapshot: ", snapshot.Name)
   233  		releaseCR, err = devFw.AsKubeDeveloper.ReleaseController.GetRelease("", snapshot.Name, devNamespace)
   234  		if err != nil {
   235  			return err
   236  		}
   237  		GinkgoWriter.Println("Release CR: ", releaseCR.Name)
   238  		return nil
   239  	}, 5*time.Minute, releasecommon.DefaultInterval).Should(Succeed(), "timed out when waiting for Snapshot and Release being created")
   240  
   241  	mFw = releasecommon.NewFramework(managedWorkspace)
   242  	// Create a ticker that ticks every 3 minutes
   243  	ticker := time.NewTicker(3 * time.Minute)
   244  	// Schedule the stop of the ticker after 15 minutes
   245  	time.AfterFunc(15*time.Minute, func() {
   246  		ticker.Stop()
   247  		fmt.Println("Stopped executing every 3 minutes.")
   248  	})
   249  	// Run a goroutine to handle the ticker ticks
   250  	go func() {
   251  		for range ticker.C {
   252  			mFw = releasecommon.NewFramework(managedWorkspace)
   253  		}
   254  	}()
   255  
   256  	Eventually(func() error {
   257  		releasePr, err = mFw.AsKubeAdmin.ReleaseController.GetPipelineRunInNamespace(mFw.UserNamespace, releaseCR.GetName(), releaseCR.GetNamespace())
   258  		if err != nil {
   259  			return err
   260  		}
   261  		Expect(err).ShouldNot(HaveOccurred())
   262  		GinkgoWriter.Println("Release PR: ", releasePr.Name)
   263  
   264  		if !releasePr.IsDone() {
   265  			return fmt.Errorf("release pipelinerun %s in namespace %s did not finish yet", releasePr.Name, releasePr.Namespace)
   266  		}
   267  		Expect(tekton.HasPipelineRunSucceeded(releasePr)).To(BeTrue(), fmt.Sprintf("release pipelinerun %s/%s did not succeed", releasePr.GetNamespace(), releasePr.GetName()))
   268  		GinkgoWriter.Println("Release PR succeeded")
   269  		return nil
   270  	}, releasecommon.ReleasePipelineRunCompletionTimeout, releasecommon.DefaultInterval).Should(Succeed(), "timed out when waiting for release pipelinerun to succeed")
   271  }
   272  
   273  func assertReleaseCRSucceeded(devFw framework.Framework, devNamespace, managedNamespace, fbcAppName string, component *appservice.Component) {
   274  	dFw := releasecommon.NewFramework(devWorkspace)
   275  	Eventually(func() error {
   276  		releaseCR, err = dFw.AsKubeDeveloper.ReleaseController.GetRelease("", snapshot.Name, devNamespace)
   277  		if err != nil {
   278  			return err
   279  		}
   280  		conditions := releaseCR.Status.Conditions
   281  		if len(conditions) > 0 {
   282  			for _, c := range conditions {
   283  				if c.Type == "Released" && c.Status == "True" {
   284  					GinkgoWriter.Println("Release CR is released")
   285  				}
   286  			}
   287  		}
   288  
   289  		if !releaseCR.IsReleased() {
   290  			return fmt.Errorf("release %s/%s is not marked as finished yet", releaseCR.GetNamespace(), releaseCR.GetName())
   291  		}
   292  		return nil
   293  	}, releasecommon.ReleaseCreationTimeout, releasecommon.DefaultInterval).Should(Succeed())
   294  }
   295  
   296  func createFBCEnterpriseContractPolicy(fbcECPName string, managedFw framework.Framework, devNamespace, managedNamespace string) {
   297  	defaultEcPolicySpec := ecp.EnterpriseContractPolicySpec{
   298  		Description: "Red Hat's enterprise requirements",
   299  		PublicKey:   "k8s://openshift-pipelines/public-key",
   300  		Sources: []ecp.Source{{
   301  			Name:   "Default",
   302  			Policy: []string{releasecommon.EcPolicyLibPath, releasecommon.EcPolicyReleasePath},
   303  			Data:   []string{releasecommon.EcPolicyDataBundle, releasecommon.EcPolicyDataPath},
   304  		}},
   305  		Configuration: &ecp.EnterpriseContractPolicyConfiguration{
   306  			Exclude: []string{"cve", "step_image_registries", "tasks.required_tasks_found:prefetch-dependencies"},
   307  			Include: []string{"minimal", "slsa3"},
   308  		},
   309  	}
   310  
   311  	_, err := managedFw.AsKubeDeveloper.TektonController.CreateEnterpriseContractPolicy(fbcECPName, managedNamespace, defaultEcPolicySpec)
   312  	Expect(err).NotTo(HaveOccurred())
   313  
   314  }
   315  
   316  func createFBCReleasePlanAdmission(fbcRPAName string, managedFw framework.Framework, devNamespace, managedNamespace, fbcAppName, fbcECPName, pathInRepoValue, hotfix, issueId, preGA, productName, productVersion string) {
   317  	var err error
   318  	data, err := json.Marshal(map[string]interface{}{
   319  		"fbc": map[string]interface{}{
   320  			"fromIndex":                       constants.FromIndex,
   321  			"targetIndex":                     constants.TargetIndex,
   322  			"binaryImage":                     constants.BinaryImage,
   323  			"publishingCredentials":           "fbc-preview-publishing-credentials",
   324  			"iibServiceConfigSecret":          "iib-preview-services-config",
   325  			"iibOverwriteFromIndexCredential": "iib-overwrite-fromimage-credentials",
   326  			"requestUpdateTimeout":            "1500",
   327  			"buildTimeoutSeconds":             "1500",
   328  			"hotfix":                          hotfix,
   329  			"issueId":                         issueId,
   330  			"preGA":                           preGA,
   331  			"productName":                     productName,
   332  			"productVersion":                  productVersion,
   333  			"allowedPackages":                 []string{"example-operator"},
   334  		},
   335  		"sign": map[string]interface{}{
   336  			"configMapName": "hacbs-signing-pipeline-config-redhatbeta2",
   337  		},
   338  	})
   339  	Expect(err).NotTo(HaveOccurred())
   340  
   341  	_, err = managedFw.AsKubeAdmin.ReleaseController.CreateReleasePlanAdmission(fbcRPAName, managedNamespace, "", devNamespace, fbcECPName, fbcServiceAccountName, []string{fbcAppName}, true, &tektonutils.PipelineRef{
   342  		Resolver: "git",
   343  		Params: []tektonutils.Param{
   344  			{Name: "url", Value: releasecommon.RelSvcCatalogURL},
   345  			{Name: "revision", Value: releasecommon.RelSvcCatalogRevision},
   346  			{Name: "pathInRepo", Value: pathInRepoValue},
   347  		},
   348  	}, &runtime.RawExtension{
   349  		Raw: data,
   350  	})
   351  	Expect(err).NotTo(HaveOccurred())
   352  }