update.go 3.1 KB

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