github.com/ali-iotechsys/cli@v20.10.0+incompatible/cli/command/image/push.go (about)

     1  package image
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"io/ioutil"
     7  
     8  	"github.com/docker/cli/cli"
     9  	"github.com/docker/cli/cli/command"
    10  	"github.com/docker/cli/cli/streams"
    11  	"github.com/docker/distribution/reference"
    12  	"github.com/docker/docker/api/types"
    13  	"github.com/docker/docker/pkg/jsonmessage"
    14  	"github.com/docker/docker/registry"
    15  	"github.com/pkg/errors"
    16  	"github.com/spf13/cobra"
    17  )
    18  
    19  type pushOptions struct {
    20  	all       bool
    21  	remote    string
    22  	untrusted bool
    23  	quiet     bool
    24  }
    25  
    26  // NewPushCommand creates a new `docker push` command
    27  func NewPushCommand(dockerCli command.Cli) *cobra.Command {
    28  	var opts pushOptions
    29  
    30  	cmd := &cobra.Command{
    31  		Use:   "push [OPTIONS] NAME[:TAG]",
    32  		Short: "Push an image or a repository to a registry",
    33  		Args:  cli.ExactArgs(1),
    34  		RunE: func(cmd *cobra.Command, args []string) error {
    35  			opts.remote = args[0]
    36  			return RunPush(dockerCli, opts)
    37  		},
    38  	}
    39  
    40  	flags := cmd.Flags()
    41  	flags.BoolVarP(&opts.all, "all-tags", "a", false, "Push all tagged images in the repository")
    42  	flags.BoolVarP(&opts.quiet, "quiet", "q", false, "Suppress verbose output")
    43  	command.AddTrustSigningFlags(flags, &opts.untrusted, dockerCli.ContentTrustEnabled())
    44  
    45  	return cmd
    46  }
    47  
    48  // RunPush performs a push against the engine based on the specified options
    49  func RunPush(dockerCli command.Cli, opts pushOptions) error {
    50  	ref, err := reference.ParseNormalizedNamed(opts.remote)
    51  	switch {
    52  	case err != nil:
    53  		return err
    54  	case opts.all && !reference.IsNameOnly(ref):
    55  		return errors.New("tag can't be used with --all-tags/-a")
    56  	case !opts.all && reference.IsNameOnly(ref):
    57  		ref = reference.TagNameOnly(ref)
    58  		if tagged, ok := ref.(reference.Tagged); ok && !opts.quiet {
    59  			_, _ = fmt.Fprintf(dockerCli.Out(), "Using default tag: %s\n", tagged.Tag())
    60  		}
    61  	}
    62  
    63  	// Resolve the Repository name from fqn to RepositoryInfo
    64  	repoInfo, err := registry.ParseRepositoryInfo(ref)
    65  	if err != nil {
    66  		return err
    67  	}
    68  
    69  	ctx := context.Background()
    70  
    71  	// Resolve the Auth config relevant for this server
    72  	authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
    73  	encodedAuth, err := command.EncodeAuthToBase64(authConfig)
    74  	if err != nil {
    75  		return err
    76  	}
    77  	requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "push")
    78  	options := types.ImagePushOptions{
    79  		All:           opts.all,
    80  		RegistryAuth:  encodedAuth,
    81  		PrivilegeFunc: requestPrivilege,
    82  	}
    83  
    84  	responseBody, err := dockerCli.Client().ImagePush(ctx, reference.FamiliarString(ref), options)
    85  	if err != nil {
    86  		return err
    87  	}
    88  
    89  	defer responseBody.Close()
    90  	if !opts.untrusted {
    91  		// TODO PushTrustedReference currently doesn't respect `--quiet`
    92  		return PushTrustedReference(dockerCli, repoInfo, ref, authConfig, responseBody)
    93  	}
    94  
    95  	if opts.quiet {
    96  		err = jsonmessage.DisplayJSONMessagesToStream(responseBody, streams.NewOut(ioutil.Discard), nil)
    97  		if err == nil {
    98  			fmt.Fprintln(dockerCli.Out(), ref.String())
    99  		}
   100  		return err
   101  	}
   102  	return jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil)
   103  }