Merge pull request #3000 from stefanberger/descriptor_annotations.pr

Add missing annotations map to Descriptor for gRPC transfer
This commit is contained in:
Michael Crosby 2019-03-22 14:05:44 -04:00 committed by GitHub
commit 9b882c44f8
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 440 additions and 66 deletions

View File

@ -1771,6 +1771,34 @@ file {
type: TYPE_INT64 type: TYPE_INT64
json_name: "size" json_name: "size"
} }
field {
name: "annotations"
number: 5
label: LABEL_REPEATED
type: TYPE_MESSAGE
type_name: ".containerd.types.Descriptor.AnnotationsEntry"
json_name: "annotations"
}
nested_type {
name: "AnnotationsEntry"
field {
name: "key"
number: 1
label: LABEL_OPTIONAL
type: TYPE_STRING
json_name: "key"
}
field {
name: "value"
number: 2
label: LABEL_OPTIONAL
type: TYPE_STRING
json_name: "value"
}
options {
map_entry: true
}
}
} }
options { options {
go_package: "github.com/containerd/containerd/api/types;types" go_package: "github.com/containerd/containerd/api/types;types"

View File

@ -28,6 +28,7 @@ import github_com_opencontainers_go_digest "github.com/opencontainers/go-digest"
import strings "strings" import strings "strings"
import reflect "reflect" import reflect "reflect"
import sortkeys "github.com/gogo/protobuf/sortkeys"
import io "io" import io "io"
@ -51,6 +52,7 @@ type Descriptor struct {
MediaType string `protobuf:"bytes,1,opt,name=media_type,json=mediaType,proto3" json:"media_type,omitempty"` MediaType string `protobuf:"bytes,1,opt,name=media_type,json=mediaType,proto3" json:"media_type,omitempty"`
Digest github_com_opencontainers_go_digest.Digest `protobuf:"bytes,2,opt,name=digest,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"digest"` Digest github_com_opencontainers_go_digest.Digest `protobuf:"bytes,2,opt,name=digest,proto3,customtype=github.com/opencontainers/go-digest.Digest" json:"digest"`
Size_ int64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"` Size_ int64 `protobuf:"varint,3,opt,name=size,proto3" json:"size,omitempty"`
Annotations map[string]string `protobuf:"bytes,5,rep,name=annotations" json:"annotations,omitempty" protobuf_key:"bytes,1,opt,name=key,proto3" protobuf_val:"bytes,2,opt,name=value,proto3"`
} }
func (m *Descriptor) Reset() { *m = Descriptor{} } func (m *Descriptor) Reset() { *m = Descriptor{} }
@ -92,6 +94,23 @@ func (m *Descriptor) MarshalTo(dAtA []byte) (int, error) {
i++ i++
i = encodeVarintDescriptor(dAtA, i, uint64(m.Size_)) i = encodeVarintDescriptor(dAtA, i, uint64(m.Size_))
} }
if len(m.Annotations) > 0 {
for k, _ := range m.Annotations {
dAtA[i] = 0x2a
i++
v := m.Annotations[k]
mapSize := 1 + len(k) + sovDescriptor(uint64(len(k))) + 1 + len(v) + sovDescriptor(uint64(len(v)))
i = encodeVarintDescriptor(dAtA, i, uint64(mapSize))
dAtA[i] = 0xa
i++
i = encodeVarintDescriptor(dAtA, i, uint64(len(k)))
i += copy(dAtA[i:], k)
dAtA[i] = 0x12
i++
i = encodeVarintDescriptor(dAtA, i, uint64(len(v)))
i += copy(dAtA[i:], v)
}
}
return i, nil return i, nil
} }
@ -118,6 +137,14 @@ func (m *Descriptor) Size() (n int) {
if m.Size_ != 0 { if m.Size_ != 0 {
n += 1 + sovDescriptor(uint64(m.Size_)) n += 1 + sovDescriptor(uint64(m.Size_))
} }
if len(m.Annotations) > 0 {
for k, v := range m.Annotations {
_ = k
_ = v
mapEntrySize := 1 + len(k) + sovDescriptor(uint64(len(k))) + 1 + len(v) + sovDescriptor(uint64(len(v)))
n += mapEntrySize + 1 + sovDescriptor(uint64(mapEntrySize))
}
}
return n return n
} }
@ -138,10 +165,21 @@ func (this *Descriptor) String() string {
if this == nil { if this == nil {
return "nil" return "nil"
} }
keysForAnnotations := make([]string, 0, len(this.Annotations))
for k, _ := range this.Annotations {
keysForAnnotations = append(keysForAnnotations, k)
}
sortkeys.Strings(keysForAnnotations)
mapStringForAnnotations := "map[string]string{"
for _, k := range keysForAnnotations {
mapStringForAnnotations += fmt.Sprintf("%v: %v,", k, this.Annotations[k])
}
mapStringForAnnotations += "}"
s := strings.Join([]string{`&Descriptor{`, s := strings.Join([]string{`&Descriptor{`,
`MediaType:` + fmt.Sprintf("%v", this.MediaType) + `,`, `MediaType:` + fmt.Sprintf("%v", this.MediaType) + `,`,
`Digest:` + fmt.Sprintf("%v", this.Digest) + `,`, `Digest:` + fmt.Sprintf("%v", this.Digest) + `,`,
`Size_:` + fmt.Sprintf("%v", this.Size_) + `,`, `Size_:` + fmt.Sprintf("%v", this.Size_) + `,`,
`Annotations:` + mapStringForAnnotations + `,`,
`}`, `}`,
}, "") }, "")
return s return s
@ -260,6 +298,124 @@ func (m *Descriptor) Unmarshal(dAtA []byte) error {
break break
} }
} }
case 5:
if wireType != 2 {
return fmt.Errorf("proto: wrong wireType = %d for field Annotations", wireType)
}
var msglen int
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDescriptor
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
msglen |= (int(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
if msglen < 0 {
return ErrInvalidLengthDescriptor
}
postIndex := iNdEx + msglen
if postIndex > l {
return io.ErrUnexpectedEOF
}
if m.Annotations == nil {
m.Annotations = make(map[string]string)
}
var mapkey string
var mapvalue string
for iNdEx < postIndex {
entryPreIndex := iNdEx
var wire uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDescriptor
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
wire |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
fieldNum := int32(wire >> 3)
if fieldNum == 1 {
var stringLenmapkey uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDescriptor
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapkey |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLenmapkey := int(stringLenmapkey)
if intStringLenmapkey < 0 {
return ErrInvalidLengthDescriptor
}
postStringIndexmapkey := iNdEx + intStringLenmapkey
if postStringIndexmapkey > l {
return io.ErrUnexpectedEOF
}
mapkey = string(dAtA[iNdEx:postStringIndexmapkey])
iNdEx = postStringIndexmapkey
} else if fieldNum == 2 {
var stringLenmapvalue uint64
for shift := uint(0); ; shift += 7 {
if shift >= 64 {
return ErrIntOverflowDescriptor
}
if iNdEx >= l {
return io.ErrUnexpectedEOF
}
b := dAtA[iNdEx]
iNdEx++
stringLenmapvalue |= (uint64(b) & 0x7F) << shift
if b < 0x80 {
break
}
}
intStringLenmapvalue := int(stringLenmapvalue)
if intStringLenmapvalue < 0 {
return ErrInvalidLengthDescriptor
}
postStringIndexmapvalue := iNdEx + intStringLenmapvalue
if postStringIndexmapvalue > l {
return io.ErrUnexpectedEOF
}
mapvalue = string(dAtA[iNdEx:postStringIndexmapvalue])
iNdEx = postStringIndexmapvalue
} else {
iNdEx = entryPreIndex
skippy, err := skipDescriptor(dAtA[iNdEx:])
if err != nil {
return err
}
if skippy < 0 {
return ErrInvalidLengthDescriptor
}
if (iNdEx + skippy) > postIndex {
return io.ErrUnexpectedEOF
}
iNdEx += skippy
}
}
m.Annotations[mapkey] = mapvalue
iNdEx = postIndex
default: default:
iNdEx = preIndex iNdEx = preIndex
skippy, err := skipDescriptor(dAtA[iNdEx:]) skippy, err := skipDescriptor(dAtA[iNdEx:])
@ -391,20 +547,25 @@ func init() {
} }
var fileDescriptorDescriptor = []byte{ var fileDescriptorDescriptor = []byte{
// 234 bytes of a gzipped FileDescriptorProto // 311 bytes of a gzipped FileDescriptorProto
0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xb2, 0x4e, 0xcf, 0x2c, 0xc9, 0x1f, 0x8b, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0xff, 0xe2, 0xb2, 0x4e, 0xcf, 0x2c, 0xc9,
0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d, 0x28, 0x4d, 0xd2, 0x4b, 0xce, 0xcf, 0xd5, 0x4f, 0xce, 0xcf, 0x2b, 0x49, 0xcc, 0xcc, 0x4b, 0x2d,
0x4a, 0x41, 0x66, 0x26, 0x16, 0x64, 0xea, 0x97, 0x54, 0x16, 0xa4, 0x16, 0xeb, 0xa7, 0xa4, 0x16, 0x4a, 0x41, 0x66, 0x26, 0x16, 0x64, 0xea, 0x97, 0x54, 0x16, 0xa4, 0x16, 0xeb, 0xa7, 0xa4, 0x16,
0x27, 0x17, 0x65, 0x16, 0x94, 0xe4, 0x17, 0xe9, 0x15, 0x14, 0xe5, 0x97, 0xe4, 0x0b, 0x09, 0x20, 0x27, 0x17, 0x65, 0x16, 0x94, 0xe4, 0x17, 0xe9, 0x15, 0x14, 0xe5, 0x97, 0xe4, 0x0b, 0x09, 0x20,
0x94, 0xe9, 0x81, 0x95, 0x48, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x25, 0xf5, 0x41, 0x2c, 0x88, 0x94, 0xe9, 0x81, 0x95, 0x48, 0x89, 0xa4, 0xe7, 0xa7, 0xe7, 0x83, 0x25, 0xf5, 0x41, 0x2c, 0x88,
0x3a, 0xa5, 0x6e, 0x46, 0x2e, 0x2e, 0x17, 0xb8, 0x66, 0x21, 0x59, 0x2e, 0xae, 0xdc, 0xd4, 0x94, 0x3a, 0xa5, 0x39, 0x4c, 0x5c, 0x5c, 0x2e, 0x70, 0xcd, 0x42, 0xb2, 0x5c, 0x5c, 0xb9, 0xa9, 0x29,
0xcc, 0xc4, 0x78, 0x90, 0x1e, 0x09, 0x46, 0x05, 0x46, 0x0d, 0xce, 0x20, 0x4e, 0xb0, 0x48, 0x48, 0x99, 0x89, 0xf1, 0x20, 0x3d, 0x12, 0x8c, 0x0a, 0x8c, 0x1a, 0x9c, 0x41, 0x9c, 0x60, 0x91, 0x90,
0x65, 0x41, 0xaa, 0x90, 0x17, 0x17, 0x5b, 0x4a, 0x66, 0x7a, 0x6a, 0x71, 0x89, 0x04, 0x13, 0x48, 0xca, 0x82, 0x54, 0x21, 0x2f, 0x2e, 0xb6, 0x94, 0xcc, 0xf4, 0xd4, 0xe2, 0x12, 0x09, 0x26, 0x90,
0xca, 0xc9, 0xe8, 0xc4, 0x3d, 0x79, 0x86, 0x5b, 0xf7, 0xe4, 0xb5, 0x90, 0x9c, 0x9a, 0x5f, 0x90, 0x94, 0x93, 0xd1, 0x89, 0x7b, 0xf2, 0x0c, 0xb7, 0xee, 0xc9, 0x6b, 0x21, 0x39, 0x35, 0xbf, 0x20,
0x9a, 0x07, 0xb7, 0xbc, 0x58, 0x3f, 0x3d, 0x5f, 0x17, 0xa2, 0x45, 0xcf, 0x05, 0x4c, 0x05, 0x41, 0x35, 0x0f, 0x6e, 0x79, 0xb1, 0x7e, 0x7a, 0xbe, 0x2e, 0x44, 0x8b, 0x9e, 0x0b, 0x98, 0x0a, 0x82,
0x4d, 0x10, 0x12, 0xe2, 0x62, 0x29, 0xce, 0xac, 0x4a, 0x95, 0x60, 0x56, 0x60, 0xd4, 0x60, 0x0e, 0x9a, 0x20, 0x24, 0xc4, 0xc5, 0x52, 0x9c, 0x59, 0x95, 0x2a, 0xc1, 0xac, 0xc0, 0xa8, 0xc1, 0x1c,
0x02, 0xb3, 0x9d, 0xbc, 0x4e, 0x3c, 0x94, 0x63, 0xb8, 0xf1, 0x50, 0x8e, 0xa1, 0xe1, 0x91, 0x1c, 0x04, 0x66, 0x0b, 0xf9, 0x73, 0x71, 0x27, 0xe6, 0xe5, 0xe5, 0x97, 0x24, 0x96, 0x64, 0xe6, 0xe7,
0xe3, 0x89, 0x47, 0x72, 0x8c, 0x17, 0x1e, 0xc9, 0x31, 0x3e, 0x78, 0x24, 0xc7, 0x18, 0x65, 0x40, 0x15, 0x4b, 0xb0, 0x2a, 0x30, 0x6b, 0x70, 0x1b, 0xe9, 0xea, 0xa1, 0xfb, 0x45, 0x0f, 0xe1, 0x62,
0x7c, 0x60, 0x58, 0x83, 0xc9, 0x08, 0x86, 0x24, 0x36, 0xb0, 0x17, 0x8d, 0x01, 0x01, 0x00, 0x00, 0x3d, 0x47, 0x84, 0x7a, 0xd7, 0xbc, 0x92, 0xa2, 0xca, 0x20, 0x64, 0x13, 0xa4, 0xec, 0xb8, 0x04,
0xff, 0xff, 0xea, 0xac, 0x78, 0x9a, 0x49, 0x01, 0x00, 0x00, 0xd0, 0x15, 0x08, 0x09, 0x70, 0x31, 0x67, 0xa7, 0x56, 0x42, 0x3d, 0x07, 0x62, 0x0a, 0x89, 0x70,
0xb1, 0x96, 0x25, 0xe6, 0x94, 0xa6, 0x42, 0x7c, 0x15, 0x04, 0xe1, 0x58, 0x31, 0x59, 0x30, 0x3a,
0x79, 0x9d, 0x78, 0x28, 0xc7, 0x70, 0xe3, 0xa1, 0x1c, 0x43, 0xc3, 0x23, 0x39, 0xc6, 0x13, 0x8f,
0xe4, 0x18, 0x2f, 0x3c, 0x92, 0x63, 0x7c, 0xf0, 0x48, 0x8e, 0x31, 0xca, 0x80, 0xf8, 0xd8, 0xb1,
0x06, 0x93, 0x11, 0x0c, 0x49, 0x6c, 0xe0, 0x30, 0x37, 0x06, 0x04, 0x00, 0x00, 0xff, 0xff, 0x22,
0x8a, 0x20, 0x4a, 0xda, 0x01, 0x00, 0x00,
} }

View File

@ -15,4 +15,5 @@ message Descriptor {
string media_type = 1; string media_type = 1;
string digest = 2 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false]; string digest = 2 [(gogoproto.customtype) = "github.com/opencontainers/go-digest.Digest", (gogoproto.nullable) = false];
int64 size = 3; int64 size = 3;
map<string, string> annotations = 5;
} }

