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 Oct 11, 2024
1 parent b2ed0c1 commit da0b7e4
Show file tree
Hide file tree
Showing 17 changed files with 288 additions and 16 deletions.
2 changes: 1 addition & 1 deletion magefiles/magefile.go
Original file line number Diff line number Diff line change
Expand Up @@ -1296,7 +1296,7 @@ func CleanWorkload() error {
func runTests(labelsToRun string, junitReportFile string) error {

ginkgoArgs := []string{"-p", "--output-interceptor-mode=none", "--no-color",
"--timeout=90m", fmt.Sprintf("--output-dir=%s", artifactDir),
"--timeout=240m", fmt.Sprintf("--output-dir=%s", artifactDir),
"--junit-report=" + junitReportFile, "--label-filter=" + labelsToRun}

if os.Getenv("GINKGO_PROCS") != "" {
Expand Down
6 changes: 5 additions & 1 deletion pkg/clients/release/plans.go
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ import (
releaseApi "github.com/konflux-ci/release-service/api/v1alpha1"
releaseMetadata "github.com/konflux-ci/release-service/metadata"
k8sErrors "k8s.io/apimachinery/pkg/api/errors"
tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/types"
)
Expand Down Expand Up @@ -43,7 +44,7 @@ func (r *ReleaseController) CreateReleasePlan(name, namespace, application, targ
}

// CreateReleasePlanAdmission creates a new ReleasePlanAdmission using the given parameters.
func (r *ReleaseController) CreateReleasePlanAdmission(name, namespace, environment, origin, policy, serviceAccountName string, applications []string, autoRelease bool, pipelineRef *tektonutils.PipelineRef, data *runtime.RawExtension) (*releaseApi.ReleasePlanAdmission, error) {
func (r *ReleaseController) CreateReleasePlanAdmission(name, namespace, environment, origin, policy, serviceAccountName string, applications []string, autoRelease bool, pipelineRef *tektonutils.PipelineRef, data *runtime.RawExtension, timeouts *tektonv1.TimeoutFields) (*releaseApi.ReleasePlanAdmission, error) {
releasePlanAdmission := &releaseApi.ReleasePlanAdmission{
ObjectMeta: metav1.ObjectMeta{
Name: name,
Expand All @@ -64,6 +65,9 @@ func (r *ReleaseController) CreateReleasePlanAdmission(name, namespace, environm
Policy: policy,
},
}
if timeouts != nil {
releasePlanAdmission.Spec.Pipeline.Timeouts = *timeouts
}

return releasePlanAdmission, r.KubeRest().Create(context.Background(), releasePlanAdmission)
}
Expand Down
2 changes: 1 addition & 1 deletion tests/build/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -1532,7 +1532,7 @@ var _ = framework.BuildSuiteDescribe("Build service E2E tests", Label("build-ser
{Name: "url", Value: constants.RELEASE_CATALOG_DEFAULT_URL},
{Name: "revision", Value: constants.RELEASE_CATALOG_DEFAULT_REVISION},
{Name: "pathInRepo", Value: "pipelines/e2e/e2e.yaml"},
}}, &runtime.RawExtension{Raw: rawData})
}}, &runtime.RawExtension{Raw: rawData}, nil)
Expect(err).NotTo(HaveOccurred())

// get the build pipeline bundle annotation
Expand Down
2 changes: 1 addition & 1 deletion tests/konflux-demo/konflux-demo.go
Original file line number Diff line number Diff line change
Expand Up @@ -468,7 +468,7 @@ func createReleaseConfig(fw framework.Framework, managedNamespace, componentName
{Name: "revision", Value: releasecommon.RelSvcCatalogRevision},
{Name: "pathInRepo", Value: "pipelines/e2e/e2e.yaml"},
},
}, nil)
}, nil, nil)
Expect(err).NotTo(HaveOccurred())

_, err = fw.AsKubeAdmin.TektonController.CreatePVCInAccessMode("release-pvc", managedNamespace, corev1.ReadWriteOnce)
Expand Down
2 changes: 1 addition & 1 deletion tests/release/pipelines/fbc_release.go
Original file line number Diff line number Diff line change
Expand Up @@ -321,6 +321,6 @@ func createFBCReleasePlanAdmission(fbcRPAName string, managedFw framework.Framew
},
}, &runtime.RawExtension{
Raw: data,
})
}, nil)
Expect(err).NotTo(HaveOccurred())
}
2 changes: 1 addition & 1 deletion tests/release/pipelines/multiarch_advisories.go
Original file line number Diff line number Diff line change
Expand Up @@ -270,6 +270,6 @@ func createMultiArchReleasePlanAdmission(multiarchRPAName string, managedFw fram
},
}, &runtime.RawExtension{
Raw: data,
})
}, nil)
Expect(err).NotTo(HaveOccurred())
}
268 changes: 268 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,268 @@
package pipelines

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

appservice "github.com/konflux-ci/application-api/api/v1alpha1"
ecp "github.com/enterprise-contract/enterprise-contract-controller/api/v1alpha1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
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"
tektonv1 "github.com/tektoncd/pipeline/pkg/apis/pipeline/v1"

"github.com/devfile/library/v2/pkg/util"
"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"
"k8s.io/apimachinery/pkg/runtime"
"knative.dev/pkg/apis"

