command: use meta struct for common options

This commit is contained in:
Ryan Uber
2015-09-14 13:13:52 -07:00
parent 34d77eeb04
commit 7e26f938a2
20 changed files with 173 additions and 300 deletions

View File

@@ -67,8 +67,8 @@ type WriteMeta struct {
// Config is used to configure the creation of a client
type Config struct {
// URL is the address of the Nomad agent
URL string
// Address is the address of the Nomad agent
Address string
// Region to use. If not provided, the default agent region is used.
Region string
@@ -85,11 +85,11 @@ type Config struct {
// DefaultConfig returns a default configuration for the client
func DefaultConfig() *Config {
config := &Config{
URL: "http://127.0.0.1:4646",
Address: "http://127.0.0.1:4646",
HttpClient: http.DefaultClient,
}
if url := os.Getenv("NOMAD_HTTP_URL"); url != "" {
config.URL = url
if addr := os.Getenv("NOMAD_ADDR"); addr != "" {
config.Address = addr
}
return config
}
@@ -104,10 +104,10 @@ func NewClient(config *Config) (*Client, error) {
// bootstrap the config
defConfig := DefaultConfig()
if config.URL == "" {
config.URL = defConfig.URL
} else if _, err := url.Parse(config.URL); err != nil {
return nil, fmt.Errorf("invalid url '%s': %v", config.URL, err)
if config.Address == "" {
config.Address = defConfig.Address
} else if _, err := url.Parse(config.Address); err != nil {
return nil, fmt.Errorf("invalid address '%s': %v", config.Address, err)
}
if config.HttpClient == nil {
@@ -194,7 +194,7 @@ func (r *request) toHTTP() (*http.Request, error) {
// newRequest is used to create a new request
func (c *Client) newRequest(method, path string) *request {
base, _ := url.Parse(c.config.URL)
base, _ := url.Parse(c.config.Address)
u, _ := url.Parse(path)
r := &request{
config: &c.config,

View File

@@ -24,7 +24,7 @@ func makeClient(t *testing.T, cb1 configCallback,
// Create server
server := testutil.NewTestServer(t, cb2)
conf.URL = "http://" + server.HTTPAddr
conf.Address = "http://" + server.HTTPAddr
// Create client
client, err := NewClient(conf)
@@ -39,13 +39,13 @@ func TestDefaultConfig_env(t *testing.T) {
t.Parallel()
url := "http://1.2.3.4:5678"
os.Setenv("NOMAD_HTTP_URL", url)
defer os.Setenv("NOMAD_HTTP_URL", "")
os.Setenv("NOMAD_ADDR", url)
defer os.Setenv("NOMAD_ADDR", "")
config := DefaultConfig()
if config.URL != url {
t.Errorf("expected %q to be %q", config.URL, url)
if config.Address != url {
t.Errorf("expected %q to be %q", config.Address, url)
}
}

View File

@@ -1,15 +1,12 @@
package command
import (
"flag"
"fmt"
"strings"
"github.com/mitchellh/cli"
)
type AgentForceLeaveCommand struct {
Ui cli.Ui
Meta
}
func (c *AgentForceLeaveCommand) Help() string {
@@ -21,51 +18,41 @@ Usage: nomad agent-force-leave [options] <node>
Note that if the member is actually still alive, it will
eventually rejoin the cluster again.
Options:
General Options:
-help
Display this message
-http-addr
Address of the Nomad API to connect. Can also be specified
using the environment variable NOMAD_HTTP_ADDR.
Default = http://127.0.0.1:4646
`
` + generalOptionsUsage()
return strings.TrimSpace(helpText)
}
func (c *AgentForceLeaveCommand) Synopsis() string {
return "Forces a member to leave the Nomad cluster"
return "Force a member into the 'left' state"
}
func (c *AgentForceLeaveCommand) Run(args []string) int {
var httpAddr *string
flags := flag.NewFlagSet("agent-force-leave", flag.ContinueOnError)
flags := c.Meta.FlagSet("force-leave", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
httpAddr = httpAddrFlag(flags)
if err := flags.Parse(args); err != nil {
return 1
}
// Check that we got exactly one node
if len(flags.Args()) != 1 {
args = flags.Args()
if len(args) != 1 {
c.Ui.Error(c.Help())
return 1
}
node := flags.Args()[0]
node := args[0]
// Get the HTTP client
client, err := httpClient(*httpAddr)
client, err := c.Meta.Client()
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed initializing Nomad client: %s", err))
c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
return 1
}
// Call force-leave on the node
if err := client.Agent().ForceLeave(node); err != nil {
c.Ui.Error(fmt.Sprintf("Failed to force-leave node %s: %s", node, err))
c.Ui.Error(fmt.Sprintf("Error force-leaving node %s: %s", node, err))
return 1
}

View File

@@ -1,15 +1,12 @@
package command
import (
"flag"
"fmt"
"strings"
"github.com/mitchellh/cli"
)
type AgentInfoCommand struct {
Ui cli.Ui
Meta
}
func (c *AgentInfoCommand) Help() string {
@@ -18,51 +15,41 @@ Usage: nomad agent-info [options]
Display status information about the local agent.
Options:
General Options:
-help
Display this message
-http-addr
Address of the Nomad API to connect. Can also be specified
using the environment variable NOMAD_HTTP_ADDR.
Default = http://127.0.0.1:4646
`
` + generalOptionsUsage()
return strings.TrimSpace(helpText)
}
func (c *AgentInfoCommand) Synopsis() string {
return "Display local agent information and status"
return "Display status information about the local agent"
}
func (c *AgentInfoCommand) Run(args []string) int {
var httpAddr *string
flags := flag.NewFlagSet("agent-info", flag.ContinueOnError)
flags := c.Meta.FlagSet("agent-info", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
httpAddr = httpAddrFlag(flags)
if err := flags.Parse(args); err != nil {
return 1
}
// Check that we either got no jobs or exactly one.
if len(flags.Args()) > 0 {
args = flags.Args()
if len(args) > 0 {
c.Ui.Error(c.Help())
return 1
}
// Get the HTTP client
client, err := httpClient(*httpAddr)
client, err := c.Meta.Client()
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed initializing Nomad client: %s", err))
c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
return 1
}
// Query the agent info
info, err := client.Agent().Self()
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed querying agent info: %s", err))
c.Ui.Error(fmt.Sprintf("Error querying agent info: %s", err))
return 1
}

View File

@@ -16,9 +16,9 @@ func TestAgentInfoCommand_Run(t *testing.T) {
defer srv.Stop()
ui := new(cli.MockUi)
cmd := &AgentInfoCommand{Ui: ui}
cmd := &AgentInfoCommand{Meta: Meta{Ui: ui}}
code := cmd.Run([]string{"-http-addr=" + url})
code := cmd.Run([]string{"-address=" + url})
if code != 0 {
t.Fatalf("expected exit 0, got: %d %s", code)
}
@@ -26,7 +26,7 @@ func TestAgentInfoCommand_Run(t *testing.T) {
func TestAgentInfoCommand_Fails(t *testing.T) {
ui := new(cli.MockUi)
cmd := &AgentInfoCommand{Ui: ui}
cmd := &AgentInfoCommand{Meta: Meta{Ui: ui}}
// Fails on misuse
if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 {
@@ -38,10 +38,10 @@ func TestAgentInfoCommand_Fails(t *testing.T) {
ui.ErrorWriter.Reset()
// Fails on connection failure
if code := cmd.Run([]string{"-http-addr=nope"}); code != 1 {
if code := cmd.Run([]string{"-address=nope"}); code != 1 {
t.Fatalf("expected exit code 1, got: %d", code)
}
if out := ui.ErrorWriter.String(); !strings.Contains(out, "Failed querying agent info") {
if out := ui.ErrorWriter.String(); !strings.Contains(out, "Error querying agent info") {
t.Fatalf("expected failed query error, got: %s", out)
}
}

View File

@@ -1,15 +1,12 @@
package command
import (
"flag"
"fmt"
"strings"
"github.com/mitchellh/cli"
)
type AgentJoinCommand struct {
Ui cli.Ui
Meta
}
func (c *AgentJoinCommand) Help() string {
@@ -22,52 +19,42 @@ Usage: nomad agent-join [options] <addr> [<addr>...]
gossip layer will handle discovery of the other server nodes in
the cluster.
Options:
General Options:
-help
Display this message
-http-addr
Address of the Nomad API to connect. Can also be specified
using the environment variable NOMAD_HTTP_ADDR.
Default = http://127.0.0.1:4646
`
` + generalOptionsUsage()
return strings.TrimSpace(helpText)
}
func (c *AgentJoinCommand) Synopsis() string {
return "Joins server nodes together"
return "Join server nodes together"
}
func (c *AgentJoinCommand) Run(args []string) int {
var httpAddr *string
flags := flag.NewFlagSet("agent-join", flag.ContinueOnError)
flags := c.Meta.FlagSet("agent-join", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
httpAddr = httpAddrFlag(flags)
if err := flags.Parse(args); err != nil {
return 1
}
// Check that we got at least one node
if len(flags.Args()) < 1 {
args = flags.Args()
if len(args) < 1 {
c.Ui.Error(c.Help())
return 1
}
nodes := flags.Args()
nodes := args
// Get the HTTP client
client, err := httpClient(*httpAddr)
client, err := c.Meta.Client()
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed initializing Nomad client: %s", err))
c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
return 1
}
// Attempt the join
n, err := client.Agent().Join(nodes...)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed to join: %s", err))
c.Ui.Error(fmt.Sprintf("Error joining: %s", err))
return 1
}

View File

@@ -1,17 +1,15 @@
package command
import (
"flag"
"fmt"
"strings"
"github.com/hashicorp/nomad/api"
"github.com/mitchellh/cli"
"github.com/ryanuber/columnize"
)
type AgentMembersCommand struct {
Ui cli.Ui
Meta
}
func (c *AgentMembersCommand) Help() string {
@@ -20,20 +18,16 @@ Usage: nomad agent-members [options]
Display a list of the known members and their status.
Options:
General Options:
` + generalOptionsUsage() + `
Agent Members Options:
-detailed
Show detailed information about each member. This dumps
a raw set of tags which shows more information than the
default output format.
-help
Display this message
-http-addr
Address of the Nomad API to connect. Can also be specified
using the environment variable NOMAD_HTTP_ADDR.
Default = http://127.0.0.1:4646
`
return strings.TrimSpace(helpText)
}
@@ -43,35 +37,34 @@ func (c *AgentMembersCommand) Synopsis() string {
}
func (c *AgentMembersCommand) Run(args []string) int {
var httpAddr *string
var detailed bool
flags := flag.NewFlagSet("agent-members", flag.ContinueOnError)
flags := c.Meta.FlagSet("agent-members", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&detailed, "detailed", false, "Show detailed output")
httpAddr = httpAddrFlag(flags)
if err := flags.Parse(args); err != nil {
return 1
}
// Check for extra arguments
if len(flags.Args()) != 0 {
args = flags.Args()
if len(args) != 0 {
c.Ui.Error(c.Help())
return 1
}
// Get the HTTP client
client, err := httpClient(*httpAddr)
client, err := c.Meta.Client()
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed initializing Nomad client: %s", err))
c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
return 1
}
// Query the members
mem, err := client.Agent().Members()
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed querying members: %s", err))
c.Ui.Error(fmt.Sprintf("Error querying members: %s", err))
return 1
}

View File

@@ -16,7 +16,7 @@ func TestAgentMembersCommand_Run(t *testing.T) {
defer srv.Stop()
ui := new(cli.MockUi)
cmd := &AgentMembersCommand{Ui: ui}
cmd := &AgentMembersCommand{Meta: Meta{Ui: ui}}
// Get our own node name
name, err := client.Agent().NodeName()
@@ -25,7 +25,7 @@ func TestAgentMembersCommand_Run(t *testing.T) {
}
// Query the members
if code := cmd.Run([]string{"-http-addr=" + url}); code != 0 {
if code := cmd.Run([]string{"-address=" + url}); code != 0 {
t.Fatalf("expected exit 0, got: %d", code)
}
if out := ui.OutputWriter.String(); !strings.Contains(out, name) {
@@ -34,7 +34,7 @@ func TestAgentMembersCommand_Run(t *testing.T) {
ui.OutputWriter.Reset()
// Query members with detailed output
if code := cmd.Run([]string{"-http-addr=" + url, "-detailed"}); code != 0 {
if code := cmd.Run([]string{"-address=" + url, "-detailed"}); code != 0 {
t.Fatalf("expected exit 0, got: %d", code)
}
if out := ui.OutputWriter.String(); !strings.Contains(out, "Tags") {
@@ -44,7 +44,7 @@ func TestAgentMembersCommand_Run(t *testing.T) {
func TestMembersCommand_Fails(t *testing.T) {
ui := new(cli.MockUi)
cmd := &AgentMembersCommand{Ui: ui}
cmd := &AgentMembersCommand{Meta: Meta{Ui: ui}}
// Fails on misuse
if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 {
@@ -56,10 +56,10 @@ func TestMembersCommand_Fails(t *testing.T) {
ui.ErrorWriter.Reset()
// Fails on connection failure
if code := cmd.Run([]string{"-http-addr=nope"}); code != 1 {
if code := cmd.Run([]string{"-address=nope"}); code != 1 {
t.Fatalf("expected exit code 1, got: %d", code)
}
if out := ui.ErrorWriter.String(); !strings.Contains(out, "Failed querying members") {
if out := ui.ErrorWriter.String(); !strings.Contains(out, "Error querying members") {
t.Fatalf("expected failed query error, got: %s", out)
}
}

View File

@@ -1,38 +0,0 @@
package command
import (
"flag"
"os"
"github.com/hashicorp/nomad/api"
)
const (
// Environment variable used to control the HTTP address
// we connect to while using various commands. This may
// be overridden using the -http-addr flag.
HttpEnvVar = "NOMAD_HTTP_ADDR"
// DefaultHTTPAddr is the default address used for the
// HTTP address flag.
DefaultHttpAddr = "http://127.0.0.1:4646"
)
// httpAddrFlag is used to add the -http-addr flag to a flag
// set. Allows setting the value from an environment variable.
func httpAddrFlag(f *flag.FlagSet) *string {
defaultAddr := os.Getenv(HttpEnvVar)
if defaultAddr == "" {
defaultAddr = DefaultHttpAddr
}
return f.String("http-addr", defaultAddr,
"HTTP address of the Nomad agent")
}
// httpClient is used to get a new Nomad client using the
// given address.
func httpClient(addr string) (*api.Client, error) {
conf := api.DefaultConfig()
conf.URL = addr
return api.NewClient(conf)
}

View File

@@ -1,44 +0,0 @@
package command
import (
"flag"
"os"
"testing"
)
func TestHelpers_HttpAddrFlag(t *testing.T) {
var addr *string
// Returns the default
flags := flag.NewFlagSet("test", flag.ContinueOnError)
addr = httpAddrFlag(flags)
if err := flags.Parse([]string{}); err != nil {
t.Fatalf("err: %s", err)
}
if *addr != DefaultHttpAddr {
t.Fatalf("expect %q, got: %q", DefaultHttpAddr, *addr)
}
// Returns from the env var
if err := os.Setenv(HttpEnvVar, "http://127.0.0.1:1111"); err != nil {
t.Fatalf("err: %s", err)
}
flags = flag.NewFlagSet("test", flag.ContinueOnError)
addr = httpAddrFlag(flags)
if err := flags.Parse([]string{}); err != nil {
t.Fatalf("err: %s", err)
}
if *addr != "http://127.0.0.1:1111" {
t.Fatalf("expect %q, got: %q", "http://127.0.0.1:1111", *addr)
}
// Returns from flag
flags = flag.NewFlagSet("test", flag.ContinueOnError)
addr = httpAddrFlag(flags)
if err := flags.Parse([]string{"-http-addr", "http://127.0.0.1:2222"}); err != nil {
t.Fatalf("err: %s", err)
}
if *addr != "http://127.0.0.1:2222" {
t.Fatalf("expect %q, got: %q", "http://127.0.0.1:2222", *addr)
}
}

View File

@@ -4,18 +4,27 @@ import (
"bufio"
"flag"
"io"
"os"
"strings"
"github.com/hashicorp/nomad/api"
"github.com/mitchellh/cli"
)
const (
// Names of environment variables used to supply various
// config options to the Nomad CLI.
EnvNomadAddress = "NOMAD_ADDR"
)
// FlagSetFlags is an enum to define what flags are present in the
// default FlagSet returned by Meta.FlagSet.
type FlagSetFlags uint
const (
FlagSetNone FlagSetFlags = 0
FlagSetServer FlagSetFlags = 1 << iota
FlagSetDefault = FlagSetServer
FlagSetClient FlagSetFlags = 1 << iota
FlagSetDefault = FlagSetClient
)
// Meta contains the meta-options and functionality that nearly every
@@ -34,9 +43,9 @@ type Meta struct {
func (m *Meta) FlagSet(n string, fs FlagSetFlags) *flag.FlagSet {
f := flag.NewFlagSet(n, flag.ContinueOnError)
// FlagSetServer tells us to enable the settings for selecting
// the server information.
if fs&FlagSetServer != 0 {
// FlagSetClient is used to enable the settings for specifying
// client connectivity options.
if fs&FlagSetClient != 0 {
f.StringVar(&m.flagAddress, "address", "", "")
}
@@ -55,3 +64,27 @@ func (m *Meta) FlagSet(n string, fs FlagSetFlags) *flag.FlagSet {
return f
}
// Client is used to initialize and return a new API client using
// the default command line arguments and env vars.
func (m *Meta) Client() (*api.Client, error) {
config := api.DefaultConfig()
if v := os.Getenv(EnvNomadAddress); v != "" {
config.Address = v
}
if m.flagAddress != "" {
config.Address = m.flagAddress
}
return api.NewClient(config)
}
// generalOptionsUsage returns the help string for the global options.
func generalOptionsUsage() string {
helpText := `
-address=<addr>
The address of the Nomad server.
Overrides the NOMAD_ADDR environment variable if set.
Default = http://127.0.0.1:4646
`
return strings.TrimSpace(helpText)
}

View File

@@ -7,7 +7,7 @@ import (
"testing"
)
func TestFlagSet(t *testing.T) {
func TestMeta_FlagSet(t *testing.T) {
cases := []struct {
Flags FlagSetFlags
Expected []string
@@ -17,7 +17,7 @@ func TestFlagSet(t *testing.T) {
[]string{},
},
{
FlagSetServer,
FlagSetClient,
[]string{"address"},
},
}

View File

@@ -1,15 +1,12 @@
package command
import (
"flag"
"fmt"
"strings"
"github.com/mitchellh/cli"
)
type NodeDrainCommand struct {
Ui cli.Ui
Meta
}
func (c *NodeDrainCommand) Help() string {
@@ -19,21 +16,17 @@ Usage: nomad node-drain [options] <node>
Toggles node draining on a specified node. It is required
that either -enable or -disable is specified, but not both.
Options:
General Options:
` + generalOptionsUsage() + `
Node Drain Options:
-disable
Disable draining for the specified node.
-enable
Enable draining for the specified node.
-help
Display this message
-http-addr
Address of the Nomad API to connect. Can also be specified
using the environment variable NOMAD_HTTP_ADDR.
Default = http://127.0.0.1:4646
`
return strings.TrimSpace(helpText)
}
@@ -43,14 +36,12 @@ func (c *NodeDrainCommand) Synopsis() string {
}
func (c *NodeDrainCommand) Run(args []string) int {
var httpAddr *string
var enable, disable bool
flags := flag.NewFlagSet("node-drain", flag.ContinueOnError)
flags := c.Meta.FlagSet("node-drain", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&enable, "enable", false, "Enable drain mode")
flags.BoolVar(&disable, "disable", false, "Disable drain mode")
httpAddr = httpAddrFlag(flags)
if err := flags.Parse(args); err != nil {
return 1
@@ -63,22 +54,23 @@ func (c *NodeDrainCommand) Run(args []string) int {
}
// Check that we got a node ID
if len(flags.Args()) != 1 {
args = flags.Args()
if len(args) != 1 {
c.Ui.Error(c.Help())
return 1
}
nodeID := flags.Args()[0]
nodeID := args[0]
// Get the HTTP client
client, err := httpClient(*httpAddr)
client, err := c.Meta.Client()
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed initializing Nomad client: %s", err))
c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
return 1
}
// Toggle node draining
if _, err := client.Nodes().ToggleDrain(nodeID, enable, nil); err != nil {
c.Ui.Error(fmt.Sprintf("Failed to toggle drain mode: %s", err))
c.Ui.Error(fmt.Sprintf("Error toggling drain mode: %s", err))
return 1
}
return 0

View File

@@ -16,7 +16,7 @@ func TestNodeDrainCommand_Fails(t *testing.T) {
defer srv.Stop()
ui := new(cli.MockUi)
cmd := &NodeDrainCommand{Ui: ui}
cmd := &NodeDrainCommand{Meta: Meta{Ui: ui}}
// Fails on misuse
if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 {
@@ -28,16 +28,16 @@ func TestNodeDrainCommand_Fails(t *testing.T) {
ui.ErrorWriter.Reset()
// Fails on connection failure
if code := cmd.Run([]string{"-http-addr=nope", "-enable", "nope"}); code != 1 {
if code := cmd.Run([]string{"-address=nope", "-enable", "nope"}); code != 1 {
t.Fatalf("expected exit code 1, got: %d", code)
}
if out := ui.ErrorWriter.String(); !strings.Contains(out, "Failed to toggle") {
if out := ui.ErrorWriter.String(); !strings.Contains(out, "Error toggling") {
t.Fatalf("expected failed toggle error, got: %s", out)
}
ui.ErrorWriter.Reset()
// Fails on non-existent node
if code := cmd.Run([]string{"-http-addr=" + url, "-enable", "nope"}); code != 1 {
if code := cmd.Run([]string{"-address=" + url, "-enable", "nope"}); code != 1 {
t.Fatalf("expected exit 1, got: %d", code)
}
if out := ui.ErrorWriter.String(); !strings.Contains(out, "not found") {

View File

@@ -1,16 +1,14 @@
package command
import (
"flag"
"fmt"
"strings"
"github.com/mitchellh/cli"
"github.com/ryanuber/columnize"
)
type NodeStatusCommand struct {
Ui cli.Ui
Meta
}
func (c *NodeStatusCommand) Help() string {
@@ -25,16 +23,9 @@ Usage: nomad node-status [options] [node]
be displayed. If no node ID's are passed, then a short-hand
list of all nodes will be displayed.
Options:
General Options:
-help
Display this message
-http-addr
Address of the Nomad API to connect. Can also be specified
using the environment variable NOMAD_HTTP_ADDR.
Default = http://127.0.0.1:4646
`
` + generalOptionsUsage()
return strings.TrimSpace(helpText)
}
@@ -43,35 +34,32 @@ func (c *NodeStatusCommand) Synopsis() string {
}
func (c *NodeStatusCommand) Run(args []string) int {
var httpAddr *string
flags := flag.NewFlagSet("node-status", flag.ContinueOnError)
flags := c.Meta.FlagSet("node-status", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
httpAddr = httpAddrFlag(flags)
if err := flags.Parse(args); err != nil {
return 1
}
// Check that we got either a single node or none
if len(flags.Args()) > 1 {
args = flags.Args()
if len(args) > 1 {
c.Ui.Error(c.Help())
return 1
}
// Get the HTTP client
client, err := httpClient(*httpAddr)
client, err := c.Meta.Client()
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed initializing Nomad client: %s", err))
c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
return 1
}
// Use list mode if no node name was provided
if len(flags.Args()) == 0 {
if len(args) == 0 {
// Query the node info
nodes, _, err := client.Nodes().List(nil)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed querying node status: %s", err))
c.Ui.Error(fmt.Sprintf("Error querying node status: %s", err))
return 1
}
@@ -99,10 +87,10 @@ func (c *NodeStatusCommand) Run(args []string) int {
}
// Query the specific node
nodeID := flags.Args()[0]
nodeID := args[0]
node, _, err := client.Nodes().Info(nodeID, nil)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed querying node info: %s", err))
c.Ui.Error(fmt.Sprintf("Error querying node info: %s", err))
return 1
}

View File

@@ -16,10 +16,10 @@ func TestNodeStatusCommand_Run(t *testing.T) {
defer srv.Stop()
ui := new(cli.MockUi)
cmd := &NodeStatusCommand{Ui: ui}
cmd := &NodeStatusCommand{Meta: Meta{Ui: ui}}
// Query all node statuses
if code := cmd.Run([]string{"-http-addr=" + url}); code != 0 {
if code := cmd.Run([]string{"-address=" + url}); code != 0 {
t.Fatalf("expected exit 0, got: %d", code)
}
@@ -34,7 +34,7 @@ func TestNodeStatusCommand_Fails(t *testing.T) {
defer srv.Stop()
ui := new(cli.MockUi)
cmd := &NodeStatusCommand{Ui: ui}
cmd := &NodeStatusCommand{Meta: Meta{Ui: ui}}
// Fails on misuse
if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 {
@@ -46,15 +46,15 @@ func TestNodeStatusCommand_Fails(t *testing.T) {
ui.ErrorWriter.Reset()
// Fails on connection failure
if code := cmd.Run([]string{"-http-addr=nope"}); code != 1 {
if code := cmd.Run([]string{"-address=nope"}); code != 1 {
t.Fatalf("expected exit code 1, got: %d", code)
}
if out := ui.ErrorWriter.String(); !strings.Contains(out, "Failed querying node status") {
if out := ui.ErrorWriter.String(); !strings.Contains(out, "Error querying node status") {
t.Fatalf("expected failed query error, got: %s", out)
}
// Fails on non-existent node
if code := cmd.Run([]string{"-http-addr=" + url, "nope"}); code != 1 {
if code := cmd.Run([]string{"-address=" + url, "nope"}); code != 1 {
t.Fatalf("expected exit 1, got: %d", code)
}
if out := ui.ErrorWriter.String(); !strings.Contains(out, "not found") {

View File

@@ -1,16 +1,14 @@
package command
import (
"flag"
"fmt"
"strings"
"github.com/mitchellh/cli"
"github.com/ryanuber/columnize"
)
type StatusCommand struct {
Ui cli.Ui
Meta
}
func (c *StatusCommand) Help() string {
@@ -20,16 +18,9 @@ Usage: nomad status [options] [job]
Display status information about jobs. If no job ID is given,
a list of all known jobs will be dumped.
Options:
General Options:
-help
Display this message
-http-addr
Address of the Nomad API to connect. Can also be specified
using the environment variable NOMAD_HTTP_ADDR.
Default = http://127.0.0.1:4646
`
` + generalOptionsUsage()
return strings.TrimSpace(helpText)
}
@@ -38,34 +29,31 @@ func (c *StatusCommand) Synopsis() string {
}
func (c *StatusCommand) Run(args []string) int {
var httpAddr *string
flags := flag.NewFlagSet("status", flag.ContinueOnError)
flags := c.Meta.FlagSet("status", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
httpAddr = httpAddrFlag(flags)
if err := flags.Parse(args); err != nil {
return 1
}
// Check that we either got no jobs or exactly one.
if len(flags.Args()) > 1 {
args = flags.Args()
if len(args) > 1 {
c.Ui.Error(c.Help())
return 1
}
// Get the HTTP client
client, err := httpClient(*httpAddr)
client, err := c.Meta.Client()
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed initializing Nomad client: %s", err))
c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err))
return 1
}
// Invoke list mode if no job ID.
if len(flags.Args()) == 0 {
if len(args) == 0 {
jobs, _, err := client.Jobs().List(nil)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed querying jobs: %s", err))
c.Ui.Error(fmt.Sprintf("Error querying jobs: %s", err))
return 1
}
@@ -88,10 +76,10 @@ func (c *StatusCommand) Run(args []string) int {
}
// Try querying the job
jobID := flags.Args()[0]
jobID := args[0]
job, _, err := client.Jobs().Info(jobID, nil)
if err != nil {
c.Ui.Error(fmt.Sprintf("Failed querying job: %s", err))
c.Ui.Error(fmt.Sprintf("Error querying job: %s", err))
return 1
}

View File

@@ -17,10 +17,10 @@ func TestStatusCommand_Run(t *testing.T) {
defer srv.Stop()
ui := new(cli.MockUi)
cmd := &StatusCommand{Ui: ui}
cmd := &StatusCommand{Meta: Meta{Ui: ui}}
// Should return blank for no jobs
if code := cmd.Run([]string{"-http-addr=" + url}); code != 0 {
if code := cmd.Run([]string{"-address=" + url}); code != 0 {
t.Fatalf("expected exit 0, got: %d", code)
}
@@ -42,7 +42,7 @@ func TestStatusCommand_Run(t *testing.T) {
}
// Query again and check the result
if code := cmd.Run([]string{"-http-addr=" + url}); code != 0 {
if code := cmd.Run([]string{"-address=" + url}); code != 0 {
t.Fatalf("expected exit 0, got: %d", code)
}
out := ui.OutputWriter.String()
@@ -52,7 +52,7 @@ func TestStatusCommand_Run(t *testing.T) {
ui.OutputWriter.Reset()
// Query a single job
if code := cmd.Run([]string{"-http-addr=" + url, "job2"}); code != 0 {
if code := cmd.Run([]string{"-address=" + url, "job2"}); code != 0 {
t.Fatalf("expected exit 0, got: %d", code)
}
out = ui.OutputWriter.String()
@@ -63,7 +63,7 @@ func TestStatusCommand_Run(t *testing.T) {
func TestStatusCommand_Fails(t *testing.T) {
ui := new(cli.MockUi)
cmd := &StatusCommand{Ui: ui}
cmd := &StatusCommand{Meta: Meta{Ui: ui}}
// Fails on misuse
if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 {
@@ -75,10 +75,10 @@ func TestStatusCommand_Fails(t *testing.T) {
ui.ErrorWriter.Reset()
// Fails on connection failure
if code := cmd.Run([]string{"-http-addr=nope"}); code != 1 {
if code := cmd.Run([]string{"-address=nope"}); code != 1 {
t.Fatalf("expected exit code 1, got: %d", code)
}
if out := ui.ErrorWriter.String(); !strings.Contains(out, "Failed querying jobs") {
if out := ui.ErrorWriter.String(); !strings.Contains(out, "Error querying jobs") {
t.Fatalf("expected failed query error, got: %s", out)
}
}

View File

@@ -16,10 +16,10 @@ func testServer(t *testing.T) (*testutil.TestServer, *api.Client, string) {
// Make a client
clientConf := api.DefaultConfig()
clientConf.URL = "http://" + srv.HTTPAddr
clientConf.Address = "http://" + srv.HTTPAddr
client, err := api.NewClient(clientConf)
if err != nil {
t.Fatalf("err: %s", err)
}
return srv, client, clientConf.URL
return srv, client, clientConf.Address
}

View File

@@ -36,43 +36,43 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
"agent-force-leave": func() (cli.Command, error) {
return &command.AgentForceLeaveCommand{
Ui: meta.Ui,
Meta: meta,
}, nil
},
"agent-info": func() (cli.Command, error) {
return &command.AgentInfoCommand{
Ui: meta.Ui,
Meta: meta,
}, nil
},
"agent-join": func() (cli.Command, error) {
return &command.AgentJoinCommand{
Ui: meta.Ui,
Meta: meta,
}, nil
},
"agent-members": func() (cli.Command, error) {
return &command.AgentMembersCommand{
Ui: meta.Ui,
Meta: meta,
}, nil
},
"node-drain": func() (cli.Command, error) {
return &command.NodeDrainCommand{
Ui: meta.Ui,
Meta: meta,
}, nil
},
"node-status": func() (cli.Command, error) {
return &command.NodeStatusCommand{
Ui: meta.Ui,
Meta: meta,
}, nil
},
"status": func() (cli.Command, error) {
return &command.StatusCommand{
Ui: meta.Ui,
Meta: meta,
}, nil
},