Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

test(e2e): use ZOT as testing backend for oras blob specs #1083

Merged
merged 23 commits into from
Aug 29, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -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
4 changes: 2 additions & 2 deletions test/e2e/internal/utils/prepare.go
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/internal/utils/testdata.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down
10 changes: 5 additions & 5 deletions test/e2e/suite/command/attach.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()).
Expand All @@ -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).
Expand All @@ -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).
Expand All @@ -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").
Expand All @@ -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)).
Expand Down
99 changes: 44 additions & 55 deletions test/e2e/suite/command/blob.go
Original file line number Diff line number Diff line change
Expand Up @@ -39,44 +39,46 @@ 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()
})

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(Host, repo, pushDigest), "-", "--size", "3").
WithInput(strings.NewReader(pushContent)).ExpectFailure().
ORAS("blob", "push", RegistryRef(ZOTHost, repo, digest), "-", "--size", "3").
WithInput(strings.NewReader(content)).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()
})

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()
})

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()
})
Expand All @@ -99,22 +101,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()
})

Expand All @@ -127,35 +129,35 @@ 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 <name@digest>", 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").
Exec()
})

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").
Expand All @@ -169,28 +171,22 @@ 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(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()
qweeah marked this conversation as resolved.
Show resolved Hide resolved
})

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(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() {
toDeleteRef := RegistryRef(Host, ImageRepo, invalidDigest)
toDeleteRef := RegistryRef(ZOTHost, ImageRepo, invalidDigest)
ORAS("blob", "delete", toDeleteRef, "--force").
MatchKeyWords("Missing", toDeleteRef).
Exec()
Expand All @@ -201,61 +197,54 @@ 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()
})

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).
Expand All @@ -266,25 +255,25 @@ 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).
WithWorkDir(tempDir).Exec()
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").
Expand Down
2 changes: 1 addition & 1 deletion test/e2e/suite/command/discover.go
Original file line number Diff line number Diff line change
Expand Up @@ -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()
})
})
})
Expand Down
Loading