github.com/portworx/docker@v1.12.1/api/client/node/update.go (about)

     1  package node
     2  
     3  import (
     4  	"fmt"
     5  
     6  	"github.com/docker/docker/api/client"
     7  	"github.com/docker/docker/cli"
     8  	"github.com/docker/docker/opts"
     9  	runconfigopts "github.com/docker/docker/runconfig/opts"
    10  	"github.com/docker/engine-api/types/swarm"
    11  	"github.com/spf13/cobra"
    12  	"github.com/spf13/pflag"
    13  	"golang.org/x/net/context"
    14  )
    15  
    16  func newUpdateCommand(dockerCli *client.DockerCli) *cobra.Command {
    17  	nodeOpts := newNodeOptions()
    18  
    19  	cmd := &cobra.Command{
    20  		Use:   "update [OPTIONS] NODE",
    21  		Short: "Update a node",
    22  		Args:  cli.ExactArgs(1),
    23  		RunE: func(cmd *cobra.Command, args []string) error {
    24  			return runUpdate(dockerCli, cmd.Flags(), args[0])
    25  		},
    26  	}
    27  
    28  	flags := cmd.Flags()
    29  	flags.StringVar(&nodeOpts.role, flagRole, "", "Role of the node (worker/manager)")
    30  	flags.StringVar(&nodeOpts.availability, flagAvailability, "", "Availability of the node (active/pause/drain)")
    31  	flags.Var(&nodeOpts.annotations.labels, flagLabelAdd, "Add or update a node label (key=value)")
    32  	labelKeys := opts.NewListOpts(nil)
    33  	flags.Var(&labelKeys, flagLabelRemove, "Remove a node label if exists")
    34  	return cmd
    35  }
    36  
    37  func runUpdate(dockerCli *client.DockerCli, flags *pflag.FlagSet, nodeID string) error {
    38  	success := func(_ string) {
    39  		fmt.Fprintln(dockerCli.Out(), nodeID)
    40  	}
    41  	return updateNodes(dockerCli, []string{nodeID}, mergeNodeUpdate(flags), success)
    42  }
    43  
    44  func updateNodes(dockerCli *client.DockerCli, nodes []string, mergeNode func(node *swarm.Node) error, success func(nodeID string)) error {
    45  	client := dockerCli.Client()
    46  	ctx := context.Background()
    47  
    48  	for _, nodeID := range nodes {
    49  		node, _, err := client.NodeInspectWithRaw(ctx, nodeID)
    50  		if err != nil {
    51  			return err
    52  		}
    53  
    54  		err = mergeNode(&node)
    55  		if err != nil {
    56  			return err
    57  		}
    58  		err = client.NodeUpdate(ctx, node.ID, node.Version, node.Spec)
    59  		if err != nil {
    60  			return err
    61  		}
    62  		success(nodeID)
    63  	}
    64  	return nil
    65  }
    66  
    67  func mergeNodeUpdate(flags *pflag.FlagSet) func(*swarm.Node) error {
    68  	return func(node *swarm.Node) error {
    69  		spec := &node.Spec
    70  
    71  		if flags.Changed(flagRole) {
    72  			str, err := flags.GetString(flagRole)
    73  			if err != nil {
    74  				return err
    75  			}
    76  			spec.Role = swarm.NodeRole(str)
    77  		}
    78  		if flags.Changed(flagAvailability) {
    79  			str, err := flags.GetString(flagAvailability)
    80  			if err != nil {
    81  				return err
    82  			}
    83  			spec.Availability = swarm.NodeAvailability(str)
    84  		}
    85  		if spec.Annotations.Labels == nil {
    86  			spec.Annotations.Labels = make(map[string]string)
    87  		}
    88  		if flags.Changed(flagLabelAdd) {
    89  			labels := flags.Lookup(flagLabelAdd).Value.(*opts.ListOpts).GetAll()
    90  			for k, v := range runconfigopts.ConvertKVStringsToMap(labels) {
    91  				spec.Annotations.Labels[k] = v
    92  			}
    93  		}
    94  		if flags.Changed(flagLabelRemove) {
    95  			keys := flags.Lookup(flagLabelRemove).Value.(*opts.ListOpts).GetAll()
    96  			for _, k := range keys {
    97  				// if a key doesn't exist, fail the command explicitly
    98  				if _, exists := spec.Annotations.Labels[k]; !exists {
    99  					return fmt.Errorf("key %s doesn't exist in node's labels", k)
   100  				}
   101  				delete(spec.Annotations.Labels, k)
   102  			}
   103  		}
   104  		return nil
   105  	}
   106  }
   107  
   108  const (
   109  	flagRole         = "role"
   110  	flagAvailability = "availability"
   111  	flagLabelAdd     = "label-add"
   112  	flagLabelRemove  = "label-rm"
   113  )