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): add oci artifact spec for common registry users #746

Merged
merged 14 commits into from
Jan 13, 2023
4 changes: 2 additions & 2 deletions .github/workflows/build.yml
Original file line number Diff line number Diff line change
Expand Up @@ -55,9 +55,9 @@ jobs:
--env REGISTRY_STORAGE_DELETE_ENABLED=true \
--env REGISTRY_AUTH_HTPASSWD_REALM=test-basic \
--env REGISTRY_AUTH_HTPASSWD_PATH=/etc/docker/registry/passwd \
--mount type=bind,source=$mnt_root/docker,target=/opt/data/registry-root-dir/docker \
--mount type=bind,source=$mnt_root/docker,target=/var/lib/registry/docker \
--mount type=bind,source=$mnt_root/passwd_bcrypt,target=/etc/docker/registry/passwd \
ghcr.io/oras-project/registry:v1.0.0-rc.2
ghcr.io/oras-project/registry:v1.0.0-rc.3
ginkgo -r -p --succinct suite
docker kill oras-e2e || true
env:
Expand Down
3 changes: 2 additions & 1 deletion test/e2e/internal/utils/init.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ import (
// ORASPath points to the to-be-tested oras binary.
var ORASPath string

// Host points to the registry service where E2E tests will be run against.
// Host points to the registry service where E2E specs will be run against.
var Host string

func init() {
Expand All @@ -37,6 +37,7 @@ func init() {
Host = "localhost:5000"
fmt.Fprintln(os.Stderr, "cannot find host name in ORAS_REGISTRY_HOST, using", Host, "instead")
}

ref := registry.Reference{
Registry: Host,
}
Expand Down
4 changes: 3 additions & 1 deletion test/e2e/internal/utils/registry.go
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ limitations under the License.
package utils

import (
"strings"

"github.com/onsi/gomega"
"oras.land/oras-go/v2/registry"
)
Expand All @@ -23,7 +25,7 @@ func Reference(reg string, repo string, tagOrDigest string) string {
ref := registry.Reference{
Registry: reg,
Repository: repo,
Reference: tagOrDigest,
Reference: strings.TrimSpace(tagOrDigest),
}
gomega.Expect(ref.Validate()).ShouldNot(gomega.HaveOccurred())
return ref.String()
Expand Down
18 changes: 9 additions & 9 deletions test/e2e/suite/command/push.go
Original file line number Diff line number Diff line change
Expand Up @@ -48,10 +48,10 @@ var _ = Describe("Remote registry users:", func() {
}

ORAS("push", Reference(Host, repo, tag), files[1], "-v").
MatchStatus(statusKeys, true, 2).
MatchStatus(statusKeys, true, 1).
WithWorkDir(tempDir).Exec()
fetched := ORAS("manifest", "fetch", Reference(Host, repo, tag)).Exec().Out
Binary("jq", ".layers[]", "--compact-output").
Binary("jq", ".blobs[]", "--compact-output").
MatchTrimmedContent(fmt.Sprintf(layerDescriptorTemplate, ocispec.MediaTypeImageLayer)).
WithInput(fetched).Exec()
})
Expand All @@ -65,10 +65,10 @@ var _ = Describe("Remote registry users:", func() {
}

ORAS("push", Reference(Host, repo, tag), files[1]+":"+layerType, "-v").
MatchStatus(statusKeys, true, 2).
MatchStatus(statusKeys, true, 1).
WithWorkDir(tempDir).Exec()
fetched := ORAS("manifest", "fetch", Reference(Host, repo, tag)).Exec().Out
Binary("jq", ".layers[]", "--compact-output").
Binary("jq", ".blobs[]", "--compact-output").
MatchTrimmedContent(fmt.Sprintf(layerDescriptorTemplate, layerType)).
WithInput(fetched).Exec()
})
Expand All @@ -83,7 +83,7 @@ var _ = Describe("Remote registry users:", func() {

exportPath := "packed.json"
ORAS("push", Reference(Host, repo, tag), files[1]+":"+layerType, "-v", "--export-manifest", exportPath).
MatchStatus(statusKeys, true, 2).
MatchStatus(statusKeys, true, 1).
WithWorkDir(tempDir).Exec()
fetched := ORAS("manifest", "fetch", Reference(Host, repo, tag)).Exec().Out.Contents()
MatchFile(filepath.Join(tempDir, exportPath), string(fetched), DefaultTimeout)
Expand Down Expand Up @@ -138,11 +138,11 @@ var _ = Describe("Remote registry users:", func() {
}

ORAS("push", Reference(Host, repo, tag), files[1], "-v", "--annotation", fmt.Sprintf("%s=%s", key, value)).
MatchStatus(statusKeys, true, 2).
MatchStatus(statusKeys, true, 1).
WithWorkDir(tempDir).Exec()
fetched := ORAS("manifest", "fetch", Reference(Host, repo, tag)).Exec().Out

Binary("jq", `.annotations|del(.["org.opencontainers.image.created"])`, "--compact-output").
Binary("jq", `.annotations|del(.["org.opencontainers.artifact.created"])`, "--compact-output").
MatchTrimmedContent(fmt.Sprintf(`{"%s":"%s"}`, key, value)).
WithInput(fetched).Exec()
})
Expand All @@ -154,8 +154,8 @@ var _ = Describe("Remote registry users:", func() {
panic(err)
}

ORAS("push", Reference(Host, repo, tag), files[1], "-v", "--annotation-file", "foobar/annotation.json").
MatchStatus(statusKeys, true, 2).
ORAS("push", Reference(Host, repo, tag), files[1], "-v", "--annotation-file", "foobar/annotation.json", "--config", files[0]).
MatchStatus(statusKeys, true, 1).
WithWorkDir(tempDir).Exec()
fetched := ORAS("manifest", "fetch", Reference(Host, repo, tag)).Exec().Out

Expand Down
42 changes: 42 additions & 0 deletions test/e2e/suite/scenario/const.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
/*
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.
*/

package scenario

import "oras.land/oras/test/e2e/internal/utils/match"

var (
blobFileNames = []string{
"foobar/foo1",
"foobar/foo2",
"foobar/bar",
}
pushFileStateKeys = []match.StateKey{
{Digest: "2c26b46b68ff", Name: blobFileNames[0]},
{Digest: "2c26b46b68ff", Name: blobFileNames[1]},
{Digest: "fcde2b2edba5", Name: blobFileNames[2]},
}

configFileName = "foobar/config.json"
configFileStateKey = match.StateKey{
Digest: "46b68ac1696c", Name: "application/vnd.unknown.config.v1+json",
}

attachFileName = "foobar/to-be-attached"
attachFileMedia = "test/oras.e2e"
attachFileStateKey = match.StateKey{
Digest: "d3b29f7d12d9", Name: attachFileName,
}
)
104 changes: 104 additions & 0 deletions test/e2e/suite/scenario/oci_artifact.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,104 @@
/*
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.
*/

package scenario

import (
"fmt"
"path/filepath"

. "github.com/onsi/ginkgo/v2"
. "oras.land/oras/test/e2e/internal/utils"
"oras.land/oras/test/e2e/internal/utils/match"
)

var _ = Describe("Common OCI artifact users:", Ordered, func() {
repo := "scenario/oci-artifact"
When("pushing images and attaching", func() {
tag := "artifact"
var tempDir string
BeforeAll(func() {
tempDir = GinkgoT().TempDir()
if err := CopyTestData(tempDir); err != nil {
panic(err)
}
})

pulledManifest := "packed.json"
pullRoot := "pulled"
It("should push and pull an artifact", func() {
ORAS("push", Reference(Host, repo, tag), "--artifact-type", "test-artifact", blobFileNames[0], blobFileNames[1], blobFileNames[2], "-v", "--export-manifest", pulledManifest).
MatchStatus(pushFileStateKeys, true, 3).
WithWorkDir(tempDir).
WithDescription("push with manifest exported").Exec()

fetched := ORAS("manifest", "fetch", Reference(Host, repo, tag)).Exec()
MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout)

ORAS("pull", Reference(Host, repo, tag), "-v", "-o", pullRoot).
MatchStatus(pushFileStateKeys, true, 3).
WithWorkDir(tempDir).
WithDescription("pull artFiles with config").Exec()

for _, f := range blobFileNames {
Binary("diff", filepath.Join(f), filepath.Join(pullRoot, f)).
WithWorkDir(tempDir).
WithDescription("download identical file " + f).Exec()
}
})

It("should attach and pull an artifact", func() {
subject := Reference(Host, repo, tag)
ORAS("attach", subject, "--artifact-type", "test.artifact1", fmt.Sprint(attachFileName, ":", attachFileMedia), "-v", "--export-manifest", pulledManifest).
MatchStatus([]match.StateKey{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", Reference(Host, repo, digest)).MatchKeyWords(attachFileMedia).Exec()
MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout)

ORAS("pull", Reference(Host, repo, digest), "-v", "-o", pullRoot).
MatchStatus([]match.StateKey{attachFileStateKey}, true, 1).
WithWorkDir(tempDir).
WithDescription("pull attached artifact").Exec()
Binary("diff", filepath.Join(attachFileName), filepath.Join(pullRoot, attachFileName)).
WithWorkDir(tempDir).
WithDescription("download identical file " + attachFileName).Exec()

ORAS("attach", subject, "--artifact-type", "test.artifact2", fmt.Sprint(attachFileName, ":", attachFileMedia), "-v", "--export-manifest", pulledManifest).
MatchStatus([]match.StateKey{attachFileStateKey}, true, 1).
WithWorkDir(tempDir).
WithDescription("attach again with manifest exported").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", Reference(Host, repo, digest)).MatchKeyWords(attachFileMedia).Exec()
MatchFile(filepath.Join(tempDir, pulledManifest), string(fetched.Out.Contents()), DefaultTimeout)

ORAS("pull", Reference(Host, repo, string(digest)), "-v", "-o", pullRoot, "--include-subject").
MatchStatus(append(pushFileStateKeys, attachFileStateKey), true, 4).
WithWorkDir(tempDir).
WithDescription("pull attached artifact and subject").Exec()

for _, f := range append(blobFileNames, attachFileName) {
Binary("diff", filepath.Join(f), filepath.Join(pullRoot, f)).
WithWorkDir(tempDir).
WithDescription("download identical file " + f).Exec()
}
})
})
})
18 changes: 2 additions & 16 deletions test/e2e/suite/scenario/oci_image.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,26 +18,12 @@ import (

. "github.com/onsi/ginkgo/v2"
. "oras.land/oras/test/e2e/internal/utils"
"oras.land/oras/test/e2e/internal/utils/match"
)

var (
files = []string{
"foobar/config.json",
"foobar/foo1",
"foobar/foo2",
"foobar/bar",
}
statusKeys = []match.StateKey{
{Digest: "46b68ac1696c", Name: "application/vnd.unknown.config.v1+json"},
{Digest: "2c26b46b68ff", Name: files[1]},
{Digest: "2c26b46b68ff", Name: files[2]},
{Digest: "fcde2b2edba5", Name: files[3]},
}
)

var _ = Describe("OCI image user:", Ordered, func() {
repo := "scenario/oci-image"
files := append([]string{configFileName}, blobFileNames...)
statusKeys := append(pushFileStateKeys, configFileStateKey)
When("pushing images and check", func() {
tag := "image"
var tempDir string
Expand Down
1 change: 1 addition & 0 deletions test/e2e/testdata/files/foobar/to-be-attached
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
mocked to-be-attached file