...
1 package ocischema
2
3 import (
4 "context"
5 "errors"
6
7 "github.com/docker/distribution"
8 "github.com/docker/distribution/manifest"
9 "github.com/opencontainers/go-digest"
10 v1 "github.com/opencontainers/image-spec/specs-go/v1"
11 )
12
13
14 type Builder struct {
15
16 bs distribution.BlobService
17
18
19 configJSON []byte
20
21
22
23 layers []distribution.Descriptor
24
25
26 annotations map[string]string
27
28
29 mediaType string
30 }
31
32
33
34
35 func NewManifestBuilder(bs distribution.BlobService, configJSON []byte, annotations map[string]string) distribution.ManifestBuilder {
36 mb := &Builder{
37 bs: bs,
38 configJSON: make([]byte, len(configJSON)),
39 annotations: annotations,
40 mediaType: v1.MediaTypeImageManifest,
41 }
42 copy(mb.configJSON, configJSON)
43
44 return mb
45 }
46
47
48
49 func (mb *Builder) SetMediaType(mediaType string) error {
50 if mediaType != "" && mediaType != v1.MediaTypeImageManifest {
51 return errors.New("invalid media type for OCI image manifest")
52 }
53
54 mb.mediaType = mediaType
55 return nil
56 }
57
58
59 func (mb *Builder) Build(ctx context.Context) (distribution.Manifest, error) {
60 m := Manifest{
61 Versioned: manifest.Versioned{
62 SchemaVersion: 2,
63 MediaType: mb.mediaType,
64 },
65 Layers: make([]distribution.Descriptor, len(mb.layers)),
66 Annotations: mb.annotations,
67 }
68 copy(m.Layers, mb.layers)
69
70 configDigest := digest.FromBytes(mb.configJSON)
71
72 var err error
73 m.Config, err = mb.bs.Stat(ctx, configDigest)
74 switch err {
75 case nil:
76
77
78 m.Config.MediaType = v1.MediaTypeImageConfig
79 return FromStruct(m)
80 case distribution.ErrBlobUnknown:
81
82 default:
83 return nil, err
84 }
85
86
87 m.Config, err = mb.bs.Put(ctx, v1.MediaTypeImageConfig, mb.configJSON)
88
89
90 m.Config.MediaType = v1.MediaTypeImageConfig
91 if err != nil {
92 return nil, err
93 }
94
95 return FromStruct(m)
96 }
97
98
99 func (mb *Builder) AppendReference(d distribution.Describable) error {
100 mb.layers = append(mb.layers, d.Descriptor())
101 return nil
102 }
103
104
105 func (mb *Builder) References() []distribution.Descriptor {
106 return mb.layers
107 }
108
View as plain text