github.com/hernad/nomad@v1.6.112/command/node_meta_apply.go (about) 1 // Copyright (c) HashiCorp, Inc. 2 // SPDX-License-Identifier: MPL-2.0 3 4 package command 5 6 import ( 7 "fmt" 8 "strings" 9 10 "github.com/hernad/nomad/api" 11 "github.com/hernad/nomad/helper/pointer" 12 "github.com/posener/complete" 13 ) 14 15 type NodeMetaApplyCommand struct { 16 Meta 17 } 18 19 func (c *NodeMetaApplyCommand) Help() string { 20 helpText := ` 21 Usage: nomad node meta apply [-node-id ...] [-unset ...] key1=value1 ... kN=vN 22 23 Modify a node's metadata. This command only applies to client agents, and can 24 be used to update the scheduling metadata the node registers. 25 26 Changes are batched and may take up to 10 seconds to propagate to the 27 servers and affect scheduling. 28 29 General Options: 30 31 ` + generalOptionsUsage(usageOptsDefault|usageOptsNoNamespace) + ` 32 33 Node Meta Apply Options: 34 35 -node-id 36 Updates metadata on the specified node. If not specified the node receiving 37 the request will be used by default. 38 39 -unset key1,...,keyN 40 Unset the comma separated list of keys. 41 42 Example: 43 $ nomad node meta apply -unset testing,tempvar ready=1 role=preinit-db 44 ` 45 return strings.TrimSpace(helpText) 46 } 47 48 func (c *NodeMetaApplyCommand) Synopsis() string { 49 return "Modify node metadata" 50 } 51 52 func (c *NodeMetaApplyCommand) Name() string { return "node meta apply" } 53 54 func (c *NodeMetaApplyCommand) Run(args []string) int { 55 var unset, nodeID string 56 57 flags := c.Meta.FlagSet(c.Name(), FlagSetClient) 58 flags.Usage = func() { c.Ui.Output(c.Help()) } 59 flags.StringVar(&unset, "unset", "", "") 60 flags.StringVar(&nodeID, "node-id", "", "") 61 62 if err := flags.Parse(args); err != nil { 63 return 1 64 } 65 args = flags.Args() 66 67 if unset == "" && len(args) == 0 { 68 c.Ui.Error("Must specify -unset or at least 1 key=value pair") 69 return 1 70 } 71 72 // Get the HTTP client 73 client, err := c.Meta.Client() 74 if err != nil { 75 c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) 76 return 1 77 } 78 79 // Lookup nodeID 80 if nodeID != "" { 81 nodeID, err = lookupNodeID(client.Nodes(), nodeID) 82 if err != nil { 83 c.Ui.Error(err.Error()) 84 return 1 85 } 86 } 87 88 // Parse parameters 89 meta := parseMapFromArgs(args) 90 applyNodeMetaUnset(meta, unset) 91 92 req := api.NodeMetaApplyRequest{ 93 NodeID: nodeID, 94 Meta: meta, 95 } 96 97 if _, err := client.Nodes().Meta().Apply(&req, nil); err != nil { 98 c.Ui.Error(fmt.Sprintf("Error applying dynamic node metadata: %s", err)) 99 return 1 100 } 101 102 return 0 103 } 104 105 func (c *NodeMetaApplyCommand) AutocompleteFlags() complete.Flags { 106 return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient), 107 complete.Flags{ 108 "-node-id": complete.PredictNothing, 109 "-unset": complete.PredictNothing, 110 }) 111 } 112 113 func (c *NodeMetaApplyCommand) AutocompleteArgs() complete.Predictor { 114 return complete.PredictAnything 115 } 116 117 // parseMapFromArgs parses a slice of key=value pairs into a map. 118 func parseMapFromArgs(args []string) map[string]*string { 119 m := make(map[string]*string, len(args)) 120 for _, pair := range args { 121 kv := strings.SplitN(pair, "=", 2) 122 switch len(kv) { 123 case 0: 124 // Nothing to do 125 case 1: 126 m[kv[0]] = pointer.Of("") 127 default: 128 m[kv[0]] = &kv[1] 129 } 130 } 131 return m 132 } 133 134 // applyNodeMetaUnset parses a comma separated list of keys to set as nil in 135 // node metadata. The empty string key is ignored as its invalid to set. 136 func applyNodeMetaUnset(m map[string]*string, unset string) { 137 for _, k := range strings.Split(unset, ",") { 138 if k != "" { 139 m[k] = nil 140 } 141 } 142 }