diff --git a/go.mod b/go.mod index 9be4dbbc0..11a3a4fc6 100644 --- a/go.mod +++ b/go.mod @@ -59,6 +59,7 @@ require ( k8s.io/utils v0.0.0-20240102154912-e7106e64919e knative.dev/pkg v0.0.0-20240219120257-9227ebb57a4e sigs.k8s.io/controller-runtime v0.17.5 + oras.land/oras-go/v2 v2.3.0 sigs.k8s.io/yaml v1.4.0 ) @@ -303,7 +304,6 @@ require ( k8s.io/kube-openapi v0.0.0-20240221221325-2ac9dc51f3f1 // indirect k8s.io/kubectl v0.29.2 // indirect k8s.io/kubernetes v1.29.2 // indirect - oras.land/oras-go/v2 v2.3.0 // indirect sigs.k8s.io/json v0.0.0-20221116044647-bc3834ca7abd // indirect sigs.k8s.io/kustomize/api v0.13.5-0.20230601165947-6ce0bf390ce3 // indirect sigs.k8s.io/kustomize/kyaml v0.14.3-0.20230601165947-6ce0bf390ce3 // indirect diff --git a/pkg/clients/oras/client.go b/pkg/clients/oras/client.go new file mode 100644 index 000000000..f4b9f2679 --- /dev/null +++ b/pkg/clients/oras/client.go @@ -0,0 +1,52 @@ +package oras + +import ( + "context" + "os" + + "github.com/openshift/library-go/pkg/image/reference" + oras "oras.land/oras-go/v2" + "oras.land/oras-go/v2/content/file" + "oras.land/oras-go/v2/registry/remote" + "oras.land/oras-go/v2/registry/remote/auth" + "oras.land/oras-go/v2/registry/remote/retry" +) + +// PullArtifacts pulls artifacts from the given imagePullSpec. +// Pulled artifacts will be stored in a local directory, whose path is returned. +func PullArtifacts(imagePullSpec string) (string, error) { + storePath, err := os.MkdirTemp("", "pulled-artifacts") + if err != nil { + return "", err + } + fs, err := file.New(storePath) + if err != nil { + return "", err + } + defer fs.Close() + + imageRef, err := reference.Parse(imagePullSpec) + if err != nil { + return "", err + } + + repo, err := remote.NewRepository(imagePullSpec) + if err != nil { + return "", err + } + repo.Client = &auth.Client{ + Client: retry.DefaultClient, + Cache: auth.NewCache(), + Credential: auth.StaticCredential(imageRef.Registry, auth.Credential{ + AccessToken: os.Getenv("QUAY_TOKEN"), + }), + } + + ctx := context.Background() + tag := imageRef.Tag + if _, err := oras.Copy(ctx, repo, tag, fs, tag, oras.DefaultCopyOptions); err != nil { + return "", err + } + + return storePath, nil +} diff --git a/tests/build/build_templates.go b/tests/build/build_templates.go index e4e3a030a..05a0aa335 100644 --- a/tests/build/build_templates.go +++ b/tests/build/build_templates.go @@ -4,6 +4,7 @@ import ( "encoding/json" "fmt" "os" + "path/filepath" "strings" "time" @@ -15,6 +16,7 @@ import ( "github.com/konflux-ci/e2e-tests/pkg/clients/common" "github.com/konflux-ci/e2e-tests/pkg/clients/has" kubeapi "github.com/konflux-ci/e2e-tests/pkg/clients/kubernetes" + "github.com/konflux-ci/e2e-tests/pkg/clients/oras" "github.com/konflux-ci/e2e-tests/pkg/constants" "github.com/konflux-ci/e2e-tests/pkg/framework" "github.com/konflux-ci/e2e-tests/pkg/utils" @@ -345,6 +347,10 @@ var _ = framework.BuildSuiteDescribe("Build templates E2E test", Label("build", Expect(buildSummaryLog).To(ContainSubstring(binaryImage)) }) + It("should push Dockerfile to registry", Label(buildTemplatesTestLabel), func() { + ensureOriginalDockerfileIsPushed(kubeadminClient, pr) + }) + It("floating tags are created successfully", func() { _, _, _, _, _, checkAdditionalTags := GetComponentScenarioDetailsFromGitUrl(gitUrl) if !checkAdditionalTags { @@ -801,3 +807,46 @@ func applyAdditionalTagsInPipelineBundle(customDockerBuildBundle string, additio } return newDockerBuildPipeline.String(), nil } + +func ensureOriginalDockerfileIsPushed(hub *framework.ControllerHub, pr *tektonpipeline.PipelineRun) { + binaryImage := build.GetBinaryImage(pr) + Expect(binaryImage).ShouldNot(BeEmpty()) + + binaryImageRef, err := reference.Parse(binaryImage) + Expect(err).Should(Succeed()) + + tagInfo, err := build.GetImageTag(binaryImageRef.Namespace, binaryImageRef.Name, binaryImageRef.Tag) + Expect(err).Should(Succeed()) + + dockerfileImageTag := fmt.Sprintf("%s.dockerfile", strings.Replace(tagInfo.ManifestDigest, ":", "-", 1)) + + dockerfileImage := reference.DockerImageReference{ + Registry: binaryImageRef.Registry, + Namespace: binaryImageRef.Namespace, + Name: binaryImageRef.Name, + Tag: dockerfileImageTag, + }.String() + exists, err := build.DoesTagExistsInQuay(dockerfileImage) + Expect(err).Should(Succeed()) + Expect(exists).Should(BeTrue()) + + // Ensure the original Dockerfile used for build was pushed + c := hub.CommonController.KubeRest() + originDockerfileContent, err := build.ReadDockerfileUsedForBuild(c, hub.TektonController, pr) + Expect(err).Should(Succeed()) + + storePath, err := oras.PullArtifacts(dockerfileImage) + Expect(err).Should(Succeed()) + entries, err := os.ReadDir(storePath) + Expect(err).Should(Succeed()) + for _, entry := range entries { + if entry.Type().IsRegular() && entry.Name() == "Dockerfile" { + content, err := os.ReadFile(filepath.Join(storePath, entry.Name())) + Expect(err).Should(Succeed()) + Expect(content).Should(Equal(originDockerfileContent)) + return + } + } + + Fail(fmt.Sprintf("Dockerfile is not found from the pulled artifacts for %s", dockerfileImage)) +} diff --git a/tests/build/multi-platform.go b/tests/build/multi-platform.go index ca1af2ed0..994e971c7 100644 --- a/tests/build/multi-platform.go +++ b/tests/build/multi-platform.go @@ -457,7 +457,6 @@ var _ = framework.MultiPlatformBuildSuiteDescribe("Multi Platform Controller E2E return nil }, timeout, interval).Should(Succeed(), "timed out when verifying that the remote host was cleaned up correctly") }) - }) }) })