From 0ea8fdfa81d3ea0413036cd2ec6efd08486a0359 Mon Sep 17 00:00:00 2001 From: James Rasell Date: Mon, 13 Jan 2020 11:34:46 +0100 Subject: [PATCH] cli: add system command and subcmds to interact with system API. The system command includes gc and reconcile-summaries subcommands which covers all currently available system API calls. The help information is largely pulled from the current Nomad website API documentation. --- command/commands.go | 20 ++++++++ command/system.go | 35 ++++++++++++++ command/system_gc.go | 54 ++++++++++++++++++++++ command/system_gc_test.go | 27 +++++++++++ command/system_reconcile.go | 37 +++++++++++++++ command/system_reconcile_summaries.go | 54 ++++++++++++++++++++++ command/system_reconcile_summaries_test.go | 27 +++++++++++ command/system_reconcile_test.go | 12 +++++ command/system_test.go | 12 +++++ 9 files changed, 278 insertions(+) create mode 100644 command/system.go create mode 100644 command/system_gc.go create mode 100644 command/system_gc_test.go create mode 100644 command/system_reconcile.go create mode 100644 command/system_reconcile_summaries.go create mode 100644 command/system_reconcile_summaries_test.go create mode 100644 command/system_reconcile_test.go create mode 100644 command/system_test.go diff --git a/command/commands.go b/command/commands.go index 2c2d3052a..ff2100a9d 100644 --- a/command/commands.go +++ b/command/commands.go @@ -610,6 +610,26 @@ func Commands(metaPtr *Meta, agentUi cli.Ui) map[string]cli.CommandFactory { Meta: meta, }, nil }, + "system": func() (cli.Command, error) { + return &SystemCommand{ + Meta: meta, + }, nil + }, + "system gc": func() (cli.Command, error) { + return &SystemGCCommand{ + Meta: meta, + }, nil + }, + "system reconcile": func() (cli.Command, error) { + return &SystemReconcileCommand{ + Meta: meta, + }, nil + }, + "system reconcile summaries": func() (cli.Command, error) { + return &SystemReconcileSummariesCommand{ + Meta: meta, + }, nil + }, "ui": func() (cli.Command, error) { return &UiCommand{ Meta: meta, diff --git a/command/system.go b/command/system.go new file mode 100644 index 000000000..fe61fa4f5 --- /dev/null +++ b/command/system.go @@ -0,0 +1,35 @@ +package command + +import ( + "strings" + + "github.com/mitchellh/cli" +) + +type SystemCommand struct { + Meta +} + +func (sc *SystemCommand) Help() string { + helpText := ` +Usage: nomad system [options] + + This command groups subcommands for interacting with the system API. Users + can perform system maintenance tasks such as trigger the garbage collector or + perform job summary reconciliation. + + Please see the individual subcommand help for detailed usage information. +` + + return strings.TrimSpace(helpText) +} + +func (sc *SystemCommand) Synopsis() string { + return "Interact with the system API" +} + +func (sc *SystemCommand) Name() string { return "system" } + +func (sc *SystemCommand) Run(args []string) int { + return cli.RunResultHelp +} diff --git a/command/system_gc.go b/command/system_gc.go new file mode 100644 index 000000000..9897f5c95 --- /dev/null +++ b/command/system_gc.go @@ -0,0 +1,54 @@ +package command + +import ( + "fmt" + "strings" + + "github.com/posener/complete" +) + +type SystemGCCommand struct { + Meta +} + +func (c *SystemGCCommand) Help() string { + helpText := ` +Usage: nomad system gc [options] + + Initializes a garbage collection of jobs, evaluations, allocations, and nodes. + +General Options: + + ` + generalOptionsUsage() + return strings.TrimSpace(helpText) +} + +func (c *SystemGCCommand) Synopsis() string { + return "Run the system garbage collection process" +} + +func (c *SystemGCCommand) AutocompleteFlags() complete.Flags { + return c.Meta.AutocompleteFlags(FlagSetClient) +} + +func (c *SystemGCCommand) AutocompleteArgs() complete.Predictor { + return complete.PredictNothing +} + +func (c *SystemGCCommand) Name() string { return "system gc" } + +func (c *SystemGCCommand) Run(args []string) int { + + // Get the HTTP client + client, err := c.Meta.Client() + if err != nil { + c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) + return 1 + } + + if err := client.System().GarbageCollect(); err != nil { + c.Ui.Error(fmt.Sprintf("Error running system garbage-collection: %s", err)) + return 1 + } + return 0 +} diff --git a/command/system_gc_test.go b/command/system_gc_test.go new file mode 100644 index 000000000..89b11cfd2 --- /dev/null +++ b/command/system_gc_test.go @@ -0,0 +1,27 @@ +package command + +import ( + "testing" + + "github.com/mitchellh/cli" +) + +func TestSystemGCCommand_Implements(t *testing.T) { + t.Parallel() + var _ cli.Command = &SystemGCCommand{} +} + +func TestSystemGCCommand_Good(t *testing.T) { + t.Parallel() + + // Create a server + srv, _, url := testServer(t, true, nil) + defer srv.Shutdown() + + ui := new(cli.MockUi) + cmd := &SystemGCCommand{Meta: Meta{Ui: ui, flagAddress: url}} + + if code := cmd.Run([]string{"-address=" + url}); code != 0 { + t.Fatalf("expected exit 0, got: %d; %v", code, ui.ErrorWriter.String()) + } +} diff --git a/command/system_reconcile.go b/command/system_reconcile.go new file mode 100644 index 000000000..298ea71e7 --- /dev/null +++ b/command/system_reconcile.go @@ -0,0 +1,37 @@ +package command + +import ( + "strings" + + "github.com/mitchellh/cli" +) + +type SystemReconcileCommand struct { + Meta +} + +func (s *SystemReconcileCommand) Help() string { + helpText := ` +Usage: nomad system reconcile [options] + + This command groups subcommands for interacting with the system reconcile API. + + Reconcile the summaries of all registered jobs: + + $ nomad system reconcile summaries + + Please see the individual subcommand help for detailed usage information. +` + + return strings.TrimSpace(helpText) +} + +func (s *SystemReconcileCommand) Synopsis() string { + return "Perform system reconciliation tasks" +} + +func (s *SystemReconcileCommand) Name() string { return "system reconcile" } + +func (s *SystemReconcileCommand) Run(args []string) int { + return cli.RunResultHelp +} diff --git a/command/system_reconcile_summaries.go b/command/system_reconcile_summaries.go new file mode 100644 index 000000000..62fafb667 --- /dev/null +++ b/command/system_reconcile_summaries.go @@ -0,0 +1,54 @@ +package command + +import ( + "fmt" + "strings" + + "github.com/posener/complete" +) + +type SystemReconcileSummariesCommand struct { + Meta +} + +func (c *SystemReconcileSummariesCommand) Help() string { + helpText := ` +Usage: nomad system reconcile summaries [options] + + Reconciles the summaries of all registered jobs. + +General Options: + + ` + generalOptionsUsage() + return strings.TrimSpace(helpText) +} + +func (c *SystemReconcileSummariesCommand) Synopsis() string { + return "Reconciles the summaries of all registered jobs" +} + +func (c *SystemReconcileSummariesCommand) AutocompleteFlags() complete.Flags { + return c.Meta.AutocompleteFlags(FlagSetClient) +} + +func (c *SystemReconcileSummariesCommand) AutocompleteArgs() complete.Predictor { + return complete.PredictNothing +} + +func (c *SystemReconcileSummariesCommand) Name() string { return "system reconcile summaries" } + +func (c *SystemReconcileSummariesCommand) Run(args []string) int { + + // Get the HTTP client + client, err := c.Meta.Client() + if err != nil { + c.Ui.Error(fmt.Sprintf("Error initializing client: %s", err)) + return 1 + } + + if err := client.System().ReconcileSummaries(); err != nil { + c.Ui.Error(fmt.Sprintf("Error running system summary reconciliation: %s", err)) + return 1 + } + return 0 +} diff --git a/command/system_reconcile_summaries_test.go b/command/system_reconcile_summaries_test.go new file mode 100644 index 000000000..3423f4eb6 --- /dev/null +++ b/command/system_reconcile_summaries_test.go @@ -0,0 +1,27 @@ +package command + +import ( + "testing" + + "github.com/mitchellh/cli" +) + +func TestSystemReconcileSummariesCommand_Implements(t *testing.T) { + t.Parallel() + var _ cli.Command = &SystemReconcileSummariesCommand{} +} + +func TestSystemReconcileSummariesCommand_Good(t *testing.T) { + t.Parallel() + + // Create a server + srv, _, url := testServer(t, true, nil) + defer srv.Shutdown() + + ui := new(cli.MockUi) + cmd := &SystemReconcileSummariesCommand{Meta: Meta{Ui: ui, flagAddress: url}} + + if code := cmd.Run([]string{"-address=" + url}); code != 0 { + t.Fatalf("expected exit 0, got: %d; %v", code, ui.ErrorWriter.String()) + } +} diff --git a/command/system_reconcile_test.go b/command/system_reconcile_test.go new file mode 100644 index 000000000..defb5cdc8 --- /dev/null +++ b/command/system_reconcile_test.go @@ -0,0 +1,12 @@ +package command + +import ( + "testing" + + "github.com/mitchellh/cli" +) + +func TestSystemReconcileCommand_Implements(t *testing.T) { + t.Parallel() + var _ cli.Command = &SystemCommand{} +} diff --git a/command/system_test.go b/command/system_test.go new file mode 100644 index 000000000..fa4ca3ceb --- /dev/null +++ b/command/system_test.go @@ -0,0 +1,12 @@ +package command + +import ( + "testing" + + "github.com/mitchellh/cli" +) + +func TestSystemCommand_Implements(t *testing.T) { + t.Parallel() + var _ cli.Command = &SystemCommand{} +}