From c84fd2b29284ce1dd3a09171dfeb35578346fd56 Mon Sep 17 00:00:00 2001 From: Alex Dadgar Date: Thu, 1 Oct 2015 16:46:42 -0700 Subject: [PATCH 1/4] Add parsing of client configuration from the commandline --- command/agent/command.go | 83 ++++++++++++++++++++++++++++++++--- command/agent/command_test.go | 16 ++++++- 2 files changed, 92 insertions(+), 7 deletions(-) diff --git a/command/agent/command.go b/command/agent/command.go index 49093588a14..79ed262ad12 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -70,6 +70,18 @@ func (c *Command) readConfig() *Config { // Server-only options flags.IntVar(&cmdConfig.Server.BootstrapExpect, "bootstrap-expect", 0, "") + // Client-only options + flags.StringVar(&cmdConfig.Client.StateDir, "state-dir", "", "") + flags.StringVar(&cmdConfig.Client.AllocDir, "alloc-dir", "", "") + flags.StringVar(&cmdConfig.Client.NodeID, "node-id", "", "") + flags.StringVar(&cmdConfig.Client.NodeClass, "node-class", "", "") + + var servers string + flags.StringVar(&servers, "servers", "", "") + + var meta []string + flags.Var((*sliceflag.StringFlag)(&meta), "meta", "") + // General options flags.Var((*sliceflag.StringFlag)(&configPath), "config", "config") flags.StringVar(&cmdConfig.BindAddr, "bind", "", "") @@ -88,6 +100,25 @@ func (c *Command) readConfig() *Config { return nil } + // Split the servers. + if servers != "" { + cmdConfig.Client.Servers = strings.Split(servers, ",") + } + + // Parse the meta flags. + if len(meta) != 0 { + cmdConfig.Client.Meta = make(map[string]string) + for _, kv := range meta { + parts := strings.Split(kv, "=") + if len(parts) != 2 { + c.Ui.Error(fmt.Sprintf("Error parsing Client.Meta value: %v", kv)) + return nil + } + + cmdConfig.Client.Meta[parts[0]] = parts[1] + } + } + // Load the configuration var config *Config if dev { @@ -134,10 +165,26 @@ func (c *Command) readConfig() *Config { return config } - // Check that we have a data-dir - if config.DataDir == "" { + // Check for valid modes. + if config.Server.Enabled && config.Client.Enabled { + c.Ui.Error("To run both as a server and client, use -dev mode.") + return nil + } else if !(config.Server.Enabled || config.Client.Enabled) { + c.Ui.Error("Must specify either server, client or dev mode for the agent.") + return nil + } + + // Ensure that we have the directories we neet to run. + if config.Server.Enabled && config.DataDir == "" { c.Ui.Error("Must specify data directory") return nil + } else if config.Client.Enabled && config.DataDir == "" { + // The config is valid if the top-level data-dir is set or if both + // alloc-dir and state-dir are set. + if config.Client.AllocDir == "" || config.Client.StateDir == "" { + c.Ui.Error("Must specify both the state and alloc dir if data-dir is omitted.") + return nil + } } // Check the bootstrap flags @@ -588,9 +635,35 @@ Server Options: Client Options: -client - Enable client mode for the agent. Client mode enables a given node - to be evaluated for allocations. If client mode is not enabled, - no work will be scheduled to the agent. + Enable client mode for the agent. Client mode enables a given node to be + evaluated for allocations. If client mode is not enabled, no work will be + scheduled to the agent. + + -state-dir + The directory used to store state and other persistent data. If not + specified a subdirectory under the "-data-dir" will be used. + + -alloc-dir + The directory used to store allocation data such as downloaded artificats as + well as data produced by tasks. If not specified, a subdirectory under the + "-data-dir" will be used. + + -servers + A list of known server addresses to connect to given as "host:port" and + delimited by commas. + + -node-id + A unique identifier for the node to use. If not provided, a UUID is + generated. + + -node-class + Mark this node as a member of a node-class. This can be used to label + similiar node types. + + -meta + User specified metadata to associated with the node. Each instance of -meta + parses a single KEY=VALUE pair. Repeat the meta flag for each key/value pair + to be added. Atlas Options: diff --git a/command/agent/command_test.go b/command/agent/command_test.go index 3dbb13504ef..5097a1fc830 100644 --- a/command/agent/command_test.go +++ b/command/agent/command_test.go @@ -27,16 +27,28 @@ func TestCommand_Args(t *testing.T) { tcases := []tcase{ { []string{}, - "Must specify data directory", + "Must specify either server, client or dev mode for the agent.", + }, + { + []string{"-client", "-server"}, + "To run both as a server and client, use -dev mode.", }, { - []string{"-data-dir=" + tmpDir, "-bootstrap-expect=1"}, + []string{"-client", "-data-dir=" + tmpDir, "-bootstrap-expect=1"}, "Bootstrap requires server mode to be enabled", }, { []string{"-data-dir=" + tmpDir, "-server", "-bootstrap-expect=1"}, "WARNING: Bootstrap mode enabled!", }, + { + []string{"-server"}, + "Must specify data directory", + }, + { + []string{"-client", "-alloc-dir="}, + "Must specify both the state and alloc dir if data-dir is omitted.", + }, } for _, tc := range tcases { // Make a new command. We pre-emptively close the shutdownCh From 6c9732c356094e4f5d36894116aa33f5e940a789 Mon Sep 17 00:00:00 2001 From: Alex Dadgar Date: Thu, 1 Oct 2015 17:19:52 -0700 Subject: [PATCH 2/4] Move declerations to top and use SplitN to be more flexible for Meta values --- command/agent/command.go | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/command/agent/command.go b/command/agent/command.go index 79ed262ad12..9ca82306f7e 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -50,6 +50,8 @@ type Command struct { func (c *Command) readConfig() *Config { var dev bool var configPath []string + var servers string + var meta []string // Make a new, empty config. cmdConfig := &Config{ @@ -75,11 +77,7 @@ func (c *Command) readConfig() *Config { flags.StringVar(&cmdConfig.Client.AllocDir, "alloc-dir", "", "") flags.StringVar(&cmdConfig.Client.NodeID, "node-id", "", "") flags.StringVar(&cmdConfig.Client.NodeClass, "node-class", "", "") - - var servers string flags.StringVar(&servers, "servers", "", "") - - var meta []string flags.Var((*sliceflag.StringFlag)(&meta), "meta", "") // General options @@ -109,7 +107,7 @@ func (c *Command) readConfig() *Config { if len(meta) != 0 { cmdConfig.Client.Meta = make(map[string]string) for _, kv := range meta { - parts := strings.Split(kv, "=") + parts := strings.SplitN(kv, "=", 2) if len(parts) != 2 { c.Ui.Error(fmt.Sprintf("Error parsing Client.Meta value: %v", kv)) return nil From 15a854be7a5ea8364d904e71c97cc062dcf3d97e Mon Sep 17 00:00:00 2001 From: Alex Dadgar Date: Thu, 1 Oct 2015 17:21:32 -0700 Subject: [PATCH 3/4] Use the known size of meta to initialize the map --- command/agent/command.go | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/command/agent/command.go b/command/agent/command.go index 9ca82306f7e..94c0484cb4f 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -104,8 +104,9 @@ func (c *Command) readConfig() *Config { } // Parse the meta flags. - if len(meta) != 0 { - cmdConfig.Client.Meta = make(map[string]string) + metaLength := len(meta) + if metaLength != 0 { + cmdConfig.Client.Meta = make(map[string]string, metaLength) for _, kv := range meta { parts := strings.SplitN(kv, "=", 2) if len(parts) != 2 { From e9254c5f2d31284f7224fb36b8aa494c8f1717b0 Mon Sep 17 00:00:00 2001 From: Alex Dadgar Date: Thu, 1 Oct 2015 17:27:36 -0700 Subject: [PATCH 4/4] Don't enfoce that the agent can't be run as both server and client --- command/agent/command.go | 15 +++++++-------- command/agent/command_test.go | 4 ---- 2 files changed, 7 insertions(+), 12 deletions(-) diff --git a/command/agent/command.go b/command/agent/command.go index 94c0484cb4f..a800425552d 100644 --- a/command/agent/command.go +++ b/command/agent/command.go @@ -164,11 +164,8 @@ func (c *Command) readConfig() *Config { return config } - // Check for valid modes. - if config.Server.Enabled && config.Client.Enabled { - c.Ui.Error("To run both as a server and client, use -dev mode.") - return nil - } else if !(config.Server.Enabled || config.Client.Enabled) { + // Check that the server is running in at least one mode. + if !(config.Server.Enabled || config.Client.Enabled) { c.Ui.Error("Must specify either server, client or dev mode for the agent.") return nil } @@ -177,9 +174,11 @@ func (c *Command) readConfig() *Config { if config.Server.Enabled && config.DataDir == "" { c.Ui.Error("Must specify data directory") return nil - } else if config.Client.Enabled && config.DataDir == "" { - // The config is valid if the top-level data-dir is set or if both - // alloc-dir and state-dir are set. + } + + // The config is valid if the top-level data-dir is set or if both + // alloc-dir and state-dir are set. + if config.Client.Enabled && config.DataDir == "" { if config.Client.AllocDir == "" || config.Client.StateDir == "" { c.Ui.Error("Must specify both the state and alloc dir if data-dir is omitted.") return nil diff --git a/command/agent/command_test.go b/command/agent/command_test.go index 5097a1fc830..c68da5a5a8a 100644 --- a/command/agent/command_test.go +++ b/command/agent/command_test.go @@ -29,10 +29,6 @@ func TestCommand_Args(t *testing.T) { []string{}, "Must specify either server, client or dev mode for the agent.", }, - { - []string{"-client", "-server"}, - "To run both as a server and client, use -dev mode.", - }, { []string{"-client", "-data-dir=" + tmpDir, "-bootstrap-expect=1"}, "Bootstrap requires server mode to be enabled",