diff --git a/manifest/ocischema/index.go b/manifest/ocischema/index.go index 97b3943a6..16b7b6873 100644 --- a/manifest/ocischema/index.go +++ b/manifest/ocischema/index.go @@ -60,6 +60,10 @@ type ImageIndex struct { // Manifests references a list of manifests Manifests []ManifestDescriptor `json:"manifests"` + + // Annotations is an optional field that contains arbitrary metadata for the + // image index + Annotations map[string]string `json:"annotations,omitempty"` } // References returns the distribution descriptors for the referenced image @@ -83,20 +87,22 @@ type DeserializedImageIndex struct { canonical []byte } -// FromDescriptors takes a slice of descriptors, and returns a -// DeserializedManifestList which contains the resulting manifest list -// and its JSON representation. -func FromDescriptors(descriptors []ManifestDescriptor) (*DeserializedImageIndex, error) { - return fromDescriptorsWithMediaType(descriptors, v1.MediaTypeImageIndex) +// FromDescriptors takes a slice of descriptors and a map of annotations, and +// returns a DeserializedManifestList which contains the resulting manifest list +// and its JSON representation. If annotations is nil or empty then the +// annotations property will be omitted from the JSON representation. +func FromDescriptors(descriptors []ManifestDescriptor, annotations map[string]string) (*DeserializedImageIndex, error) { + return fromDescriptorsWithMediaType(descriptors, annotations, v1.MediaTypeImageIndex) } // fromDescriptorsWithMediaType is for testing purposes, it's useful to be able to specify the media type explicitly -func fromDescriptorsWithMediaType(descriptors []ManifestDescriptor, mediaType string) (*DeserializedImageIndex, error) { +func fromDescriptorsWithMediaType(descriptors []ManifestDescriptor, annotations map[string]string, mediaType string) (*DeserializedImageIndex, error) { m := ImageIndex{ Versioned: manifest.Versioned{ SchemaVersion: 2, MediaType: mediaType, }, + Annotations: annotations, } m.Manifests = make([]ManifestDescriptor, len(descriptors)) diff --git a/manifest/ocischema/index_test.go b/manifest/ocischema/index_test.go index 90d9f5861..06af34f9a 100644 --- a/manifest/ocischema/index_test.go +++ b/manifest/ocischema/index_test.go @@ -11,12 +11,6 @@ import ( v1 "github.com/opencontainers/image-spec/specs-go/v1" ) -// TODO (mikebrow): add annotations on the manifest list (index) and support for -// empty platform structs (move to Platform *Platform `json:"platform,omitempty"` -// from current Platform PlatformSpec `json:"platform"`) in the manifest descriptor. -// Requires changes to distribution/distribution/manifest/manifestlist.ManifestList and .ManifestDescriptor -// and associated serialization APIs in manifestlist.go. Or split the OCI index and -// docker manifest list implementations, which would require a lot of refactoring. const expectedOCIImageIndexSerialization = `{ "schemaVersion": 2, "mediaType": "application/vnd.oci.image.index.v1+json", @@ -50,7 +44,11 @@ const expectedOCIImageIndexSerialization = `{ "os": "sunos" } } - ] + ], + "annotations": { + "com.example.favourite-colour": "blue", + "com.example.locale": "en_GB" + } }` func makeTestOCIImageIndex(t *testing.T, mediaType string) ([]ManifestDescriptor, *DeserializedImageIndex) { @@ -87,8 +85,12 @@ func makeTestOCIImageIndex(t *testing.T, mediaType string) ([]ManifestDescriptor }, }, } + annotations := map[string]string{ + "com.example.favourite-colour": "blue", + "com.example.locale": "en_GB", + } - deserialized, err := fromDescriptorsWithMediaType(manifestDescriptors, mediaType) + deserialized, err := fromDescriptorsWithMediaType(manifestDescriptors, annotations, mediaType) if err != nil { t.Fatalf("error creating DeserializedManifestList: %v", err) } diff --git a/registry/storage/manifeststore_test.go b/registry/storage/manifeststore_test.go index dd51c2f41..bba3538e1 100644 --- a/registry/storage/manifeststore_test.go +++ b/registry/storage/manifeststore_test.go @@ -576,7 +576,7 @@ func TestLinkPathFuncs(t *testing.T) { } func ociIndexFromDesriptorsWithMediaType(descriptors []ocischema.ManifestDescriptor, mediaType string) (*ocischema.DeserializedImageIndex, error) { - manifest, err := ocischema.FromDescriptors(descriptors) + manifest, err := ocischema.FromDescriptors(descriptors, nil) if err != nil { return nil, err }