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

     1  package context
     2  
     3  import (
     4  	"bytes"
     5  	"fmt"
     6  	"text/tabwriter"
     7  
     8  	"github.com/docker/cli/cli"
     9  	"github.com/docker/cli/cli/command"
    10  	"github.com/docker/cli/cli/context/docker"
    11  	"github.com/docker/cli/cli/context/kubernetes"
    12  	"github.com/docker/cli/cli/context/store"
    13  	"github.com/pkg/errors"
    14  	"github.com/spf13/cobra"
    15  )
    16  
    17  // UpdateOptions are the options used to update a context
    18  type UpdateOptions struct {
    19  	Name                     string
    20  	Description              string
    21  	DefaultStackOrchestrator string
    22  	Docker                   map[string]string
    23  	Kubernetes               map[string]string
    24  }
    25  
    26  func longUpdateDescription() string {
    27  	buf := bytes.NewBuffer(nil)
    28  	buf.WriteString("Update a context\n\nDocker endpoint config:\n\n")
    29  	tw := tabwriter.NewWriter(buf, 20, 1, 3, ' ', 0)
    30  	fmt.Fprintln(tw, "NAME\tDESCRIPTION")
    31  	for _, d := range dockerConfigKeysDescriptions {
    32  		fmt.Fprintf(tw, "%s\t%s\n", d.name, d.description)
    33  	}
    34  	tw.Flush()
    35  	buf.WriteString("\nKubernetes endpoint config:\n\n")
    36  	tw = tabwriter.NewWriter(buf, 20, 1, 3, ' ', 0)
    37  	fmt.Fprintln(tw, "NAME\tDESCRIPTION")
    38  	for _, d := range kubernetesConfigKeysDescriptions {
    39  		fmt.Fprintf(tw, "%s\t%s\n", d.name, d.description)
    40  	}
    41  	tw.Flush()
    42  	buf.WriteString("\nExample:\n\n$ docker context update my-context --description \"some description\" --docker \"host=tcp://myserver:2376,ca=~/ca-file,cert=~/cert-file,key=~/key-file\"\n")
    43  	return buf.String()
    44  }
    45  
    46  func newUpdateCommand(dockerCli command.Cli) *cobra.Command {
    47  	opts := &UpdateOptions{}
    48  	cmd := &cobra.Command{
    49  		Use:   "update [OPTIONS] CONTEXT",
    50  		Short: "Update a context",
    51  		Args:  cli.ExactArgs(1),
    52  		RunE: func(cmd *cobra.Command, args []string) error {
    53  			opts.Name = args[0]
    54  			return RunUpdate(dockerCli, opts)
    55  		},
    56  		Long: longUpdateDescription(),
    57  	}
    58  	flags := cmd.Flags()
    59  	flags.StringVar(&opts.Description, "description", "", "Description of the context")
    60  	flags.StringVar(
    61  		&opts.DefaultStackOrchestrator,
    62  		"default-stack-orchestrator", "",
    63  		"Default orchestrator for stack operations to use with this context (swarm|kubernetes|all)")
    64  	flags.StringToStringVar(&opts.Docker, "docker", nil, "set the docker endpoint")
    65  	flags.StringToStringVar(&opts.Kubernetes, "kubernetes", nil, "set the kubernetes endpoint")
    66  	return cmd
    67  }
    68  
    69  // RunUpdate updates a Docker context
    70  func RunUpdate(cli command.Cli, o *UpdateOptions) error {
    71  	if err := validateContextName(o.Name); err != nil {
    72  		return err
    73  	}
    74  	s := cli.ContextStore()
    75  	c, err := s.GetMetadata(o.Name)
    76  	if err != nil {
    77  		return err
    78  	}
    79  	dockerContext, err := command.GetDockerContext(c)
    80  	if err != nil {
    81  		return err
    82  	}
    83  	if o.DefaultStackOrchestrator != "" {
    84  		stackOrchestrator, err := command.NormalizeOrchestrator(o.DefaultStackOrchestrator)
    85  		if err != nil {
    86  			return errors.Wrap(err, "unable to parse default-stack-orchestrator")
    87  		}
    88  		dockerContext.StackOrchestrator = stackOrchestrator
    89  	}
    90  	if o.Description != "" {
    91  		dockerContext.Description = o.Description
    92  	}
    93  
    94  	c.Metadata = dockerContext
    95  
    96  	tlsDataToReset := make(map[string]*store.EndpointTLSData)
    97  
    98  	if o.Docker != nil {
    99  		dockerEP, dockerTLS, err := getDockerEndpointMetadataAndTLS(cli, o.Docker)
   100  		if err != nil {
   101  			return errors.Wrap(err, "unable to create docker endpoint config")
   102  		}
   103  		c.Endpoints[docker.DockerEndpoint] = dockerEP
   104  		tlsDataToReset[docker.DockerEndpoint] = dockerTLS
   105  	}
   106  	if o.Kubernetes != nil {
   107  		kubernetesEP, kubernetesTLS, err := getKubernetesEndpointMetadataAndTLS(cli, o.Kubernetes)
   108  		if err != nil {
   109  			return errors.Wrap(err, "unable to create kubernetes endpoint config")
   110  		}
   111  		if kubernetesEP == nil {
   112  			delete(c.Endpoints, kubernetes.KubernetesEndpoint)
   113  		} else {
   114  			c.Endpoints[kubernetes.KubernetesEndpoint] = kubernetesEP
   115  			tlsDataToReset[kubernetes.KubernetesEndpoint] = kubernetesTLS
   116  		}
   117  	}
   118  	if err := validateEndpointsAndOrchestrator(c); err != nil {
   119  		return err
   120  	}
   121  	if err := s.CreateOrUpdate(c); err != nil {
   122  		return err
   123  	}
   124  	for ep, tlsData := range tlsDataToReset {
   125  		if err := s.ResetEndpointTLSMaterial(o.Name, ep, tlsData); err != nil {
   126  			return err
   127  		}
   128  	}
   129  
   130  	fmt.Fprintln(cli.Out(), o.Name)
   131  	fmt.Fprintf(cli.Err(), "Successfully updated context %q\n", o.Name)
   132  	return nil
   133  }
   134  
   135  func validateEndpointsAndOrchestrator(c store.Metadata) error {
   136  	dockerContext, err := command.GetDockerContext(c)
   137  	if err != nil {
   138  		return err
   139  	}
   140  	if _, ok := c.Endpoints[kubernetes.KubernetesEndpoint]; !ok && dockerContext.StackOrchestrator.HasKubernetes() {
   141  		return errors.Errorf("cannot specify orchestrator %q without configuring a Kubernetes endpoint", dockerContext.StackOrchestrator)
   142  	}
   143  	return nil
   144  }