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  }