From 7f91cd12f44023893e28b82996929ee97efec934 Mon Sep 17 00:00:00 2001 From: Kyle Havlovitz Date: Wed, 11 Jan 2017 16:07:11 -0500 Subject: [PATCH] Add -node-meta to agent command line options --- command/agent/agent.go | 10 ++++++++++ command/agent/command.go | 12 ++++++++++++ command/agent/command_test.go | 26 ++++++++++++++++++++++++++ command/agent/http.go | 8 ++------ consul/structs/structs.go | 6 ------ 5 files changed, 50 insertions(+), 12 deletions(-) diff --git a/command/agent/agent.go b/command/agent/agent.go index 582c625706..850733a772 100644 --- a/command/agent/agent.go +++ b/command/agent/agent.go @@ -1710,6 +1710,16 @@ func (a *Agent) loadMetadata(conf *Config) error { return nil } +// parseMetaPair parses a key/value pair of the form key:value +func parseMetaPair(raw string) (string, string) { + pair := strings.SplitN(raw, ":", 2) + if len(pair) == 2 { + return pair[0], pair[1] + } else { + return pair[0], "" + } +} + // validateMeta validates a set of key/value pairs from the agent config func validateMetadata(meta map[string]string) error { if len(meta) > metaMaxKeyPairs { diff --git a/command/agent/command.go b/command/agent/command.go index 03f3b25e1d..10e62a77c0 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -73,12 +73,14 @@ func (c *Command) readConfig() *Config { var dnsRecursors []string var dev bool var dcDeprecated string + var nodeMeta []string cmdFlags := flag.NewFlagSet("agent", flag.ContinueOnError) cmdFlags.Usage = func() { c.Ui.Output(c.Help()) } cmdFlags.Var((*AppendSliceValue)(&configFiles), "config-file", "json file to read config from") cmdFlags.Var((*AppendSliceValue)(&configFiles), "config-dir", "directory of json files to read") cmdFlags.Var((*AppendSliceValue)(&dnsRecursors), "recursor", "address of an upstream DNS server") + cmdFlags.Var((*AppendSliceValue)(&nodeMeta), "node-meta", "arbitrary metadata key/value pair") cmdFlags.BoolVar(&dev, "dev", false, "development server mode") cmdFlags.StringVar(&cmdConfig.LogLevel, "log-level", "", "log level") @@ -161,6 +163,14 @@ func (c *Command) readConfig() *Config { cmdConfig.RetryIntervalWan = dur } + if len(nodeMeta) > 0 { + cmdConfig.Meta = make(map[string]string) + for _, entry := range nodeMeta { + key, value := parseMetaPair(entry) + cmdConfig.Meta[key] = value + } + } + var config *Config if dev { config = DevConfig() @@ -1242,6 +1252,8 @@ Options: will retry indefinitely. -log-level=info Log level of the agent. -node=hostname Name of this node. Must be unique in the cluster + -node-meta=key:value An arbitrary metadata key/value pair for this node. + This can be specified multiple times. -protocol=N Sets the protocol version. Defaults to latest. -rejoin Ignores a previous leave and attempts to rejoin the cluster. -server Switches agent to server mode. diff --git a/command/agent/command_test.go b/command/agent/command_test.go index fc9a2c1e0b..5e97406cc0 100644 --- a/command/agent/command_test.go +++ b/command/agent/command_test.go @@ -13,6 +13,7 @@ import ( "github.com/hashicorp/consul/logger" "github.com/hashicorp/consul/testutil" "github.com/mitchellh/cli" + "reflect" ) func TestCommand_implements(t *testing.T) { @@ -129,6 +130,7 @@ func TestReadCliConfig(t *testing.T) { "-advertise-wan", "1.2.3.4", "-serf-wan-bind", "4.3.2.1", "-serf-lan-bind", "4.3.2.2", + "-node-meta", "somekey:somevalue", }, ShutdownCh: shutdownCh, Ui: new(cli.MockUi), @@ -144,6 +146,30 @@ func TestReadCliConfig(t *testing.T) { if config.SerfLanBindAddr != "4.3.2.2" { t.Fatalf("expected -serf-lan-bind 4.3.2.2 got %s", config.SerfLanBindAddr) } + if len(config.Meta) != 1 || config.Meta["somekey"] != "somevalue" { + t.Fatalf("expected somekey=somevalue, got %v", config.Meta) + } + } + + // Test multiple node meta flags + { + cmd := &Command{ + args: []string{ + "-data-dir", tmpDir, + "-node-meta", "somekey:somevalue", + "-node-meta", "otherkey:othervalue", + }, + ShutdownCh: shutdownCh, + Ui: new(cli.MockUi), + } + expected := map[string]string{ + "somekey": "somevalue", + "otherkey": "othervalue", + } + config := cmd.readConfig() + if !reflect.DeepEqual(config.Meta, expected) { + t.Fatalf("bad: %v %v", config.Meta, expected) + } } // Test LeaveOnTerm and SkipLeaveOnInt defaults for server mode diff --git a/command/agent/http.go b/command/agent/http.go index 74f1f25310..b228b9c0e3 100644 --- a/command/agent/http.go +++ b/command/agent/http.go @@ -590,12 +590,8 @@ func (s *HTTPServer) parseMetaFilter(req *http.Request) map[string]string { if filterList, ok := req.URL.Query()["node-meta"]; ok { filters := make(map[string]string) for _, filter := range filterList { - pair := strings.SplitN(filter, ":", 2) - if len(pair) == 2 { - filters[pair[0]] = pair[1] - } else { - filters[pair[0]] = "" - } + key, value := parseMetaPair(filter) + filters[key] = value } return filters } diff --git a/consul/structs/structs.go b/consul/structs/structs.go index e7dbbd0685..e34a8b6353 100644 --- a/consul/structs/structs.go +++ b/consul/structs/structs.go @@ -287,12 +287,6 @@ type Node struct { } type Nodes []*Node -// Used for filtering nodes by metadata key/value pairs -type NodeMetaFilter struct { - Key string - Value string -} - // Used to return information about a provided services. // Maps service name to available tags type Services map[string][]string