Test storing OCI image manifests and indexes with/without a media type
OCI Image manifests and indexes are supported both with and without an embeded MediaType (the field is reserved according to the spec). Test storing and retrieving both types from the manifest store. Signed-off-by: Owen W. Taylor <otaylor@fishsoup.net>
This commit is contained in:
@@ -9,6 +9,8 @@ import (
|
||||
|
||||
"github.com/docker/distribution"
|
||||
"github.com/docker/distribution/manifest"
|
||||
"github.com/docker/distribution/manifest/manifestlist"
|
||||
"github.com/docker/distribution/manifest/ocischema"
|
||||
"github.com/docker/distribution/manifest/schema1"
|
||||
"github.com/docker/distribution/reference"
|
||||
"github.com/docker/distribution/registry/storage/cache/memory"
|
||||
@@ -17,6 +19,7 @@ import (
|
||||
"github.com/docker/distribution/testutil"
|
||||
"github.com/docker/libtrust"
|
||||
"github.com/opencontainers/go-digest"
|
||||
"github.com/opencontainers/image-spec/specs-go/v1"
|
||||
)
|
||||
|
||||
type manifestStoreTestEnv struct {
|
||||
@@ -356,6 +359,155 @@ func testManifestStorage(t *testing.T, options ...RegistryOption) {
|
||||
}
|
||||
}
|
||||
|
||||
func TestOCIManifestStorage(t *testing.T) {
|
||||
testOCIManifestStorage(t, "includeMediaTypes=true", true)
|
||||
testOCIManifestStorage(t, "includeMediaTypes=false", false)
|
||||
}
|
||||
|
||||
func testOCIManifestStorage(t *testing.T, testname string, includeMediaTypes bool) {
|
||||
var imageMediaType string
|
||||
var indexMediaType string
|
||||
if includeMediaTypes {
|
||||
imageMediaType = v1.MediaTypeImageManifest
|
||||
indexMediaType = v1.MediaTypeImageIndex
|
||||
} else {
|
||||
imageMediaType = ""
|
||||
indexMediaType = ""
|
||||
}
|
||||
|
||||
repoName, _ := reference.WithName("foo/bar")
|
||||
env := newManifestStoreTestEnv(t, repoName, "thetag",
|
||||
BlobDescriptorCacheProvider(memory.NewInMemoryBlobDescriptorCacheProvider()),
|
||||
EnableDelete, EnableRedirect)
|
||||
|
||||
ctx := context.Background()
|
||||
ms, err := env.repository.Manifests(ctx)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
// Build a manifest and store it and its layers in the registry
|
||||
|
||||
blobStore := env.repository.Blobs(ctx)
|
||||
builder := ocischema.NewManifestBuilder(blobStore, []byte{}, map[string]string{})
|
||||
builder.(*ocischema.Builder).SetMediaType(imageMediaType)
|
||||
|
||||
// Add some layers
|
||||
for i := 0; i < 2; i++ {
|
||||
rs, ds, err := testutil.CreateRandomTarFile()
|
||||
if err != nil {
|
||||
t.Fatalf("%s: unexpected error generating test layer file", testname)
|
||||
}
|
||||
dgst := digest.Digest(ds)
|
||||
|
||||
wr, err := env.repository.Blobs(env.ctx).Create(env.ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: unexpected error creating test upload: %v", testname, err)
|
||||
}
|
||||
|
||||
if _, err := io.Copy(wr, rs); err != nil {
|
||||
t.Fatalf("%s: unexpected error copying to upload: %v", testname, err)
|
||||
}
|
||||
|
||||
if _, err := wr.Commit(env.ctx, distribution.Descriptor{Digest: dgst}); err != nil {
|
||||
t.Fatalf("%s: unexpected error finishing upload: %v", testname, err)
|
||||
}
|
||||
|
||||
builder.AppendReference(distribution.Descriptor{Digest: dgst})
|
||||
}
|
||||
|
||||
manifest, err := builder.Build(ctx)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: unexpected error generating manifest: %v", testname, err)
|
||||
}
|
||||
|
||||
var manifestDigest digest.Digest
|
||||
if manifestDigest, err = ms.Put(ctx, manifest); err != nil {
|
||||
t.Fatalf("%s: unexpected error putting manifest: %v", testname, err)
|
||||
}
|
||||
|
||||
// Also create an image index that contains the manifest
|
||||
|
||||
descriptor, err := env.registry.BlobStatter().Stat(ctx, manifestDigest)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: unexpected error getting manifest descriptor", testname)
|
||||
}
|
||||
descriptor.MediaType = v1.MediaTypeImageManifest
|
||||
|
||||
platformSpec := manifestlist.PlatformSpec{
|
||||
Architecture: "atari2600",
|
||||
OS: "CP/M",
|
||||
}
|
||||
|
||||
manifestDescriptors := []manifestlist.ManifestDescriptor{
|
||||
manifestlist.ManifestDescriptor{
|
||||
Descriptor: descriptor,
|
||||
Platform: platformSpec,
|
||||
},
|
||||
}
|
||||
|
||||
imageIndex, err := manifestlist.FromDescriptorsWithMediaType(manifestDescriptors, indexMediaType)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: unexpected error creating image index: %v", testname, err)
|
||||
}
|
||||
|
||||
var indexDigest digest.Digest
|
||||
if indexDigest, err = ms.Put(ctx, imageIndex); err != nil {
|
||||
t.Fatalf("%s: unexpected error putting image index: %v", testname, err)
|
||||
}
|
||||
|
||||
// Now check that we can retrieve the manifest
|
||||
|
||||
fromStore, err := ms.Get(ctx, manifestDigest)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: unexpected error fetching manifest: %v", testname, err)
|
||||
}
|
||||
|
||||
fetchedManifest, ok := fromStore.(*ocischema.DeserializedManifest)
|
||||
if !ok {
|
||||
t.Fatalf("%s: unexpected type for fetched manifest", testname)
|
||||
}
|
||||
|
||||
if fetchedManifest.MediaType != imageMediaType {
|
||||
t.Fatalf("%s: unexpected MediaType for result, %s", testname, fetchedManifest.MediaType)
|
||||
}
|
||||
|
||||
payloadMediaType, _, err := fromStore.Payload()
|
||||
if err != nil {
|
||||
t.Fatalf("%s: error getting payload %v", testname, err)
|
||||
}
|
||||
|
||||
if payloadMediaType != v1.MediaTypeImageManifest {
|
||||
t.Fatalf("%s: unexpected MediaType for manifest payload, %s", testname, payloadMediaType)
|
||||
}
|
||||
|
||||
// and the image index
|
||||
|
||||
fromStore, err = ms.Get(ctx, indexDigest)
|
||||
if err != nil {
|
||||
t.Fatalf("%s: unexpected error fetching image index: %v", testname, err)
|
||||
}
|
||||
|
||||
fetchedIndex, ok := fromStore.(*manifestlist.DeserializedManifestList)
|
||||
if !ok {
|
||||
t.Fatalf("%s: unexpected type for fetched manifest", testname)
|
||||
}
|
||||
|
||||
if fetchedIndex.MediaType != indexMediaType {
|
||||
t.Fatalf("%s: unexpected MediaType for result, %s", testname, fetchedManifest.MediaType)
|
||||
}
|
||||
|
||||
payloadMediaType, _, err = fromStore.Payload()
|
||||
if err != nil {
|
||||
t.Fatalf("%s: error getting payload %v", testname, err)
|
||||
}
|
||||
|
||||
if payloadMediaType != v1.MediaTypeImageIndex {
|
||||
t.Fatalf("%s: unexpected MediaType for index payload, %s", testname, payloadMediaType)
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// TestLinkPathFuncs ensures that the link path functions behavior are locked
|
||||
// down and implemented as expected.
|
||||
func TestLinkPathFuncs(t *testing.T) {
|
||||
@@ -387,5 +539,4 @@ func TestLinkPathFuncs(t *testing.T) {
|
||||
t.Fatalf("incorrect path returned: %q != %q", p, testcase.expected)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
Reference in New Issue
Block a user