View File

@ -74,6 +74,7 @@ func WithCheckpointTask(ctx context.Context, client *Client, c *containers.Conta
Size: d.Size_, Size: d.Size_,
Digest: d.Digest, Digest: d.Digest,
Platform: &platformSpec, Platform: &platformSpec,
Annotations: d.Annotations,
}) })
} }
// save copts // save copts

View File

@ -83,6 +83,7 @@ func toDescriptor(d *types.Descriptor) ocispec.Descriptor {
MediaType: d.MediaType, MediaType: d.MediaType,
Digest: d.Digest, Digest: d.Digest,
Size: d.Size_, Size: d.Size_,
Annotations: d.Annotations,
} }
} }
@ -91,6 +92,7 @@ func fromDescriptor(d ocispec.Descriptor) *types.Descriptor {
MediaType: d.MediaType, MediaType: d.MediaType,
Digest: d.Digest, Digest: d.Digest,
Size_: d.Size, Size_: d.Size,
Annotations: d.Annotations,
} }
} }

View File

@ -140,6 +140,7 @@ func descFromProto(desc *types.Descriptor) ocispec.Descriptor {
MediaType: desc.MediaType, MediaType: desc.MediaType,
Size: desc.Size_, Size: desc.Size_,
Digest: desc.Digest, Digest: desc.Digest,
Annotations: desc.Annotations,
} }
} }
@ -148,5 +149,6 @@ func descToProto(desc *ocispec.Descriptor) types.Descriptor {
MediaType: desc.MediaType, MediaType: desc.MediaType,
Size_: desc.Size, Size_: desc.Size,
Digest: desc.Digest, Digest: desc.Digest,
Annotations: desc.Annotations,
} }
} }

