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.
This commit is contained in:
James Rasell
2020-01-13 11:34:46 +01:00
parent 56937bf87f
commit 0ea8fdfa81
9 changed files with 278 additions and 0 deletions

View File

@@ -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,

35
command/system.go Normal file
View File

@@ -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 <subcommand> [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
}

54
command/system_gc.go Normal file
View File

@@ -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
}

27
command/system_gc_test.go Normal file
View File

@@ -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())
}
}

View File

@@ -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 <subcommand> [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
}

View File

@@ -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
}

View File

@@ -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())
}
}

View File

@@ -0,0 +1,12 @@
package command
import (
"testing"
"github.com/mitchellh/cli"
)
func TestSystemReconcileCommand_Implements(t *testing.T) {
t.Parallel()
var _ cli.Command = &SystemCommand{}
}

12
command/system_test.go Normal file
View File

@@ -0,0 +1,12 @@
package command
import (
"testing"
"github.com/mitchellh/cli"
)
func TestSystemCommand_Implements(t *testing.T) {
t.Parallel()
var _ cli.Command = &SystemCommand{}
}