From 39180ec9e05f826b67a2126e8c06d014f8e65e6b Mon Sep 17 00:00:00 2001 From: Ryan Uber Date: Wed, 16 Sep 2015 16:05:57 -0700 Subject: [PATCH] command: adding eval-monitor --- command/eval_monitor.go | 72 ++++++++++++++++++++++++++++++++++++ command/eval_monitor_test.go | 46 +++++++++++++++++++++++ 2 files changed, 118 insertions(+) create mode 100644 command/eval_monitor.go create mode 100644 command/eval_monitor_test.go diff --git a/command/eval_monitor.go b/command/eval_monitor.go new file mode 100644 index 000000000..b7bcb0117 --- /dev/null +++ b/command/eval_monitor.go @@ -0,0 +1,72 @@ +package command + +import ( + "fmt" + "strings" + + "github.com/mitchellh/cli" +) + +type EvalMonitorCommand struct { + Meta +} + +func (c *EvalMonitorCommand) Help() string { + helpText := ` +Usage: nomad eval-monitor [options] + + Start an interactive monitoring session for an existing evaluation. + The monitor command periodically polls for information about the + provided evaluation, including status updates, new allocations, + updates to allocations, and failures. Status is printed in near + real-time to the terminal. + + The command will exit when the given evaluation reaches a terminal + state (completed or failed). The exit status will reflect the + result of the evaluation (0 on success, 1 on failure). Exit code + 1 may also be encountered for client connectivity errors. + +General Options: + + ` + generalOptionsUsage() + return strings.TrimSpace(helpText) +} + +func (c *EvalMonitorCommand) Synopsis() string { + return "Monitor an evaluation interactively" +} + +func (c *EvalMonitorCommand) Run(args []string) int { + // Set up the prefixed output + c.Ui = &cli.PrefixedUi{ + InfoPrefix: "==> ", + OutputPrefix: " ", + ErrorPrefix: "==> ", + Ui: c.Ui, + } + + flags := c.Meta.FlagSet("eval-monitor", FlagSetClient) + flags.Usage = func() { c.Ui.Output(c.Help()) } + if err := flags.Parse(args); err != nil { + return 1 + } + + // Check that we got exactly one eval ID + args = flags.Args() + if len(args) != 1 { + c.Ui.Error(c.Help()) + return 1 + } + evalID := args[0] + + // Get the HTTP client + client, err := c.Meta.Client() + if err != nil { + c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) + return 1 + } + + // Start monitoring + mon := newMonitor(c.Ui, client) + return mon.monitor(evalID) +} diff --git a/command/eval_monitor_test.go b/command/eval_monitor_test.go new file mode 100644 index 000000000..a7c341252 --- /dev/null +++ b/command/eval_monitor_test.go @@ -0,0 +1,46 @@ +package command + +import ( + "strings" + "testing" + + "github.com/mitchellh/cli" +) + +func TestEvalMonitorCommand_Implements(t *testing.T) { + var _ cli.Command = &EvalMonitorCommand{} +} + +func TestEvalMonitorCommand_Fails(t *testing.T) { + srv, _, url := testServer(t, nil) + defer srv.Stop() + + ui := new(cli.MockUi) + cmd := &EvalMonitorCommand{Meta: Meta{Ui: ui}} + + // Fails on misuse + if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 { + t.Fatalf("expected exit code 1, got: %d", code) + } + if out := ui.ErrorWriter.String(); !strings.Contains(out, cmd.Help()) { + t.Fatalf("expected help output, got: %s", out) + } + ui.ErrorWriter.Reset() + + // Fails on eval lookup failure + if code := cmd.Run([]string{"-address=" + url, "3E55C771-76FC-423B-BCED-3E5314F433B1"}); code != 1 { + t.Fatalf("expect exit 1, got: %d", code) + } + if out := ui.ErrorWriter.String(); !strings.Contains(out, "not found") { + t.Fatalf("expect not found error, got: %s", out) + } + ui.ErrorWriter.Reset() + + // Fails on connection failure + if code := cmd.Run([]string{"-address=nope", "nope"}); code != 1 { + t.Fatalf("expected exit code 1, got: %d", code) + } + if out := ui.ErrorWriter.String(); !strings.Contains(out, "Error reading evaluation") { + t.Fatalf("expected failed query error, got: %s", out) + } +}