forked from TrueCloudLab/distribution
adding some support for annotations at the manifest level
Signed-off-by: Mike Brown <brownwm@us.ibm.com>
This commit is contained in:
parent
ec2aa05cdf
commit
f186e1da1c
3 changed files with 28 additions and 10 deletions
|
@ -18,15 +18,19 @@ type builder struct {
|
||||||
// layers is a list of layer descriptors that gets built by successive
|
// layers is a list of layer descriptors that gets built by successive
|
||||||
// calls to AppendReference.
|
// calls to AppendReference.
|
||||||
layers []distribution.Descriptor
|
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
|
// NewManifestBuilder is used to build new manifests for the current schema
|
||||||
// version. It takes a BlobService so it can publish the configuration blob
|
// version. It takes a BlobService so it can publish the configuration blob
|
||||||
// as part of the Build process.
|
// as part of the Build process, and annotations.
|
||||||
func NewManifestBuilder(bs distribution.BlobService, configJSON []byte) distribution.ManifestBuilder {
|
func NewManifestBuilder(bs distribution.BlobService, configJSON []byte, annotations map[string]string) distribution.ManifestBuilder {
|
||||||
mb := &builder{
|
mb := &builder{
|
||||||
bs: bs,
|
bs: bs,
|
||||||
configJSON: make([]byte, len(configJSON)),
|
configJSON: make([]byte, len(configJSON)),
|
||||||
|
annotations: annotations,
|
||||||
}
|
}
|
||||||
copy(mb.configJSON, configJSON)
|
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.
|
// Build produces a final manifest from the given references.
|
||||||
func (mb *builder) Build(ctx context.Context) (distribution.Manifest, error) {
|
func (mb *builder) Build(ctx context.Context) (distribution.Manifest, error) {
|
||||||
m := Manifest{
|
m := Manifest{
|
||||||
Versioned: SchemaVersion,
|
Versioned: SchemaVersion,
|
||||||
Layers: make([]distribution.Descriptor, len(mb.layers)),
|
Layers: make([]distribution.Descriptor, len(mb.layers)),
|
||||||
|
Annotations: mb.annotations,
|
||||||
}
|
}
|
||||||
copy(m.Layers, mb.layers)
|
copy(m.Layers, mb.layers)
|
||||||
|
|
||||||
|
|
|
@ -88,6 +88,9 @@ func TestBuilder(t *testing.T) {
|
||||||
],
|
],
|
||||||
"type": "layers"
|
"type": "layers"
|
||||||
},
|
},
|
||||||
|
"annotations": {
|
||||||
|
"hot": "potato"
|
||||||
|
}
|
||||||
"history": [
|
"history": [
|
||||||
{
|
{
|
||||||
"created": "2015-10-31T22:22:54.690851953Z",
|
"created": "2015-10-31T22:22:54.690851953Z",
|
||||||
|
@ -120,9 +123,10 @@ func TestBuilder(t *testing.T) {
|
||||||
MediaType: v1.MediaTypeImageLayerGzip,
|
MediaType: v1.MediaTypeImageLayerGzip,
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
annotations := map[string]string{"hot": "potato"}
|
||||||
|
|
||||||
bs := &mockBlobService{descriptors: make(map[digest.Digest]distribution.Descriptor)}
|
bs := &mockBlobService{descriptors: make(map[digest.Digest]distribution.Descriptor)}
|
||||||
builder := NewManifestBuilder(bs, imgJSON)
|
builder := NewManifestBuilder(bs, imgJSON, annotations)
|
||||||
|
|
||||||
for _, d := range descriptors {
|
for _, d := range descriptors {
|
||||||
if err := builder.AppendReference(d); err != nil {
|
if err := builder.AppendReference(d); err != nil {
|
||||||
|
@ -142,6 +146,9 @@ func TestBuilder(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
manifest := built.(*DeserializedManifest).Manifest
|
manifest := built.(*DeserializedManifest).Manifest
|
||||||
|
if manifest.Annotations["hot"] != "potato" {
|
||||||
|
t.Fatalf("unexpected annotation in manifest: %s", manifest.Annotations["hot"])
|
||||||
|
}
|
||||||
|
|
||||||
if manifest.Versioned.SchemaVersion != 2 {
|
if manifest.Versioned.SchemaVersion != 2 {
|
||||||
t.Fatal("SchemaVersion != 2")
|
t.Fatal("SchemaVersion != 2")
|
||||||
|
@ -154,7 +161,7 @@ func TestBuilder(t *testing.T) {
|
||||||
if target.MediaType != v1.MediaTypeImageConfig {
|
if target.MediaType != v1.MediaTypeImageConfig {
|
||||||
t.Fatalf("unexpected media type in target: %s", target.MediaType)
|
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)
|
t.Fatalf("unexpected size in target: %d", target.Size)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
"github.com/opencontainers/image-spec/specs-go/v1"
|
"github.com/opencontainers/image-spec/specs-go/v1"
|
||||||
)
|
)
|
||||||
|
|
||||||
// TODO (mikebrow): add annotations to the test
|
|
||||||
var expectedManifestSerialization = []byte(`{
|
var expectedManifestSerialization = []byte(`{
|
||||||
"schemaVersion": 2,
|
"schemaVersion": 2,
|
||||||
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
"mediaType": "application/vnd.oci.image.manifest.v1+json",
|
||||||
|
@ -31,7 +30,10 @@ var expectedManifestSerialization = []byte(`{
|
||||||
"lettuce": "wrap"
|
"lettuce": "wrap"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
]
|
],
|
||||||
|
"annotations": {
|
||||||
|
"hot": "potato"
|
||||||
|
}
|
||||||
}`)
|
}`)
|
||||||
|
|
||||||
func TestManifest(t *testing.T) {
|
func TestManifest(t *testing.T) {
|
||||||
|
@ -51,6 +53,7 @@ func TestManifest(t *testing.T) {
|
||||||
Annotations: map[string]string{"lettuce": "wrap"},
|
Annotations: map[string]string{"lettuce": "wrap"},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
Annotations: map[string]string{"hot": "potato"},
|
||||||
}
|
}
|
||||||
|
|
||||||
deserialized, err := FromStruct(manifest)
|
deserialized, err := FromStruct(manifest)
|
||||||
|
@ -87,6 +90,9 @@ func TestManifest(t *testing.T) {
|
||||||
if !reflect.DeepEqual(&unmarshalled, deserialized) {
|
if !reflect.DeepEqual(&unmarshalled, deserialized) {
|
||||||
t.Fatalf("manifests are different after unmarshaling: %v != %v", 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()
|
target := deserialized.Target()
|
||||||
if target.Digest != "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b" {
|
if target.Digest != "sha256:1a9ec845ee94c202b2d5da74a24f0ed2058318bfa9879fa541efaecba272e86b" {
|
||||||
|
|
Loading…
Reference in a new issue