github.com/werf/oras@v0.4.0/pkg/oras/push.go (about) 1 package oras 2 3 import ( 4 "context" 5 "encoding/json" 6 7 "github.com/containerd/containerd/content" 8 "github.com/containerd/containerd/remotes" 9 digest "github.com/opencontainers/go-digest" 10 specs "github.com/opencontainers/image-spec/specs-go" 11 ocispec "github.com/opencontainers/image-spec/specs-go/v1" 12 ) 13 14 // Push pushes files to the remote 15 func Push(ctx context.Context, resolver remotes.Resolver, ref string, provider content.Provider, descriptors []ocispec.Descriptor, opts ...PushOpt) (ocispec.Descriptor, error) { 16 if resolver == nil { 17 return ocispec.Descriptor{}, ErrResolverUndefined 18 } 19 if len(descriptors) == 0 { 20 return ocispec.Descriptor{}, ErrEmptyDescriptors 21 } 22 opt := pushOptsDefaults() 23 for _, o := range opts { 24 if err := o(opt); err != nil { 25 return ocispec.Descriptor{}, err 26 } 27 } 28 if opt.validateName != nil { 29 for _, desc := range descriptors { 30 if err := opt.validateName(desc); err != nil { 31 return ocispec.Descriptor{}, err 32 } 33 } 34 } 35 36 pusher, err := resolver.Pusher(ctx, ref) 37 if err != nil { 38 return ocispec.Descriptor{}, err 39 } 40 41 desc, provider, err := pack(provider, descriptors, opt) 42 if err != nil { 43 return ocispec.Descriptor{}, err 44 } 45 46 if err := remotes.PushContent(ctx, pusher, desc, provider, nil, opt.baseHandlers...); err != nil { 47 return ocispec.Descriptor{}, err 48 } 49 return desc, nil 50 } 51 52 func pack(provider content.Provider, descriptors []ocispec.Descriptor, opts *pushOpts) (ocispec.Descriptor, content.Provider, error) { 53 store := newHybridStoreFromProvider(provider) 54 55 // Config 56 var config ocispec.Descriptor 57 if opts.config == nil { 58 configBytes := []byte("{}") 59 config = ocispec.Descriptor{ 60 MediaType: ocispec.MediaTypeImageConfig, 61 Digest: digest.FromBytes(configBytes), 62 Size: int64(len(configBytes)), 63 } 64 store.Set(config, configBytes) 65 } else { 66 config = *opts.config 67 } 68 config.Annotations = opts.configAnnotations 69 70 // Manifest 71 manifest := ocispec.Manifest{ 72 Versioned: specs.Versioned{ 73 SchemaVersion: 2, // historical value. does not pertain to OCI or docker version 74 }, 75 Config: config, 76 Layers: descriptors, 77 Annotations: opts.manifestAnnotations, 78 } 79 manifestBytes, err := json.Marshal(manifest) 80 if err != nil { 81 return ocispec.Descriptor{}, nil, err 82 } 83 manifestDescriptor := ocispec.Descriptor{ 84 MediaType: ocispec.MediaTypeImageManifest, 85 Digest: digest.FromBytes(manifestBytes), 86 Size: int64(len(manifestBytes)), 87 } 88 store.Set(manifestDescriptor, manifestBytes) 89 90 return manifestDescriptor, store, nil 91 }