diff --git a/manifest/ocischema/builder.go b/manifest/ocischema/builder.go index a6d6633a8..c10376f8d 100644 --- a/manifest/ocischema/builder.go +++ b/manifest/ocischema/builder.go @@ -18,15 +18,19 @@ type builder struct { // layers is a list of layer descriptors that gets built by successive // calls to AppendReference. layers []distribution.Descriptor + + // Annotations contains arbitrary metadata relating to the targeted content. + annotations map[string]string } // NewManifestBuilder is used to build new manifests for the current schema // version. It takes a BlobService so it can publish the configuration blob -// as part of the Build process. -func NewManifestBuilder(bs distribution.BlobService, configJSON []byte) distribution.ManifestBuilder { +// as part of the Build process, and annotations. +func NewManifestBuilder(bs distribution.BlobService, configJSON []byte, annotations map[string]string) distribution.ManifestBuilder { mb := &builder{ - bs: bs, - configJSON: make([]byte, len(configJSON)), + bs: bs, + configJSON: make([]byte, len(configJSON)), + annotations: annotations, } copy(mb.configJSON, configJSON) @@ -36,8 +40,9 @@ func NewManifestBuilder(bs distribution.BlobService, configJSON []byte) distribu // Build produces a final manifest from the given references. func (mb *builder) Build(ctx context.Context) (distribution.Manifest, error) { m := Manifest{ - Versioned: SchemaVersion, - Layers: make([]distribution.Descriptor, len(mb.layers)), + Versioned: SchemaVersion, + Layers: make([]distribution.Descriptor, len(mb.layers)), + Annotations: mb.annotations, } copy(m.Layers, mb.layers) diff --git a/manifest/ocischema/builder_test.go b/manifest/ocischema/builder_test.go index 27562cfd0..557681ba9 100644 --- a/manifest/ocischema/builder_test.go +++ b/manifest/ocischema/builder_test.go @@ -88,6 +88,9 @@ func TestBuilder(t *testing.T) { ], "type": "layers" }, + "annotations": { + "hot": "potato" + } "history": [ { "created": "2015-10-31T22:22:54.690851953Z", @@ -120,9 +123,10 @@ func TestBuilder(t *testing.T) { MediaType: v1.MediaTypeImageLayerGzip, }, } + annotations := map[string]string{"hot": "potato"} bs := &mockBlobService{descriptors: make(map[digest.Digest]distribution.Descriptor)} - builder := NewManifestBuilder(bs, imgJSON) + builder := NewManifestBuilder(bs, imgJSON, annotations) for _, d := range descriptors { if err := builder.AppendReference(d); err != nil { @@ -142,6 +146,9 @@ func TestBuilder(t *testing.T) { } manifest := built.(*DeserializedManifest).Manifest + if manifest.Annotations["hot"] != "potato" { + t.Fatalf("unexpected annotation in manifest: %s", manifest.Annotations["hot"]) + } if manifest.Versioned.SchemaVersion != 2 { t.Fatal("SchemaVersion != 2") @@ -154,7 +161,7 @@ func TestBuilder(t *testing.T) { if target.MediaType != v1.MediaTypeImageConfig { t.Fatalf("unexpected media type in target: %s", target.MediaType) } - if target.Size != 1582 { + if target.Size != 1632 { t.Fatalf("unexpected size in target: %d", target.Size) } diff --git a/manifest/ocischema/manifest_test.go b/manifest/ocischema/manifest_test.go index c37fe8fb3..749cb859f 100644 --- a/manifest/ocischema/manifest_test.go +++ b/manifest/ocischema/manifest_test.go @@ -10,7 +10,6 @@ import ( "github.com/opencontainers/image-spec/specs-go/v1" ) -// TODO (mikebrow): add annotations to the test var expectedManifestSerialization = []byte(`{ "schemaVersion": 2, "mediaType": "application/vnd.oci.image.manifest.v1+json", @@ -31,7 +30,10 @@ var expectedManifestSerialization = []byte(`{ "lettuce": "wrap" } } - ] + ], + "annotations": { + "hot": "potato" + } }`) func TestManifest(t *testing.T) { @@ -51,6 +53,7 @@ func TestManifest(t *testing.T) { Annotations: map[string]string{"lettuce": "wrap"}, }, }, + Annotations: map[string]string{"hot": "potato"}, } deserialized, err := FromStruct(manifest) @@ -87,6 +90,9 @@ func TestManifest(t *testing.T) { if !reflect.DeepEqual(&unmarshalled, deserialized) { t.Fatalf("manifests are different after unmarshaling: %v != %v", unmarshalled, *deserialized) } + if deserialized.Annotations["hot"] != "potato" { + t.Fatalf("unexpected annotation in manifest: %s", deserialized.Annotations["hot"]) + } target := deserialized.Target() if target.Digest != "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b" {