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  }