1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124
|
package containerimage
import (
"maps"
ocispecs "github.com/opencontainers/image-spec/specs-go/v1"
"github.com/pkg/errors"
"github.com/containerd/platforms"
"github.com/moby/buildkit/exporter/containerimage/exptypes"
)
type Annotations struct {
Index map[string]string
IndexDescriptor map[string]string
Manifest map[string]string
ManifestDescriptor map[string]string
}
// AnnotationsGroup is a map of annotations keyed by the reference key
type AnnotationsGroup map[string]*Annotations
func ParseAnnotations(data map[string][]byte) (AnnotationsGroup, map[string][]byte, error) {
ag := make(AnnotationsGroup)
rest := make(map[string][]byte)
for k, v := range data {
a, ok, err := exptypes.ParseAnnotationKey(k)
if !ok {
rest[k] = v
continue
}
if err != nil {
return nil, nil, err
}
p := a.PlatformString()
if ag[p] == nil {
ag[p] = &Annotations{
IndexDescriptor: make(map[string]string),
Index: make(map[string]string),
Manifest: make(map[string]string),
ManifestDescriptor: make(map[string]string),
}
}
switch a.Type {
case exptypes.AnnotationIndex:
ag[p].Index[a.Key] = string(v)
case exptypes.AnnotationIndexDescriptor:
ag[p].IndexDescriptor[a.Key] = string(v)
case exptypes.AnnotationManifest:
ag[p].Manifest[a.Key] = string(v)
case exptypes.AnnotationManifestDescriptor:
ag[p].ManifestDescriptor[a.Key] = string(v)
default:
return nil, nil, errors.Errorf("unrecognized annotation type %s", a.Type)
}
}
return ag, rest, nil
}
func (ag AnnotationsGroup) Platform(p *ocispecs.Platform) *Annotations {
res := &Annotations{
IndexDescriptor: make(map[string]string),
Index: make(map[string]string),
Manifest: make(map[string]string),
ManifestDescriptor: make(map[string]string),
}
ps := []string{""}
if p != nil {
ps = append(ps, platforms.Format(*p))
}
for _, a := range ag {
maps.Copy(res.Index, a.Index)
maps.Copy(res.IndexDescriptor, a.IndexDescriptor)
}
for _, pk := range ps {
if _, ok := ag[pk]; !ok {
continue
}
maps.Copy(res.Manifest, ag[pk].Manifest)
maps.Copy(res.ManifestDescriptor, ag[pk].ManifestDescriptor)
}
return res
}
func (ag AnnotationsGroup) Merge(other AnnotationsGroup) AnnotationsGroup {
if other == nil {
return ag
}
if ag == nil {
ag = make(AnnotationsGroup)
}
for k, v := range other {
ag[k] = ag[k].merge(v)
}
return ag
}
func (a *Annotations) merge(other *Annotations) *Annotations {
if other == nil {
return a
}
if a == nil {
a = &Annotations{
IndexDescriptor: make(map[string]string),
Index: make(map[string]string),
Manifest: make(map[string]string),
ManifestDescriptor: make(map[string]string),
}
}
maps.Copy(a.Index, other.Index)
maps.Copy(a.IndexDescriptor, other.IndexDescriptor)
maps.Copy(a.Manifest, other.Manifest)
maps.Copy(a.ManifestDescriptor, other.ManifestDescriptor)
return a
}
|