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 )