Support annotations in the OCI Image Index

Empty platform structs were already supported after splitting OCI Image
Index out from Docker Manifest List.

Signed-off-by: Bracken Dawson <abdawson@gmail.com>
This commit is contained in:
Bracken Dawson 2023-03-31 14:01:15 +01:00
parent e72294d075
commit 88646f54da
No known key found for this signature in database
GPG key ID: 7C6C7FA182101826
3 changed files with 23 additions and 15 deletions

View file

@ -60,6 +60,10 @@ type ImageIndex struct {
// Manifests references a list of manifests // Manifests references a list of manifests
Manifests []ManifestDescriptor `json:"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 // References returns the distribution descriptors for the referenced image
@ -83,20 +87,22 @@ type DeserializedImageIndex struct {
canonical []byte canonical []byte
} }
// FromDescriptors takes a slice of descriptors, and returns a // FromDescriptors takes a slice of descriptors and a map of annotations, and
// DeserializedManifestList which contains the resulting manifest list // returns a DeserializedManifestList which contains the resulting manifest list
// and its JSON representation. // and its JSON representation. If annotations is nil or empty then the
func FromDescriptors(descriptors []ManifestDescriptor) (*DeserializedImageIndex, error) { // annotations property will be omitted from the JSON representation.
return fromDescriptorsWithMediaType(descriptors, v1.MediaTypeImageIndex) 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 // 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{ m := ImageIndex{
Versioned: manifest.Versioned{ Versioned: manifest.Versioned{
SchemaVersion: 2, SchemaVersion: 2,
MediaType: mediaType, MediaType: mediaType,
}, },
Annotations: annotations,
} }
m.Manifests = make([]ManifestDescriptor, len(descriptors)) m.Manifests = make([]ManifestDescriptor, len(descriptors))

View file

@ -11,12 +11,6 @@ import (
v1 "github.com/opencontainers/image-spec/specs-go/v1" 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 = `{ const expectedOCIImageIndexSerialization = `{
"schemaVersion": 2, "schemaVersion": 2,
"mediaType": "application/vnd.oci.image.index.v1+json", "mediaType": "application/vnd.oci.image.index.v1+json",
@ -50,7 +44,11 @@ const expectedOCIImageIndexSerialization = `{
"os": "sunos" "os": "sunos"
} }
} }
] ],
"annotations": {
"com.example.favourite-colour": "blue",
"com.example.locale": "en_GB"
}
}` }`
func makeTestOCIImageIndex(t *testing.T, mediaType string) ([]ManifestDescriptor, *DeserializedImageIndex) { 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 { if err != nil {
t.Fatalf("error creating DeserializedManifestList: %v", err) t.Fatalf("error creating DeserializedManifestList: %v", err)
} }

View file

@ -576,7 +576,7 @@ func TestLinkPathFuncs(t *testing.T) {
} }
func ociIndexFromDesriptorsWithMediaType(descriptors []ocischema.ManifestDescriptor, mediaType string) (*ocischema.DeserializedImageIndex, error) { func ociIndexFromDesriptorsWithMediaType(descriptors []ocischema.ManifestDescriptor, mediaType string) (*ocischema.DeserializedImageIndex, error) {
manifest, err := ocischema.FromDescriptors(descriptors) manifest, err := ocischema.FromDescriptors(descriptors, nil)
if err != nil { if err != nil {
return nil, err return nil, err
} }