View File

@ -23,6 +23,7 @@ import (
"io/ioutil" "io/ioutil"
"math/rand" "math/rand"
"reflect"
"runtime" "runtime"
"testing" "testing"
@ -94,11 +95,11 @@ func TestImport(t *testing.T) {
c1, d2 := createConfig() c1, d2 := createConfig()
m1, d3 := createManifest(c1, [][]byte{b1}) m1, d3, expManifest := createManifest(c1, [][]byte{b1})
provider := client.ContentStore() provider := client.ContentStore()
checkManifest := func(ctx context.Context, t *testing.T, d ocispec.Descriptor) { checkManifest := func(ctx context.Context, t *testing.T, d ocispec.Descriptor, expManifest *ocispec.Manifest) {
m, err := images.Manifest(ctx, provider, d, nil) m, err := images.Manifest(ctx, provider, d, nil)
if err != nil { if err != nil {
t.Fatalf("unable to read target blob: %+v", err) t.Fatalf("unable to read target blob: %+v", err)
@ -115,6 +116,15 @@ func TestImport(t *testing.T) {
if m.Layers[0].Digest != d1 { if m.Layers[0].Digest != d1 {
t.Fatalf("unexpected layer hash %s, expected %s", m.Layers[0].Digest, d1) t.Fatalf("unexpected layer hash %s, expected %s", m.Layers[0].Digest, d1)
} }
if expManifest != nil {
if !reflect.DeepEqual(m.Layers, expManifest.Layers) {
t.Fatalf("DeepEqual on Layers failed: %v vs. %v", m.Layers, expManifest.Layers)
}
if !reflect.DeepEqual(m.Config, expManifest.Config) {
t.Fatalf("DeepEqual on Config failed: %v vs. %v", m.Config, expManifest.Config)
}
}
} }
for _, tc := range []struct { for _, tc := range []struct {
@ -154,7 +164,7 @@ func TestImport(t *testing.T) {
} }
checkImages(t, imgs[0].Target.Digest, imgs, names...) checkImages(t, imgs[0].Target.Digest, imgs, names...)
checkManifest(ctx, t, imgs[0].Target) checkManifest(ctx, t, imgs[0].Target, nil)
}, },
}, },
{ {
@ -181,7 +191,7 @@ func TestImport(t *testing.T) {
} }
checkImages(t, d3, imgs, names...) checkImages(t, d3, imgs, names...)
checkManifest(ctx, t, imgs[0].Target) checkManifest(ctx, t, imgs[0].Target, expManifest)
}, },
}, },
{ {
@ -202,7 +212,7 @@ func TestImport(t *testing.T) {
} }
checkImages(t, d3, imgs, names...) checkImages(t, d3, imgs, names...)
checkManifest(ctx, t, imgs[0].Target) checkManifest(ctx, t, imgs[0].Target, expManifest)
}, },
Opts: []ImportOpt{ Opts: []ImportOpt{
WithImageRefTranslator(archive.AddRefPrefix("localhost:5000/myimage")), WithImageRefTranslator(archive.AddRefPrefix("localhost:5000/myimage")),
@ -226,7 +236,7 @@ func TestImport(t *testing.T) {
} }
checkImages(t, d3, imgs, names...) checkImages(t, d3, imgs, names...)
checkManifest(ctx, t, imgs[0].Target) checkManifest(ctx, t, imgs[0].Target, expManifest)
}, },
Opts: []ImportOpt{ Opts: []ImportOpt{
WithImageRefTranslator(archive.FilterRefPrefix("localhost:5000/myimage")), WithImageRefTranslator(archive.FilterRefPrefix("localhost:5000/myimage")),
@ -288,7 +298,7 @@ func createConfig() ([]byte, digest.Digest) {
return b, digest.FromBytes(b) return b, digest.FromBytes(b)
} }
func createManifest(config []byte, layers [][]byte) ([]byte, digest.Digest) { func createManifest(config []byte, layers [][]byte) ([]byte, digest.Digest, *ocispec.Manifest) {
manifest := ocispec.Manifest{ manifest := ocispec.Manifest{
Versioned: specs.Versioned{ Versioned: specs.Versioned{
SchemaVersion: 2, SchemaVersion: 2,
@ -297,6 +307,9 @@ func createManifest(config []byte, layers [][]byte) ([]byte, digest.Digest) {
MediaType: ocispec.MediaTypeImageConfig, MediaType: ocispec.MediaTypeImageConfig,
Digest: digest.FromBytes(config), Digest: digest.FromBytes(config),
Size: int64(len(config)), Size: int64(len(config)),
Annotations: map[string]string{
"ocispec": "manifest.config.descriptor",
},
}, },
} }
for _, l := range layers { for _, l := range layers {
@ -304,12 +317,15 @@ func createManifest(config []byte, layers [][]byte) ([]byte, digest.Digest) {
MediaType: ocispec.MediaTypeImageLayer, MediaType: ocispec.MediaTypeImageLayer,
Digest: digest.FromBytes(l), Digest: digest.FromBytes(l),
Size: int64(len(l)), Size: int64(len(l)),
Annotations: map[string]string{
"ocispec": "manifest.layers.descriptor",
},
}) })
} }
b, _ := json.Marshal(manifest) b, _ := json.Marshal(manifest)
return b, digest.FromBytes(b) return b, digest.FromBytes(b), &manifest
} }
func createIndex(manifest []byte, tags ...string) []byte { func createIndex(manifest []byte, tags ...string) []byte {

View File

@ -24,6 +24,7 @@ import (
) )
var ( var (
bucketKeyAnnotations = []byte("annotations")
bucketKeyLabels = []byte("labels") bucketKeyLabels = []byte("labels")
bucketKeyCreatedAt = []byte("createdat") bucketKeyCreatedAt = []byte("createdat")
bucketKeyUpdatedAt = []byte("updatedat") bucketKeyUpdatedAt = []byte("updatedat")
@ -32,7 +33,17 @@ var (
// ReadLabels reads the labels key from the bucket // ReadLabels reads the labels key from the bucket
// Uses the key "labels" // Uses the key "labels"
func ReadLabels(bkt *bolt.Bucket) (map[string]string, error) { func ReadLabels(bkt *bolt.Bucket) (map[string]string, error) {
lbkt := bkt.Bucket(bucketKeyLabels) return readMap(bkt, bucketKeyLabels)
}
// ReadAnnotations reads the OCI Descriptor Annotations key from the bucket
// Uses the key "annotations"
func ReadAnnotations(bkt *bolt.Bucket) (map[string]string, error) {
return readMap(bkt, bucketKeyAnnotations)
}
func readMap(bkt *bolt.Bucket, bucketName []byte) (map[string]string, error) {
lbkt := bkt.Bucket(bucketName)
if lbkt == nil { if lbkt == nil {
return nil, nil return nil, nil
} }
@ -53,9 +64,18 @@ func ReadLabels(bkt *bolt.Bucket) (map[string]string, error) {
// bucket. Typically, this removes zero-value entries. // bucket. Typically, this removes zero-value entries.
// Uses the key "labels" // Uses the key "labels"
func WriteLabels(bkt *bolt.Bucket, labels map[string]string) error { func WriteLabels(bkt *bolt.Bucket, labels map[string]string) error {
return writeMap(bkt, bucketKeyLabels, labels)
}
// WriteAnnotations writes the OCI Descriptor Annotations
func WriteAnnotations(bkt *bolt.Bucket, labels map[string]string) error {
return writeMap(bkt, bucketKeyAnnotations, labels)
}
func writeMap(bkt *bolt.Bucket, bucketName []byte, labels map[string]string) error {
// Remove existing labels to keep from merging // Remove existing labels to keep from merging
if lbkt := bkt.Bucket(bucketKeyLabels); lbkt != nil { if lbkt := bkt.Bucket(bucketName); lbkt != nil {
if err := bkt.DeleteBucket(bucketKeyLabels); err != nil { if err := bkt.DeleteBucket(bucketName); err != nil {
return err return err
} }
} }
@ -64,7 +84,7 @@ func WriteLabels(bkt *bolt.Bucket, labels map[string]string) error {
return nil return nil
} }
lbkt, err := bkt.CreateBucket(bucketKeyLabels) lbkt, err := bkt.CreateBucket(bucketName)
if err != nil { if err != nil {
return err return err
} }

View File

@ -192,6 +192,14 @@ func (s *imageStore) Update(ctx context.Context, image images.Image, fieldpaths
key := strings.TrimPrefix(path, "labels.") key := strings.TrimPrefix(path, "labels.")
updated.Labels[key] = image.Labels[key] updated.Labels[key] = image.Labels[key]
continue continue
} else if strings.HasPrefix(path, "annotations.") {
if updated.Target.Annotations == nil {
updated.Target.Annotations = map[string]string{}
}
key := strings.TrimPrefix(path, "annotations.")
updated.Target.Annotations[key] = image.Target.Annotations[key]
continue
} }
switch path { switch path {
@ -204,6 +212,8 @@ func (s *imageStore) Update(ctx context.Context, image images.Image, fieldpaths
// make sense to modify the size or digest without touching the // make sense to modify the size or digest without touching the
// mediatype, as well, for example. // mediatype, as well, for example.
updated.Target = image.Target updated.Target = image.Target
case "annotations":
updated.Target.Annotations = image.Target.Annotations
default: default:
return errors.Wrapf(errdefs.ErrInvalidArgument, "cannot update %q field on image %q", path, image.Name) return errors.Wrapf(errdefs.ErrInvalidArgument, "cannot update %q field on image %q", path, image.Name)
} }
@ -298,6 +308,11 @@ func readImage(image *images.Image, bkt *bolt.Bucket) error {
} }
image.Labels = labels image.Labels = labels
image.Target.Annotations, err = boltutil.ReadAnnotations(bkt)
if err != nil {
return err
}
tbkt := bkt.Bucket(bucketKeyTarget) tbkt := bkt.Bucket(bucketKeyTarget)
if tbkt == nil { if tbkt == nil {
return errors.New("unable to read target bucket") return errors.New("unable to read target bucket")
@ -331,6 +346,10 @@ func writeImage(bkt *bolt.Bucket, image *images.Image) error {
return errors.Wrapf(err, "writing labels for image %v", image.Name) return errors.Wrapf(err, "writing labels for image %v", image.Name)
} }
if err := boltutil.WriteAnnotations(bkt, image.Target.Annotations); err != nil {
return errors.Wrapf(err, "writing Annotations for image %v", image.Name)
}
// write the target bucket // write the target bucket
tbkt, err := bkt.CreateBucketIfNotExists(bucketKeyTarget) tbkt, err := bkt.CreateBucketIfNotExists(bucketKeyTarget)
if err != nil { if err != nil {

View File

@ -49,6 +49,9 @@ func TestImagesList(t *testing.T) {
Size: 10, Size: 10,
MediaType: "application/vnd.containerd.test", MediaType: "application/vnd.containerd.test",
Digest: digest.FromString(id), Digest: digest.FromString(id),
Annotations: map[string]string{
"foo": "bar",
},
}, },
} }
@ -168,6 +171,9 @@ func TestImagesCreateUpdateDelete(t *testing.T) {
Target: ocispec.Descriptor{ Target: ocispec.Descriptor{
Size: 10, Size: 10,
MediaType: "application/vnd.oci.blab", MediaType: "application/vnd.oci.blab",
Annotations: map[string]string{
"foo": "bar",
},
}, },
}, },
expected: images.Image{ expected: images.Image{
@ -178,6 +184,9 @@ func TestImagesCreateUpdateDelete(t *testing.T) {
Target: ocispec.Descriptor{ Target: ocispec.Descriptor{
Size: 10, Size: 10,
MediaType: "application/vnd.oci.blab", MediaType: "application/vnd.oci.blab",
Annotations: map[string]string{
"foo": "bar",
},
}, },
}, },
}, },
@ -203,6 +212,9 @@ func TestImagesCreateUpdateDelete(t *testing.T) {
Target: ocispec.Descriptor{ Target: ocispec.Descriptor{
Size: 10, Size: 10,
MediaType: "application/vnd.oci.blab", MediaType: "application/vnd.oci.blab",
Annotations: map[string]string{
"foo": "bar",
},
}, },
}, },
expected: images.Image{ expected: images.Image{
@ -213,6 +225,9 @@ func TestImagesCreateUpdateDelete(t *testing.T) {
Target: ocispec.Descriptor{ Target: ocispec.Descriptor{
Size: 10, Size: 10,
MediaType: "application/vnd.oci.blab", MediaType: "application/vnd.oci.blab",
Annotations: map[string]string{
"foo": "bar",
},
}, },
}, },
}, },
@ -227,6 +242,10 @@ func TestImagesCreateUpdateDelete(t *testing.T) {
Target: ocispec.Descriptor{ Target: ocispec.Descriptor{
Size: 20, // ignored Size: 20, // ignored
MediaType: "application/vnd.oci.blab+ignored", // make sure other stuff is ignored MediaType: "application/vnd.oci.blab+ignored", // make sure other stuff is ignored
Annotations: map[string]string{
"not": "bar",
"new": "boo",
},
}, },
}, },
fieldpaths: []string{"labels"}, fieldpaths: []string{"labels"},
@ -238,6 +257,41 @@ func TestImagesCreateUpdateDelete(t *testing.T) {
Target: ocispec.Descriptor{ Target: ocispec.Descriptor{
Size: 10, Size: 10,
MediaType: "application/vnd.oci.blab", MediaType: "application/vnd.oci.blab",
Annotations: map[string]string{
"foo": "bar",
"baz": "boo",
},
},
},
},
{
name: "ReplaceLabelsAnnotationsFieldPath",
original: imageBase(),
input: images.Image{
Labels: map[string]string{
"for": "bar",
"boo": "boo",
},
Target: ocispec.Descriptor{
Size: 20, // ignored
MediaType: "application/vnd.oci.blab+ignored", // make sure other stuff is ignored
Annotations: map[string]string{
"foo": "boo",
},
},
},
fieldpaths: []string{"annotations", "labels"},
expected: images.Image{
Labels: map[string]string{
"for": "bar",
"boo": "boo",
},
Target: ocispec.Descriptor{
Size: 10,
MediaType: "application/vnd.oci.blab",
Annotations: map[string]string{
"foo": "boo",
},
}, },
}, },
}, },
@ -252,6 +306,9 @@ func TestImagesCreateUpdateDelete(t *testing.T) {
Target: ocispec.Descriptor{ Target: ocispec.Descriptor{
Size: 20, // ignored Size: 20, // ignored
MediaType: "application/vnd.oci.blab+ignored", // make sure other stuff is ignored MediaType: "application/vnd.oci.blab+ignored", // make sure other stuff is ignored
Annotations: map[string]string{
"foo": "bar",
},
}, },
}, },
fieldpaths: []string{"labels.foo"}, fieldpaths: []string{"labels.foo"},
@ -263,6 +320,43 @@ func TestImagesCreateUpdateDelete(t *testing.T) {
Target: ocispec.Descriptor{ Target: ocispec.Descriptor{
Size: 10, Size: 10,
MediaType: "application/vnd.oci.blab", MediaType: "application/vnd.oci.blab",
Annotations: map[string]string{
"foo": "bar",
"baz": "boo",
},
},
},
},
{
name: "ReplaceAnnotation",
original: imageBase(),
input: images.Image{
Labels: map[string]string{
"foo": "baz",
"baz": "bunk",
},
Target: ocispec.Descriptor{
Size: 20, // ignored
MediaType: "application/vnd.oci.blab+ignored", // make sure other stuff is ignored
Annotations: map[string]string{
"foo": "baz",
"baz": "bunk",
},
},
},
fieldpaths: []string{"annotations.foo"},
expected: images.Image{
Labels: map[string]string{
"foo": "bar",
"baz": "boo",
},
Target: ocispec.Descriptor{
Size: 10,
MediaType: "application/vnd.oci.blab",
Annotations: map[string]string{
"foo": "baz",
"baz": "boo",
},
}, },
}, },
}, },
@ -273,6 +367,9 @@ func TestImagesCreateUpdateDelete(t *testing.T) {
Target: ocispec.Descriptor{ Target: ocispec.Descriptor{
Size: 10, Size: 10,
MediaType: "application/vnd.oci.blab+replaced", MediaType: "application/vnd.oci.blab+replaced",
Annotations: map[string]string{
"fox": "dog",
},
}, },
}, },
fieldpaths: []string{"target"}, fieldpaths: []string{"target"},
@ -284,6 +381,9 @@ func TestImagesCreateUpdateDelete(t *testing.T) {
Target: ocispec.Descriptor{ Target: ocispec.Descriptor{
Size: 10, Size: 10,
MediaType: "application/vnd.oci.blab+replaced", MediaType: "application/vnd.oci.blab+replaced",
Annotations: map[string]string{
"fox": "dog",
},
}, },
}, },
}, },
@ -298,6 +398,9 @@ func TestImagesCreateUpdateDelete(t *testing.T) {
Target: ocispec.Descriptor{ Target: ocispec.Descriptor{
Size: 0, Size: 0,
MediaType: "application/vnd.oci.blab", MediaType: "application/vnd.oci.blab",
Annotations: map[string]string{
"foo": "bar",
},
}, },
}, },
cause: errdefs.ErrInvalidArgument, cause: errdefs.ErrInvalidArgument,
@ -311,6 +414,9 @@ func TestImagesCreateUpdateDelete(t *testing.T) {
}, },
Target: ocispec.Descriptor{ Target: ocispec.Descriptor{
MediaType: "application/vnd.oci.blab", MediaType: "application/vnd.oci.blab",
Annotations: map[string]string{
"foo": "bar",
},
}, },
}, },
createerr: errdefs.ErrInvalidArgument, createerr: errdefs.ErrInvalidArgument,
@ -352,6 +458,9 @@ func TestImagesCreateUpdateDelete(t *testing.T) {
Target: ocispec.Descriptor{ Target: ocispec.Descriptor{
Size: 10, Size: 10,
MediaType: "application/vnd.oci.blab", MediaType: "application/vnd.oci.blab",
Annotations: map[string]string{
"foo": "bar",
},
}, },
}, },
input: images.Image{ input: images.Image{
@ -363,6 +472,9 @@ func TestImagesCreateUpdateDelete(t *testing.T) {
Target: ocispec.Descriptor{ Target: ocispec.Descriptor{
Size: 10, Size: 10,
MediaType: "application/vnd.oci.blab", MediaType: "application/vnd.oci.blab",
Annotations: map[string]string{
"foo": "bar",
},
}, },
}, },
cause: errdefs.ErrNotFound, cause: errdefs.ErrNotFound,
@ -440,6 +552,10 @@ func imageBase() images.Image {
Target: ocispec.Descriptor{ Target: ocispec.Descriptor{
Size: 10, Size: 10,
MediaType: "application/vnd.oci.blab", MediaType: "application/vnd.oci.blab",
Annotations: map[string]string{
"foo": "bar",
"baz": "boo",
},
}, },
} }
} }

