Skip to content

Commit

Permalink
feat(RELEASE-1043): add e2e test for rhel-ai pipeline
Browse files Browse the repository at this point in the history
Signed-off-by: Jing Qi <[email protected]>
  • Loading branch information
jinqi7 committed Sep 12, 2024
1 parent cfef6ad commit e50f123
Show file tree
Hide file tree
Showing 4 changed files with 324 additions and 0 deletions.
1 change: 1 addition & 0 deletions pkg/clients/release/plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"strconv"

tektonutils "github.com/konflux-ci/release-service/tekton/utils"
tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"

Check failure on line 8 in pkg/clients/release/plans.go

View workflow job for this annotation

GitHub Actions / Unit tests

"github.com/tektoncd/pipeline/pkg/apis/pipeline/v1" imported as tektonv1 and not used
"k8s.io/apimachinery/pkg/runtime"

releaseApi "github.com/konflux-ci/release-service/api/v1alpha1"
Expand Down
48 changes: 48 additions & 0 deletions pkg/constants/constants.go
Original file line number Diff line number Diff line change
Expand Up @@ -79,6 +79,54 @@ const (
// Toolchain API URL used for authentication against stage/prod cluster
TOOLCHAIN_API_URL_ENV = "TOOLCHAIN_API_URL"

// Key auth for accessing exodus prod
EXODUS_PROD_KEY_ENV string = "EXODUS_PROD_KEY"

// Cert auth for accessing exodus prod
EXODUS_PROD_CERT_ENV string = "EXODUS_PROD_CERT"

// Key auth for accessing exodus stage
EXODUS_STAGE_KEY_ENV string = "EXODUS_STAGE_KEY"

// Cert auth for accessing exodus stage
EXODUS_STAGE_CERT_ENV string = "EXODUS_STAGE_CERT"

// URL for accessing exodus stage
EXODUS_STAGE_URL_ENV string = "EXODUS_STAGE_URL"

// Key auth for udccache qa
UDCCACHE_QA_KEY_ENV string = "UDCCACHE_QA_KEY"

// Cert auth for udccache qa
UDCCACHE_QA_CERT_ENV string = "UDCCACHE_QA_CERT"

// URL for udccache qa
UDCCACHE_QA_URL_ENV string = "UDCCACHE_QA_URL"

// Key auth for pulp qa
PULP_QA_KEY_ENV string = "UDCCACHE_QA_KEY"

// Cert auth for pulp qa
PULP_QA_CERT_ENV string = "UDCCACHE_QA_CERT"

// URL for pulp qa
PULP_QA_URL_ENV string = "UDCCACHE_QA_URL"

// Content GateWay username
CGW_USERNAME_ENV string = "CGW_USERNAME"

// Content GateWay token
CGW_TOKEN_ENV string = "CGW_TOKEN"

// Pulp Stage key
PULP_STAGE_KEY_ENV = "PULP_STAGE_KEY"

// Pulp Stage cert
PULP_STAGE_CERT_ENV = "PULP_STAGE_CERT"

// Pulp Stage URL
PULP_STAGT_URL_ENV = "PULP_STAGT_URL"

// Dev workspace for release pipelines tests
RELEASE_DEV_WORKSPACE_ENV = "RELEASE_DEV_WORKSPACE"

Expand Down
11 changes: 11 additions & 0 deletions tests/release/const.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,17 @@ const (
HacbsReleaseTestsTokenSecret string = "redhat-appstudio-registry-pull-secret"
PublicSecretNameAuth string = "cosign-public-key"
ReleasePipelineServiceAccountDefault string = "release-service-account"
ExodusProdSecretName string = "exodus-prod-secret"
ExodusStageSecretName string = "exodus-stage-secret"
RHSMPulpStageSecretName string = "rhsm-pulp-stage-secret"
RHSMPulpProdSecretName string = "rhsm-pulp-prod-secret"
RHSMPulpQaSecretName string = "rhsm-pulp-qa-secret"
UdcacheProdSecretName string = "udcache-prod-secret"
UdcacheStageSecretName string = "udcache-stage-secret"
UdcacheQaSecretName string = "udcache-qa-secret"
CgwStageSecretName string = "cgw-service-account-stage-secret"
CgwProdSecretName string = "cgw-service-account-prod-secret"
CgwSecretName string = "publish-to-cgw-secret"

SourceReleasePlanName string = "source-releaseplan"
SecondReleasePlanName string = "the-second-releaseplan"
Expand Down
264 changes: 264 additions & 0 deletions tests/release/pipelines/push_disk_images_to_cdn.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,264 @@
package pipelines

import (
"encoding/json"
"fmt"
"time"

"github.com/devfile/library/v2/pkg/util"
ecp "github.com/enterprise-contract/enterprise-contract-controller/api/v1alpha1"
appservice "github.com/konflux-ci/application-api/api/v1alpha1"
"github.com/konflux-ci/e2e-tests/pkg/constants"
"github.com/konflux-ci/e2e-tests/pkg/framework"
"github.com/konflux-ci/e2e-tests/pkg/utils"
"github.com/konflux-ci/e2e-tests/pkg/utils/tekton"
releasecommon "github.com/konflux-ci/e2e-tests/tests/release"
releaseapi "github.com/konflux-ci/release-service/api/v1alpha1"
tektonutils "github.com/konflux-ci/release-service/tekton/utils"
. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
"k8s.io/apimachinery/pkg/runtime"
"knative.dev/pkg/apis"
)

const (
rhaiServiceAccountName = "release-service-account"
rhaiCatalogPathInRepo = "pipelines/push-disk-images-to-cdn/push-disk-images-to-cdn.yaml"
rhaiGitSourceURL = "https://gitlab.com/redhat/rhel-ai/disk-images/nvidia-bootc"
rhaiGitSrcSHA = "5b0ad5399cac20d8d7e321566a3ac3baa82ff91f"
)

var rhaiComponentName = "rhai-comp-" + util.GenerateRandomString(4)

var _ = framework.ReleasePipelinesSuiteDescribe("e2e tests for push-disk-images-to-cdn pipeline", Label("release-pipelines", "push-disk-images-to-cdn"), func() {
defer GinkgoRecover()

var devWorkspace = utils.GetEnv(constants.RELEASE_DEV_WORKSPACE_ENV, constants.DevReleaseTeam)
var managedWorkspace = utils.GetEnv(constants.RELEASE_MANAGED_WORKSPACE_ENV, constants.ManagedReleaseTeam)

var devNamespace = devWorkspace + "-tenant"
var managedNamespace = managedWorkspace + "-tenant"

var err error
var devFw *framework.Framework
var managedFw *framework.Framework
var rhaiApplicationName = "rhai-app-" + util.GenerateRandomString(4)
var rhaiReleasePlanName = "rhai-rp-" + util.GenerateRandomString(4)
var rhaiReleasePlanAdmissionName = "rhai-rpa-" + util.GenerateRandomString(4)
var rhaiEnterpriseContractPolicyName = "rhai-policy-" + util.GenerateRandomString(4)
var sampleImage = "quay.io/hacbs-release-tests/disk-image-test@sha256:a56644589bed7c7d939e5aa9475131bda64f24a9b3e52defa5751a1d6774232f"

var snapshotPush *appservice.Snapshot
var releaseCR *releaseapi.Release

AfterEach(framework.ReportFailure(&devFw))

Describe("Push-disk-images-to-cdn happy path", Label("PushDisk"), func() {
BeforeAll(func() {
devFw = releasecommon.NewFramework(devWorkspace)
managedFw = releasecommon.NewFramework(managedWorkspace)

managedNamespace = managedFw.UserNamespace

_ = managedFw.AsKubeAdmin.CommonController.LinkSecretToServiceAccount(managedNamespace, releasecommon.RedhatAppstudioUserSecret, constants.DefaultPipelineServiceAccount, true)

_, err = devFw.AsKubeDeveloper.HasController.CreateApplication(rhaiApplicationName, devNamespace)
Expect(err).NotTo(HaveOccurred())

_, err = devFw.AsKubeDeveloper.ReleaseController.CreateReleasePlan(rhaiReleasePlanName, devNamespace, rhaiApplicationName, managedNamespace, "true", nil, nil)
Expect(err).NotTo(HaveOccurred())

createRHAIReleasePlanAdmission(rhaiReleasePlanAdmissionName, *managedFw, devNamespace, managedNamespace, rhaiApplicationName, rhaiEnterpriseContractPolicyName, rhaiCatalogPathInRepo)

createRHAIEnterpriseContractPolicy(rhaiEnterpriseContractPolicyName, *managedFw, devNamespace, managedNamespace)

snapshotPush, err = releasecommon.CreateSnapshotWithImageSource(*devFw, rhaiComponentName, rhaiApplicationName, devNamespace, sampleImage, rhaiGitSourceURL, rhaiGitSrcSHA, "", "", "", "")
Expect(err).ShouldNot(HaveOccurred())
})

AfterAll(func() {
devFw = releasecommon.NewFramework(devWorkspace)
managedFw = releasecommon.NewFramework(managedWorkspace)
Expect(devFw.AsKubeDeveloper.HasController.DeleteApplication(rhaiApplicationName, devNamespace, false)).NotTo(HaveOccurred())
Expect(managedFw.AsKubeDeveloper.TektonController.DeleteEnterpriseContractPolicy(rhaiEnterpriseContractPolicyName, managedNamespace, false)).NotTo(HaveOccurred())
Expect(managedFw.AsKubeDeveloper.ReleaseController.DeleteReleasePlanAdmission(rhaiReleasePlanAdmissionName, managedNamespace, false)).NotTo(HaveOccurred())
})

var _ = Describe("Post-release verification", func() {

It("verifies the rhai release pipelinerun is running and succeeds", func() {
Eventually(func() error {
releaseCR, err = devFw.AsKubeDeveloper.ReleaseController.GetRelease("", snapshotPush.Name, devNamespace)
if err != nil {
return err
}
return nil
}, 10*time.Minute, releasecommon.DefaultInterval).Should(Succeed())

Eventually(func() error {
pipelineRun, err := managedFw.AsKubeAdmin.ReleaseController.GetPipelineRunInNamespace(managedNamespace, releaseCR.GetName(), releaseCR.GetNamespace())
if err != nil {
return fmt.Errorf("PipelineRun has not been created yet for release %s/%s", releaseCR.GetNamespace(), releaseCR.GetName())
}

for _, condition := range pipelineRun.Status.Conditions {
GinkgoWriter.Printf("PipelineRun %s reason: %s\n", pipelineRun.Name, condition.Reason)
}

if !pipelineRun.IsDone(){
return fmt.Errorf("PipelineRun %s has still not finished yet", pipelineRun.Name)
}

if pipelineRun.GetStatusCondition().GetCondition(apis.ConditionSucceeded).IsTrue() {
return nil
} else {
prLogs := ""
if prLogs, err = tekton.GetFailedPipelineRunLogs(managedFw.AsKubeAdmin.ReleaseController.KubeRest(), managedFw.AsKubeAdmin.ReleaseController.KubeInterface(), pipelineRun); err != nil {
GinkgoWriter.Printf("failed to get PLR logs: %+v", err)
Expect(err).ShouldNot(HaveOccurred())
return nil
}
GinkgoWriter.Printf("logs: %s", prLogs)
Expect(prLogs).To(Equal(""), fmt.Sprintf("PipelineRun %s failed", pipelineRun.Name))
return nil
}
}, releasecommon.BuildPipelineRunCompletionTimeout, releasecommon.DefaultInterval).Should(Succeed(), fmt.Sprintf("timed out when waiting for the release PipelineRun to be finished for the release %s/%s", releaseCR.GetName(), releaseCR.GetNamespace()))
})

It("verifies release CR completed and set succeeded.", func() {
Eventually(func() error {
releaseCR, err = devFw.AsKubeDeveloper.ReleaseController.GetRelease("", snapshotPush.Name, devNamespace)
if err != nil {
return err
}
GinkgoWriter.Printf("releaseCR: %s", releaseCR.Name)
conditions := releaseCR.Status.Conditions
GinkgoWriter.Printf("len of conditions: %d", len(conditions))
if len(conditions) > 0 {
for _, c := range conditions {
GinkgoWriter.Printf("type of c: %s", c.Type)
if c.Type == "Released" {
GinkgoWriter.Printf("status of c: %s", c.Status)
if c.Status == "True" {
GinkgoWriter.Println("Release CR is released")
return nil
} else if c.Status == "False" {
GinkgoWriter.Println("Release CR failed")
Expect(string(c.Status)).To(Equal("True"), fmt.Sprintf("Release %s failed", releaseCR.Name))
return nil
} else {
return fmt.Errorf("release %s/%s is not marked as finished yet", releaseCR.GetNamespace(), releaseCR.GetName())
}
}
}
}
return nil
}, releasecommon.ReleaseCreationTimeout, releasecommon.DefaultInterval).Should(Succeed())
})

})
})
})

func createRHAIEnterpriseContractPolicy(rhaiECPName string, managedFw framework.Framework, devNamespace, managedNamespace string) {
releasePublicKeyDecoded := []byte("-----BEGIN PUBLIC KEY-----\n" +
"MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAEHHTvfqOgdrdt9TXDyYDMYlwZ8r8r\n" +
"AsiNjiVlB/DrkEdj3mNgxW7Papn1MgtxqRL/gJ3Jql2Z9tOYKNA08ojFAg==\n" +
"-----END PUBLIC KEY-----")
Expect(managedFw.AsKubeAdmin.TektonController.CreateOrUpdateSigningSecret(
releasePublicKeyDecoded, releasecommon.PublicSecretNameAuth, managedNamespace)).To(Succeed())
err = managedFw.AsKubeAdmin.CommonController.LinkSecretToServiceAccount(managedNamespace, releasecommon.PublicSecretNameAuth, rhaiServiceAccountName, true)
Expect(err).ToNot(HaveOccurred())
err = managedFw.AsKubeAdmin.CommonController.LinkSecretToServiceAccount(managedNamespace, releasecommon.RedhatAppstudioUserSecret, constants.DefaultPipelineServiceAccount, true)
Expect(err).ToNot(HaveOccurred())

_, _ = managedFw.AsKubeAdmin.CommonController.CreateRole("role-release-service-account", managedNamespace, map[string][]string{
"apiGroupsList": {""},
"roleResources": {"secrets"},
"roleVerbs": {"get", "list", "watch"},
})

_, _ = managedFw.AsKubeAdmin.CommonController.CreateRoleBinding("role-release-service-account-binding", managedNamespace, "ServiceAccount", "release-service-account", managedNamespace, "Role", "role-release-service-account", "rbac.authorization.k8s.io")

defaultEcPolicySpec := ecp.EnterpriseContractPolicySpec{
Description: "Red Hat's enterprise requirements",
PublicKey: fmt.Sprintf("k8s://%s/%s", managedNamespace, releasecommon.PublicSecretNameAuth),
Sources: []ecp.Source{{
Name: "Default",
Policy: []string{releasecommon.EcPolicyLibPath, releasecommon.EcPolicyReleasePath},
Data: []string{releasecommon.EcPolicyDataBundle, releasecommon.EcPolicyDataPath},
}},
Configuration: &ecp.EnterpriseContractPolicyConfiguration{
Exclude: []string{"step_image_registries", "tasks.required_tasks_found:prefetch-dependencies"},
Include: []string{"@slsa3"},
},
}

_, err := managedFw.AsKubeDeveloper.TektonController.CreateEnterpriseContractPolicy(rhaiECPName, managedNamespace, defaultEcPolicySpec)
Expect(err).NotTo(HaveOccurred())

}

func createRHAIReleasePlanAdmission(rhaiRPAName string, managedFw framework.Framework, devNamespace, managedNamespace, rhaiAppName, rhaiECPName, pathInRepoValue string) {
var err error

data, err := json.Marshal(map[string]interface{}{
"mapping": map[string]interface{}{
"components": []map[string]interface{}{
{
"name": rhaiComponentName,
"staged": map[string]interface{}{
"destination": "rhelai-1_DOT_1-for-rhel-9-x86_64-isos",
"version": "1.1",
"files": []map[string]interface{}{
{
"filename": "rhel-ai-nvidia-1.1-{{ timestamp }}-x86_64-kvm.qcow2",
"source": "disk.qcow2",
},
{
"filename": "rhel-ai-nvidia-1.1-{{ timestamp }}-x86_64.raw",
"source": "disk.qcow2",
},
},
},
"contentGateway": map[string]interface{}{
"productName": "E2ETest Red Hat Enterprise Linux AI",
"productCode": "RHELAIE2ETest",
"productVersionName": "RHELAI 1.1",
"filePrefix": "rhel-ai-nvidia-1.1",
},
},
},
},
"tags": []string{"time-{{ timestamp }}", "git-{{ git_sha }}" },
"cdn": map[string]interface{}{
"env": "stage",
},
"sign": map[string]interface{}{
"configMapName": "hacbs-signing-pipeline-config-redhatbeta2",
},
"pyxis": map[string]interface{}{
"server": "stage",
"secret": "pyxis",
},
"releaseNotes": map[string]interface{}{
"product_id": "932",
"product_name": "E2ETest Red Hat Enterprise Linux AI",
"product_version": "1.1",
"type": "RHSA",
},
})
Expect(err).NotTo(HaveOccurred())

_, err = managedFw.AsKubeAdmin.ReleaseController.CreateReleasePlanAdmission(rhaiRPAName, managedNamespace, "", devNamespace, rhaiECPName, rhaiServiceAccountName, []string{rhaiAppName}, true, &tektonutils.PipelineRef{
Resolver: "git",
Params: []tektonutils.Param{
{Name: "url", Value: releasecommon.RelSvcCatalogURL},
{Name: "revision", Value: releasecommon.RelSvcCatalogRevision},
{Name: "pathInRepo", Value: pathInRepoValue},
},
}, &runtime.RawExtension{
Raw: data,
} )
Expect(err).NotTo(HaveOccurred())
}

0 comments on commit e50f123

Please sign in to comment.