From f61b791981e00975dd1d31d93cd322b4e1cf3095 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Tue, 22 Aug 2023 08:12:41 +0000 Subject: [PATCH 01/28] test(e2e): add zot Signed-off-by: Billy Zha --- test/e2e/README.md | 7 +++++-- test/e2e/internal/utils/init.go | 13 +++++++++++++ test/e2e/internal/utils/testdata.go | 1 + test/e2e/scripts/e2e.sh | 21 +++++++++++++++++---- 4 files changed, 36 insertions(+), 6 deletions(-) diff --git a/test/e2e/README.md b/test/e2e/README.md index 26e7332a8..15be2cff1 100644 --- a/test/e2e/README.md +++ b/test/e2e/README.md @@ -30,9 +30,12 @@ go test oras.land/oras/test/e2e/suite/${suite_name} This is super handy when you want to do step-by-step debugging from command-line or via an IDE. If you need to debug certain specs, use [focused specs](https://onsi.github.io/ginkgo/#focused-specs) but don't check it in. ### 4. Testing Registry Services -The backend of E2E tests are two registry services: [oras-distribution](https://github.com/oras-project/distribution) and [upstream distribution](https://github.com/distribution/distribution). The former is expected to support image and artifact media types and referrer API; The latter is expected to only support image media type with subject and provide referrers via [tag schema](https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#referrers-tag-schema). +The backend of E2E tests are three registry services: +- [oras-distribution](https://github.com/oras-project/distribution): registry service supports artifact and image types in [image-spec 1.1.0 rc2](https://github.com/opencontainers/image-spec/tree/v1.1.0-rc2) and referrer API +- [upstream distribution](https://github.com/distribution/distribution): registry service supports image media type with subject and provide referrers via [tag schema](https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#referrers-tag-schema). +- [zot](https://github.com/project-zot/zot): registry service supports artifact and image types in [image-spec 1.1.0 rc4](https://github.com/opencontainers/image-spec/tree/v1.1.0-rc4) and referrer API -You can run scenario test suite against your own registry services via setting `ORAS_REGISTRY_HOST` or `ORAS_REGISTRY_FALLBACK_HOST` environmental variables. +You can run scenario test suite against your own registry services via setting `ORAS_REGISTRY_HOST`, `ORAS_REGISTRY_FALLBACK_HOST` and `ZOT_REGISTRY_HOST` environmental variables. ### 5. Constant Build & Watch This is a good choice if you want to debug certain re-runnable specs: diff --git a/test/e2e/internal/utils/init.go b/test/e2e/internal/utils/init.go index ecefaa3ad..7513d1737 100644 --- a/test/e2e/internal/utils/init.go +++ b/test/e2e/internal/utils/init.go @@ -36,6 +36,9 @@ var Host string // FallbackHost points to the registry service where fallback E2E specs will be run against. var FallbackHost string +// ZotHost points to the zot service where E2E specs will be run against. +var ZotHost string + func init() { Host = os.Getenv(RegHostKey) if Host == "" { @@ -59,6 +62,16 @@ func init() { panic(err) } + ZotHost = os.Getenv(ZotHostKey) + if ZotHost == "" { + ZotHost = "localhost:7000" + fmt.Fprintf(os.Stderr, "cannot find zot host name in %s, using %s instead\n", ZotHostKey, ZotHost) + } + ref.Registry = ZotHost + if err := ref.ValidateRegistry(); err != nil { + panic(err) + } + // setup test data pwd, err := os.Getwd() if err != nil { diff --git a/test/e2e/internal/utils/testdata.go b/test/e2e/internal/utils/testdata.go index 5adac93ef..eb7e4ab28 100644 --- a/test/e2e/internal/utils/testdata.go +++ b/test/e2e/internal/utils/testdata.go @@ -25,6 +25,7 @@ const ( // env RegHostKey = "ORAS_REGISTRY_HOST" FallbackRegHostKey = "ORAS_REGISTRY_FALLBACK_HOST" + ZotHostKey = "ZOT_REGISTRY_HOST" ) var ( diff --git a/test/e2e/scripts/e2e.sh b/test/e2e/scripts/e2e.sh index b110e38c6..1198b4873 100755 --- a/test/e2e/scripts/e2e.sh +++ b/test/e2e/scripts/e2e.sh @@ -17,6 +17,8 @@ export ORAS_REGISTRY_PORT="5000" export ORAS_REGISTRY_HOST="localhost:${ORAS_REGISTRY_PORT}" export ORAS_REGISTRY_FALLBACK_PORT="6000" export ORAS_REGISTRY_FALLBACK_HOST="localhost:${ORAS_REGISTRY_FALLBACK_PORT}" +export ZOT_REGISTRY_PORT="7000" +export ZOT_REGISTRY_HOST="localhost:${ZOT_REGISTRY_PORT}" repo_root=$1 if [ -z "${repo_root}" ]; then @@ -36,14 +38,16 @@ trap "cd $cwd" EXIT # start registries . ${repo_root}/test/e2e/scripts/common.sh +e2e_root="${repo_root}/test/e2e" +oras_container_name="oras-e2e" +upstream_container_name="oras-e2e-fallback" +zot_container_name="oras-e2e-zot" + if [ "$clean_up" = '--clean' ]; then echo " === setting deferred clean up jobs === " - trap "try_clean_up oras-e2e oras-e2e-fallback" EXIT + trap "try_clean_up $oras_container_name $upstream_container_name $zot_container_name" EXIT fi -oras_container_name="oras-e2e" -upstream_container_name="oras-e2e-fallback" -e2e_root="${repo_root}/test/e2e" echo " === preparing oras distribution === " run_registry \ ${e2e_root}/testdata/distribution/mount \ @@ -58,6 +62,13 @@ run_registry \ $upstream_container_name \ $ORAS_REGISTRY_FALLBACK_PORT +echo " === preparing zot === " +try_clean_up $zot_container_name +docker run -d -p $ZOT_REGISTRY_PORT:5000 -it \ + --name $zot_container_name \ + --mount type=bind,source="${e2e_root}/testdata/zot/",target=/etc/zot \ + --rm ghcr.io/project-zot/zot-linux-amd64:v2.0.0-rc6 + echo " === run tests === " if ! ginkgo -r -p --succinct suite; then echo " === retriving registry error logs === " @@ -65,5 +76,7 @@ if ! ginkgo -r -p --succinct suite; then docker logs -t --tail 200 $oras_container_name echo '-------- upstream distribution trace -------------' docker logs -t --tail 200 $upstream_container_name + echo '-------- zot trace -------------' + docker logs -t --tail 200 $zot_container_name exit 1 fi From 06abf607605cdb593021fa8dfe24a82aa0ed973b Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Tue, 22 Aug 2023 08:13:12 +0000 Subject: [PATCH 02/28] add auth tests Signed-off-by: Billy Zha --- test/e2e/suite/auth/auth.go | 40 ++++++++++++++++++------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/test/e2e/suite/auth/auth.go b/test/e2e/suite/auth/auth.go index c15f9c4f1..49176c78e 100644 --- a/test/e2e/suite/auth/auth.go +++ b/test/e2e/suite/auth/auth.go @@ -27,38 +27,38 @@ import ( var _ = Describe("Common registry user", Ordered, func() { When("logging out", Ordered, func() { It("should use logout command to logout", func() { - ORAS("logout", Host, "--registry-config", AuthConfigPath).Exec() + ORAS("logout", ZotHost, "--registry-config", AuthConfigPath).Exec() }) It("should run commands without logging in", func() { - RunWithoutLogin("attach", Host+"/repo:tag", "-a", "test=true", "--artifact-type", "doc/example") - ORAS("copy", Host+"/repo:from", Host+"/repo:to", "--from-registry-config", AuthConfigPath, "--to-registry-config", AuthConfigPath). + RunWithoutLogin("attach", ZotHost+"/repo:tag", "-a", "test=true", "--artifact-type", "doc/example") + ORAS("copy", ZotHost+"/repo:from", ZotHost+"/repo:to", "--from-registry-config", AuthConfigPath, "--to-registry-config", AuthConfigPath). ExpectFailure(). MatchErrKeyWords("Error:", "credential required"). WithDescription("fail without logging in").Exec() - RunWithoutLogin("discover", Host+"/repo:tag") - RunWithoutLogin("push", "-a", "key=value", Host+"/repo:tag") - RunWithoutLogin("pull", Host+"/repo:tag") - RunWithoutLogin("manifest", "fetch", Host+"/repo:tag") - RunWithoutLogin("blob", "delete", Host+"/repo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") - RunWithoutLogin("blob", "push", Host+"/repo", WriteTempFile("blob", "test")) - RunWithoutLogin("tag", Host+"/repo:tag", "tag1") - RunWithoutLogin("repo", "ls", Host) - RunWithoutLogin("repo", "tags", RegistryRef(Host, "repo", "")) - RunWithoutLogin("manifest", "fetch-config", Host+"/repo:tag") + RunWithoutLogin("discover", ZotHost+"/repo:tag") + RunWithoutLogin("push", "-a", "key=value", ZotHost+"/repo:tag") + RunWithoutLogin("pull", ZotHost+"/repo:tag") + RunWithoutLogin("manifest", "fetch", ZotHost+"/repo:tag") + RunWithoutLogin("blob", "delete", ZotHost+"/repo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") + RunWithoutLogin("blob", "push", ZotHost+"/repo", WriteTempFile("blob", "test")) + RunWithoutLogin("tag", ZotHost+"/repo:tag", "tag1") + RunWithoutLogin("repo", "ls", ZotHost) + RunWithoutLogin("repo", "tags", RegistryRef(ZotHost, "repo", "")) + RunWithoutLogin("manifest", "fetch-config", ZotHost+"/repo:tag") }) }) When("logging in", func() { It("should use basic auth", func() { - ORAS("login", Host, "-u", Username, "-p", Password, "--registry-config", AuthConfigPath). + ORAS("login", ZotHost, "-u", Username, "-p", Password, "--registry-config", AuthConfigPath). WithTimeOut(20*time.Second). MatchContent("Login Succeeded\n"). MatchErrKeyWords("WARNING", "Using --password via the CLI is insecure", "Use --password-stdin").Exec() }) It("should fail if no username input", func() { - ORAS("login", Host, "--registry-config", AuthConfigPath). + ORAS("login", ZotHost, "--registry-config", AuthConfigPath). WithTimeOut(20 * time.Second). WithInput(strings.NewReader("")). MatchKeyWords("username:"). @@ -67,14 +67,14 @@ var _ = Describe("Common registry user", Ordered, func() { }) It("should fail if no password input", func() { - ORAS("login", Host, "--registry-config", AuthConfigPath). + ORAS("login", ZotHost, "--registry-config", AuthConfigPath). WithTimeOut(20*time.Second). MatchKeyWords("Username: ", "Password: "). WithInput(strings.NewReader(fmt.Sprintf("%s\n", Username))).ExpectFailure().Exec() }) It("should fail if password is empty", func() { - ORAS("login", Host, "--registry-config", AuthConfigPath). + ORAS("login", ZotHost, "--registry-config", AuthConfigPath). WithTimeOut(20*time.Second). MatchKeyWords("Username: ", "Password: "). MatchErrKeyWords("Error: password required"). @@ -82,14 +82,14 @@ var _ = Describe("Common registry user", Ordered, func() { }) It("should fail if no token input", func() { - ORAS("login", Host, "--registry-config", AuthConfigPath). + ORAS("login", ZotHost, "--registry-config", AuthConfigPath). WithTimeOut(20*time.Second). MatchKeyWords("Username: ", "Token: "). WithInput(strings.NewReader("\n")).ExpectFailure().Exec() }) It("should fail if token is empty", func() { - ORAS("login", Host, "--registry-config", AuthConfigPath). + ORAS("login", ZotHost, "--registry-config", AuthConfigPath). WithTimeOut(20*time.Second). MatchKeyWords("Username: ", "Token: "). MatchErrKeyWords("Error: token required"). @@ -97,7 +97,7 @@ var _ = Describe("Common registry user", Ordered, func() { }) It("should use prompted input", func() { - ORAS("login", Host, "--registry-config", AuthConfigPath). + ORAS("login", ZotHost, "--registry-config", AuthConfigPath). WithTimeOut(20*time.Second). WithInput(strings.NewReader(fmt.Sprintf("%s\n%s\n", Username, Password))). MatchKeyWords("Username: ", "Password: ", "Login Succeeded\n").Exec() From 8e644c61101220728929b3260e55d2de8d5e2a80 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 23 Aug 2023 01:57:33 +0000 Subject: [PATCH 03/28] uncomment changes Signed-off-by: Billy Zha --- test/e2e/suite/scenario/oci_artifact.go | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/test/e2e/suite/scenario/oci_artifact.go b/test/e2e/suite/scenario/oci_artifact.go index bbd744e3c..502b0b6c8 100644 --- a/test/e2e/suite/scenario/oci_artifact.go +++ b/test/e2e/suite/scenario/oci_artifact.go @@ -84,10 +84,10 @@ var _ = Describe("Common OCI artifact users:", Ordered, func() { // FIXME: oras distribution doesn't support OCI image with artifactType field // Below test can be run after https://github.com/oras-project/oras/issues/1071 is done. - // session = ORAS("discover", subject, "-o", "json", "--artifact-type", "test.artifact2").Exec() - // digest = string(Binary("jq", "-r", ".manifests[].digest").WithInput(session.Out).Exec().Out.Contents()) - // fetched = ORAS("manifest", "fetch", RegistryRef(Host, repo, digest)).MatchKeyWords(foobar.AttachFileMedia).Exec() - // MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout) + session = ORAS("discover", subject, "-o", "json", "--artifact-type", "test.artifact2").Exec() + digest = string(Binary("jq", "-r", ".manifests[].digest").WithInput(session.Out).Exec().Out.Contents()) + fetched = ORAS("manifest", "fetch", RegistryRef(Host, repo, digest)).MatchKeyWords(foobar.AttachFileMedia).Exec() + MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout) ORAS("pull", RegistryRef(Host, repo, string(digest)), "-v", "-o", pullRoot, "--include-subject"). MatchStatus(append(foobar.FileStateKeys, foobar.AttachFileStateKey), true, 4). From 0c7a3ee3f39fbf30a1c2d34f05c248ddc8ad0032 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 23 Aug 2023 04:39:38 +0000 Subject: [PATCH 04/28] move auth and scenario suite to zot Signed-off-by: Billy Zha --- test/e2e/internal/utils/init.go | 2 ++ .../internal/utils/{file.go => prepare.go} | 6 +++++ test/e2e/suite/scenario/oci_artifact.go | 26 +++++++++---------- 3 files changed, 20 insertions(+), 14 deletions(-) rename test/e2e/internal/utils/{file.go => prepare.go} (94%) diff --git a/test/e2e/internal/utils/init.go b/test/e2e/internal/utils/init.go index 7513d1737..977cd4f8d 100644 --- a/test/e2e/internal/utils/init.go +++ b/test/e2e/internal/utils/init.go @@ -124,5 +124,7 @@ func init() { gomega.Expect(cmd.Run()).ShouldNot(gomega.HaveOccurred()) cmd = exec.Command(ORASPath, "login", FallbackHost, "-u", Username, "-p", Password) gomega.Expect(cmd.Run()).ShouldNot(gomega.HaveOccurred()) + cmd = exec.Command(ORASPath, "login", ZotHost, "-u", Username, "-p", Password) + gomega.Expect(cmd.Run()).ShouldNot(gomega.HaveOccurred()) }) } diff --git a/test/e2e/internal/utils/file.go b/test/e2e/internal/utils/prepare.go similarity index 94% rename from test/e2e/internal/utils/file.go rename to test/e2e/internal/utils/prepare.go index eea029237..3359d2b86 100644 --- a/test/e2e/internal/utils/file.go +++ b/test/e2e/internal/utils/prepare.go @@ -28,6 +28,12 @@ import ( "github.com/onsi/gomega/gbytes" ) +func PrepareRepository() string { + tempDir := GinkgoT().TempDir() + Expect(CopyTestFiles(tempDir)).ShouldNot(HaveOccurred()) + return tempDir +} + // PrepareTempFiles copies test data into a temp folder and return it. func PrepareTempFiles() string { tempDir := GinkgoT().TempDir() diff --git a/test/e2e/suite/scenario/oci_artifact.go b/test/e2e/suite/scenario/oci_artifact.go index 502b0b6c8..fe9d4eb74 100644 --- a/test/e2e/suite/scenario/oci_artifact.go +++ b/test/e2e/suite/scenario/oci_artifact.go @@ -25,7 +25,7 @@ import ( "oras.land/oras/test/e2e/internal/utils/match" ) -var _ = Describe("Common OCI artifact users:", Ordered, func() { +var _ = Describe("OCI artifact users:", Ordered, func() { repo := "scenario/oci-artifact" When("pushing images and attaching", func() { tag := "artifact" @@ -37,15 +37,15 @@ var _ = Describe("Common OCI artifact users:", Ordered, func() { pulledManifest := "packed.json" pullRoot := "pulled" It("should push and pull an artifact", func() { - ORAS("push", RegistryRef(Host, repo, tag), "--artifact-type", "test-artifact", foobar.FileLayerNames[0], foobar.FileLayerNames[1], foobar.FileLayerNames[2], "-v", "--export-manifest", pulledManifest). + ORAS("push", RegistryRef(ZotHost, repo, tag), "--artifact-type", "test/artifact", foobar.FileLayerNames[0], foobar.FileLayerNames[1], foobar.FileLayerNames[2], "-v", "--export-manifest", pulledManifest). MatchStatus(foobar.FileStateKeys, true, 3). WithWorkDir(tempDir). WithDescription("push with manifest exported").Exec() - fetched := ORAS("manifest", "fetch", RegistryRef(Host, repo, tag)).Exec() + fetched := ORAS("manifest", "fetch", RegistryRef(ZotHost, repo, tag)).Exec() MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout) - ORAS("pull", RegistryRef(Host, repo, tag), "-v", "-o", pullRoot). + ORAS("pull", RegistryRef(ZotHost, repo, tag), "-v", "-o", pullRoot). MatchStatus(foobar.FileStateKeys, true, 3). WithWorkDir(tempDir). WithDescription("pull artFiles with config").Exec() @@ -58,18 +58,18 @@ var _ = Describe("Common OCI artifact users:", Ordered, func() { }) It("should attach and pull an artifact", func() { - subject := RegistryRef(Host, repo, tag) - ORAS("attach", subject, "--artifact-type", "test.artifact1", fmt.Sprint(foobar.AttachFileName, ":", foobar.AttachFileMedia), "-v", "--export-manifest", pulledManifest). + subject := RegistryRef(ZotHost, repo, tag) + ORAS("attach", subject, "--artifact-type", "test/artifact1", fmt.Sprint(foobar.AttachFileName, ":", foobar.AttachFileMedia), "-v", "--export-manifest", pulledManifest). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, true, 1). WithWorkDir(tempDir). WithDescription("attach with manifest exported").Exec() session := ORAS("discover", subject, "-o", "json").Exec() digest := string(Binary("jq", "-r", ".manifests[].digest").WithInput(session.Out).Exec().Out.Contents()) - fetched := ORAS("manifest", "fetch", RegistryRef(Host, repo, digest)).MatchKeyWords(foobar.AttachFileMedia).Exec() + fetched := ORAS("manifest", "fetch", RegistryRef(ZotHost, repo, digest)).MatchKeyWords(foobar.AttachFileMedia).Exec() MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout) - ORAS("pull", RegistryRef(Host, repo, digest), "-v", "-o", pullRoot). + ORAS("pull", RegistryRef(ZotHost, repo, digest), "-v", "-o", pullRoot). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, true, 1). WithWorkDir(tempDir). WithDescription("pull attached artifact").Exec() @@ -77,19 +77,17 @@ var _ = Describe("Common OCI artifact users:", Ordered, func() { WithWorkDir(tempDir). WithDescription("download identical file " + foobar.AttachFileName).Exec() - ORAS("attach", subject, "--artifact-type", "test.artifact2", fmt.Sprint(foobar.AttachFileName, ":", foobar.AttachFileMedia), "-v", "--export-manifest", pulledManifest). + ORAS("attach", subject, "--artifact-type", "test/artifact2", fmt.Sprint(foobar.AttachFileName, ":", foobar.AttachFileMedia), "-v", "--export-manifest", pulledManifest). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, true, 1). WithWorkDir(tempDir). WithDescription("attach again with manifest exported").Exec() - // FIXME: oras distribution doesn't support OCI image with artifactType field - // Below test can be run after https://github.com/oras-project/oras/issues/1071 is done. - session = ORAS("discover", subject, "-o", "json", "--artifact-type", "test.artifact2").Exec() + session = ORAS("discover", subject, "-o", "json", "--artifact-type", "test/artifact2").Exec() digest = string(Binary("jq", "-r", ".manifests[].digest").WithInput(session.Out).Exec().Out.Contents()) - fetched = ORAS("manifest", "fetch", RegistryRef(Host, repo, digest)).MatchKeyWords(foobar.AttachFileMedia).Exec() + fetched = ORAS("manifest", "fetch", RegistryRef(ZotHost, repo, digest)).MatchKeyWords(foobar.AttachFileMedia).Exec() MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout) - ORAS("pull", RegistryRef(Host, repo, string(digest)), "-v", "-o", pullRoot, "--include-subject"). + ORAS("pull", RegistryRef(ZotHost, repo, string(digest)), "-v", "-o", pullRoot, "--include-subject"). MatchStatus(append(foobar.FileStateKeys, foobar.AttachFileStateKey), true, 4). WithWorkDir(tempDir). WithDescription("pull attached artifact and subject").Exec() From 35d8bd484dee63cdc1ac329f4fb1977cc4c5643a Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 23 Aug 2023 04:49:12 +0000 Subject: [PATCH 05/28] add password Signed-off-by: Billy Zha --- test/e2e/testdata/zot/passwd_bcrypt | 1 + 1 file changed, 1 insertion(+) create mode 100644 test/e2e/testdata/zot/passwd_bcrypt diff --git a/test/e2e/testdata/zot/passwd_bcrypt b/test/e2e/testdata/zot/passwd_bcrypt new file mode 100644 index 000000000..71e4a0113 --- /dev/null +++ b/test/e2e/testdata/zot/passwd_bcrypt @@ -0,0 +1 @@ +hello:$2y$05$7VA2NX15rMmt6Y14Ep7wReDybGvD8e7ko9tsxmvZQwnC4wBfG9Thy From 1700e2326586d5d7a8ecc9ce89f65ebd844502a5 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 23 Aug 2023 04:53:36 +0000 Subject: [PATCH 06/28] update description Signed-off-by: Billy Zha --- test/e2e/suite/command/attach.go | 26 ++++++++++++------------- test/e2e/suite/command/blob.go | 2 +- test/e2e/suite/command/cp.go | 2 +- test/e2e/suite/command/custom_header.go | 4 ++-- test/e2e/suite/command/discover.go | 4 ++-- test/e2e/suite/command/manifest.go | 2 +- test/e2e/suite/command/repo.go | 2 +- test/e2e/suite/command/resolve_host.go | 4 ++-- test/e2e/suite/command/tag.go | 2 +- 9 files changed, 24 insertions(+), 24 deletions(-) diff --git a/test/e2e/suite/command/attach.go b/test/e2e/suite/command/attach.go index b0e5fba68..c9c58c2ee 100644 --- a/test/e2e/suite/command/attach.go +++ b/test/e2e/suite/command/attach.go @@ -67,14 +67,14 @@ var _ = Describe("ORAS beginners:", func() { }) }) -var _ = Describe("Common registry users:", func() { +var _ = Describe("1.1 registry users:", func() { When("running attach command", func() { It("should attach a file to a subject", func() { testRepo := attachTestRepo("simple") tempDir := PrepareTempFiles() subjectRef := RegistryRef(Host, testRepo, foobar.Tag) prepare(RegistryRef(Host, ImageRepo, foobar.Tag), subjectRef) - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). + ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(tempDir). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() }) @@ -87,7 +87,7 @@ var _ = Describe("Common registry users:", func() { subjectRef := RegistryRef(Host, testRepo, foobar.Tag) prepare(RegistryRef(Host, ImageRepo, foobar.Tag), subjectRef) // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--export-manifest", exportName). + ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--export-manifest", exportName). WithWorkDir(tempDir). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() // validate @@ -105,7 +105,7 @@ var _ = Describe("Common registry users:", func() { subjectRef := RegistryRef(Host, testRepo, foobar.Tag) prepare(RegistryRef(Host, ImageRepo, foobar.Tag), subjectRef) // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). + ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(tempDir). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() // validate @@ -124,7 +124,7 @@ var _ = Describe("Common registry users:", func() { prepare(RegistryRef(Host, ImageRepo, foobar.Tag), subjectRef) statusKey := foobar.AttachFileStateKey statusKey.Name = absAttachFileName - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", absAttachFileName, foobar.AttachFileMedia), "--disable-path-validation"). + ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", absAttachFileName, foobar.AttachFileMedia), "--disable-path-validation"). MatchStatus([]match.StateKey{statusKey}, false, 1). Exec() }) @@ -137,14 +137,14 @@ var _ = Describe("Common registry users:", func() { prepare(RegistryRef(Host, ImageRepo, foobar.Tag), subjectRef) statusKey := foobar.AttachFileStateKey statusKey.Name = absAttachFileName - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", absAttachFileName, foobar.AttachFileMedia)). + ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", absAttachFileName, foobar.AttachFileMedia)). ExpectFailure(). Exec() }) }) }) -var _ = Describe("Fallback registry users:", func() { +var _ = Describe("1.0 registry users:", func() { When("running attach command", func() { It("should attach a file via a OCI Image", func() { testRepo := attachTestRepo("fallback/image") @@ -152,7 +152,7 @@ var _ = Describe("Fallback registry users:", func() { subjectRef := RegistryRef(FallbackHost, testRepo, foobar.Tag) prepare(RegistryRef(FallbackHost, ArtifactRepo, foobar.Tag), subjectRef) // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). + ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(tempDir). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() @@ -170,7 +170,7 @@ var _ = Describe("Fallback registry users:", func() { subjectRef := RegistryRef(FallbackHost, testRepo, foobar.Tag) prepare(RegistryRef(FallbackHost, ArtifactRepo, foobar.Tag), subjectRef) // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). + ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(tempDir). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() @@ -188,7 +188,7 @@ var _ = Describe("Fallback registry users:", func() { subjectRef := RegistryRef(FallbackHost, testRepo, foobar.Tag) prepare(RegistryRef(FallbackHost, ArtifactRepo, foobar.Tag), subjectRef) // test - ORAS("attach", "--artifact-type", "test.attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--distribution-spec", "v1.1-referrers-tag"). + ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--distribution-spec", "v1.1-referrers-tag"). WithWorkDir(tempDir). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() @@ -211,7 +211,7 @@ var _ = Describe("OCI image layout users:", func() { root := PrepareTempFiles() subjectRef := LayoutRef(root, foobar.Tag) prepare(root) - ORAS("attach", "--artifact-type", "test.attach", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). + ORAS("attach", "--artifact-type", "test/attach", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(root). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() }) @@ -223,7 +223,7 @@ var _ = Describe("OCI image layout users:", func() { subjectRef := LayoutRef(root, foobar.Tag) prepare(root) // test - ORAS("attach", "--artifact-type", "test.attach", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--export-manifest", exportName). + ORAS("attach", "--artifact-type", "test/attach", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--export-manifest", exportName). WithWorkDir(root). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() // validate @@ -240,7 +240,7 @@ var _ = Describe("OCI image layout users:", func() { subjectRef := LayoutRef(root, foobar.Tag) prepare(root) // test - ORAS("attach", "--artifact-type", "test.attach", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). + ORAS("attach", "--artifact-type", "test/attach", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(root). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() diff --git a/test/e2e/suite/command/blob.go b/test/e2e/suite/command/blob.go index 12ca81dd2..abf1d0a83 100644 --- a/test/e2e/suite/command/blob.go +++ b/test/e2e/suite/command/blob.go @@ -164,7 +164,7 @@ var _ = Describe("ORAS beginners:", func() { }) }) -var _ = Describe("Common registry users:", func() { +var _ = Describe("1.1 registry users:", func() { repoFmt := fmt.Sprintf("command/blob/%%s/%d/%%s", GinkgoRandomSeed()) When("running `blob delete`", func() { It("should delete a blob with interactive confirmation", func() { diff --git a/test/e2e/suite/command/cp.go b/test/e2e/suite/command/cp.go index 4b49187fa..3d06cf1e4 100644 --- a/test/e2e/suite/command/cp.go +++ b/test/e2e/suite/command/cp.go @@ -68,7 +68,7 @@ func CompareRef(src, dst string) { Expect(srcManifest).To(Equal(dstManifest)) } -var _ = Describe("Common registry users:", func() { +var _ = Describe("1.1 registry users:", func() { When("running `cp`", func() { It("should copy an image to a new repository via tag", func() { src := RegistryRef(Host, ImageRepo, foobar.Tag) diff --git a/test/e2e/suite/command/custom_header.go b/test/e2e/suite/command/custom_header.go index 05408174f..1920ef14d 100644 --- a/test/e2e/suite/command/custom_header.go +++ b/test/e2e/suite/command/custom_header.go @@ -24,7 +24,7 @@ import ( . "oras.land/oras/test/e2e/internal/utils" ) -var _ = Describe("Common registry users:", func() { +var _ = Describe("1.1 registry users:", func() { headerTestRepo := func(text string) string { return fmt.Sprintf("command/headertest/%d/%s", GinkgoRandomSeed(), text) } @@ -40,7 +40,7 @@ var _ = Describe("Common registry users:", func() { tempDir := PrepareTempFiles() subjectRef := RegistryRef(Host, testRepo, foobar.Tag) prepare(RegistryRef(Host, ImageRepo, foobar.Tag), subjectRef) - ORAS("attach", "--artifact-type", "test.attach", subjectRef, + ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "-d", "-H", FoobarHeaderInput, "-H", AbHeaderInput). WithWorkDir(tempDir).MatchRequestHeaders(FoobarHeader, AbHeader).Exec() diff --git a/test/e2e/suite/command/discover.go b/test/e2e/suite/command/discover.go index 22d717d02..15d3ba771 100644 --- a/test/e2e/suite/command/discover.go +++ b/test/e2e/suite/command/discover.go @@ -66,7 +66,7 @@ var _ = Describe("ORAS beginners:", func() { }) }) -var _ = Describe("Common registry users:", func() { +var _ = Describe("1.1 registry users:", func() { subjectRef := RegistryRef(Host, ArtifactRepo, foobar.Tag) When("running discover command with json output", func() { format := "json" @@ -137,7 +137,7 @@ var _ = Describe("Common registry users:", func() { }) }) -var _ = Describe("Fallback registry users:", func() { +var _ = Describe("1.0 registry users:", func() { subjectRef := RegistryRef(FallbackHost, ArtifactRepo, foobar.Tag) When("running discover command", func() { It("should discover direct referrers of a subject via json output", func() { diff --git a/test/e2e/suite/command/manifest.go b/test/e2e/suite/command/manifest.go index 109e4ecc3..44d8f4ff0 100644 --- a/test/e2e/suite/command/manifest.go +++ b/test/e2e/suite/command/manifest.go @@ -168,7 +168,7 @@ var _ = Describe("ORAS beginners:", func() { }) }) -var _ = Describe("Common registry users:", func() { +var _ = Describe("1.1 registry users:", func() { repoFmt := fmt.Sprintf("command/manifest/%%s/%d/%%s", GinkgoRandomSeed()) When("running `manifest fetch`", func() { It("should fetch manifest list with digest", func() { diff --git a/test/e2e/suite/command/repo.go b/test/e2e/suite/command/repo.go index 9cfa3e15e..844c9f5f1 100644 --- a/test/e2e/suite/command/repo.go +++ b/test/e2e/suite/command/repo.go @@ -64,7 +64,7 @@ var _ = Describe("ORAS beginners:", func() { }) }) -var _ = Describe("Common registry users:", func() { +var _ = Describe("1.1 registry users:", func() { When("running `repo ls`", func() { It("should list repositories", func() { ORAS("repository", "list", Host).MatchKeyWords(ImageRepo).Exec() diff --git a/test/e2e/suite/command/resolve_host.go b/test/e2e/suite/command/resolve_host.go index 4a5815a21..a6e95bd47 100644 --- a/test/e2e/suite/command/resolve_host.go +++ b/test/e2e/suite/command/resolve_host.go @@ -67,7 +67,7 @@ func ResolveFlags(reg string, host string, flagType resolveType) []string { return []string{fp + resolveFlag, fmt.Sprintf("%s:80:127.0.0.1:%s", host, port), fp + usernameFlag, Username, fp + passwordFlag, Password, fp + plainHttpFlag} } -var _ = Describe("Common registry users:", func() { +var _ = Describe("1.1 registry users:", func() { if strings.HasPrefix(Host, "localhost:") { When("custom host is provided", func() { // mockedHost represents a non-existent host name which @@ -85,7 +85,7 @@ var _ = Describe("Common registry users:", func() { tempDir := PrepareTempFiles() prepare(RegistryRef(Host, ImageRepo, foobar.Tag), RegistryRef(Host, repo, foobar.Tag)) - ORAS(append([]string{"attach", "--artifact-type", "test.attach", RegistryRef(mockedHost, repo, foobar.Tag), fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)}, unary...)...). + ORAS(append([]string{"attach", "--artifact-type", "test/attach", RegistryRef(mockedHost, repo, foobar.Tag), fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)}, unary...)...). WithWorkDir(tempDir). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() // validate diff --git a/test/e2e/suite/command/tag.go b/test/e2e/suite/command/tag.go index d5836ee26..2a012acc2 100644 --- a/test/e2e/suite/command/tag.go +++ b/test/e2e/suite/command/tag.go @@ -42,7 +42,7 @@ var _ = Describe("ORAS beginners:", func() { }) }) -var _ = Describe("Common registry users:", func() { +var _ = Describe("1.1 registry users:", func() { var tagAndValidate = func(reg string, repo string, tagOrDigest string, digest string, tags ...string) { out := ORAS(append([]string{"tag", RegistryRef(reg, repo, tagOrDigest)}, tags...)...).MatchKeyWords(tags...).Exec().Out hint := regexp.QuoteMeta(fmt.Sprintf("Tagging [registry] %s", RegistryRef(reg, repo, digest))) From 7267ca47714b48fabe6776f16bc6b68df9314c38 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 23 Aug 2023 06:44:35 +0000 Subject: [PATCH 07/28] separate prepare script out Signed-off-by: Billy Zha --- Makefile | 2 +- test/e2e/README.md | 31 +++++++++++------- test/e2e/scripts/e2e.sh | 62 ++++++++++------------------------- test/e2e/scripts/prepare.sh | 64 +++++++++++++++++++++++++++++++++++++ 4 files changed, 101 insertions(+), 58 deletions(-) create mode 100644 test/e2e/scripts/prepare.sh diff --git a/Makefile b/Makefile index df548f223..ffd8d526c 100644 --- a/Makefile +++ b/Makefile @@ -37,7 +37,7 @@ test: tidy vendor check-encoding ## tidy and run tests .PHONY: teste2e teste2e: ## run end to end tests - ./test/e2e/scripts/e2e.sh $(shell git rev-parse --show-toplevel) --clean + ./test/e2e/scripts/e2e.sh $(shell git rev-parse --show-toplevel) --clean .PHONY: covhtml covhtml: ## look at code coverage diff --git a/test/e2e/README.md b/test/e2e/README.md index 15be2cff1..5837e3a47 100644 --- a/test/e2e/README.md +++ b/test/e2e/README.md @@ -5,8 +5,8 @@ Install [git](https://git-scm.com/download/linux), [docker](https://docs.docker. ## Run E2E Script ```shell -REPO_ROOT=$(git rev-parse --show-toplevel) # REPO_ROOT is root folder of oras CLI code -$REPO_ROOT/test/e2e/scripts/e2e.sh $REPO_ROOT --clean +# in root folder of oras CLI code +make teste2e ``` If the tests fails with errors like `ginkgo: not found`, use below command to add GOPATH into the PATH variable @@ -15,13 +15,20 @@ PATH+=:$(go env GOPATH)/bin ``` ## Development -### 1. Using IDE +### 1. Prepare E2E Test Environment +You may use the prepare script to setup an E2E test environment before developing E2E tests: +```shell +REPO_ROOT=$(git rev-parse --show-toplevel) # REPO_ROOT is root folder of oras CLI code +$REPO_ROOT/test/e2e/scripts/prepare.sh $REPO_ROOT +``` + +### 2. Using IDE Since E2E test suites are added as an nested module, the module file and checksum file are separated from oras CLI. To develop E2E tests, it's better to set the working directory to `$REPO_ROOT/test/e2e/` or open your IDE at it. -### 2. Testing pre-built ORAS Binary +### 3. Testing pre-built ORAS Binary By default, Gomega builds a temp binary every time before running e2e tests, which makes sure that latest code changes in the working directory are covered. If you are making changes to E2E test code only, set `ORAS_PATH` towards your pre-built ORAS binary to skip building and speed up the test. -### 3. Debugging via `go test` +### 4. Debugging via `go test` E2E specs can be ran natively without `ginkgo`: ```shell # run below command in the target test suite folder @@ -29,7 +36,7 @@ go test oras.land/oras/test/e2e/suite/${suite_name} ``` This is super handy when you want to do step-by-step debugging from command-line or via an IDE. If you need to debug certain specs, use [focused specs](https://onsi.github.io/ginkgo/#focused-specs) but don't check it in. -### 4. Testing Registry Services +### 5. Testing Registry Services The backend of E2E tests are three registry services: - [oras-distribution](https://github.com/oras-project/distribution): registry service supports artifact and image types in [image-spec 1.1.0 rc2](https://github.com/opencontainers/image-spec/tree/v1.1.0-rc2) and referrer API - [upstream distribution](https://github.com/distribution/distribution): registry service supports image media type with subject and provide referrers via [tag schema](https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#referrers-tag-schema). @@ -37,17 +44,17 @@ The backend of E2E tests are three registry services: You can run scenario test suite against your own registry services via setting `ORAS_REGISTRY_HOST`, `ORAS_REGISTRY_FALLBACK_HOST` and `ZOT_REGISTRY_HOST` environmental variables. -### 5. Constant Build & Watch +### 6. Constant Build & Watch This is a good choice if you want to debug certain re-runnable specs: ```shell cd $REPO_ROOT/test/e2e ginkgo watch -r ``` -### 6. Trouble-shooting CLI +### 7. Trouble-shooting CLI The executed commands should be shown in the ginkgo logs after `[It]`, with full execution output in the E2E log. -### 7. Adding New Tests +### 8. Adding New Tests Three suites will be maintained for E2E testing: - command: contains test specs for single oras command execution - auth: contains test specs similar to command specs but specific to auth. It cannot be ran in parallel with command suite specs @@ -62,9 +69,9 @@ Describe: Expect: (detailed checks for execution results) ``` -### 8. Adding New Test Data +### 9. Adding New Test Data -#### 8.1 Command Suite +#### 9.1 Command Suite Command suite uses pre-baked test data, which is a bunch of layered archive files compressed from registry storage. Test data are all stored in `$REPO_ROOT/test/e2e/testdata/distribution/` but separated in different sub-folders: oras distribution uses `mount` and upstream distribution uses `mount_fallback`. For both registries, the repository name should follow the convention of `command/$repo_suffix`. To add a new layer to the test data, use the below command to compress the `docker` folder from the root directory of the registry storage and copy it to the corresponding subfolder in `$REPO_ROOT/test/e2e/testdata/distribution/mount`. @@ -138,5 +145,5 @@ graph TD; end end ``` -#### 8.2 Scenario Suite +#### 9.2 Scenario Suite Test files used by scenario-based specs are placed in `$REPO_ROOT/test/e2e/testdata/files`. \ No newline at end of file diff --git a/test/e2e/scripts/e2e.sh b/test/e2e/scripts/e2e.sh index 1198b4873..3e9b7989c 100755 --- a/test/e2e/scripts/e2e.sh +++ b/test/e2e/scripts/e2e.sh @@ -13,62 +13,34 @@ # See the License for the specific language governing permissions and # limitations under the License. -export ORAS_REGISTRY_PORT="5000" -export ORAS_REGISTRY_HOST="localhost:${ORAS_REGISTRY_PORT}" -export ORAS_REGISTRY_FALLBACK_PORT="6000" -export ORAS_REGISTRY_FALLBACK_HOST="localhost:${ORAS_REGISTRY_FALLBACK_PORT}" -export ZOT_REGISTRY_PORT="7000" -export ZOT_REGISTRY_HOST="localhost:${ZOT_REGISTRY_PORT}" +# help +help () { + echo "Usage" + echo " e2e.sh [--clean]" + exit 1 +} +# 1. Prepare repo_root=$1 if [ -z "${repo_root}" ]; then echo "repository root path is not provided." - echo "Usage" - echo " e2e.sh [--clean]" - exit 1 + help fi -clean_up=$2 -echo " === installing ginkgo === " -repo_root=$(realpath --canonicalize-existing ${repo_root}) -cwd=$(pwd) -cd ${repo_root}/test/e2e && go install github.com/onsi/ginkgo/v2/ginkgo@latest -trap "cd $cwd" EXIT - -# start registries -. ${repo_root}/test/e2e/scripts/common.sh +clean=$2 +if [ "${clean}" != '--clean' ] && [ -n "${clean}" ]; then + echo "invalid flag found: ${clean}" + help +fi -e2e_root="${repo_root}/test/e2e" -oras_container_name="oras-e2e" -upstream_container_name="oras-e2e-fallback" -zot_container_name="oras-e2e-zot" +. ${repo_root}/test/e2e/scripts/prepare.sh $1 $2 -if [ "$clean_up" = '--clean' ]; then +if [ "${clean}" = '--clean' ]; then echo " === setting deferred clean up jobs === " - trap "try_clean_up $oras_container_name $upstream_container_name $zot_container_name" EXIT + trap "try_clean_up $ORAS_CTR_NAME $UPSTREAM_CTR_NAME $ZOT_CTR_NAME" EXIT fi -echo " === preparing oras distribution === " -run_registry \ - ${e2e_root}/testdata/distribution/mount \ - ghcr.io/oras-project/registry:v1.0.0-rc.4 \ - $oras_container_name \ - $ORAS_REGISTRY_PORT - -echo " === preparing upstream distribution === " -run_registry \ - ${e2e_root}/testdata/distribution/mount_fallback \ - registry:2.8.1 \ - $upstream_container_name \ - $ORAS_REGISTRY_FALLBACK_PORT - -echo " === preparing zot === " -try_clean_up $zot_container_name -docker run -d -p $ZOT_REGISTRY_PORT:5000 -it \ - --name $zot_container_name \ - --mount type=bind,source="${e2e_root}/testdata/zot/",target=/etc/zot \ - --rm ghcr.io/project-zot/zot-linux-amd64:v2.0.0-rc6 - +# 2. Test echo " === run tests === " if ! ginkgo -r -p --succinct suite; then echo " === retriving registry error logs === " diff --git a/test/e2e/scripts/prepare.sh b/test/e2e/scripts/prepare.sh new file mode 100644 index 000000000..1098777c6 --- /dev/null +++ b/test/e2e/scripts/prepare.sh @@ -0,0 +1,64 @@ +#!/bin/sh -e + +# Copyright The ORAS Authors. +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. + +export ORAS_REGISTRY_PORT="5000" +export ORAS_REGISTRY_HOST="localhost:${ORAS_REGISTRY_PORT}" +export ORAS_REGISTRY_FALLBACK_PORT="6000" +export ORAS_REGISTRY_FALLBACK_HOST="localhost:${ORAS_REGISTRY_FALLBACK_PORT}" +export ZOT_REGISTRY_PORT="7000" +export ZOT_REGISTRY_HOST="localhost:${ZOT_REGISTRY_PORT}" +export ORAS_CTR_NAME="oras-e2e" +export UPSTREAM_CTR_NAME="oras-e2e-fallback" +export ZOT_CTR_NAME="oras-e2e-zot" + +repo_root=$1 +if [ -z "${repo_root}" ]; then + echo "repository root path is not provided." + echo "Usage" + echo " prepare.sh " + exit 1 +fi +e2e_root="${repo_root}/test/e2e" + +echo " === installing ginkgo === " +repo_root=$(realpath --canonicalize-existing ${repo_root}) +cwd=$(pwd) +cd ${repo_root}/test/e2e && go install github.com/onsi/ginkgo/v2/ginkgo@latest +trap "cd $cwd" EXIT + +# start registries +. ${repo_root}/test/e2e/scripts/common.sh + + +echo " === preparing oras distribution === " +run_registry \ + ${e2e_root}/testdata/distribution/mount \ + ghcr.io/oras-project/registry:v1.0.0-rc.4 \ + $ORAS_CTR_NAME \ + $ORAS_REGISTRY_PORT + +echo " === preparing upstream distribution === " +run_registry \ + ${e2e_root}/testdata/distribution/mount_fallback \ + registry:2.8.1 \ + $UPSTREAM_CTR_NAME \ + $ORAS_REGISTRY_FALLBACK_PORT + +echo " === preparing zot === " +try_clean_up $ZOT_CTR_NAME +docker run -d -p $ZOT_REGISTRY_PORT:5000 -it \ + --name $ZOT_CTR_NAME \ + --mount type=bind,source="${e2e_root}/testdata/zot/",target=/etc/zot \ + --rm ghcr.io/project-zot/zot-linux-amd64:v2.0.0-rc6 From a2cc4ea857068a488f9a7388ef8562ab89b03599 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 23 Aug 2023 07:06:46 +0000 Subject: [PATCH 08/28] check in zot config Signed-off-by: Billy Zha --- test/e2e/testdata/zot/config.json | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) create mode 100644 test/e2e/testdata/zot/config.json diff --git a/test/e2e/testdata/zot/config.json b/test/e2e/testdata/zot/config.json new file mode 100644 index 000000000..3eab8b75d --- /dev/null +++ b/test/e2e/testdata/zot/config.json @@ -0,0 +1,17 @@ +{ + "storage": { + "rootDirectory": "/var/lib/registry" + }, + "http": { + "address": "0.0.0.0", + "port": "5000", + "auth": { + "htpasswd": { + "path": "/etc/zot/passwd_bcrypt" + } + } + }, + "log": { + "level": "debug" + } +} \ No newline at end of file From e5f73987598f056acd22711edfeff309e7b73b32 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 23 Aug 2023 07:09:05 +0000 Subject: [PATCH 09/28] add run access Signed-off-by: Billy Zha --- test/e2e/scripts/prepare.sh | 0 1 file changed, 0 insertions(+), 0 deletions(-) mode change 100644 => 100755 test/e2e/scripts/prepare.sh diff --git a/test/e2e/scripts/prepare.sh b/test/e2e/scripts/prepare.sh old mode 100644 new mode 100755 From 2feed93ba54ef9b9481fd00e6200c16177094c06 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Wed, 23 Aug 2023 07:17:05 +0000 Subject: [PATCH 10/28] fix prepare bug Signed-off-by: Billy Zha --- test/e2e/scripts/prepare.sh | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/test/e2e/scripts/prepare.sh b/test/e2e/scripts/prepare.sh index 1098777c6..cb5593d29 100755 --- a/test/e2e/scripts/prepare.sh +++ b/test/e2e/scripts/prepare.sh @@ -30,7 +30,6 @@ if [ -z "${repo_root}" ]; then echo " prepare.sh " exit 1 fi -e2e_root="${repo_root}/test/e2e" echo " === installing ginkgo === " repo_root=$(realpath --canonicalize-existing ${repo_root}) @@ -40,25 +39,27 @@ trap "cd $cwd" EXIT # start registries . ${repo_root}/test/e2e/scripts/common.sh - - -echo " === preparing oras distribution === " +echo " >>> preparing: oras distribution >>> " +e2e_root="${repo_root}/test/e2e" run_registry \ ${e2e_root}/testdata/distribution/mount \ ghcr.io/oras-project/registry:v1.0.0-rc.4 \ $ORAS_CTR_NAME \ $ORAS_REGISTRY_PORT +echo " <<< prepared : oras distribution <<< " -echo " === preparing upstream distribution === " +echo " >>> preparing: upstream distribution >>> " run_registry \ ${e2e_root}/testdata/distribution/mount_fallback \ registry:2.8.1 \ $UPSTREAM_CTR_NAME \ $ORAS_REGISTRY_FALLBACK_PORT +echo " prepared : upstream distribution " -echo " === preparing zot === " +echo " >>> preparing: zot >>> " try_clean_up $ZOT_CTR_NAME docker run -d -p $ZOT_REGISTRY_PORT:5000 -it \ --name $ZOT_CTR_NAME \ --mount type=bind,source="${e2e_root}/testdata/zot/",target=/etc/zot \ --rm ghcr.io/project-zot/zot-linux-amd64:v2.0.0-rc6 +echo " <<< prepared : zot <<< " From 96fc8899b841d4812b2f8f6d7422d43ac49ca208 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Thu, 24 Aug 2023 02:05:59 +0000 Subject: [PATCH 11/28] remove prepare changes Signed-off-by: Billy Zha --- test/e2e/internal/utils/prepare.go | 6 ------ 1 file changed, 6 deletions(-) diff --git a/test/e2e/internal/utils/prepare.go b/test/e2e/internal/utils/prepare.go index 3359d2b86..eea029237 100644 --- a/test/e2e/internal/utils/prepare.go +++ b/test/e2e/internal/utils/prepare.go @@ -28,12 +28,6 @@ import ( "github.com/onsi/gomega/gbytes" ) -func PrepareRepository() string { - tempDir := GinkgoT().TempDir() - Expect(CopyTestFiles(tempDir)).ShouldNot(HaveOccurred()) - return tempDir -} - // PrepareTempFiles copies test data into a temp folder and return it. func PrepareTempFiles() string { tempDir := GinkgoT().TempDir() From 2c2b597e02d42b716a401c014c819307d04412af Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Fri, 25 Aug 2023 05:55:05 +0000 Subject: [PATCH 12/28] run zot container via current user Signed-off-by: Billy Zha --- test/e2e/scripts/prepare.sh | 3 ++- test/e2e/testdata/zot/config.json | 2 +- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/test/e2e/scripts/prepare.sh b/test/e2e/scripts/prepare.sh index cb5593d29..e040507ef 100755 --- a/test/e2e/scripts/prepare.sh +++ b/test/e2e/scripts/prepare.sh @@ -58,8 +58,9 @@ echo " prepared : upstream distribution " echo " >>> preparing: zot >>> " try_clean_up $ZOT_CTR_NAME -docker run -d -p $ZOT_REGISTRY_PORT:5000 -it \ +docker run --pull always -dp $ZOT_REGISTRY_PORT:5000 \ --name $ZOT_CTR_NAME \ + -u $(id -u $(whoami)) \ --mount type=bind,source="${e2e_root}/testdata/zot/",target=/etc/zot \ --rm ghcr.io/project-zot/zot-linux-amd64:v2.0.0-rc6 echo " <<< prepared : zot <<< " diff --git a/test/e2e/testdata/zot/config.json b/test/e2e/testdata/zot/config.json index 3eab8b75d..843360d91 100644 --- a/test/e2e/testdata/zot/config.json +++ b/test/e2e/testdata/zot/config.json @@ -1,6 +1,6 @@ { "storage": { - "rootDirectory": "/var/lib/registry" + "rootDirectory": "/etc/zot" }, "http": { "address": "0.0.0.0", From 6f9f3c2a12ad250400bac76dcd06bb09f1786f63 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Fri, 25 Aug 2023 05:58:45 +0000 Subject: [PATCH 13/28] rename zot Signed-off-by: Billy Zha --- test/e2e/internal/utils/init.go | 16 +++++----- test/e2e/internal/utils/testdata.go | 2 +- test/e2e/suite/auth/auth.go | 40 ++++++++++++------------- test/e2e/suite/scenario/oci_artifact.go | 16 +++++----- 4 files changed, 37 insertions(+), 37 deletions(-) diff --git a/test/e2e/internal/utils/init.go b/test/e2e/internal/utils/init.go index 977cd4f8d..5218aa367 100644 --- a/test/e2e/internal/utils/init.go +++ b/test/e2e/internal/utils/init.go @@ -36,8 +36,8 @@ var Host string // FallbackHost points to the registry service where fallback E2E specs will be run against. var FallbackHost string -// ZotHost points to the zot service where E2E specs will be run against. -var ZotHost string +// ZOTHost points to the zot service where E2E specs will be run against. +var ZOTHost string func init() { Host = os.Getenv(RegHostKey) @@ -62,12 +62,12 @@ func init() { panic(err) } - ZotHost = os.Getenv(ZotHostKey) - if ZotHost == "" { - ZotHost = "localhost:7000" - fmt.Fprintf(os.Stderr, "cannot find zot host name in %s, using %s instead\n", ZotHostKey, ZotHost) + ZOTHost = os.Getenv(ZOTHostKey) + if ZOTHost == "" { + ZOTHost = "localhost:7000" + fmt.Fprintf(os.Stderr, "cannot find zot host name in %s, using %s instead\n", ZOTHostKey, ZOTHost) } - ref.Registry = ZotHost + ref.Registry = ZOTHost if err := ref.ValidateRegistry(); err != nil { panic(err) } @@ -124,7 +124,7 @@ func init() { gomega.Expect(cmd.Run()).ShouldNot(gomega.HaveOccurred()) cmd = exec.Command(ORASPath, "login", FallbackHost, "-u", Username, "-p", Password) gomega.Expect(cmd.Run()).ShouldNot(gomega.HaveOccurred()) - cmd = exec.Command(ORASPath, "login", ZotHost, "-u", Username, "-p", Password) + cmd = exec.Command(ORASPath, "login", ZOTHost, "-u", Username, "-p", Password) gomega.Expect(cmd.Run()).ShouldNot(gomega.HaveOccurred()) }) } diff --git a/test/e2e/internal/utils/testdata.go b/test/e2e/internal/utils/testdata.go index eb7e4ab28..c29cce1f8 100644 --- a/test/e2e/internal/utils/testdata.go +++ b/test/e2e/internal/utils/testdata.go @@ -25,7 +25,7 @@ const ( // env RegHostKey = "ORAS_REGISTRY_HOST" FallbackRegHostKey = "ORAS_REGISTRY_FALLBACK_HOST" - ZotHostKey = "ZOT_REGISTRY_HOST" + ZOTHostKey = "ZOT_REGISTRY_HOST" ) var ( diff --git a/test/e2e/suite/auth/auth.go b/test/e2e/suite/auth/auth.go index 49176c78e..e664e6cbc 100644 --- a/test/e2e/suite/auth/auth.go +++ b/test/e2e/suite/auth/auth.go @@ -27,38 +27,38 @@ import ( var _ = Describe("Common registry user", Ordered, func() { When("logging out", Ordered, func() { It("should use logout command to logout", func() { - ORAS("logout", ZotHost, "--registry-config", AuthConfigPath).Exec() + ORAS("logout", ZOTHost, "--registry-config", AuthConfigPath).Exec() }) It("should run commands without logging in", func() { - RunWithoutLogin("attach", ZotHost+"/repo:tag", "-a", "test=true", "--artifact-type", "doc/example") - ORAS("copy", ZotHost+"/repo:from", ZotHost+"/repo:to", "--from-registry-config", AuthConfigPath, "--to-registry-config", AuthConfigPath). + RunWithoutLogin("attach", ZOTHost+"/repo:tag", "-a", "test=true", "--artifact-type", "doc/example") + ORAS("copy", ZOTHost+"/repo:from", ZOTHost+"/repo:to", "--from-registry-config", AuthConfigPath, "--to-registry-config", AuthConfigPath). ExpectFailure(). MatchErrKeyWords("Error:", "credential required"). WithDescription("fail without logging in").Exec() - RunWithoutLogin("discover", ZotHost+"/repo:tag") - RunWithoutLogin("push", "-a", "key=value", ZotHost+"/repo:tag") - RunWithoutLogin("pull", ZotHost+"/repo:tag") - RunWithoutLogin("manifest", "fetch", ZotHost+"/repo:tag") - RunWithoutLogin("blob", "delete", ZotHost+"/repo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") - RunWithoutLogin("blob", "push", ZotHost+"/repo", WriteTempFile("blob", "test")) - RunWithoutLogin("tag", ZotHost+"/repo:tag", "tag1") - RunWithoutLogin("repo", "ls", ZotHost) - RunWithoutLogin("repo", "tags", RegistryRef(ZotHost, "repo", "")) - RunWithoutLogin("manifest", "fetch-config", ZotHost+"/repo:tag") + RunWithoutLogin("discover", ZOTHost+"/repo:tag") + RunWithoutLogin("push", "-a", "key=value", ZOTHost+"/repo:tag") + RunWithoutLogin("pull", ZOTHost+"/repo:tag") + RunWithoutLogin("manifest", "fetch", ZOTHost+"/repo:tag") + RunWithoutLogin("blob", "delete", ZOTHost+"/repo@sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa") + RunWithoutLogin("blob", "push", ZOTHost+"/repo", WriteTempFile("blob", "test")) + RunWithoutLogin("tag", ZOTHost+"/repo:tag", "tag1") + RunWithoutLogin("repo", "ls", ZOTHost) + RunWithoutLogin("repo", "tags", RegistryRef(ZOTHost, "repo", "")) + RunWithoutLogin("manifest", "fetch-config", ZOTHost+"/repo:tag") }) }) When("logging in", func() { It("should use basic auth", func() { - ORAS("login", ZotHost, "-u", Username, "-p", Password, "--registry-config", AuthConfigPath). + ORAS("login", ZOTHost, "-u", Username, "-p", Password, "--registry-config", AuthConfigPath). WithTimeOut(20*time.Second). MatchContent("Login Succeeded\n"). MatchErrKeyWords("WARNING", "Using --password via the CLI is insecure", "Use --password-stdin").Exec() }) It("should fail if no username input", func() { - ORAS("login", ZotHost, "--registry-config", AuthConfigPath). + ORAS("login", ZOTHost, "--registry-config", AuthConfigPath). WithTimeOut(20 * time.Second). WithInput(strings.NewReader("")). MatchKeyWords("username:"). @@ -67,14 +67,14 @@ var _ = Describe("Common registry user", Ordered, func() { }) It("should fail if no password input", func() { - ORAS("login", ZotHost, "--registry-config", AuthConfigPath). + ORAS("login", ZOTHost, "--registry-config", AuthConfigPath). WithTimeOut(20*time.Second). MatchKeyWords("Username: ", "Password: "). WithInput(strings.NewReader(fmt.Sprintf("%s\n", Username))).ExpectFailure().Exec() }) It("should fail if password is empty", func() { - ORAS("login", ZotHost, "--registry-config", AuthConfigPath). + ORAS("login", ZOTHost, "--registry-config", AuthConfigPath). WithTimeOut(20*time.Second). MatchKeyWords("Username: ", "Password: "). MatchErrKeyWords("Error: password required"). @@ -82,14 +82,14 @@ var _ = Describe("Common registry user", Ordered, func() { }) It("should fail if no token input", func() { - ORAS("login", ZotHost, "--registry-config", AuthConfigPath). + ORAS("login", ZOTHost, "--registry-config", AuthConfigPath). WithTimeOut(20*time.Second). MatchKeyWords("Username: ", "Token: "). WithInput(strings.NewReader("\n")).ExpectFailure().Exec() }) It("should fail if token is empty", func() { - ORAS("login", ZotHost, "--registry-config", AuthConfigPath). + ORAS("login", ZOTHost, "--registry-config", AuthConfigPath). WithTimeOut(20*time.Second). MatchKeyWords("Username: ", "Token: "). MatchErrKeyWords("Error: token required"). @@ -97,7 +97,7 @@ var _ = Describe("Common registry user", Ordered, func() { }) It("should use prompted input", func() { - ORAS("login", ZotHost, "--registry-config", AuthConfigPath). + ORAS("login", ZOTHost, "--registry-config", AuthConfigPath). WithTimeOut(20*time.Second). WithInput(strings.NewReader(fmt.Sprintf("%s\n%s\n", Username, Password))). MatchKeyWords("Username: ", "Password: ", "Login Succeeded\n").Exec() diff --git a/test/e2e/suite/scenario/oci_artifact.go b/test/e2e/suite/scenario/oci_artifact.go index fe9d4eb74..326146464 100644 --- a/test/e2e/suite/scenario/oci_artifact.go +++ b/test/e2e/suite/scenario/oci_artifact.go @@ -37,15 +37,15 @@ var _ = Describe("OCI artifact users:", Ordered, func() { pulledManifest := "packed.json" pullRoot := "pulled" It("should push and pull an artifact", func() { - ORAS("push", RegistryRef(ZotHost, repo, tag), "--artifact-type", "test/artifact", foobar.FileLayerNames[0], foobar.FileLayerNames[1], foobar.FileLayerNames[2], "-v", "--export-manifest", pulledManifest). + ORAS("push", RegistryRef(ZOTHost, repo, tag), "--artifact-type", "test/artifact", foobar.FileLayerNames[0], foobar.FileLayerNames[1], foobar.FileLayerNames[2], "-v", "--export-manifest", pulledManifest). MatchStatus(foobar.FileStateKeys, true, 3). WithWorkDir(tempDir). WithDescription("push with manifest exported").Exec() - fetched := ORAS("manifest", "fetch", RegistryRef(ZotHost, repo, tag)).Exec() + fetched := ORAS("manifest", "fetch", RegistryRef(ZOTHost, repo, tag)).Exec() MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout) - ORAS("pull", RegistryRef(ZotHost, repo, tag), "-v", "-o", pullRoot). + ORAS("pull", RegistryRef(ZOTHost, repo, tag), "-v", "-o", pullRoot). MatchStatus(foobar.FileStateKeys, true, 3). WithWorkDir(tempDir). WithDescription("pull artFiles with config").Exec() @@ -58,7 +58,7 @@ var _ = Describe("OCI artifact users:", Ordered, func() { }) It("should attach and pull an artifact", func() { - subject := RegistryRef(ZotHost, repo, tag) + subject := RegistryRef(ZOTHost, repo, tag) ORAS("attach", subject, "--artifact-type", "test/artifact1", fmt.Sprint(foobar.AttachFileName, ":", foobar.AttachFileMedia), "-v", "--export-manifest", pulledManifest). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, true, 1). WithWorkDir(tempDir). @@ -66,10 +66,10 @@ var _ = Describe("OCI artifact users:", Ordered, func() { session := ORAS("discover", subject, "-o", "json").Exec() digest := string(Binary("jq", "-r", ".manifests[].digest").WithInput(session.Out).Exec().Out.Contents()) - fetched := ORAS("manifest", "fetch", RegistryRef(ZotHost, repo, digest)).MatchKeyWords(foobar.AttachFileMedia).Exec() + fetched := ORAS("manifest", "fetch", RegistryRef(ZOTHost, repo, digest)).MatchKeyWords(foobar.AttachFileMedia).Exec() MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout) - ORAS("pull", RegistryRef(ZotHost, repo, digest), "-v", "-o", pullRoot). + ORAS("pull", RegistryRef(ZOTHost, repo, digest), "-v", "-o", pullRoot). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, true, 1). WithWorkDir(tempDir). WithDescription("pull attached artifact").Exec() @@ -84,10 +84,10 @@ var _ = Describe("OCI artifact users:", Ordered, func() { session = ORAS("discover", subject, "-o", "json", "--artifact-type", "test/artifact2").Exec() digest = string(Binary("jq", "-r", ".manifests[].digest").WithInput(session.Out).Exec().Out.Contents()) - fetched = ORAS("manifest", "fetch", RegistryRef(ZotHost, repo, digest)).MatchKeyWords(foobar.AttachFileMedia).Exec() + fetched = ORAS("manifest", "fetch", RegistryRef(ZOTHost, repo, digest)).MatchKeyWords(foobar.AttachFileMedia).Exec() MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout) - ORAS("pull", RegistryRef(ZotHost, repo, string(digest)), "-v", "-o", pullRoot, "--include-subject"). + ORAS("pull", RegistryRef(ZOTHost, repo, string(digest)), "-v", "-o", pullRoot, "--include-subject"). MatchStatus(append(foobar.FileStateKeys, foobar.AttachFileStateKey), true, 4). WithWorkDir(tempDir). WithDescription("pull attached artifact and subject").Exec() From 0a0029216e326443b8f9f09d54ad69d4f4788bb9 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Fri, 25 Aug 2023 08:15:31 +0000 Subject: [PATCH 14/28] add images repo for command suite and attach tests Signed-off-by: Billy Zha --- .gitignore | 7 +++ test/e2e/internal/utils/prepare.go | 16 ++++++ test/e2e/suite/command/attach.go | 45 +++++++--------- ...1815e2881f1eec22958d604301904c5353041794c1 | 4 ++ ...3c1d30413413422d706483bfa0f98a5e886266e7ae | 1 + ...b5cc8fc5cc1fb637dfaedb3a9afc89bf16db9277e1 | Bin 0 -> 10240 bytes ...16f7e8649e94fb4fc21fe77e8310c060f61caaff8a | 1 + ...772dc6ab72130d9ac1906aed2fc7589a5cd145433c | 1 + ...007a025c594ce12aa7e6da27d21c7b14b50112e255 | 1 + ...8ed157ba7d1edfe7f9b8766728b8a1f25c0d9c14c1 | 1 + ...10591f0203bb6e07f11e2fb0ce1b8508e9aac4ebe2 | 5 ++ ...a28c6bc5806b7fa581c9ad7883be955a64e3cc034f | 1 + ...b721fe9b5c338d10ee429ea04fae5511b68fbf8fb9 | 1 + ...6cb4e7df0ab8a9d24adc57825099f522fe009a22bb | 1 + ...8c309f0b5afb2cc513b7a3d456b6cc29fe641386c5 | 4 ++ .../testdata/zot/command/images/index.json | 49 ++++++++++++++++++ .../testdata/zot/command/images/oci-layout | 1 + 17 files changed, 113 insertions(+), 26 deletions(-) create mode 100644 test/e2e/testdata/zot/command/images/blobs/sha256/1fd9a5fc54b634130102861815e2881f1eec22958d604301904c5353041794c1 create mode 100644 test/e2e/testdata/zot/command/images/blobs/sha256/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae create mode 100644 test/e2e/testdata/zot/command/images/blobs/sha256/2ef548696ac7dd66ef38aab5cc8fc5cc1fb637dfaedb3a9afc89bf16db9277e1 create mode 100644 test/e2e/testdata/zot/command/images/blobs/sha256/44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a create mode 100644 test/e2e/testdata/zot/command/images/blobs/sha256/4f93460061882467e6fb3b772dc6ab72130d9ac1906aed2fc7589a5cd145433c create mode 100644 test/e2e/testdata/zot/command/images/blobs/sha256/58efe73e78fe043ca31b89007a025c594ce12aa7e6da27d21c7b14b50112e255 create mode 100644 test/e2e/testdata/zot/command/images/blobs/sha256/9d84a5716c66a1d1b9c13f8ed157ba7d1edfe7f9b8766728b8a1f25c0d9c14c1 create mode 100644 test/e2e/testdata/zot/command/images/blobs/sha256/a5dfce5d28768e985f91f610591f0203bb6e07f11e2fb0ce1b8508e9aac4ebe2 create mode 100644 test/e2e/testdata/zot/command/images/blobs/sha256/e2bfc9cc6a84ec2d7365b5a28c6bc5806b7fa581c9ad7883be955a64e3cc034f create mode 100644 test/e2e/testdata/zot/command/images/blobs/sha256/fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9 create mode 100644 test/e2e/testdata/zot/command/images/blobs/sha256/fd6ed2f36b5465244d5dc86cb4e7df0ab8a9d24adc57825099f522fe009a22bb create mode 100644 test/e2e/testdata/zot/command/images/blobs/sha256/fe9dbc99451d0517d65e048c309f0b5afb2cc513b7a3d456b6cc29fe641386c5 create mode 100644 test/e2e/testdata/zot/command/images/index.json create mode 100644 test/e2e/testdata/zot/command/images/oci-layout diff --git a/.gitignore b/.gitignore index 0c2f8f30d..cb04bf2f0 100644 --- a/.gitignore +++ b/.gitignore @@ -49,3 +49,10 @@ _dist/ # Distribution storage files for local E2E testing test/e2e/testdata/distribution/mount/docker/ test/e2e/testdata/distribution/mount_fallback/docker/ + + +# OCI Layout Files ZOT storage files for local E2E testing +test/e2e/testdata/zot/ +!test/e2e/testdata/zot/command/images +!test/e2e/testdata/zot/config.json +!test/e2e/testdata/zot/passwd_bcrypt \ No newline at end of file diff --git a/test/e2e/internal/utils/prepare.go b/test/e2e/internal/utils/prepare.go index eea029237..3416e6641 100644 --- a/test/e2e/internal/utils/prepare.go +++ b/test/e2e/internal/utils/prepare.go @@ -28,6 +28,22 @@ import ( "github.com/onsi/gomega/gbytes" ) +// CopyZotRepo copies oci layout data between repostories. +func CopyZotRepo(fromRepo string, toRepo string) { + zotRoot := filepath.Join(TestDataRoot, "zot") + fromRepo = filepath.Join(zotRoot, fromRepo) + toRepo = filepath.Join(zotRoot, toRepo) + Expect(CopyFiles(fromRepo, toRepo)).ShouldNot(HaveOccurred()) +} + +// PrepareTempOCI prepares an OCI layout root via copying from an ZOT repo and +// return the path. +func PrepareTempOCI(fromZotRepo string) string { + root := PrepareTempFiles() + Expect(CopyFiles(filepath.Join(TestDataRoot, "zot", fromZotRepo), root)).ShouldNot(HaveOccurred()) + return root +} + // PrepareTempFiles copies test data into a temp folder and return it. func PrepareTempFiles() string { tempDir := GinkgoT().TempDir() diff --git a/test/e2e/suite/command/attach.go b/test/e2e/suite/command/attach.go index c9c58c2ee..d827b987c 100644 --- a/test/e2e/suite/command/attach.go +++ b/test/e2e/suite/command/attach.go @@ -46,22 +46,22 @@ var _ = Describe("ORAS beginners:", func() { }) It("should fail when no subject reference provided", func() { - ORAS("attach", "--artifact-type", "oras.test").ExpectFailure().MatchErrKeyWords("Error:").Exec() + ORAS("attach", "--artifact-type", "oras/test").ExpectFailure().MatchErrKeyWords("Error:").Exec() }) It("should fail if no file reference or manifest annotation provided for registry", func() { - ORAS("attach", "--artifact-type", "oras.test", RegistryRef(Host, ImageRepo, foobar.Tag)). + ORAS("attach", "--artifact-type", "oras/test", RegistryRef(ZOTHost, ImageRepo, foobar.Tag)). ExpectFailure().MatchErrKeyWords("Error: no blob or manifest annotation are provided").Exec() }) It("should fail if no file reference or manifest annotation provided for OCI layout", func() { root := GinkgoT().TempDir() - ORAS("attach", "--artifact-type", "oras.test", LayoutRef(root, foobar.Tag)). + ORAS("attach", "--artifact-type", "oras/test", LayoutRef(root, foobar.Tag)). ExpectFailure().MatchErrKeyWords("Error: no blob or manifest annotation are provided").Exec() }) It("should fail if distribution spec is unkown", func() { - ORAS("attach", "--artifact-type", "oras.test", RegistryRef(Host, ImageRepo, foobar.Tag), "--distribution-spec", "???"). + ORAS("attach", "--artifact-type", "oras/test", RegistryRef(ZOTHost, ImageRepo, foobar.Tag), "--distribution-spec", "???"). ExpectFailure().MatchErrKeyWords("unknown distribution specification flag").Exec() }) }) @@ -71,11 +71,10 @@ var _ = Describe("1.1 registry users:", func() { When("running attach command", func() { It("should attach a file to a subject", func() { testRepo := attachTestRepo("simple") - tempDir := PrepareTempFiles() - subjectRef := RegistryRef(Host, testRepo, foobar.Tag) - prepare(RegistryRef(Host, ImageRepo, foobar.Tag), subjectRef) + CopyZotRepo(ImageRepo, testRepo) + subjectRef := RegistryRef(ZOTHost, testRepo, foobar.Tag) ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). - WithWorkDir(tempDir). + WithWorkDir(PrepareTempFiles()). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() }) @@ -84,8 +83,8 @@ var _ = Describe("1.1 registry users:", func() { testRepo := attachTestRepo("export-manifest") tempDir := PrepareTempFiles() exportName := "manifest.json" - subjectRef := RegistryRef(Host, testRepo, foobar.Tag) - prepare(RegistryRef(Host, ImageRepo, foobar.Tag), subjectRef) + subjectRef := RegistryRef(ZOTHost, testRepo, foobar.Tag) + CopyZotRepo(ImageRepo, testRepo) // test ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--export-manifest", exportName). WithWorkDir(tempDir). @@ -95,15 +94,15 @@ var _ = Describe("1.1 registry users:", func() { bytes := ORAS("discover", subjectRef, "-o", "json").Exec().Out.Contents() Expect(json.Unmarshal(bytes, &index)).ShouldNot(HaveOccurred()) Expect(len(index.Manifests)).To(Equal(1)) - fetched := ORAS("manifest", "fetch", RegistryRef(Host, testRepo, index.Manifests[0].Digest.String())).Exec().Out.Contents() + fetched := ORAS("manifest", "fetch", RegistryRef(ZOTHost, testRepo, index.Manifests[0].Digest.String())).Exec().Out.Contents() MatchFile(filepath.Join(tempDir, exportName), string(fetched), DefaultTimeout) }) It("should attach a file via a OCI Image", func() { testRepo := attachTestRepo("image") tempDir := PrepareTempFiles() - subjectRef := RegistryRef(Host, testRepo, foobar.Tag) - prepare(RegistryRef(Host, ImageRepo, foobar.Tag), subjectRef) + subjectRef := RegistryRef(ZOTHost, testRepo, foobar.Tag) + CopyZotRepo(ImageRepo, testRepo) // test ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(tempDir). @@ -120,8 +119,8 @@ var _ = Describe("1.1 registry users:", func() { testRepo := attachTestRepo("simple") absAttachFileName := filepath.Join(PrepareTempFiles(), foobar.AttachFileName) - subjectRef := RegistryRef(Host, testRepo, foobar.Tag) - prepare(RegistryRef(Host, ImageRepo, foobar.Tag), subjectRef) + subjectRef := RegistryRef(ZOTHost, testRepo, foobar.Tag) + CopyZotRepo(ImageRepo, testRepo) statusKey := foobar.AttachFileStateKey statusKey.Name = absAttachFileName ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", absAttachFileName, foobar.AttachFileMedia), "--disable-path-validation"). @@ -133,8 +132,8 @@ var _ = Describe("1.1 registry users:", func() { testRepo := attachTestRepo("simple") absAttachFileName := filepath.Join(PrepareTempFiles(), foobar.AttachFileName) - subjectRef := RegistryRef(Host, testRepo, foobar.Tag) - prepare(RegistryRef(Host, ImageRepo, foobar.Tag), subjectRef) + subjectRef := RegistryRef(ZOTHost, testRepo, foobar.Tag) + CopyZotRepo(ImageRepo, testRepo) statusKey := foobar.AttachFileStateKey statusKey.Name = absAttachFileName ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", absAttachFileName, foobar.AttachFileMedia)). @@ -204,13 +203,9 @@ var _ = Describe("1.0 registry users:", func() { var _ = Describe("OCI image layout users:", func() { When("running attach command", func() { - prepare := func(root string) { - ORAS("cp", RegistryRef(Host, ImageRepo, foobar.Tag), Flags.ToLayout, LayoutRef(root, foobar.Tag)).Exec() - } It("should attach a file to a subject", func() { - root := PrepareTempFiles() + root := PrepareTempOCI(ImageRepo) subjectRef := LayoutRef(root, foobar.Tag) - prepare(root) ORAS("attach", "--artifact-type", "test/attach", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(root). MatchStatus([]match.StateKey{foobar.AttachFileStateKey}, false, 1).Exec() @@ -218,10 +213,9 @@ var _ = Describe("OCI image layout users:", func() { It("should attach a file to a subject and export the built manifest", func() { // prepare - root := PrepareTempFiles() exportName := "manifest.json" + root := PrepareTempOCI(ImageRepo) subjectRef := LayoutRef(root, foobar.Tag) - prepare(root) // test ORAS("attach", "--artifact-type", "test/attach", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--export-manifest", exportName). WithWorkDir(root). @@ -236,9 +230,8 @@ var _ = Describe("OCI image layout users:", func() { MatchFile(filepath.Join(root, exportName), string(fetched), DefaultTimeout) }) It("should attach a file via a OCI Image", func() { - root := PrepareTempFiles() + root := PrepareTempOCI(ImageRepo) subjectRef := LayoutRef(root, foobar.Tag) - prepare(root) // test ORAS("attach", "--artifact-type", "test/attach", Flags.Layout, subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(root). diff --git a/test/e2e/testdata/zot/command/images/blobs/sha256/1fd9a5fc54b634130102861815e2881f1eec22958d604301904c5353041794c1 b/test/e2e/testdata/zot/command/images/blobs/sha256/1fd9a5fc54b634130102861815e2881f1eec22958d604301904c5353041794c1 new file mode 100644 index 000000000..42968ffca --- /dev/null +++ b/test/e2e/testdata/zot/command/images/blobs/sha256/1fd9a5fc54b634130102861815e2881f1eec22958d604301904c5353041794c1 @@ -0,0 +1,4 @@ +{ + "architecture": "arm64", + "os": "linux" +} \ No newline at end of file diff --git a/test/e2e/testdata/zot/command/images/blobs/sha256/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae b/test/e2e/testdata/zot/command/images/blobs/sha256/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae new file mode 100644 index 000000000..191028156 --- /dev/null +++ b/test/e2e/testdata/zot/command/images/blobs/sha256/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae @@ -0,0 +1 @@ +foo \ No newline at end of file diff --git a/test/e2e/testdata/zot/command/images/blobs/sha256/2ef548696ac7dd66ef38aab5cc8fc5cc1fb637dfaedb3a9afc89bf16db9277e1 b/test/e2e/testdata/zot/command/images/blobs/sha256/2ef548696ac7dd66ef38aab5cc8fc5cc1fb637dfaedb3a9afc89bf16db9277e1 new file mode 100644 index 0000000000000000000000000000000000000000..428f90aab2bd378850dcefe70f7d46eb6e3ddb44 GIT binary patch literal 10240 zcmeIvK?=e!5QX76O1wasX`*uluTfB_5?ZJc#nYRvD&4s1qVUgVl1vDXFa0&=u_^B& z+m+UGcd5<%sK0$4)zc)FVykwFQBBm^q%J|Xi?qD_e3WhqLGHKV(|5KER;z#W)%Cq> z&-4F>*Er?NVK14 Date: Fri, 25 Aug 2023 08:31:12 +0000 Subject: [PATCH 15/28] update blob tests Signed-off-by: Billy Zha --- test/e2e/internal/utils/prepare.go | 4 +- test/e2e/suite/command/attach.go | 10 ++-- test/e2e/suite/command/blob.go | 89 ++++++++++++++---------------- 3 files changed, 48 insertions(+), 55 deletions(-) diff --git a/test/e2e/internal/utils/prepare.go b/test/e2e/internal/utils/prepare.go index 3416e6641..5d92fc347 100644 --- a/test/e2e/internal/utils/prepare.go +++ b/test/e2e/internal/utils/prepare.go @@ -28,8 +28,8 @@ import ( "github.com/onsi/gomega/gbytes" ) -// CopyZotRepo copies oci layout data between repostories. -func CopyZotRepo(fromRepo string, toRepo string) { +// CopyZOTRepo copies oci layout data between repostories. +func CopyZOTRepo(fromRepo string, toRepo string) { zotRoot := filepath.Join(TestDataRoot, "zot") fromRepo = filepath.Join(zotRoot, fromRepo) toRepo = filepath.Join(zotRoot, toRepo) diff --git a/test/e2e/suite/command/attach.go b/test/e2e/suite/command/attach.go index d827b987c..0c813d9e7 100644 --- a/test/e2e/suite/command/attach.go +++ b/test/e2e/suite/command/attach.go @@ -71,7 +71,7 @@ var _ = Describe("1.1 registry users:", func() { When("running attach command", func() { It("should attach a file to a subject", func() { testRepo := attachTestRepo("simple") - CopyZotRepo(ImageRepo, testRepo) + CopyZOTRepo(ImageRepo, testRepo) subjectRef := RegistryRef(ZOTHost, testRepo, foobar.Tag) ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(PrepareTempFiles()). @@ -84,7 +84,7 @@ var _ = Describe("1.1 registry users:", func() { tempDir := PrepareTempFiles() exportName := "manifest.json" subjectRef := RegistryRef(ZOTHost, testRepo, foobar.Tag) - CopyZotRepo(ImageRepo, testRepo) + CopyZOTRepo(ImageRepo, testRepo) // test ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia), "--export-manifest", exportName). WithWorkDir(tempDir). @@ -102,7 +102,7 @@ var _ = Describe("1.1 registry users:", func() { testRepo := attachTestRepo("image") tempDir := PrepareTempFiles() subjectRef := RegistryRef(ZOTHost, testRepo, foobar.Tag) - CopyZotRepo(ImageRepo, testRepo) + CopyZOTRepo(ImageRepo, testRepo) // test ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", foobar.AttachFileName, foobar.AttachFileMedia)). WithWorkDir(tempDir). @@ -120,7 +120,7 @@ var _ = Describe("1.1 registry users:", func() { absAttachFileName := filepath.Join(PrepareTempFiles(), foobar.AttachFileName) subjectRef := RegistryRef(ZOTHost, testRepo, foobar.Tag) - CopyZotRepo(ImageRepo, testRepo) + CopyZOTRepo(ImageRepo, testRepo) statusKey := foobar.AttachFileStateKey statusKey.Name = absAttachFileName ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", absAttachFileName, foobar.AttachFileMedia), "--disable-path-validation"). @@ -133,7 +133,7 @@ var _ = Describe("1.1 registry users:", func() { absAttachFileName := filepath.Join(PrepareTempFiles(), foobar.AttachFileName) subjectRef := RegistryRef(ZOTHost, testRepo, foobar.Tag) - CopyZotRepo(ImageRepo, testRepo) + CopyZOTRepo(ImageRepo, testRepo) statusKey := foobar.AttachFileStateKey statusKey.Name = absAttachFileName ORAS("attach", "--artifact-type", "test/attach", subjectRef, fmt.Sprintf("%s:%s", absAttachFileName, foobar.AttachFileMedia)). diff --git a/test/e2e/suite/command/blob.go b/test/e2e/suite/command/blob.go index abf1d0a83..778f6e7ed 100644 --- a/test/e2e/suite/command/blob.go +++ b/test/e2e/suite/command/blob.go @@ -39,13 +39,13 @@ var _ = Describe("ORAS beginners:", func() { When("running `blob push`", func() { It("should fail to read blob content and password from stdin at the same time", func() { repo := fmt.Sprintf(repoFmt, "push", "password-stdin") - ORAS("blob", "push", RegistryRef(Host, repo, ""), "--password-stdin", "-"). + ORAS("blob", "push", RegistryRef(ZOTHost, repo, ""), "--password-stdin", "-"). ExpectFailure(). MatchErrKeyWords("Error: `-` read file from input and `--password-stdin` read password from input cannot be both used").Exec() }) It("should fail to push a blob from stdin but no blob size provided", func() { repo := fmt.Sprintf(repoFmt, "push", "no-size") - ORAS("blob", "push", RegistryRef(Host, repo, pushDigest), "-"). + ORAS("blob", "push", RegistryRef(ZOTHost, repo, pushDigest), "-"). WithInput(strings.NewReader(pushContent)). ExpectFailure(). MatchErrKeyWords("Error: `--size` must be provided if the blob is read from stdin").Exec() @@ -53,14 +53,14 @@ var _ = Describe("ORAS beginners:", func() { It("should fail to push a blob from stdin if invalid blob size provided", func() { repo := fmt.Sprintf(repoFmt, "push", "invalid-stdin-size") - ORAS("blob", "push", RegistryRef(Host, repo, pushDigest), "-", "--size", "3"). + ORAS("blob", "push", RegistryRef(ZOTHost, repo, pushDigest), "-", "--size", "3"). WithInput(strings.NewReader(pushContent)).ExpectFailure(). Exec() }) It("should fail to push a blob from stdin if invalid digest provided", func() { repo := fmt.Sprintf(repoFmt, "push", "invalid-stdin-digest") - ORAS("blob", "push", RegistryRef(Host, repo, invalidDigest), "-", "--size", strconv.Itoa(len(pushContent))). + ORAS("blob", "push", RegistryRef(ZOTHost, repo, invalidDigest), "-", "--size", strconv.Itoa(len(pushContent))). WithInput(strings.NewReader(pushContent)).ExpectFailure(). Exec() }) @@ -68,7 +68,7 @@ var _ = Describe("ORAS beginners:", func() { It("should fail to push a blob from file if invalid blob size provided", func() { repo := fmt.Sprintf(repoFmt, "push", "invalid-file-digest") blobPath := WriteTempFile("blob", pushContent) - ORAS("blob", "push", RegistryRef(Host, repo, pushDigest), blobPath, "--size", "3"). + ORAS("blob", "push", RegistryRef(ZOTHost, repo, pushDigest), blobPath, "--size", "3"). ExpectFailure(). Exec() }) @@ -76,7 +76,7 @@ var _ = Describe("ORAS beginners:", func() { It("should fail to push a blob from file if invalid digest provided", func() { repo := fmt.Sprintf(repoFmt, "push", "invalid-stdin-size") blobPath := WriteTempFile("blob", pushContent) - ORAS("blob", "push", RegistryRef(Host, repo, invalidDigest), blobPath, "--size", strconv.Itoa(len(pushContent))). + ORAS("blob", "push", RegistryRef(ZOTHost, repo, invalidDigest), blobPath, "--size", strconv.Itoa(len(pushContent))). WithInput(strings.NewReader(pushContent)).ExpectFailure(). Exec() }) @@ -99,22 +99,22 @@ var _ = Describe("ORAS beginners:", func() { }) It("should fail if neither output path nor descriptor flag are not provided", func() { - ORAS("blob", "fetch", RegistryRef(Host, ImageRepo, "sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae")). + ORAS("blob", "fetch", RegistryRef(ZOTHost, ImageRepo, "sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae")). ExpectFailure().Exec() }) It("should fail if no digest provided", func() { - ORAS("blob", "fetch", RegistryRef(Host, ImageRepo, "")). + ORAS("blob", "fetch", RegistryRef(ZOTHost, ImageRepo, "")). ExpectFailure().Exec() }) It("should fail if provided digest doesn't existed", func() { - ORAS("blob", "fetch", RegistryRef(Host, ImageRepo, "sha256:2aaa2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a")). + ORAS("blob", "fetch", RegistryRef(ZOTHost, ImageRepo, "sha256:2aaa2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a2a")). ExpectFailure().Exec() }) It("should fail if output path points to stdout and descriptor flag is provided", func() { - ORAS("blob", "fetch", RegistryRef(Host, ImageRepo, ""), "--descriptor", "--output", "-"). + ORAS("blob", "fetch", RegistryRef(ZOTHost, ImageRepo, ""), "--descriptor", "--output", "-"). ExpectFailure().Exec() }) @@ -127,27 +127,27 @@ var _ = Describe("ORAS beginners:", func() { When("running `blob delete`", func() { It("should fail if no blob reference is provided", func() { dstRepo := fmt.Sprintf(repoFmt, "delete", "no-ref") - ORAS("cp", RegistryRef(Host, ImageRepo, foobar.Digest), RegistryRef(Host, dstRepo, foobar.Digest)).Exec() + CopyZOTRepo(ImageRepo, dstRepo) ORAS("blob", "delete").ExpectFailure().Exec() - ORAS("blob", "fetch", RegistryRef(Host, dstRepo, foobar.FooBlobDigest), "--output", "-").MatchContent(foobar.FooBlobContent).Exec() + ORAS("blob", "fetch", RegistryRef(ZOTHost, dstRepo, foobar.FooBlobDigest), "--output", "-").MatchContent(foobar.FooBlobContent).Exec() }) It("should fail if no force flag and descriptor flag is provided", func() { dstRepo := fmt.Sprintf(repoFmt, "delete", "no-confirm") - ORAS("cp", RegistryRef(Host, ImageRepo, foobar.Digest), RegistryRef(Host, dstRepo, foobar.Digest)).Exec() - ORAS("blob", "delete", RegistryRef(Host, dstRepo, foobar.FooBlobDigest), "--descriptor").ExpectFailure().Exec() - ORAS("blob", "fetch", RegistryRef(Host, dstRepo, foobar.FooBlobDigest), "--output", "-").MatchContent(foobar.FooBlobContent).Exec() + CopyZOTRepo(ImageRepo, dstRepo) + ORAS("blob", "delete", RegistryRef(ZOTHost, dstRepo, foobar.FooBlobDigest), "--descriptor").ExpectFailure().Exec() + ORAS("blob", "fetch", RegistryRef(ZOTHost, dstRepo, foobar.FooBlobDigest), "--output", "-").MatchContent(foobar.FooBlobContent).Exec() }) It("should fail if the blob reference is not in the form of ", func() { dstRepo := fmt.Sprintf(repoFmt, "delete", "wrong-ref-form") - ORAS("blob", "delete", fmt.Sprintf("%s/%s:%s", Host, dstRepo, "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), "--descriptor", "--force").ExpectFailure().Exec() - ORAS("blob", "delete", fmt.Sprintf("%s/%s:%s", Host, dstRepo, "test"), "--descriptor", "--force").ExpectFailure().Exec() - ORAS("blob", "delete", fmt.Sprintf("%s/%s@%s", Host, dstRepo, "test"), "--descriptor", "--force").ExpectFailure().Exec() + ORAS("blob", "delete", fmt.Sprintf("%s/%s:%s", ZOTHost, dstRepo, "sha256:aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"), "--descriptor", "--force").ExpectFailure().Exec() + ORAS("blob", "delete", fmt.Sprintf("%s/%s:%s", ZOTHost, dstRepo, "test"), "--descriptor", "--force").ExpectFailure().Exec() + ORAS("blob", "delete", fmt.Sprintf("%s/%s@%s", ZOTHost, dstRepo, "test"), "--descriptor", "--force").ExpectFailure().Exec() }) It("should fail to delete a non-existent blob without force flag set", func() { - toDeleteRef := RegistryRef(Host, ImageRepo, invalidDigest) + toDeleteRef := RegistryRef(ZOTHost, ImageRepo, invalidDigest) ORAS("blob", "delete", toDeleteRef). ExpectFailure(). MatchErrKeyWords(toDeleteRef, "the specified blob does not exist"). @@ -155,7 +155,7 @@ var _ = Describe("ORAS beginners:", func() { }) It("should fail to delete a non-existent blob and output descriptor, with force flag set", func() { - toDeleteRef := RegistryRef(Host, ImageRepo, invalidDigest) + toDeleteRef := RegistryRef(ZOTHost, ImageRepo, invalidDigest) ORAS("blob", "delete", toDeleteRef, "--force", "--descriptor"). ExpectFailure(). MatchErrKeyWords(toDeleteRef, "the specified blob does not exist"). @@ -169,8 +169,8 @@ var _ = Describe("1.1 registry users:", func() { When("running `blob delete`", func() { It("should delete a blob with interactive confirmation", func() { dstRepo := fmt.Sprintf(repoFmt, "delete", "prompt-confirmation") - ORAS("cp", RegistryRef(Host, ImageRepo, foobar.Digest), RegistryRef(Host, dstRepo, foobar.Digest)).Exec() - toDeleteRef := RegistryRef(Host, dstRepo, foobar.FooBlobDigest) + CopyZOTRepo(ImageRepo, dstRepo) + toDeleteRef := RegistryRef(ZOTHost, dstRepo, foobar.FooBlobDigest) ORAS("blob", "delete", toDeleteRef). WithInput(strings.NewReader("y")). MatchKeyWords("Deleted", toDeleteRef).Exec() @@ -183,14 +183,14 @@ var _ = Describe("1.1 registry users:", func() { It("should delete a blob with force flag and output descriptor", func() { dstRepo := fmt.Sprintf(repoFmt, "delete", "flag-confirmation") - ORAS("cp", RegistryRef(Host, ImageRepo, foobar.Digest), RegistryRef(Host, dstRepo, foobar.Digest)).Exec() - toDeleteRef := RegistryRef(Host, dstRepo, foobar.FooBlobDigest) + CopyZOTRepo(ImageRepo, dstRepo) + toDeleteRef := RegistryRef(ZOTHost, dstRepo, foobar.FooBlobDigest) ORAS("blob", "delete", toDeleteRef, "--force", "--descriptor").MatchContent(foobar.FooBlobDescriptor).Exec() ORAS("blob", "delete", toDeleteRef).WithDescription("validate").ExpectFailure().MatchErrKeyWords("Error:", toDeleteRef, "the specified blob does not exist").Exec() }) It("should return success when deleting a non-existent blob with force flag set", func() { - toDeleteRef := RegistryRef(Host, ImageRepo, invalidDigest) + toDeleteRef := RegistryRef(ZOTHost, ImageRepo, invalidDigest) ORAS("blob", "delete", toDeleteRef, "--force"). MatchKeyWords("Missing", toDeleteRef). Exec() @@ -201,11 +201,11 @@ var _ = Describe("1.1 registry users:", func() { mediaType := "test.media" repo := fmt.Sprintf(repoFmt, "push", "blob-file-media-type") blobPath := WriteTempFile("blob", pushContent) - ORAS("blob", "push", RegistryRef(Host, repo, ""), blobPath, "--media-type", mediaType, "--descriptor"). + ORAS("blob", "push", RegistryRef(ZOTHost, repo, ""), blobPath, "--media-type", mediaType, "--descriptor"). MatchContent(fmt.Sprintf(pushDescFmt, mediaType)).Exec() - ORAS("blob", "fetch", RegistryRef(Host, repo, pushDigest), "--output", "-").MatchContent(pushContent).Exec() + ORAS("blob", "fetch", RegistryRef(ZOTHost, repo, pushDigest), "--output", "-").MatchContent(pushContent).Exec() - ORAS("blob", "push", RegistryRef(Host, repo, ""), blobPath, "-v"). + ORAS("blob", "push", RegistryRef(ZOTHost, repo, ""), blobPath, "-v"). WithDescription("skip the pushing if the blob already exists in the target repo"). MatchKeyWords("Exists").Exec() }) @@ -213,49 +213,42 @@ var _ = Describe("1.1 registry users:", func() { It("should push a blob from a stdin and output the descriptor with specific media-type", func() { mediaType := "test.media" repo := fmt.Sprintf(repoFmt, "push", "blob-file-media-type") - ORAS("blob", "push", RegistryRef(Host, repo, pushDigest), "-", "--media-type", mediaType, "--descriptor", "--size", strconv.Itoa(len(pushContent))). + ORAS("blob", "push", RegistryRef(ZOTHost, repo, pushDigest), "-", "--media-type", mediaType, "--descriptor", "--size", strconv.Itoa(len(pushContent))). WithInput(strings.NewReader(pushContent)). MatchContent(fmt.Sprintf(pushDescFmt, mediaType)).Exec() - ORAS("blob", "fetch", RegistryRef(Host, repo, pushDigest), "--output", "-").MatchContent(pushContent).Exec() + ORAS("blob", "fetch", RegistryRef(ZOTHost, repo, pushDigest), "--output", "-").MatchContent(pushContent).Exec() }) }) When("running `blob fetch`", func() { It("should fetch blob descriptor ", func() { - ORAS("blob", "fetch", RegistryRef(Host, ImageRepo, foobar.FooBlobDigest), "--descriptor"). + ORAS("blob", "fetch", RegistryRef(ZOTHost, ImageRepo, foobar.FooBlobDigest), "--descriptor"). MatchContent(foobar.FooBlobDescriptor).Exec() }) It("should fetch blob content and output to stdout", func() { - ORAS("blob", "fetch", RegistryRef(Host, ImageRepo, foobar.FooBlobDigest), "--output", "-"). + ORAS("blob", "fetch", RegistryRef(ZOTHost, ImageRepo, foobar.FooBlobDigest), "--output", "-"). MatchContent(foobar.FooBlobContent).Exec() }) It("should fetch blob content and output to a file", func() { tempDir := GinkgoT().TempDir() contentPath := filepath.Join(tempDir, "fetched") - ORAS("blob", "fetch", RegistryRef(Host, ImageRepo, foobar.FooBlobDigest), "--output", contentPath). + ORAS("blob", "fetch", RegistryRef(ZOTHost, ImageRepo, foobar.FooBlobDigest), "--output", contentPath). WithWorkDir(tempDir).Exec() MatchFile(contentPath, foobar.FooBlobContent, DefaultTimeout) }) It("should fetch blob descriptor and output content to a file", func() { - tempDir := GinkgoT().TempDir() - contentPath := filepath.Join(tempDir, "fetched") - ORAS("blob", "fetch", RegistryRef(Host, ImageRepo, foobar.FooBlobDigest), "--output", contentPath, "--descriptor"). - MatchContent(foobar.FooBlobDescriptor). - WithWorkDir(tempDir).Exec() + contentPath := filepath.Join(GinkgoT().TempDir(), "fetched") + ORAS("blob", "fetch", RegistryRef(ZOTHost, ImageRepo, foobar.FooBlobDigest), "--output", contentPath, "--descriptor"). + MatchContent(foobar.FooBlobDescriptor).Exec() MatchFile(contentPath, foobar.FooBlobContent, DefaultTimeout) }) }) }) var _ = Describe("OCI image layout users:", func() { - prepare := func(from string) string { - tmpRoot := GinkgoT().TempDir() - ORAS("cp", from, Flags.ToLayout, tmpRoot).WithDescription("prepare image from registry to OCI layout").Exec() - return tmpRoot - } When("running `blob delete`", func() { It("should not support deleting a blob", func() { - toDeleteRef := LayoutRef(prepare(RegistryRef(Host, ImageRepo, foobar.Tag)), foobar.FooBlobDigest) + toDeleteRef := LayoutRef(PrepareTempOCI(ImageRepo), foobar.FooBlobDigest) ORAS("blob", "delete", Flags.Layout, toDeleteRef). WithInput(strings.NewReader("y")). MatchErrKeyWords("Error:", "unknown flag", Flags.Layout). @@ -266,17 +259,17 @@ var _ = Describe("OCI image layout users:", func() { When("running `blob fetch`", func() { It("should fetch blob descriptor", func() { - root := prepare(RegistryRef(Host, ImageRepo, foobar.Tag)) + root := PrepareTempOCI(ImageRepo) ORAS("blob", "fetch", Flags.Layout, LayoutRef(root, foobar.FooBlobDigest), "--descriptor"). MatchContent(foobar.FooBlobDescriptor).Exec() }) It("should fetch blob content and output to stdout", func() { - root := prepare(RegistryRef(Host, ImageRepo, foobar.Tag)) + root := PrepareTempOCI(ImageRepo) ORAS("blob", "fetch", Flags.Layout, LayoutRef(root, foobar.FooBlobDigest), "--output", "-"). MatchContent(foobar.FooBlobContent).Exec() }) It("should fetch blob content and output to a file", func() { - root := prepare(RegistryRef(Host, ImageRepo, foobar.Tag)) + root := PrepareTempOCI(ImageRepo) tempDir := GinkgoT().TempDir() contentPath := filepath.Join(tempDir, "fetched") ORAS("blob", "fetch", Flags.Layout, LayoutRef(root, foobar.FooBlobDigest), "--output", contentPath). @@ -284,7 +277,7 @@ var _ = Describe("OCI image layout users:", func() { MatchFile(contentPath, foobar.FooBlobContent, DefaultTimeout) }) It("should fetch blob descriptor and output content to a file", func() { - root := prepare(RegistryRef(Host, ImageRepo, foobar.Tag)) + root := PrepareTempOCI(ImageRepo) tempDir := GinkgoT().TempDir() contentPath := filepath.Join(tempDir, "fetched") ORAS("blob", "fetch", Flags.Layout, LayoutRef(root, foobar.FooBlobDigest), "--output", contentPath, "--descriptor"). From 8efd1852d475d4cc21e823a95927efe14e037e9a Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Mon, 28 Aug 2023 04:11:36 +0000 Subject: [PATCH 16/28] add doc Signed-off-by: Billy Zha --- test/e2e/README.md | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/test/e2e/README.md b/test/e2e/README.md index 5837e3a47..a9e030441 100644 --- a/test/e2e/README.md +++ b/test/e2e/README.md @@ -38,7 +38,7 @@ This is super handy when you want to do step-by-step debugging from command-line ### 5. Testing Registry Services The backend of E2E tests are three registry services: -- [oras-distribution](https://github.com/oras-project/distribution): registry service supports artifact and image types in [image-spec 1.1.0 rc2](https://github.com/opencontainers/image-spec/tree/v1.1.0-rc2) and referrer API +- [oras-distribution](https://github.com/oras-project/distribution): registry service supports artifact and image types in [image-spec 1.1.0 rc2](https://github.com/opencontainers/image-spec/tree/v1.1.0-rc2) and referrer API. Will be deprecated when [image-spec 1.1.0 rc2](https://github.com/opencontainers/image-spec/tree/v1.1.0-rc2) is not supported by oras CLI. - [upstream distribution](https://github.com/distribution/distribution): registry service supports image media type with subject and provide referrers via [tag schema](https://github.com/opencontainers/distribution-spec/blob/v1.1.0-rc1/spec.md#referrers-tag-schema). - [zot](https://github.com/project-zot/zot): registry service supports artifact and image types in [image-spec 1.1.0 rc4](https://github.com/opencontainers/image-spec/tree/v1.1.0-rc4) and referrer API @@ -72,12 +72,13 @@ Describe: ### 9. Adding New Test Data #### 9.1 Command Suite -Command suite uses pre-baked test data, which is a bunch of layered archive files compressed from registry storage. Test data are all stored in `$REPO_ROOT/test/e2e/testdata/distribution/` but separated in different sub-folders: oras distribution uses `mount` and upstream distribution uses `mount_fallback`. +Command suite uses two kinds of pre-baked test data: +- Layered distribution archive files: those test data is compressed from registry runtime storage directly and is stored in `$REPO_ROOT/test/e2e/testdata/distribution/`. ORAS distribution uses sub-folder `mount` and upstream distribution uses sub-folder `mount_fallback`. For both registries, the repository name should follow the convention of `command/$repo_suffix`. To add a new layer to the test data, use the below command to compress the `docker` folder from the root directory of the registry storage and copy it to the corresponding subfolder in `$REPO_ROOT/test/e2e/testdata/distribution/mount`. + ```shell + tar -cvzf ${repo_suffix}.tar.gz --owner=0 --group=0 docker/ + ``` +- OCI layout files: those test data are stored in `$REPO_ROOT/test/e2e/testdata/zot/` and used by ZOT registry service. You may use stable release of ORAS CLI to build it. When adding new artifacts in, please make sure the repository folder is excluded in `$REPO_ROOT/.gitignore`. -For both registries, the repository name should follow the convention of `command/$repo_suffix`. To add a new layer to the test data, use the below command to compress the `docker` folder from the root directory of the registry storage and copy it to the corresponding subfolder in `$REPO_ROOT/test/e2e/testdata/distribution/mount`. -```shell -tar -cvzf ${repo_suffix}.tar.gz --owner=0 --group=0 docker/ -``` ##### Test Data for ORAS-Distribution ```mermaid @@ -145,5 +146,9 @@ graph TD; end end ``` + +##### Test Data for ZOT +Still WIP. + #### 9.2 Scenario Suite Test files used by scenario-based specs are placed in `$REPO_ROOT/test/e2e/testdata/files`. \ No newline at end of file From f3cf89ee2d8e230578089e53c33b161475aae938 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Mon, 28 Aug 2023 04:13:42 +0000 Subject: [PATCH 17/28] doc clean Signed-off-by: Billy Zha --- test/e2e/README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/e2e/README.md b/test/e2e/README.md index a9e030441..b217a9a2a 100644 --- a/test/e2e/README.md +++ b/test/e2e/README.md @@ -73,11 +73,11 @@ Describe: #### 9.1 Command Suite Command suite uses two kinds of pre-baked test data: -- Layered distribution archive files: those test data is compressed from registry runtime storage directly and is stored in `$REPO_ROOT/test/e2e/testdata/distribution/`. ORAS distribution uses sub-folder `mount` and upstream distribution uses sub-folder `mount_fallback`. For both registries, the repository name should follow the convention of `command/$repo_suffix`. To add a new layer to the test data, use the below command to compress the `docker` folder from the root directory of the registry storage and copy it to the corresponding subfolder in `$REPO_ROOT/test/e2e/testdata/distribution/mount`. +- Layered distribution archive files: test data compressed from registry runtime storage directly and stored in `$REPO_ROOT/test/e2e/testdata/distribution/`. ORAS distribution uses sub-folder `mount` and upstream distribution uses sub-folder `mount_fallback`. For both registries, the repository name should follow the convention of `command/$repo_suffix`. To add a new layer to the test data, use the below command to compress the `docker` folder from the root directory of the registry storage and copy it to the corresponding subfolder in `$REPO_ROOT/test/e2e/testdata/distribution/mount`. ```shell tar -cvzf ${repo_suffix}.tar.gz --owner=0 --group=0 docker/ ``` -- OCI layout files: those test data are stored in `$REPO_ROOT/test/e2e/testdata/zot/` and used by ZOT registry service. You may use stable release of ORAS CLI to build it. When adding new artifacts in, please make sure the repository folder is excluded in `$REPO_ROOT/.gitignore`. +- OCI layout files: test data stored in `$REPO_ROOT/test/e2e/testdata/zot/` and used by ZOT registry service. You may use stable release of ORAS CLI to build it. When adding new artifacts in, please make sure the repository folder is excluded in `$REPO_ROOT/.gitignore`. ##### Test Data for ORAS-Distribution From dea043d239b21c85469d169e7c5292bf10e49123 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Mon, 28 Aug 2023 07:15:32 +0000 Subject: [PATCH 18/28] fix e2e Signed-off-by: Billy Zha --- .gitignore | 1 + test/e2e/internal/utils/testdata.go | 2 +- test/e2e/suite/command/blob.go | 16 ++++++---------- test/e2e/suite/command/discover.go | 2 +- test/e2e/suite/command/repo.go | 14 +++++++------- ...b453c1d30413413422d706483bfa0f98a5e886266e7ae | 1 + test/e2e/testdata/zot/command/blobs/index.json | 1 + test/e2e/testdata/zot/command/blobs/oci-layout | 1 + 8 files changed, 19 insertions(+), 19 deletions(-) create mode 100644 test/e2e/testdata/zot/command/blobs/blobs/sha256/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae create mode 100644 test/e2e/testdata/zot/command/blobs/index.json create mode 100644 test/e2e/testdata/zot/command/blobs/oci-layout diff --git a/.gitignore b/.gitignore index cb04bf2f0..163bf6ab3 100644 --- a/.gitignore +++ b/.gitignore @@ -54,5 +54,6 @@ test/e2e/testdata/distribution/mount_fallback/docker/ # OCI Layout Files ZOT storage files for local E2E testing test/e2e/testdata/zot/ !test/e2e/testdata/zot/command/images +!test/e2e/testdata/zot/command/blobs !test/e2e/testdata/zot/config.json !test/e2e/testdata/zot/passwd_bcrypt \ No newline at end of file diff --git a/test/e2e/internal/utils/testdata.go b/test/e2e/internal/utils/testdata.go index c29cce1f8..b4aab0f84 100644 --- a/test/e2e/internal/utils/testdata.go +++ b/test/e2e/internal/utils/testdata.go @@ -19,8 +19,8 @@ const ( PreviewDesc = "** This command is in preview and under development. **" ExampleDesc = "\nExample - " ImageRepo = "command/images" + BlobRepo = "command/blobs" ArtifactRepo = "command/artifacts" - Repo = "command/images" Namespace = "command" // env RegHostKey = "ORAS_REGISTRY_HOST" diff --git a/test/e2e/suite/command/blob.go b/test/e2e/suite/command/blob.go index 778f6e7ed..1eceee148 100644 --- a/test/e2e/suite/command/blob.go +++ b/test/e2e/suite/command/blob.go @@ -52,9 +52,11 @@ var _ = Describe("ORAS beginners:", func() { }) It("should fail to push a blob from stdin if invalid blob size provided", func() { + content := "another-test" + digest := "sha256:c897eff15c4586525388034f8246346681cb48d75a619039c566c4939a18102e" repo := fmt.Sprintf(repoFmt, "push", "invalid-stdin-size") - ORAS("blob", "push", RegistryRef(ZOTHost, repo, pushDigest), "-", "--size", "3"). - WithInput(strings.NewReader(pushContent)).ExpectFailure(). + ORAS("blob", "push", RegistryRef(ZOTHost, repo, digest), "-", "--size", "3"). + WithInput(strings.NewReader(content)).ExpectFailure(). Exec() }) @@ -169,24 +171,18 @@ var _ = Describe("1.1 registry users:", func() { When("running `blob delete`", func() { It("should delete a blob with interactive confirmation", func() { dstRepo := fmt.Sprintf(repoFmt, "delete", "prompt-confirmation") - CopyZOTRepo(ImageRepo, dstRepo) + CopyZOTRepo(BlobRepo, dstRepo) toDeleteRef := RegistryRef(ZOTHost, dstRepo, foobar.FooBlobDigest) ORAS("blob", "delete", toDeleteRef). WithInput(strings.NewReader("y")). MatchKeyWords("Deleted", toDeleteRef).Exec() - ORAS("blob", "delete", toDeleteRef). - WithDescription("validate"). - WithInput(strings.NewReader("y")). - ExpectFailure(). - MatchErrKeyWords("Error:", toDeleteRef, "the specified blob does not exist").Exec() }) It("should delete a blob with force flag and output descriptor", func() { dstRepo := fmt.Sprintf(repoFmt, "delete", "flag-confirmation") - CopyZOTRepo(ImageRepo, dstRepo) + CopyZOTRepo(BlobRepo, dstRepo) toDeleteRef := RegistryRef(ZOTHost, dstRepo, foobar.FooBlobDigest) ORAS("blob", "delete", toDeleteRef, "--force", "--descriptor").MatchContent(foobar.FooBlobDescriptor).Exec() - ORAS("blob", "delete", toDeleteRef).WithDescription("validate").ExpectFailure().MatchErrKeyWords("Error:", toDeleteRef, "the specified blob does not exist").Exec() }) It("should return success when deleting a non-existent blob with force flag set", func() { diff --git a/test/e2e/suite/command/discover.go b/test/e2e/suite/command/discover.go index 15d3ba771..5690f535c 100644 --- a/test/e2e/suite/command/discover.go +++ b/test/e2e/suite/command/discover.go @@ -61,7 +61,7 @@ var _ = Describe("ORAS beginners:", func() { }) It("should fail when no tag or digest found in provided subject reference", func() { - ORAS("discover", RegistryRef(Host, Repo, "")).ExpectFailure().MatchErrKeyWords("Error:", "invalid image reference").Exec() + ORAS("discover", RegistryRef(Host, ImageRepo, "")).ExpectFailure().MatchErrKeyWords("Error:", "invalid image reference").Exec() }) }) }) diff --git a/test/e2e/suite/command/repo.go b/test/e2e/suite/command/repo.go index 844c9f5f1..2176001d0 100644 --- a/test/e2e/suite/command/repo.go +++ b/test/e2e/suite/command/repo.go @@ -42,7 +42,7 @@ var _ = Describe("ORAS beginners:", func() { It("should fail listing repositories if wrong registry provided", func() { ORAS("repo", "ls").ExpectFailure().MatchErrKeyWords("Error:").Exec() - ORAS("repo", "ls", RegistryRef(Host, Repo, "some-tag")).ExpectFailure().MatchErrKeyWords("Error:").Exec() + ORAS("repo", "ls", RegistryRef(Host, ImageRepo, "some-tag")).ExpectFailure().MatchErrKeyWords("Error:").Exec() }) }) When("running `repo tags`", func() { @@ -70,16 +70,16 @@ var _ = Describe("1.1 registry users:", func() { ORAS("repository", "list", Host).MatchKeyWords(ImageRepo).Exec() }) It("should list repositories under provided namespace", func() { - ORAS("repo", "ls", RegistryRef(Host, Namespace, "")).MatchKeyWords(Repo[len(Namespace)+1:]).Exec() + ORAS("repo", "ls", RegistryRef(Host, Namespace, "")).MatchKeyWords(ImageRepo[len(Namespace)+1:]).Exec() }) It("should not list repositories without a fully matched namespace", func() { repo := "command-draft/images" - ORAS("cp", RegistryRef(Host, Repo, foobar.Tag), RegistryRef(Host, repo, foobar.Tag)). + ORAS("cp", RegistryRef(Host, ImageRepo, foobar.Tag), RegistryRef(Host, repo, foobar.Tag)). WithDescription("prepare destination repo: " + repo). Exec() - ORAS("repo", "ls", Host).MatchKeyWords(Repo, repo).Exec() - session := ORAS("repo", "ls", RegistryRef(Host, Namespace, "")).MatchKeyWords(Repo[len(Namespace)+1:]).Exec() + ORAS("repo", "ls", Host).MatchKeyWords(ImageRepo, repo).Exec() + session := ORAS("repo", "ls", RegistryRef(Host, Namespace, "")).MatchKeyWords(ImageRepo[len(Namespace)+1:]).Exec() Expect(session.Out).ShouldNot(gbytes.Say(repo[len(Namespace)+1:])) }) @@ -115,10 +115,10 @@ var _ = Describe("1.1 registry users:", func() { repo := repoWithName("filter-tag") tags := []string{foobar.Tag, "bax", "bay", "baz"} refWithTags := fmt.Sprintf("%s:%s", RegistryRef(Host, repo, ""), strings.Join(tags, ",")) - ORAS("cp", RegistryRef(Host, Repo, foobar.Tag), refWithTags). + ORAS("cp", RegistryRef(Host, ImageRepo, foobar.Tag), refWithTags). WithDescription("prepare: copy and create multiple tags to " + refWithTags). Exec() - ORAS("cp", RegistryRef(Host, Repo, multi_arch.Tag), RegistryRef(Host, Repo, "")). + ORAS("cp", RegistryRef(Host, ImageRepo, multi_arch.Tag), RegistryRef(Host, ImageRepo, "")). WithDescription("prepare: copy tag with different digest"). Exec() // test diff --git a/test/e2e/testdata/zot/command/blobs/blobs/sha256/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae b/test/e2e/testdata/zot/command/blobs/blobs/sha256/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae new file mode 100644 index 000000000..191028156 --- /dev/null +++ b/test/e2e/testdata/zot/command/blobs/blobs/sha256/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae @@ -0,0 +1 @@ +foo \ No newline at end of file diff --git a/test/e2e/testdata/zot/command/blobs/index.json b/test/e2e/testdata/zot/command/blobs/index.json new file mode 100644 index 000000000..442b81d76 --- /dev/null +++ b/test/e2e/testdata/zot/command/blobs/index.json @@ -0,0 +1 @@ +{"schemaVersion":2,"manifests":null} \ No newline at end of file diff --git a/test/e2e/testdata/zot/command/blobs/oci-layout b/test/e2e/testdata/zot/command/blobs/oci-layout new file mode 100644 index 000000000..1343d370f --- /dev/null +++ b/test/e2e/testdata/zot/command/blobs/oci-layout @@ -0,0 +1 @@ +{"imageLayoutVersion":"1.0.0"} \ No newline at end of file From 1945b87308138491e2aaad147f0662a48c1ca00b Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Mon, 28 Aug 2023 08:53:20 +0000 Subject: [PATCH 19/28] test(e2e): migrate `oras push` specs to ZOT Signed-off-by: Billy Zha --- test/e2e/suite/command/push.go | 44 +++++++++++++++++----------------- 1 file changed, 22 insertions(+), 22 deletions(-) diff --git a/test/e2e/suite/command/push.go b/test/e2e/suite/command/push.go index 0fe788a79..fcc8f6f52 100644 --- a/test/e2e/suite/command/push.go +++ b/test/e2e/suite/command/push.go @@ -42,7 +42,7 @@ var _ = Describe("ORAS beginners:", func() { }) }) -var _ = Describe("Remote registry users:", func() { +var _ = Describe("1.1 registry users:", func() { tag := "e2e" When("pushing to registy without OCI artifact support", func() { repoPrefix := fmt.Sprintf("command/push/%d", GinkgoRandomSeed()) @@ -53,7 +53,7 @@ var _ = Describe("Remote registry users:", func() { It("should push files without customized media types", func() { repo := fmt.Sprintf("%s/%s", repoPrefix, "no-mediatype") tempDir := PrepareTempFiles() - ref := RegistryRef(Host, repo, tag) + ref := RegistryRef(ZOTHost, repo, tag) ORAS("push", ref, foobar.FileBarName, "-v"). MatchStatus(statusKeys, true, len(statusKeys)). @@ -68,7 +68,7 @@ var _ = Describe("Remote registry users:", func() { It("should push files with path validation disabled", func() { repo := fmt.Sprintf("%s/%s", repoPrefix, "disable-path-validation") - ref := RegistryRef(Host, repo, tag) + ref := RegistryRef(ZOTHost, repo, tag) absBarName := filepath.Join(PrepareTempFiles(), foobar.FileBarName) ORAS("push", ref, absBarName, "-v", "--disable-path-validation"). @@ -90,7 +90,7 @@ var _ = Describe("Remote registry users:", func() { It("should fail path validation when pushing file with absolute path", func() { repo := fmt.Sprintf("%s/%s", repoPrefix, "path-validation") - ref := RegistryRef(Host, repo, tag) + ref := RegistryRef(ZOTHost, repo, tag) absBarName := filepath.Join(PrepareTempFiles(), foobar.FileBarName) // test ORAS("push", ref, absBarName, "-v"). @@ -104,30 +104,30 @@ var _ = Describe("Remote registry users:", func() { tempDir := PrepareTempFiles() extraTag := "2e2" - ORAS("push", fmt.Sprintf("%s,%s", RegistryRef(Host, repo, tag), extraTag), foobar.FileBarName, "-v"). + ORAS("push", fmt.Sprintf("%s,%s", RegistryRef(ZOTHost, repo, tag), extraTag), foobar.FileBarName, "-v"). MatchStatus(statusKeys, true, len(statusKeys)). WithWorkDir(tempDir).Exec() // validate - fetched := ORAS("manifest", "fetch", RegistryRef(Host, repo, tag)).Exec().Out.Contents() + fetched := ORAS("manifest", "fetch", RegistryRef(ZOTHost, repo, tag)).Exec().Out.Contents() var manifest ocispec.Manifest Expect(json.Unmarshal(fetched, &manifest)).ShouldNot(HaveOccurred()) Expect(manifest.Layers).Should(ContainElements(foobar.BlobBarDescriptor("application/vnd.oci.image.layer.v1.tar"))) - fetched = ORAS("manifest", "fetch", RegistryRef(Host, repo, extraTag)).Exec().Out.Contents() + fetched = ORAS("manifest", "fetch", RegistryRef(ZOTHost, repo, extraTag)).Exec().Out.Contents() Expect(json.Unmarshal(fetched, &manifest)).ShouldNot(HaveOccurred()) Expect(manifest.Layers).Should(ContainElements(foobar.BlobBarDescriptor("application/vnd.oci.image.layer.v1.tar"))) }) It("should push files with customized media types", func() { repo := fmt.Sprintf("%s/%s", repoPrefix, "layer-mediatype") - layerType := "layer.type" + layerType := "layer/type" tempDir := PrepareTempFiles() - ORAS("push", RegistryRef(Host, repo, tag), foobar.FileBarName+":"+layerType, "-v"). + ORAS("push", RegistryRef(ZOTHost, repo, tag), foobar.FileBarName+":"+layerType, "-v"). MatchStatus(statusKeys, true, len(statusKeys)). WithWorkDir(tempDir).Exec() // validate - fetched := ORAS("manifest", "fetch", RegistryRef(Host, repo, tag)).Exec().Out.Contents() + fetched := ORAS("manifest", "fetch", RegistryRef(ZOTHost, repo, tag)).Exec().Out.Contents() var manifest ocispec.Manifest Expect(json.Unmarshal(fetched, &manifest)).ShouldNot(HaveOccurred()) Expect(manifest.Layers).Should(ContainElements(foobar.BlobBarDescriptor(layerType))) @@ -135,14 +135,14 @@ var _ = Describe("Remote registry users:", func() { It("should push files with manifest exported", func() { repo := fmt.Sprintf("%s/%s", repoPrefix, "export-manifest") - layerType := "layer.type" + layerType := "layer/type" tempDir := PrepareTempFiles() exportPath := "packed.json" - ORAS("push", RegistryRef(Host, repo, tag), foobar.FileBarName+":"+layerType, "-v", "--export-manifest", exportPath). + ORAS("push", RegistryRef(ZOTHost, repo, tag), foobar.FileBarName+":"+layerType, "-v", "--export-manifest", exportPath). MatchStatus(statusKeys, true, len(statusKeys)). WithWorkDir(tempDir).Exec() // validate - fetched := ORAS("manifest", "fetch", RegistryRef(Host, repo, tag)).Exec().Out.Contents() + fetched := ORAS("manifest", "fetch", RegistryRef(ZOTHost, repo, tag)).Exec().Out.Contents() MatchFile(filepath.Join(tempDir, exportPath), string(fetched), DefaultTimeout) }) @@ -150,14 +150,14 @@ var _ = Describe("Remote registry users:", func() { repo := fmt.Sprintf("%s/%s", repoPrefix, "config") tempDir := PrepareTempFiles() - ORAS("push", RegistryRef(Host, repo, tag), "--config", foobar.FileConfigName, foobar.FileBarName, "-v"). + ORAS("push", RegistryRef(ZOTHost, repo, tag), "--config", foobar.FileConfigName, foobar.FileBarName, "-v"). MatchStatus([]match.StateKey{ foobar.FileConfigStateKey, foobar.FileBarStateKey, }, true, 2). WithWorkDir(tempDir).Exec() // validate - fetched := ORAS("manifest", "fetch", RegistryRef(Host, repo, tag)).Exec().Out.Contents() + fetched := ORAS("manifest", "fetch", RegistryRef(ZOTHost, repo, tag)).Exec().Out.Contents() var manifest ocispec.Manifest Expect(json.Unmarshal(fetched, &manifest)).ShouldNot(HaveOccurred()) Expect(manifest.Config).Should(Equal(ocispec.Descriptor{ @@ -168,18 +168,18 @@ var _ = Describe("Remote registry users:", func() { }) It("should push files with customized config file and mediatype", func() { - repo := fmt.Sprintf("%s/%s", repoPrefix, "config-mediatype") + repo := fmt.Sprintf("%s/%s", repoPrefix, "config/mediatype") configType := "config.type" tempDir := PrepareTempFiles() - ORAS("push", RegistryRef(Host, repo, tag), "--config", fmt.Sprintf("%s:%s", foobar.FileConfigName, configType), foobar.FileBarName, "-v"). + ORAS("push", RegistryRef(ZOTHost, repo, tag), "--config", fmt.Sprintf("%s:%s", foobar.FileConfigName, configType), foobar.FileBarName, "-v"). MatchStatus([]match.StateKey{ {Digest: "46b68ac1696c", Name: configType}, foobar.FileBarStateKey, }, true, 2). WithWorkDir(tempDir).Exec() // validate - fetched := ORAS("manifest", "fetch", RegistryRef(Host, repo, tag)).Exec().Out.Contents() + fetched := ORAS("manifest", "fetch", RegistryRef(ZOTHost, repo, tag)).Exec().Out.Contents() var manifest ocispec.Manifest Expect(json.Unmarshal(fetched, &manifest)).ShouldNot(HaveOccurred()) Expect(manifest.Config).Should(Equal(ocispec.Descriptor{ @@ -195,11 +195,11 @@ var _ = Describe("Remote registry users:", func() { value := "image-anno-value" tempDir := PrepareTempFiles() // test - ORAS("push", RegistryRef(Host, repo, tag), foobar.FileBarName, "-v", "--annotation", fmt.Sprintf("%s=%s", key, value)). + ORAS("push", RegistryRef(ZOTHost, repo, tag), foobar.FileBarName, "-v", "--annotation", fmt.Sprintf("%s=%s", key, value)). MatchStatus(statusKeys, true, len(statusKeys)). WithWorkDir(tempDir).Exec() // validate - fetched := ORAS("manifest", "fetch", RegistryRef(Host, repo, tag)).Exec().Out.Contents() + fetched := ORAS("manifest", "fetch", RegistryRef(ZOTHost, repo, tag)).Exec().Out.Contents() var manifest ocispec.Manifest Expect(json.Unmarshal(fetched, &manifest)).ShouldNot(HaveOccurred()) Expect(manifest.Annotations[key]).To(Equal(value)) @@ -209,13 +209,13 @@ var _ = Describe("Remote registry users:", func() { repo := fmt.Sprintf("%s/%s", repoPrefix, "file-annotation") tempDir := PrepareTempFiles() - ORAS("push", RegistryRef(Host, repo, tag), foobar.FileBarName, "-v", "--annotation-file", "foobar/annotation.json", "--config", foobar.FileConfigName). + ORAS("push", RegistryRef(ZOTHost, repo, tag), foobar.FileBarName, "-v", "--annotation-file", "foobar/annotation.json", "--config", foobar.FileConfigName). MatchStatus(statusKeys, true, 1). WithWorkDir(tempDir).Exec() // validate // see testdata\files\foobar\annotation.json - fetched := ORAS("manifest", "fetch", RegistryRef(Host, repo, tag)).Exec().Out.Contents() + fetched := ORAS("manifest", "fetch", RegistryRef(ZOTHost, repo, tag)).Exec().Out.Contents() var manifest ocispec.Manifest Expect(json.Unmarshal(fetched, &manifest)).ShouldNot(HaveOccurred()) Expect(manifest.Annotations["hi"]).To(Equal("manifest")) From f028e6183b69ce7c308836fb754e6fd119533998 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Mon, 28 Aug 2023 08:58:30 +0000 Subject: [PATCH 20/28] fix e2e Signed-off-by: Billy Zha --- test/e2e/suite/command/push.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/suite/command/push.go b/test/e2e/suite/command/push.go index fcc8f6f52..ef5cd9c12 100644 --- a/test/e2e/suite/command/push.go +++ b/test/e2e/suite/command/push.go @@ -316,7 +316,7 @@ var _ = Describe("OCI image layout users:", func() { }) It("should push files with customized config file and mediatype", func() { - configType := "config.type" + configType := "config/type" tempDir := PrepareTempFiles() ref := LayoutRef(tempDir, tag) ORAS("push", Flags.Layout, ref, "--config", fmt.Sprintf("%s:%s", foobar.FileConfigName, configType), foobar.FileBarName, "-v"). From a25d23f0e9c37de67c3934e895c448a3a65be93a Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Tue, 29 Aug 2023 03:17:14 +0000 Subject: [PATCH 21/28] fix e2e Signed-off-by: Billy Zha --- test/e2e/suite/command/push.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/suite/command/push.go b/test/e2e/suite/command/push.go index fcc8f6f52..ef5cd9c12 100644 --- a/test/e2e/suite/command/push.go +++ b/test/e2e/suite/command/push.go @@ -316,7 +316,7 @@ var _ = Describe("OCI image layout users:", func() { }) It("should push files with customized config file and mediatype", func() { - configType := "config.type" + configType := "config/type" tempDir := PrepareTempFiles() ref := LayoutRef(tempDir, tag) ORAS("push", Flags.Layout, ref, "--config", fmt.Sprintf("%s:%s", foobar.FileConfigName, configType), foobar.FileBarName, "-v"). From df78befa115b4dd46c1e4fc5b84f10976934ce75 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Tue, 29 Aug 2023 04:53:42 +0000 Subject: [PATCH 22/28] test(e2e): migrate specs for `oras pull` Signed-off-by: Billy Zha --- .gitignore | 5 +- test/e2e/suite/command/pull.go | 51 ++++++++----------- ...3eed4a446712eb6fdf08a665a4f2352d6d2f8bdf17 | 1 + ...3c1d30413413422d706483bfa0f98a5e886266e7ae | 1 + ...586f84d252530b7b5fe1c4104532767e6da4e04e47 | 1 + ...16f7e8649e94fb4fc21fe77e8310c060f61caaff8a | 1 + ...888b9351d80f6f5458dca9d3abef6560e7be255a3d | 1 + ...eb40e8175760dbb8615d2f815a6ca5239c901c6b38 | 1 + ...b721fe9b5c338d10ee429ea04fae5511b68fbf8fb9 | 1 + ...6cb4e7df0ab8a9d24adc57825099f522fe009a22bb | 1 + .../testdata/zot/command/artifacts/index.json | 23 +++++++++ .../testdata/zot/command/artifacts/oci-layout | 1 + 12 files changed, 57 insertions(+), 31 deletions(-) create mode 100644 test/e2e/testdata/zot/command/artifacts/blobs/sha256/0e007dcb9ded7f49c4dc8e3eed4a446712eb6fdf08a665a4f2352d6d2f8bdf17 create mode 100644 test/e2e/testdata/zot/command/artifacts/blobs/sha256/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae create mode 100644 test/e2e/testdata/zot/command/artifacts/blobs/sha256/32b78bd00723cd7d5251d4586f84d252530b7b5fe1c4104532767e6da4e04e47 create mode 100644 test/e2e/testdata/zot/command/artifacts/blobs/sha256/44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a create mode 100644 test/e2e/testdata/zot/command/artifacts/blobs/sha256/ae2d56717c9334fdc5fdb1888b9351d80f6f5458dca9d3abef6560e7be255a3d create mode 100644 test/e2e/testdata/zot/command/artifacts/blobs/sha256/f5d51c0823fc419652bb6beb40e8175760dbb8615d2f815a6ca5239c901c6b38 create mode 100644 test/e2e/testdata/zot/command/artifacts/blobs/sha256/fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9 create mode 100644 test/e2e/testdata/zot/command/artifacts/blobs/sha256/fd6ed2f36b5465244d5dc86cb4e7df0ab8a9d24adc57825099f522fe009a22bb create mode 100644 test/e2e/testdata/zot/command/artifacts/index.json create mode 100644 test/e2e/testdata/zot/command/artifacts/oci-layout diff --git a/.gitignore b/.gitignore index 163bf6ab3..f925d1241 100644 --- a/.gitignore +++ b/.gitignore @@ -53,7 +53,8 @@ test/e2e/testdata/distribution/mount_fallback/docker/ # OCI Layout Files ZOT storage files for local E2E testing test/e2e/testdata/zot/ -!test/e2e/testdata/zot/command/images -!test/e2e/testdata/zot/command/blobs +!test/e2e/testdata/zot/command/images/ +!test/e2e/testdata/zot/command/artifacts/ +!test/e2e/testdata/zot/command/blobs/ !test/e2e/testdata/zot/config.json !test/e2e/testdata/zot/passwd_bcrypt \ No newline at end of file diff --git a/test/e2e/suite/command/pull.go b/test/e2e/suite/command/pull.go index 21dfce721..504171609 100644 --- a/test/e2e/suite/command/pull.go +++ b/test/e2e/suite/command/pull.go @@ -51,7 +51,7 @@ var _ = Describe("Remote registry users:", func() { pullRoot := "pulled" tempDir := PrepareTempFiles() stateKeys := append(foobar.ImageLayerStateKeys, foobar.ManifestStateKey, foobar.ImageConfigStateKey(configName)) - ORAS("pull", RegistryRef(Host, ImageRepo, foobar.Tag), "-v", "--config", configName, "-o", pullRoot). + ORAS("pull", RegistryRef(ZOTHost, ImageRepo, foobar.Tag), "-v", "--config", configName, "-o", pullRoot). MatchStatus(stateKeys, true, len(stateKeys)). WithWorkDir(tempDir).Exec() // check config @@ -67,7 +67,7 @@ var _ = Describe("Remote registry users:", func() { WithWorkDir(tempDir).Exec() } - ORAS("pull", RegistryRef(Host, ImageRepo, foobar.Tag), "-v", "-o", pullRoot, "--keep-old-files"). + ORAS("pull", RegistryRef(ZOTHost, ImageRepo, foobar.Tag), "-v", "-o", pullRoot, "--keep-old-files"). ExpectFailure(). WithDescription("fail if overwrite old files are disabled") }) @@ -76,7 +76,7 @@ var _ = Describe("Remote registry users:", func() { pullRoot := "pulled" tempDir := PrepareTempFiles() stateKeys := append(foobar.ImageLayerStateKeys, foobar.ManifestStateKey, foobar.ImageConfigStateKey(oras.MediaTypeUnknownConfig)) - ORAS("pull", RegistryRef(Host, ImageRepo, foobar.Tag), "-v", "--config", fmt.Sprintf("%s:%s", configName, "???"), "-o", pullRoot). + ORAS("pull", RegistryRef(ZOTHost, ImageRepo, foobar.Tag), "-v", "--config", fmt.Sprintf("%s:%s", configName, "???"), "-o", pullRoot). MatchStatus(stateKeys, true, len(stateKeys)). WithWorkDir(tempDir).Exec() // check config @@ -96,13 +96,13 @@ var _ = Describe("Remote registry users:", func() { foobar.ManifestStateKey), foobar.ImageReferrersStateKeys..., ) - ORAS("pull", RegistryRef(Host, ArtifactRepo, foobar.SignatureImageReferrer.Digest.String()), "-v", "--include-subject"). + ORAS("pull", RegistryRef(ZOTHost, ArtifactRepo, foobar.SignatureImageReferrer.Digest.String()), "-v", "--include-subject"). MatchStatus(stateKeys, true, len(stateKeys)). WithWorkDir(tempDir).Exec() }) It("should pull specific platform", func() { - ORAS("pull", RegistryRef(Host, ImageRepo, "multi"), "--platform", "linux/amd64", "-v", "-o", GinkgoT().TempDir()). + ORAS("pull", RegistryRef(ZOTHost, ImageRepo, "multi"), "--platform", "linux/amd64", "-v", "-o", GinkgoT().TempDir()). MatchStatus(multi_arch.LinuxAMD64StateKeys, true, len(multi_arch.LinuxAMD64StateKeys)).Exec() }) }) @@ -113,19 +113,15 @@ var _ = Describe("OCI image layout users:", func() { var ( configName = "test.config" ) - prepare := func(root string, repo string, tagOrDigest string) { - ORAS("cp", RegistryRef(Host, repo, tagOrDigest), Flags.ToLayout, LayoutRef(root, tagOrDigest), "-r").WithDescription("prepare oci layout test env").Exec() - } It("should pull all files in an image to a target folder", func() { pullRoot := "pulled" - tempDir := PrepareTempFiles() - prepare(tempDir, ArtifactRepo, foobar.Tag) + root := PrepareTempOCI(ImageRepo) stateKeys := append(foobar.ImageLayerStateKeys, foobar.ManifestStateKey, foobar.ImageConfigStateKey(configName)) - ORAS("pull", Flags.Layout, LayoutRef(tempDir, foobar.Tag), "-v", "--config", configName, "-o", pullRoot). + ORAS("pull", Flags.Layout, LayoutRef(root, foobar.Tag), "-v", "--config", configName, "-o", pullRoot). MatchStatus(stateKeys, true, len(stateKeys)). - WithWorkDir(tempDir).Exec() + WithWorkDir(root).Exec() // check config - configPath := filepath.Join(tempDir, pullRoot, configName) + configPath := filepath.Join(root, pullRoot, configName) Expect(configPath).Should(BeAnExistingFile()) f, err := os.Open(configPath) Expect(err).ShouldNot(HaveOccurred()) @@ -133,50 +129,47 @@ var _ = Describe("OCI image layout users:", func() { Eventually(gbytes.BufferReader(f)).Should(gbytes.Say("{}")) for _, f := range foobar.ImageLayerNames { // check layers - Binary("diff", filepath.Join(tempDir, "foobar", f), filepath.Join(pullRoot, f)). - WithWorkDir(tempDir).Exec() + Binary("diff", filepath.Join(root, "foobar", f), filepath.Join(pullRoot, f)). + WithWorkDir(root).Exec() } - ORAS("pull", Flags.Layout, LayoutRef(tempDir, foobar.Tag), "-v", "-o", pullRoot, "--keep-old-files"). + ORAS("pull", Flags.Layout, LayoutRef(root, foobar.Tag), "-v", "-o", pullRoot, "--keep-old-files"). ExpectFailure(). WithDescription("fail if overwrite old files are disabled") }) It("should skip config if media type does not match", func() { pullRoot := "pulled" - tempDir := PrepareTempFiles() - prepare(tempDir, ArtifactRepo, foobar.Tag) + root := PrepareTempOCI(ImageRepo) stateKeys := append(foobar.ImageLayerStateKeys, foobar.ManifestStateKey, foobar.ImageConfigStateKey(oras.MediaTypeUnknownConfig)) - ORAS("pull", Flags.Layout, LayoutRef(tempDir, foobar.Tag), "-v", "--config", fmt.Sprintf("%s:%s", configName, "???"), "-o", pullRoot). + ORAS("pull", Flags.Layout, LayoutRef(root, foobar.Tag), "-v", "--config", fmt.Sprintf("%s:%s", configName, "???"), "-o", pullRoot). MatchStatus(stateKeys, true, len(stateKeys)). - WithWorkDir(tempDir).Exec() + WithWorkDir(root).Exec() // check config Expect(filepath.Join(pullRoot, configName)).ShouldNot(BeAnExistingFile()) for _, f := range foobar.ImageLayerNames { // check layers - Binary("diff", filepath.Join(tempDir, "foobar", f), filepath.Join(pullRoot, f)). - WithWorkDir(tempDir). + Binary("diff", filepath.Join(root, "foobar", f), filepath.Join(pullRoot, f)). + WithWorkDir(root). WithDescription("should download identical file " + f).Exec() } }) It("should pull subject", func() { - tempDir := GinkgoT().TempDir() - prepare(tempDir, ArtifactRepo, foobar.Tag) + root := PrepareTempOCI(ArtifactRepo) stateKeys := append(append( foobar.ImageLayerStateKeys, foobar.ManifestStateKey), foobar.ImageReferrersStateKeys..., ) - ORAS("pull", Flags.Layout, LayoutRef(tempDir, foobar.SignatureImageReferrer.Digest.String()), "-v", "--include-subject"). + ORAS("pull", Flags.Layout, LayoutRef(root, foobar.SignatureImageReferrer.Digest.String()), "-v", "--include-subject"). MatchStatus(stateKeys, true, len(stateKeys)). - WithWorkDir(tempDir).Exec() + WithWorkDir(root).Exec() }) It("should pull specific platform", func() { - tempDir := GinkgoT().TempDir() - prepare(tempDir, ImageRepo, multi_arch.Tag) - ORAS("pull", Flags.Layout, LayoutRef(tempDir, multi_arch.Tag), "--platform", "linux/amd64", "-v", "-o", tempDir). + root := PrepareTempOCI(ImageRepo) + ORAS("pull", Flags.Layout, LayoutRef(root, multi_arch.Tag), "--platform", "linux/amd64", "-v", "-o", root). MatchStatus(multi_arch.LinuxAMD64StateKeys, true, len(multi_arch.LinuxAMD64StateKeys)).Exec() }) }) diff --git a/test/e2e/testdata/zot/command/artifacts/blobs/sha256/0e007dcb9ded7f49c4dc8e3eed4a446712eb6fdf08a665a4f2352d6d2f8bdf17 b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/0e007dcb9ded7f49c4dc8e3eed4a446712eb6fdf08a665a4f2352d6d2f8bdf17 new file mode 100644 index 000000000..a51f76dac --- /dev/null +++ b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/0e007dcb9ded7f49c4dc8e3eed4a446712eb6fdf08a665a4f2352d6d2f8bdf17 @@ -0,0 +1 @@ +{"schemaVersion":2,"mediaType":"application/vnd.oci.image.manifest.v1+json","config":{"mediaType":"test.signature.file","digest":"sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a","size":2},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar","digest":"sha256:ae2d56717c9334fdc5fdb1888b9351d80f6f5458dca9d3abef6560e7be255a3d","size":16,"annotations":{"org.opencontainers.image.title":"signature"}}],"subject":{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:32b78bd00723cd7d5251d4586f84d252530b7b5fe1c4104532767e6da4e04e47","size":660},"annotations":{"org.opencontainers.image.created":"2023-01-18T08:37:57Z"}} \ No newline at end of file diff --git a/test/e2e/testdata/zot/command/artifacts/blobs/sha256/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae new file mode 100644 index 000000000..191028156 --- /dev/null +++ b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae @@ -0,0 +1 @@ +foo \ No newline at end of file diff --git a/test/e2e/testdata/zot/command/artifacts/blobs/sha256/32b78bd00723cd7d5251d4586f84d252530b7b5fe1c4104532767e6da4e04e47 b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/32b78bd00723cd7d5251d4586f84d252530b7b5fe1c4104532767e6da4e04e47 new file mode 100644 index 000000000..73ffd55d3 --- /dev/null +++ b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/32b78bd00723cd7d5251d4586f84d252530b7b5fe1c4104532767e6da4e04e47 @@ -0,0 +1 @@ +{"schemaVersion":2,"mediaType":"application/vnd.oci.image.manifest.v1+json","config":{"mediaType":"test.sbom.file","digest":"sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a","size":2},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar","digest":"sha256:f5d51c0823fc419652bb6beb40e8175760dbb8615d2f815a6ca5239c901c6b38","size":11,"annotations":{"org.opencontainers.image.title":"sbom"}}],"subject":{"mediaType":"application/vnd.oci.image.manifest.v1+json","digest":"sha256:fd6ed2f36b5465244d5dc86cb4e7df0ab8a9d24adc57825099f522fe009a22bb","size":851},"annotations":{"org.opencontainers.image.created":"2023-01-18T08:37:42Z"}} \ No newline at end of file diff --git a/test/e2e/testdata/zot/command/artifacts/blobs/sha256/44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a new file mode 100644 index 000000000..9e26dfeeb --- /dev/null +++ b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a @@ -0,0 +1 @@ +{} \ No newline at end of file diff --git a/test/e2e/testdata/zot/command/artifacts/blobs/sha256/ae2d56717c9334fdc5fdb1888b9351d80f6f5458dca9d3abef6560e7be255a3d b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/ae2d56717c9334fdc5fdb1888b9351d80f6f5458dca9d3abef6560e7be255a3d new file mode 100644 index 000000000..c180babc7 --- /dev/null +++ b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/ae2d56717c9334fdc5fdb1888b9351d80f6f5458dca9d3abef6560e7be255a3d @@ -0,0 +1 @@ +mocked signature \ No newline at end of file diff --git a/test/e2e/testdata/zot/command/artifacts/blobs/sha256/f5d51c0823fc419652bb6beb40e8175760dbb8615d2f815a6ca5239c901c6b38 b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/f5d51c0823fc419652bb6beb40e8175760dbb8615d2f815a6ca5239c901c6b38 new file mode 100644 index 000000000..68b8080ee --- /dev/null +++ b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/f5d51c0823fc419652bb6beb40e8175760dbb8615d2f815a6ca5239c901c6b38 @@ -0,0 +1 @@ +mocked sbom \ No newline at end of file diff --git a/test/e2e/testdata/zot/command/artifacts/blobs/sha256/fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9 b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9 new file mode 100644 index 000000000..ba0e162e1 --- /dev/null +++ b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9 @@ -0,0 +1 @@ +bar \ No newline at end of file diff --git a/test/e2e/testdata/zot/command/artifacts/blobs/sha256/fd6ed2f36b5465244d5dc86cb4e7df0ab8a9d24adc57825099f522fe009a22bb b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/fd6ed2f36b5465244d5dc86cb4e7df0ab8a9d24adc57825099f522fe009a22bb new file mode 100644 index 000000000..0ddf954a1 --- /dev/null +++ b/test/e2e/testdata/zot/command/artifacts/blobs/sha256/fd6ed2f36b5465244d5dc86cb4e7df0ab8a9d24adc57825099f522fe009a22bb @@ -0,0 +1 @@ +{"schemaVersion":2,"mediaType":"application/vnd.oci.image.manifest.v1+json","config":{"mediaType":"application/vnd.unknown.config.v1+json","digest":"sha256:44136fa355b3678a1146ad16f7e8649e94fb4fc21fe77e8310c060f61caaff8a","size":2},"layers":[{"mediaType":"application/vnd.oci.image.layer.v1.tar","digest":"sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae","size":3,"annotations":{"org.opencontainers.image.title":"foo1"}},{"mediaType":"application/vnd.oci.image.layer.v1.tar","digest":"sha256:2c26b46b68ffc68ff99b453c1d30413413422d706483bfa0f98a5e886266e7ae","size":3,"annotations":{"org.opencontainers.image.title":"foo2"}},{"mediaType":"application/vnd.oci.image.layer.v1.tar","digest":"sha256:fcde2b2edba56bf408601fb721fe9b5c338d10ee429ea04fae5511b68fbf8fb9","size":3,"annotations":{"org.opencontainers.image.title":"bar"}}]} \ No newline at end of file diff --git a/test/e2e/testdata/zot/command/artifacts/index.json b/test/e2e/testdata/zot/command/artifacts/index.json new file mode 100644 index 000000000..e1a345312 --- /dev/null +++ b/test/e2e/testdata/zot/command/artifacts/index.json @@ -0,0 +1,23 @@ +{ + "schemaVersion": 2, + "manifests": [ + { + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "digest": "sha256:fd6ed2f36b5465244d5dc86cb4e7df0ab8a9d24adc57825099f522fe009a22bb", + "size": 851, + "annotations": { + "org.opencontainers.image.ref.name": "foobar" + } + }, + { + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "digest": "sha256:32b78bd00723cd7d5251d4586f84d252530b7b5fe1c4104532767e6da4e04e47", + "size": 660 + }, + { + "mediaType": "application/vnd.oci.image.manifest.v1+json", + "digest": "sha256:0e007dcb9ded7f49c4dc8e3eed4a446712eb6fdf08a665a4f2352d6d2f8bdf17", + "size": 670 + } + ] +} \ No newline at end of file diff --git a/test/e2e/testdata/zot/command/artifacts/oci-layout b/test/e2e/testdata/zot/command/artifacts/oci-layout new file mode 100644 index 000000000..1343d370f --- /dev/null +++ b/test/e2e/testdata/zot/command/artifacts/oci-layout @@ -0,0 +1 @@ +{"imageLayoutVersion":"1.0.0"} \ No newline at end of file From 1e9bbd8e587fbb8f0c4ddbe2adc7017ea928d8c7 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Tue, 29 Aug 2023 04:54:18 +0000 Subject: [PATCH 23/28] fix e2e Signed-off-by: Billy Zha --- test/e2e/suite/command/push.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/suite/command/push.go b/test/e2e/suite/command/push.go index ef5cd9c12..e10d47f3a 100644 --- a/test/e2e/suite/command/push.go +++ b/test/e2e/suite/command/push.go @@ -169,7 +169,7 @@ var _ = Describe("1.1 registry users:", func() { It("should push files with customized config file and mediatype", func() { repo := fmt.Sprintf("%s/%s", repoPrefix, "config/mediatype") - configType := "config.type" + configType := "config/type" tempDir := PrepareTempFiles() ORAS("push", RegistryRef(ZOTHost, repo, tag), "--config", fmt.Sprintf("%s:%s", foobar.FileConfigName, configType), foobar.FileBarName, "-v"). From 003c2c949fd4429c8775185d581cac733c16b859 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Tue, 29 Aug 2023 05:51:47 +0000 Subject: [PATCH 24/28] test(e2e): migrate `oras tag` specs to ZOT Signed-off-by: Billy Zha --- test/e2e/suite/command/tag.go | 48 ++++++++++------------------------- 1 file changed, 13 insertions(+), 35 deletions(-) diff --git a/test/e2e/suite/command/tag.go b/test/e2e/suite/command/tag.go index 2a012acc2..3895d0424 100644 --- a/test/e2e/suite/command/tag.go +++ b/test/e2e/suite/command/tag.go @@ -33,7 +33,7 @@ var _ = Describe("ORAS beginners:", func() { }) It("should fail when provided manifest reference is not found", func() { - ORAS("tag", RegistryRef(Host, ImageRepo, "i-dont-think-this-tag-exists"), "tagged").ExpectFailure().MatchErrKeyWords("Error:").Exec() + ORAS("tag", RegistryRef(ZOTHost, ImageRepo, "i-dont-think-this-tag-exists"), "tagged").ExpectFailure().MatchErrKeyWords("Error:").Exec() }) It("should fail when provided invalid reference", func() { @@ -52,16 +52,16 @@ var _ = Describe("1.1 registry users:", func() { } When("running `tag`", func() { It("should add a tag to an existent manifest when providing tag reference", func() { - tagAndValidate(Host, ImageRepo, multi_arch.Tag, multi_arch.Digest, "tag-via-tag") + tagAndValidate(ZOTHost, ImageRepo, multi_arch.Tag, multi_arch.Digest, "tag-via-tag") }) It("should add a tag to an existent manifest when providing digest reference", func() { - tagAndValidate(Host, ImageRepo, multi_arch.Digest, multi_arch.Digest, "tag-via-digest") + tagAndValidate(ZOTHost, ImageRepo, multi_arch.Digest, multi_arch.Digest, "tag-via-digest") }) It("should add multiple tags to an existent manifest when providing digest reference", func() { - tagAndValidate(Host, ImageRepo, multi_arch.Digest, multi_arch.Digest, "tag1-via-digest", "tag2-via-digest", "tag3-via-digest") + tagAndValidate(ZOTHost, ImageRepo, multi_arch.Digest, multi_arch.Digest, "tag1-via-digest", "tag2-via-digest", "tag3-via-digest") }) It("should add multiple tags to an existent manifest when providing tag reference", func() { - tagAndValidate(Host, ImageRepo, multi_arch.Tag, multi_arch.Digest, "tag1-via-tag", "tag1-via-tag", "tag1-via-tag") + tagAndValidate(ZOTHost, ImageRepo, multi_arch.Tag, multi_arch.Digest, "tag1-via-tag", "tag1-via-tag", "tag1-via-tag") }) }) }) @@ -75,51 +75,29 @@ var _ = Describe("OCI image layout users:", func() { ORAS("repo", "tags", Flags.Layout, LayoutRef(root, "")).MatchKeyWords(tags...).Exec() } When("running `tag`", func() { - prepare := func() string { - root := GinkgoT().TempDir() - ORAS("cp", RegistryRef(Host, ImageRepo, multi_arch.Tag), Flags.ToLayout, LayoutRef(root, multi_arch.Tag)).Exec() - return root - } It("should add a tag to an existent manifest when providing tag reference", func() { - tagAndValidate(prepare(), multi_arch.Tag, multi_arch.Digest, "tag-via-tag") + tagAndValidate(PrepareTempOCI(ImageRepo), multi_arch.Tag, multi_arch.Digest, "tag-via-tag") }) It("should add a tag to an existent manifest when providing digest reference", func() { - tagAndValidate(prepare(), multi_arch.Digest, multi_arch.Digest, "tag-via-digest") + tagAndValidate(PrepareTempOCI(ImageRepo), multi_arch.Digest, multi_arch.Digest, "tag-via-digest") }) It("should add multiple tags to an existent manifest when providing digest reference", func() { - tagAndValidate(prepare(), multi_arch.Digest, multi_arch.Digest, "tag1-via-digest", "tag2-via-digest", "tag3-via-digest") + tagAndValidate(PrepareTempOCI(ImageRepo), multi_arch.Digest, multi_arch.Digest, "tag1-via-digest", "tag2-via-digest", "tag3-via-digest") }) It("should add multiple tags to an existent manifest when providing tag reference", func() { - tagAndValidate(prepare(), multi_arch.Tag, multi_arch.Digest, "tag1-via-tag", "tag1-via-tag", "tag1-via-tag") + tagAndValidate(PrepareTempOCI(ImageRepo), multi_arch.Tag, multi_arch.Digest, "tag1-via-tag", "tag1-via-tag", "tag1-via-tag") }) - }) -}) - -var _ = Describe("OCI image layout users:", func() { - var tagAndValidate = func(root string, tagOrDigest string, digest string, tags ...string) { - out := ORAS(append([]string{"tag", LayoutRef(root, tagOrDigest), Flags.Layout}, tags...)...).MatchKeyWords(tags...).Exec().Out - hint := regexp.QuoteMeta(fmt.Sprintf("Tagging [oci-layout] %s", LayoutRef(root, digest))) - gomega.Expect(out).To(gbytes.Say(hint)) - gomega.Expect(out).NotTo(gbytes.Say(hint)) // should only say hint once - ORAS("repo", "tags", Flags.Layout, LayoutRef(root, "")).MatchKeyWords(tags...).Exec() - } - When("running `tag`", func() { - prepare := func() string { - root := GinkgoT().TempDir() - ORAS("cp", RegistryRef(Host, ImageRepo, multi_arch.Tag), Flags.ToLayout, LayoutRef(root, multi_arch.Tag)).Exec() - return root - } It("should add a tag to an existent manifest when providing tag reference", func() { - tagAndValidate(prepare(), multi_arch.Tag, multi_arch.Digest, "tag-via-tag") + tagAndValidate(PrepareTempOCI(ImageRepo), multi_arch.Tag, multi_arch.Digest, "tag-via-tag") }) It("should add a tag to an existent manifest when providing digest reference", func() { - tagAndValidate(prepare(), multi_arch.Digest, multi_arch.Digest, "tag-via-digest") + tagAndValidate(PrepareTempOCI(ImageRepo), multi_arch.Digest, multi_arch.Digest, "tag-via-digest") }) It("should add multiple tags to an existent manifest when providing digest reference", func() { - tagAndValidate(prepare(), multi_arch.Digest, multi_arch.Digest, "tag1-via-digest", "tag2-via-digest", "tag3-via-digest") + tagAndValidate(PrepareTempOCI(ImageRepo), multi_arch.Digest, multi_arch.Digest, "tag1-via-digest", "tag2-via-digest", "tag3-via-digest") }) It("should add multiple tags to an existent manifest when providing tag reference", func() { - tagAndValidate(prepare(), multi_arch.Tag, multi_arch.Digest, "tag1-via-tag", "tag1-via-tag", "tag1-via-tag") + tagAndValidate(PrepareTempOCI(ImageRepo), multi_arch.Tag, multi_arch.Digest, "tag1-via-tag", "tag1-via-tag", "tag1-via-tag") }) }) }) From e654e069c837238ca43f90af9700699e36205849 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Tue, 29 Aug 2023 05:45:13 +0000 Subject: [PATCH 25/28] test(e2e): migrate `oras tag` specs to ZOT Signed-off-by: Billy Zha --- test/e2e/suite/command/tag.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/suite/command/tag.go b/test/e2e/suite/command/tag.go index 3895d0424..bcb494adb 100644 --- a/test/e2e/suite/command/tag.go +++ b/test/e2e/suite/command/tag.go @@ -66,7 +66,7 @@ var _ = Describe("1.1 registry users:", func() { }) }) -var _ = Describe("OCI image layout users:", func() { +var _ = Describe("OCI image layout users:", Focus, func() { var tagAndValidate = func(root string, tagOrDigest string, digest string, tags ...string) { out := ORAS(append([]string{"tag", LayoutRef(root, tagOrDigest), Flags.Layout}, tags...)...).MatchKeyWords(tags...).Exec().Out hint := regexp.QuoteMeta(fmt.Sprintf("Tagging [oci-layout] %s", LayoutRef(root, digest))) From d57f9bcad50816d7aef41ecaec3101630d7b494b Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Tue, 29 Aug 2023 05:51:28 +0000 Subject: [PATCH 26/28] test(e2e): migrate `oras repo` specs to ZOT Signed-off-by: Billy Zha --- test/e2e/suite/command/repo.go | 52 +++++++++++++--------------------- 1 file changed, 20 insertions(+), 32 deletions(-) diff --git a/test/e2e/suite/command/repo.go b/test/e2e/suite/command/repo.go index 2176001d0..4079e3810 100644 --- a/test/e2e/suite/command/repo.go +++ b/test/e2e/suite/command/repo.go @@ -42,7 +42,7 @@ var _ = Describe("ORAS beginners:", func() { It("should fail listing repositories if wrong registry provided", func() { ORAS("repo", "ls").ExpectFailure().MatchErrKeyWords("Error:").Exec() - ORAS("repo", "ls", RegistryRef(Host, ImageRepo, "some-tag")).ExpectFailure().MatchErrKeyWords("Error:").Exec() + ORAS("repo", "ls", RegistryRef(ZOTHost, ImageRepo, "some-tag")).ExpectFailure().MatchErrKeyWords("Error:").Exec() }) }) When("running `repo tags`", func() { @@ -57,8 +57,8 @@ var _ = Describe("ORAS beginners:", func() { It("should fail listing repositories if wrong registry provided", func() { ORAS("repo", "tags").ExpectFailure().MatchErrKeyWords("Error:").Exec() - ORAS("repo", "tags", Host).ExpectFailure().MatchErrKeyWords("Error:").Exec() - ORAS("repo", "tags", RegistryRef(Host, ImageRepo, "some-tag")).ExpectFailure().MatchErrKeyWords("Error:").Exec() + ORAS("repo", "tags", ZOTHost).ExpectFailure().MatchErrKeyWords("Error:").Exec() + ORAS("repo", "tags", RegistryRef(ZOTHost, ImageRepo, "some-tag")).ExpectFailure().MatchErrKeyWords("Error:").Exec() }) }) }) @@ -67,27 +67,27 @@ var _ = Describe("ORAS beginners:", func() { var _ = Describe("1.1 registry users:", func() { When("running `repo ls`", func() { It("should list repositories", func() { - ORAS("repository", "list", Host).MatchKeyWords(ImageRepo).Exec() + ORAS("repository", "list", ZOTHost).MatchKeyWords(ImageRepo).Exec() }) It("should list repositories under provided namespace", func() { - ORAS("repo", "ls", RegistryRef(Host, Namespace, "")).MatchKeyWords(ImageRepo[len(Namespace)+1:]).Exec() + ORAS("repo", "ls", RegistryRef(ZOTHost, Namespace, "")).MatchKeyWords(ImageRepo[len(Namespace)+1:]).Exec() }) It("should not list repositories without a fully matched namespace", func() { repo := "command-draft/images" - ORAS("cp", RegistryRef(Host, ImageRepo, foobar.Tag), RegistryRef(Host, repo, foobar.Tag)). + ORAS("cp", RegistryRef(ZOTHost, ImageRepo, foobar.Tag), RegistryRef(ZOTHost, repo, foobar.Tag)). WithDescription("prepare destination repo: " + repo). Exec() - ORAS("repo", "ls", Host).MatchKeyWords(ImageRepo, repo).Exec() - session := ORAS("repo", "ls", RegistryRef(Host, Namespace, "")).MatchKeyWords(ImageRepo[len(Namespace)+1:]).Exec() + ORAS("repo", "ls", ZOTHost).MatchKeyWords(ImageRepo, repo).Exec() + session := ORAS("repo", "ls", RegistryRef(ZOTHost, Namespace, "")).MatchKeyWords(ImageRepo[len(Namespace)+1:]).Exec() Expect(session.Out).ShouldNot(gbytes.Say(repo[len(Namespace)+1:])) }) It("should list repositories via short command", func() { - ORAS("repo", "ls", Host).MatchKeyWords(ImageRepo).Exec() + ORAS("repo", "ls", ZOTHost).MatchKeyWords(ImageRepo).Exec() }) It("should list partial repositories via `last` flag", func() { - session := ORAS("repo", "ls", Host, "--last", ImageRepo).Exec() + session := ORAS("repo", "ls", ZOTHost, "--last", ImageRepo).Exec() repoRegex := regexp.QuoteMeta(ImageRepo + "\n") Expect(session.Out).ShouldNot(gbytes.Say(repoRegex)) }) @@ -97,7 +97,7 @@ var _ = Describe("1.1 registry users:", func() { repoWithName := func(name string) string { return fmt.Sprintf("command/images/repo/tags/%d/%s", GinkgoRandomSeed(), name) } - repoRef := RegistryRef(Host, ImageRepo, "") + repoRef := RegistryRef(ZOTHost, ImageRepo, "") It("should list tags", func() { ORAS("repository", "show-tags", repoRef).MatchKeyWords(multi_arch.Tag, foobar.Tag).Exec() }) @@ -114,20 +114,20 @@ var _ = Describe("1.1 registry users:", func() { // prepare repo := repoWithName("filter-tag") tags := []string{foobar.Tag, "bax", "bay", "baz"} - refWithTags := fmt.Sprintf("%s:%s", RegistryRef(Host, repo, ""), strings.Join(tags, ",")) - ORAS("cp", RegistryRef(Host, ImageRepo, foobar.Tag), refWithTags). + refWithTags := fmt.Sprintf("%s:%s", RegistryRef(ZOTHost, repo, ""), strings.Join(tags, ",")) + ORAS("cp", RegistryRef(ZOTHost, ImageRepo, foobar.Tag), refWithTags). WithDescription("prepare: copy and create multiple tags to " + refWithTags). Exec() - ORAS("cp", RegistryRef(Host, ImageRepo, multi_arch.Tag), RegistryRef(Host, ImageRepo, "")). + ORAS("cp", RegistryRef(ZOTHost, ImageRepo, multi_arch.Tag), RegistryRef(ZOTHost, ImageRepo, "")). WithDescription("prepare: copy tag with different digest"). Exec() // test - viaTag := ORAS("repo", "tags", "-v", RegistryRef(Host, repo, foobar.Tag)). + viaTag := ORAS("repo", "tags", "-v", RegistryRef(ZOTHost, repo, foobar.Tag)). MatchKeyWords(tags...). MatchErrKeyWords(feature.Experimental.Mark, foobar.Digest).Exec().Out Expect(viaTag).ShouldNot(gbytes.Say(multi_arch.Tag)) - viaDigest := ORAS("repo", "tags", "-v", RegistryRef(Host, repo, foobar.Digest)). + viaDigest := ORAS("repo", "tags", "-v", RegistryRef(ZOTHost, repo, foobar.Digest)). MatchKeyWords(tags...). MatchErrKeyWords(feature.Experimental.Mark, foobar.Digest).Exec().Out Expect(viaDigest).ShouldNot(gbytes.Say(multi_arch.Tag)) @@ -137,29 +137,19 @@ var _ = Describe("1.1 registry users:", func() { var _ = Describe("OCI image layout users:", func() { When("running `repo tags`", func() { - prepare := func(srcRef, repoRoot string, tags ...string) { - ORAS("cp", srcRef, LayoutRef(repoRoot, strings.Join(tags, ",")), Flags.ToLayout). - WithDescription("prepare in OCI layout"). - Exec() - } - foobarImageRef := RegistryRef(Host, ImageRepo, foobar.Tag) - multiImageRef := RegistryRef(Host, ImageRepo, multi_arch.Tag) tagOutput := foobar.Tag + "\n" It("should list tags", func() { - root := GinkgoT().TempDir() - prepare(foobarImageRef, root, foobar.Tag) + root := PrepareTempOCI(ImageRepo) ORAS("repository", "show-tags", root, Flags.Layout).MatchKeyWords(tagOutput).Exec() }) It("should list tags via short command", func() { - root := GinkgoT().TempDir() - prepare(foobarImageRef, root, foobar.Tag) + root := PrepareTempOCI(ImageRepo) ORAS("repository", "tags", root, Flags.Layout).MatchKeyWords(tagOutput).Exec() }) It("should list partial tags via `last` flag", func() { // prepare - root := GinkgoT().TempDir() extra := "zzz" - prepare(foobarImageRef, root, foobar.Tag, extra) + root := PrepareTempOCI(ImageRepo) // test session := ORAS("repository", "tags", root, "--last", foobar.Tag, Flags.Layout).MatchKeyWords(extra).Exec() Expect(session.Out).ShouldNot(gbytes.Say(regexp.QuoteMeta(tagOutput))) @@ -167,10 +157,8 @@ var _ = Describe("OCI image layout users:", func() { It("should list out tags associated to the provided reference", func() { // prepare - root := GinkgoT().TempDir() tags := []string{foobar.Tag, "bax", "bay", "baz"} - prepare(foobarImageRef, root, tags...) - prepare(multiImageRef, root, multi_arch.Tag) + root := PrepareTempOCI(ImageRepo) // test viaTag := ORAS("repo", "tags", "-v", LayoutRef(root, foobar.Tag), Flags.Layout). WithDescription("via tag"). From 0c7187cbf5e09e1f54e6c7a3d94c1ff9ff1b0ebe Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Tue, 29 Aug 2023 05:58:15 +0000 Subject: [PATCH 27/28] remove focus Signed-off-by: Billy Zha --- test/e2e/suite/command/tag.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/e2e/suite/command/tag.go b/test/e2e/suite/command/tag.go index bcb494adb..3895d0424 100644 --- a/test/e2e/suite/command/tag.go +++ b/test/e2e/suite/command/tag.go @@ -66,7 +66,7 @@ var _ = Describe("1.1 registry users:", func() { }) }) -var _ = Describe("OCI image layout users:", Focus, func() { +var _ = Describe("OCI image layout users:", func() { var tagAndValidate = func(root string, tagOrDigest string, digest string, tags ...string) { out := ORAS(append([]string{"tag", LayoutRef(root, tagOrDigest), Flags.Layout}, tags...)...).MatchKeyWords(tags...).Exec().Out hint := regexp.QuoteMeta(fmt.Sprintf("Tagging [oci-layout] %s", LayoutRef(root, digest))) From 1f18415eb1a7619d591ab8a7e1f8a423d765ac31 Mon Sep 17 00:00:00 2001 From: Billy Zha Date: Tue, 29 Aug 2023 07:05:25 +0000 Subject: [PATCH 28/28] test(e2e): migrate `oras repo` specs to ZOT Signed-off-by: Billy Zha --- test/e2e/suite/command/repo.go | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/test/e2e/suite/command/repo.go b/test/e2e/suite/command/repo.go index 4079e3810..3cbe628cf 100644 --- a/test/e2e/suite/command/repo.go +++ b/test/e2e/suite/command/repo.go @@ -86,11 +86,6 @@ var _ = Describe("1.1 registry users:", func() { It("should list repositories via short command", func() { ORAS("repo", "ls", ZOTHost).MatchKeyWords(ImageRepo).Exec() }) - It("should list partial repositories via `last` flag", func() { - session := ORAS("repo", "ls", ZOTHost, "--last", ImageRepo).Exec() - repoRegex := regexp.QuoteMeta(ImageRepo + "\n") - Expect(session.Out).ShouldNot(gbytes.Say(repoRegex)) - }) }) When("running `repo tags`", func() { @@ -105,10 +100,6 @@ var _ = Describe("1.1 registry users:", func() { ORAS("repo", "tags", repoRef).MatchKeyWords(multi_arch.Tag, foobar.Tag).Exec() }) - It("should list partial tags via `last` flag", func() { - session := ORAS("repo", "tags", repoRef, "--last", foobar.Tag).MatchKeyWords(multi_arch.Tag).Exec() - Expect(session.Out).ShouldNot(gbytes.Say(foobar.Tag)) - }) It("Should list out tags associated to the provided reference", func() { // prepare @@ -135,8 +126,25 @@ var _ = Describe("1.1 registry users:", func() { }) }) +var _ = Describe("1.0 registry users:", func() { + When("running `repo ls`", func() { + It("should list partial repositories via `last` flag", func() { + session := ORAS("repo", "ls", FallbackHost, "--last", ArtifactRepo).Exec() + repoRegex := regexp.QuoteMeta(ImageRepo + "\n") + Expect(session.Out).ShouldNot(gbytes.Say(repoRegex)) + }) + }) +}) + var _ = Describe("OCI image layout users:", func() { When("running `repo tags`", func() { + prepare := func(repo string, fromTag string, toTags ...string) string { + root := PrepareTempOCI(repo) + ORAS("tag", LayoutRef(root, fromTag), strings.Join(toTags, " "), Flags.Layout). + WithDescription("prepare in OCI layout"). + Exec() + return root + } tagOutput := foobar.Tag + "\n" It("should list tags", func() { root := PrepareTempOCI(ImageRepo) @@ -149,7 +157,7 @@ var _ = Describe("OCI image layout users:", func() { It("should list partial tags via `last` flag", func() { // prepare extra := "zzz" - root := PrepareTempOCI(ImageRepo) + root := prepare(ImageRepo, foobar.Tag, extra) // test session := ORAS("repository", "tags", root, "--last", foobar.Tag, Flags.Layout).MatchKeyWords(extra).Exec() Expect(session.Out).ShouldNot(gbytes.Say(regexp.QuoteMeta(tagOutput))) @@ -158,7 +166,7 @@ var _ = Describe("OCI image layout users:", func() { It("should list out tags associated to the provided reference", func() { // prepare tags := []string{foobar.Tag, "bax", "bay", "baz"} - root := PrepareTempOCI(ImageRepo) + root := prepare(ImageRepo, foobar.Tag, tags...) // test viaTag := ORAS("repo", "tags", "-v", LayoutRef(root, foobar.Tag), Flags.Layout). WithDescription("via tag").