View File

@ -167,6 +167,7 @@ func toDescriptor(d *types.Descriptor) ocispec.Descriptor {
MediaType: d.MediaType, MediaType: d.MediaType,
Digest: d.Digest, Digest: d.Digest,
Size: d.Size_, Size: d.Size_,
Annotations: d.Annotations,
} }
} }
@ -175,5 +176,6 @@ func fromDescriptor(d ocispec.Descriptor) *types.Descriptor {
MediaType: d.MediaType, MediaType: d.MediaType,
Digest: d.Digest, Digest: d.Digest,
Size_: d.Size, Size_: d.Size,
Annotations: d.Annotations,
} }
} }

View File

@ -58,6 +58,7 @@ func descFromProto(desc *types.Descriptor) ocispec.Descriptor {
MediaType: desc.MediaType, MediaType: desc.MediaType,
Size: desc.Size_, Size: desc.Size_,
Digest: desc.Digest, Digest: desc.Digest,
Annotations: desc.Annotations,
} }
} }
@ -66,5 +67,6 @@ func descToProto(desc *ocispec.Descriptor) types.Descriptor {
MediaType: desc.MediaType, MediaType: desc.MediaType,
Size_: desc.Size, Size_: desc.Size,
Digest: desc.Digest, Digest: desc.Digest,
Annotations: desc.Annotations,
} }
} }

