github.com/docker/cnab-to-oci@v0.3.0-beta4/cmd/cnab-to-oci/push.go (about)

     1  package main
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"errors"
     7  	"fmt"
     8  	"io/ioutil"
     9  	"os"
    10  
    11  	"github.com/cnabio/cnab-go/bundle"
    12  	"github.com/docker/cnab-to-oci/remotes"
    13  	"github.com/docker/distribution/reference"
    14  	"github.com/docker/docker/client"
    15  	"github.com/spf13/cobra"
    16  )
    17  
    18  type pushOptions struct {
    19  	input               string
    20  	targetRef           string
    21  	insecureRegistries  []string
    22  	allowFallbacks      bool
    23  	invocationPlatforms []string
    24  	componentPlatforms  []string
    25  	autoUpdateBundle    bool
    26  	pushImages          bool
    27  }
    28  
    29  func pushCmd() *cobra.Command {
    30  	var opts pushOptions
    31  	cmd := &cobra.Command{
    32  		Use:   "push <bundle file> [options]",
    33  		Short: "Fixes and pushes the bundle to an registry",
    34  		Args:  cobra.ExactArgs(1),
    35  		RunE: func(cmd *cobra.Command, args []string) error {
    36  			opts.input = args[0]
    37  			if opts.targetRef == "" {
    38  				return errors.New("--target flag must be set with a namespace ")
    39  			}
    40  			return runPush(opts)
    41  		},
    42  	}
    43  
    44  	cmd.Flags().StringVarP(&opts.targetRef, "target", "t", "", "reference where the bundle will be pushed")
    45  	cmd.Flags().StringSliceVar(&opts.insecureRegistries, "insecure-registries", nil, "Use plain HTTP for those registries")
    46  	cmd.Flags().BoolVar(&opts.allowFallbacks, "allow-fallbacks", true, "Enable automatic compatibility fallbacks for registries without support for custom media type, or OCI manifests")
    47  	cmd.Flags().StringSliceVar(&opts.invocationPlatforms, "invocation-platforms", nil, "Platforms to push (for multi-arch invocation images)")
    48  	cmd.Flags().StringSliceVar(&opts.componentPlatforms, "component-platforms", nil, "Platforms to push (for multi-arch component images)")
    49  	cmd.Flags().BoolVar(&opts.autoUpdateBundle, "auto-update-bundle", false, "Updates the bundle image properties with the one resolved on the registry")
    50  	cmd.Flags().BoolVar(&opts.pushImages, "push-images", true, "Allow to push missing images in the registry that are available in the local docker daemon image store")
    51  
    52  	return cmd
    53  }
    54  
    55  func runPush(opts pushOptions) error {
    56  	var b bundle.Bundle
    57  	bundleJSON, err := ioutil.ReadFile(opts.input)
    58  	if err != nil {
    59  		return err
    60  	}
    61  	if err := json.Unmarshal(bundleJSON, &b); err != nil {
    62  		return err
    63  	}
    64  	resolver := createResolver(opts.insecureRegistries)
    65  	ref, err := reference.ParseNormalizedNamed(opts.targetRef)
    66  	if err != nil {
    67  		return err
    68  	}
    69  
    70  	fixupOptions := []remotes.FixupOption{
    71  		remotes.WithEventCallback(displayEvent),
    72  		remotes.WithInvocationImagePlatforms(opts.invocationPlatforms),
    73  		remotes.WithComponentImagePlatforms(opts.componentPlatforms),
    74  	}
    75  	if opts.autoUpdateBundle {
    76  		fixupOptions = append(fixupOptions, remotes.WithAutoBundleUpdate())
    77  	}
    78  	if opts.pushImages {
    79  		cli, err := client.NewClientWithOpts(client.FromEnv)
    80  		if err != nil {
    81  			return err
    82  		}
    83  		fixupOptions = append(fixupOptions, remotes.WithPushImages(cli, os.Stdout))
    84  	}
    85  	relocationMap, err := remotes.FixupBundle(context.Background(), &b, ref, resolver, fixupOptions...)
    86  	if err != nil {
    87  		return err
    88  	}
    89  	d, err := remotes.Push(context.Background(), &b, relocationMap, ref, resolver, opts.allowFallbacks)
    90  	if err != nil {
    91  		return err
    92  	}
    93  	fmt.Printf("Pushed successfully, with digest %q\n", d.Digest)
    94  	return nil
    95  }