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 }