. "github.com/onsi/ginkgo/v2"
. "github.com/onsi/gomega"
)

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 compRandomStr = util.GenerateRandomString(4)
var rhaiComponentName = "rhel-ai-nvidia-1.1-" + compRandomStr

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

err = managedFw.AsKubeAdmin.CommonController.LinkSecretToServiceAccount(managedNamespace, releasecommon.RedhatAppstudioUserSecret, constants.DefaultPipelineServiceAccount, true)
Expect(err).ToNot(HaveOccurred())

_, 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)
if !CurrentSpecReport().Failed() {
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())
} else {
Expect(managedFw.AsKubeDeveloper.CommonController.StoreAllPods(managedNamespace)).To(Succeed())
Expect(managedFw.AsKubeDeveloper.TektonController.StoreAllPipelineRuns(managedNamespace)).To(Succeed())
}
})

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
}
}, 4*time.Hour, 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())

_, _ = 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-"+compRandomStr+"{{ timestamp }}-x86_64-kvm.qcow2",
"source": "disk.qcow2",
},
{
"filename": "rhel-ai-nvidia-1.1-"+compRandomStr+"-{{ timestamp }}-x86_64.raw",
"source": "disk.raw",
},
{
"filename": "rhel-ai-nvidia-1.1-"+compRandomStr+"-{{ timestamp }}-x86_64-boot.iso",
"source": "install.iso",
},
},
},
"contentGateway": map[string]interface{}{
"productName": "E2ETest Red Hat Enterprise Linux AI",
"productCode": "RHELAIE2ETest",
"productVersionName": "RHELAI 1.1",
"filePrefix": "rhel-ai-nvidia-1.1-"+compRandomStr,
},
},
},
},
"tags": []string{"time-{{ timestamp }}", "git-{{ git_sha }}" },
"cdn": map[string]interface{}{
"env": "qa",
},
})
Expect(err).NotTo(HaveOccurred())

timeouts := &tektonv1.TimeoutFields{
Pipeline: &metav1.Duration{Duration: 4 * time.Hour},
Tasks: &metav1.Duration{Duration: 2 * time.Hour},
}

_, 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,
}, timeouts)
Expect(err).NotTo(HaveOccurred())
}
2 changes: 1 addition & 1 deletion tests/release/pipelines/push_to_external_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ var _ = framework.ReleasePipelinesSuiteDescribe("Push to external registry", Lab
},
}, &runtime.RawExtension{
Raw: data,
})
}, nil)
Expect(err).NotTo(HaveOccurred())

_, err = fw.AsKubeAdmin.TektonController.CreatePVCInAccessMode(releasecommon.ReleasePvcName, managedNamespace, corev1.ReadWriteOnce)
Expand Down
2 changes: 1 addition & 1 deletion tests/release/pipelines/release_to_github.go
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,6 @@ func createGHReleasePlanAdmission(sampRPAName string, managedFw framework.Framew
},
}, &runtime.RawExtension{
Raw: data,
})
}, nil)
Expect(err).NotTo(HaveOccurred())
}
2 changes: 1 addition & 1 deletion tests/release/pipelines/rh_advisories.go
Original file line number Diff line number Diff line change
Expand Up @@ -271,6 +271,6 @@ func createADVSReleasePlanAdmission(advsRPAName string, managedFw framework.Fram
},
}, &runtime.RawExtension{
Raw: data,
})
}, nil)
Expect(err).NotTo(HaveOccurred())
}
2 changes: 1 addition & 1 deletion tests/release/pipelines/rh_push_to_external_registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -166,7 +166,7 @@ var _ = framework.ReleasePipelinesSuiteDescribe("[HACBS-1571]test-release-e2e-pu
},
}, &runtime.RawExtension{
Raw: data,
})
}, nil)
Expect(err).NotTo(HaveOccurred())

_, err = fw.AsKubeAdmin.TektonController.CreatePVCInAccessMode(releasecommon.ReleasePvcName, managedNamespace, corev1.ReadWriteOnce)
Expand Down
2 changes: 1 addition & 1 deletion tests/release/pipelines/rh_push_to_redhat_io.go
Original file line number Diff line number Diff line change
Expand Up @@ -247,6 +247,6 @@ func createRHIOReleasePlanAdmission(rhioRPAName string, managedFw framework.Fram
},
}, &runtime.RawExtension{
Raw: data,
})
}, nil)
Expect(err).NotTo(HaveOccurred())
}
2 changes: 1 addition & 1 deletion tests/release/pipelines/rhtap_service_push.go
Original file line number Diff line number Diff line change
Expand Up @@ -279,7 +279,7 @@ func createRHTAPReleasePlanAdmission(rhtapRPAName string, managedFw framework.Fr
},
}, &runtime.RawExtension{
Raw: data,
})
}, nil)
Expect(err).NotTo(HaveOccurred())
}

Expand Down
2 changes: 1 addition & 1 deletion tests/release/releaseLib.go
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ func NewFramework(workspace string) *framework.Framework {
// Create a ticker that ticks every 3 minutes
ticker := time.NewTicker(3 * time.Minute)
// Schedule the stop of the ticker after 30 minutes
time.AfterFunc(60*time.Minute, func() {
time.AfterFunc(240*time.Minute, func() {
ticker.Stop()
fmt.Println("Stopped executing every 3 minutes.")
})
Expand Down
Loading

0 comments on commit da0b7e4

Please sign in to comment.