View File

@ -147,6 +147,7 @@ func (l *local) Create(ctx context.Context, r *api.CreateTaskRequest, _ ...grpc.
MediaType: r.Checkpoint.MediaType, MediaType: r.Checkpoint.MediaType,
Digest: r.Checkpoint.Digest, Digest: r.Checkpoint.Digest,
Size: r.Checkpoint.Size_, Size: r.Checkpoint.Size_,
Annotations: r.Checkpoint.Annotations,
}) })
if err != nil { if err != nil {
return nil, err return nil, err
@ -628,6 +629,7 @@ func (l *local) writeContent(ctx context.Context, mediaType, ref string, r io.Re
MediaType: mediaType, MediaType: mediaType,
Digest: writer.Digest(), Digest: writer.Digest(),
Size_: size, Size_: size,
Annotations: make(map[string]string),
}, nil }, nil
} }

View File

@ -585,6 +585,7 @@ func (t *task) checkpointTask(ctx context.Context, index *v1.Index, request *tas
OS: goruntime.GOOS, OS: goruntime.GOOS,
Architecture: goruntime.GOARCH, Architecture: goruntime.GOARCH,
}, },
Annotations: d.Annotations,
}) })
} }
return nil return nil

View File

@ -62,6 +62,7 @@ func WithTaskCheckpoint(im Image) NewTaskOpts {
MediaType: m.MediaType, MediaType: m.MediaType,
Size_: m.Size, Size_: m.Size,
Digest: m.Digest, Digest: m.Digest,
Annotations: m.Annotations,
} }
return nil return nil
} }