use subcommands

This commit is contained in:
Alex Dadgar 2018-03-20 17:37:28 -07:00
parent d7f246efe1
commit b5bee9e06b
31 changed files with 320 additions and 147 deletions

19
command/alloc.go Normal file
View File

@ -0,0 +1,19 @@
package command
import "github.com/mitchellh/cli"
type AllocCommand struct {
Meta
}
func (f *AllocCommand) Help() string {
return "This command is accessed by using one of the subcommands below."
}
func (f *AllocCommand) Synopsis() string {
return "Interact with allocations"
}
func (f *AllocCommand) Run(args []string) int {
return cli.RunResultHelp
}

View File

@ -22,7 +22,7 @@ type AllocStatusCommand struct {
func (c *AllocStatusCommand) Help() string {
helpText := `
Usage: nomad alloc-status [options] <allocation>
Usage: nomad alloc status [options] <allocation>
Display information about existing allocations and its tasks. This command can
be used to inspect the current status of an allocation, including its running
@ -87,7 +87,7 @@ func (c *AllocStatusCommand) Run(args []string) int {
var short, displayStats, verbose, json bool
var tmpl string
flags := c.Meta.FlagSet("alloc-status", FlagSetClient)
flags := c.Meta.FlagSet("alloc status", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&short, "short", false, "")
flags.BoolVar(&verbose, "verbose", false, "")

View File

@ -7,20 +7,20 @@ import (
"github.com/posener/complete"
)
type ClientConfigCommand struct {
type NodeConfigCommand struct {
Meta
}
func (c *ClientConfigCommand) Help() string {
func (c *NodeConfigCommand) Help() string {
helpText := `
Usage: nomad client-config [options]
Usage: nomad node config [options]
View or modify client configuration details. This command only
works on client nodes, and can be used to update the running
client configurations it supports.
View or modify a client node's configuration details. This command only works
on client nodes, and can be used to update the running client configurations
it supports.
The arguments behave differently depending on the flags given.
See each flag's description for its specific requirements.
The arguments behave differently depending on the flags given. See each
flag's description for its specific requirements.
General Options:
@ -41,19 +41,19 @@ Client Config Options:
to configure. The set is updated atomically.
Example:
$ nomad client-config -update-servers foo:4647 bar:4647
$ nomad node config -update-servers foo:4647 bar:4647
`
return strings.TrimSpace(helpText)
}
func (c *ClientConfigCommand) Synopsis() string {
func (c *NodeConfigCommand) Synopsis() string {
return "View or modify client configuration details"
}
func (c *ClientConfigCommand) Run(args []string) int {
func (c *NodeConfigCommand) Run(args []string) int {
var listServers, updateServers bool
flags := c.Meta.FlagSet("client-servers", FlagSetClient)
flags := c.Meta.FlagSet("node config", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&listServers, "servers", false, "")
flags.BoolVar(&updateServers, "update-servers", false, "")
@ -111,7 +111,7 @@ func (c *ClientConfigCommand) Run(args []string) int {
return 1
}
func (c *ClientConfigCommand) AutocompleteFlags() complete.Flags {
func (c *NodeConfigCommand) AutocompleteFlags() complete.Flags {
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"-servers": complete.PredictNothing,
@ -119,6 +119,6 @@ func (c *ClientConfigCommand) AutocompleteFlags() complete.Flags {
})
}
func (c *ClientConfigCommand) AutocompleteArgs() complete.Predictor {
func (c *NodeConfigCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictNothing
}

View File

@ -10,7 +10,7 @@ import (
func TestClientConfigCommand_Implements(t *testing.T) {
t.Parallel()
var _ cli.Command = &ClientConfigCommand{}
var _ cli.Command = &NodeConfigCommand{}
}
func TestClientConfigCommand_UpdateServers(t *testing.T) {
@ -21,7 +21,7 @@ func TestClientConfigCommand_UpdateServers(t *testing.T) {
defer srv.Shutdown()
ui := new(cli.MockUi)
cmd := &ClientConfigCommand{Meta: Meta{Ui: ui}}
cmd := &NodeConfigCommand{Meta: Meta{Ui: ui}}
// Fails if trying to update with no servers
code := cmd.Run([]string{"-update-servers"})
@ -49,7 +49,7 @@ func TestClientConfigCommand_UpdateServers(t *testing.T) {
func TestClientConfigCommand_Fails(t *testing.T) {
t.Parallel()
ui := new(cli.MockUi)
cmd := &ClientConfigCommand{Meta: Meta{Ui: ui}}
cmd := &NodeConfigCommand{Meta: Meta{Ui: ui}}
// Fails on misuse
if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 {

19
command/eval.go Normal file
View File

@ -0,0 +1,19 @@
package command
import "github.com/mitchellh/cli"
type EvalCommand struct {
Meta
}
func (f *EvalCommand) Help() string {
return "This command is accessed by using one of the subcommands below."
}
func (f *EvalCommand) Synopsis() string {
return "Interact with evaluations"
}
func (f *EvalCommand) Run(args []string) int {
return cli.RunResultHelp
}

View File

@ -16,7 +16,7 @@ type EvalStatusCommand struct {
func (c *EvalStatusCommand) Help() string {
helpText := `
Usage: nomad eval-status [options] <evaluation>
Usage: nomad eval status [options] <evaluation>
Display information about evaluations. This command can be used to inspect the
current status of an evaluation as well as determine the reason an evaluation
@ -81,7 +81,7 @@ func (c *EvalStatusCommand) Run(args []string) int {
var monitor, verbose, json bool
var tmpl string
flags := c.Meta.FlagSet("eval-status", FlagSetClient)
flags := c.Meta.FlagSet("eval status", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&monitor, "monitor", false, "")
flags.BoolVar(&verbose, "verbose", false, "")

View File

@ -27,13 +27,13 @@ const (
defaultTailLines int64 = 10
)
type FSCommand struct {
type AllocFSCommand struct {
Meta
}
func (f *FSCommand) Help() string {
func (f *AllocFSCommand) Help() string {
helpText := `
Usage: nomad fs [options] <allocation> <path>
Usage: nomad alloc fs [options] <allocation> <path>
fs displays either the contents of an allocation directory for the passed allocation,
or displays the file at the given path. The path is relative to the root of the alloc
@ -75,11 +75,11 @@ FS Specific Options:
return strings.TrimSpace(helpText)
}
func (f *FSCommand) Synopsis() string {
func (f *AllocFSCommand) Synopsis() string {
return "Inspect the contents of an allocation directory"
}
func (c *FSCommand) AutocompleteFlags() complete.Flags {
func (c *AllocFSCommand) AutocompleteFlags() complete.Flags {
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"-H": complete.PredictNothing,
@ -93,7 +93,7 @@ func (c *FSCommand) AutocompleteFlags() complete.Flags {
})
}
func (f *FSCommand) AutocompleteArgs() complete.Predictor {
func (f *AllocFSCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictFunc(func(a complete.Args) []string {
client, err := f.Meta.Client()
if err != nil {
@ -108,11 +108,11 @@ func (f *FSCommand) AutocompleteArgs() complete.Predictor {
})
}
func (f *FSCommand) Run(args []string) int {
func (f *AllocFSCommand) Run(args []string) int {
var verbose, machine, job, stat, tail, follow bool
var numLines, numBytes int64
flags := f.Meta.FlagSet("fs", FlagSetClient)
flags := f.Meta.FlagSet("alloc fs", FlagSetClient)
flags.Usage = func() { f.Ui.Output(f.Help()) }
flags.BoolVar(&verbose, "verbose", false, "")
flags.BoolVar(&machine, "H", false, "")
@ -333,7 +333,7 @@ func (f *FSCommand) Run(args []string) int {
// followFile outputs the contents of the file to stdout relative to the end of
// the file. If numLines does not equal -1, then tail -n behavior is used.
func (f *FSCommand) followFile(client *api.Client, alloc *api.Allocation,
func (f *AllocFSCommand) followFile(client *api.Client, alloc *api.Allocation,
path, origin string, offset, numLines int64) (io.ReadCloser, error) {
cancel := make(chan struct{})

View File

@ -13,7 +13,7 @@ import (
func TestFSCommand_Implements(t *testing.T) {
t.Parallel()
var _ cli.Command = &FSCommand{}
var _ cli.Command = &AllocFSCommand{}
}
func TestFSCommand_Fails(t *testing.T) {
@ -22,7 +22,7 @@ func TestFSCommand_Fails(t *testing.T) {
defer srv.Shutdown()
ui := new(cli.MockUi)
cmd := &FSCommand{Meta: Meta{Ui: ui}}
cmd := &AllocFSCommand{Meta: Meta{Ui: ui}}
// Fails on lack of job ID
if code := cmd.Run([]string{"-job"}); code != 1 {
@ -95,7 +95,7 @@ func TestFSCommand_AutocompleteArgs(t *testing.T) {
defer srv.Shutdown()
ui := new(cli.MockUi)
cmd := &FSCommand{Meta: Meta{Ui: ui, flagAddress: url}}
cmd := &AllocFSCommand{Meta: Meta{Ui: ui, flagAddress: url}}
// Create a fake alloc
state := srv.Agent.Server().State()

View File

@ -13,15 +13,15 @@ const (
DefaultInitName = "example.nomad"
)
// InitCommand generates a new job template that you can customize to your
// JobInitCommand generates a new job template that you can customize to your
// liking, like vagrant init
type InitCommand struct {
type JobInitCommand struct {
Meta
}
func (c *InitCommand) Help() string {
func (c *JobInitCommand) Help() string {
helpText := `
Usage: nomad init
Usage: nomad job init
Creates an example job file that can be used as a starting
point to customize further.
@ -29,11 +29,11 @@ Usage: nomad init
return strings.TrimSpace(helpText)
}
func (c *InitCommand) Synopsis() string {
func (c *JobInitCommand) Synopsis() string {
return "Create an example job file"
}
func (c *InitCommand) Run(args []string) int {
func (c *JobInitCommand) Run(args []string) int {
// Check for misuse
if len(args) != 0 {
c.Ui.Error(c.Help())

View File

@ -11,13 +11,13 @@ import (
func TestInitCommand_Implements(t *testing.T) {
t.Parallel()
var _ cli.Command = &InitCommand{}
var _ cli.Command = &JobInitCommand{}
}
func TestInitCommand_Run(t *testing.T) {
t.Parallel()
ui := new(cli.MockUi)
cmd := &InitCommand{Meta: Meta{Ui: ui}}
cmd := &JobInitCommand{Meta: Meta{Ui: ui}}
// Fails on misuse
if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 {

View File

@ -9,13 +9,13 @@ import (
"github.com/posener/complete"
)
type InspectCommand struct {
type JobInspectCommand struct {
Meta
}
func (c *InspectCommand) Help() string {
func (c *JobInspectCommand) Help() string {
helpText := `
Usage: nomad inspect [options] <job>
Usage: nomad job inspect [options] <job>
Inspect is used to see the specification of a submitted job.
@ -37,11 +37,11 @@ Inspect Options:
return strings.TrimSpace(helpText)
}
func (c *InspectCommand) Synopsis() string {
func (c *JobInspectCommand) Synopsis() string {
return "Inspect a submitted job"
}
func (c *InspectCommand) AutocompleteFlags() complete.Flags {
func (c *JobInspectCommand) AutocompleteFlags() complete.Flags {
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"-version": complete.PredictAnything,
@ -50,7 +50,7 @@ func (c *InspectCommand) AutocompleteFlags() complete.Flags {
})
}
func (c *InspectCommand) AutocompleteArgs() complete.Predictor {
func (c *JobInspectCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictFunc(func(a complete.Args) []string {
client, err := c.Meta.Client()
if err != nil {
@ -65,11 +65,11 @@ func (c *InspectCommand) AutocompleteArgs() complete.Predictor {
})
}
func (c *InspectCommand) Run(args []string) int {
func (c *JobInspectCommand) Run(args []string) int {
var json bool
var tmpl, versionStr string
flags := c.Meta.FlagSet("inspect", FlagSetClient)
flags := c.Meta.FlagSet("job inspect", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&json, "json", false, "")
flags.StringVar(&tmpl, "t", "", "")

View File

@ -12,7 +12,7 @@ import (
func TestInspectCommand_Implements(t *testing.T) {
t.Parallel()
var _ cli.Command = &InspectCommand{}
var _ cli.Command = &JobInspectCommand{}
}
func TestInspectCommand_Fails(t *testing.T) {
@ -21,7 +21,7 @@ func TestInspectCommand_Fails(t *testing.T) {
defer srv.Shutdown()
ui := new(cli.MockUi)
cmd := &InspectCommand{Meta: Meta{Ui: ui}}
cmd := &JobInspectCommand{Meta: Meta{Ui: ui}}
// Fails on misuse
if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 {
@ -67,7 +67,7 @@ func TestInspectCommand_AutocompleteArgs(t *testing.T) {
defer srv.Shutdown()
ui := new(cli.MockUi)
cmd := &InspectCommand{Meta: Meta{Ui: ui, flagAddress: url}}
cmd := &JobInspectCommand{Meta: Meta{Ui: ui, flagAddress: url}}
state := srv.Agent.Server().State()
j := mock.Job()

View File

@ -7,19 +7,19 @@ import (
"strings"
)
// KeygenCommand is a Command implementation that generates an encryption
// OperatorKeygenCommand is a Command implementation that generates an encryption
// key for use in `nomad agent`.
type KeygenCommand struct {
type OperatorKeygenCommand struct {
Meta
}
func (c *KeygenCommand) Synopsis() string {
func (c *OperatorKeygenCommand) Synopsis() string {
return "Generates a new encryption key"
}
func (c *KeygenCommand) Help() string {
func (c *OperatorKeygenCommand) Help() string {
helpText := `
Usage: nomad keygen
Usage: nomad operator keygen
Generates a new encryption key that can be used to configure the
agent to encrypt traffic. The output of this command is already
@ -28,7 +28,7 @@ Usage: nomad keygen
return strings.TrimSpace(helpText)
}
func (c *KeygenCommand) Run(_ []string) int {
func (c *OperatorKeygenCommand) Run(_ []string) int {
key := make([]byte, 16)
n, err := rand.Reader.Read(key)
if err != nil {

View File

@ -10,7 +10,7 @@ import (
func TestKeygenCommand(t *testing.T) {
t.Parallel()
ui := new(cli.MockUi)
c := &KeygenCommand{Meta: Meta{Ui: ui}}
c := &OperatorKeygenCommand{Meta: Meta{Ui: ui}}
code := c.Run(nil)
if code != 0 {
t.Fatalf("bad: %d", code)

View File

@ -9,15 +9,15 @@ import (
"github.com/posener/complete"
)
// KeyringCommand is a Command implementation that handles querying, installing,
// OperatorKeyringCommand is a Command implementation that handles querying, installing,
// and removing gossip encryption keys from a keyring.
type KeyringCommand struct {
type OperatorKeyringCommand struct {
Meta
}
func (c *KeyringCommand) Help() string {
func (c *OperatorKeyringCommand) Help() string {
helpText := `
Usage: nomad keyring [options]
Usage: nomad operator keyring [options]
Manages encryption keys used for gossip messages between Nomad servers. Gossip
encryption is optional. When enabled, this command may be used to examine
@ -50,11 +50,11 @@ Keyring Options:
return strings.TrimSpace(helpText)
}
func (c *KeyringCommand) Synopsis() string {
func (c *OperatorKeyringCommand) Synopsis() string {
return "Manages gossip layer encryption keys"
}
func (c *KeyringCommand) AutocompleteFlags() complete.Flags {
func (c *OperatorKeyringCommand) AutocompleteFlags() complete.Flags {
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"-install": complete.PredictAnything,
@ -63,15 +63,15 @@ func (c *KeyringCommand) AutocompleteFlags() complete.Flags {
"-use": complete.PredictAnything,
})
}
func (c *KeyringCommand) AutocompleteArgs() complete.Predictor {
func (c *OperatorKeyringCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictNothing
}
func (c *KeyringCommand) Run(args []string) int {
func (c *OperatorKeyringCommand) Run(args []string) int {
var installKey, useKey, removeKey string
var listKeys bool
flags := c.Meta.FlagSet("keys", FlagSetClient)
flags := c.Meta.FlagSet("operator-keyring", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.StringVar(&installKey, "install", "", "install key")
@ -158,7 +158,7 @@ func (c *KeyringCommand) Run(args []string) int {
return 0
}
func (c *KeyringCommand) handleKeyResponse(resp *api.KeyringResponse) {
func (c *OperatorKeyringCommand) handleKeyResponse(resp *api.KeyringResponse) {
out := make([]string, len(resp.Keys)+1)
out[0] = "Key"
i := 1

View File

@ -14,13 +14,13 @@ import (
"github.com/posener/complete"
)
type LogsCommand struct {
type AllocLogsCommand struct {
Meta
}
func (l *LogsCommand) Help() string {
func (l *AllocLogsCommand) Help() string {
helpText := `
Usage: nomad logs [options] <allocation> <task>
Usage: nomad alloc logs [options] <allocation> <task>
Streams the stdout/stderr of the given allocation and task.
@ -57,11 +57,11 @@ Logs Specific Options:
return strings.TrimSpace(helpText)
}
func (l *LogsCommand) Synopsis() string {
func (l *AllocLogsCommand) Synopsis() string {
return "Streams the logs of a task."
}
func (c *LogsCommand) AutocompleteFlags() complete.Flags {
func (c *AllocLogsCommand) AutocompleteFlags() complete.Flags {
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"-stderr": complete.PredictNothing,
@ -74,7 +74,7 @@ func (c *LogsCommand) AutocompleteFlags() complete.Flags {
})
}
func (l *LogsCommand) AutocompleteArgs() complete.Predictor {
func (l *AllocLogsCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictFunc(func(a complete.Args) []string {
client, err := l.Meta.Client()
if err != nil {
@ -89,11 +89,11 @@ func (l *LogsCommand) AutocompleteArgs() complete.Predictor {
})
}
func (l *LogsCommand) Run(args []string) int {
func (l *AllocLogsCommand) Run(args []string) int {
var verbose, job, tail, stderr, follow bool
var numLines, numBytes int64
flags := l.Meta.FlagSet("logs", FlagSetClient)
flags := l.Meta.FlagSet("alloc logs", FlagSetClient)
flags.Usage = func() { l.Ui.Output(l.Help()) }
flags.BoolVar(&verbose, "verbose", false, "")
flags.BoolVar(&job, "job", false, "")
@ -262,7 +262,7 @@ func (l *LogsCommand) Run(args []string) int {
// followFile outputs the contents of the file to stdout relative to the end of
// the file.
func (l *LogsCommand) followFile(client *api.Client, alloc *api.Allocation,
func (l *AllocLogsCommand) followFile(client *api.Client, alloc *api.Allocation,
follow bool, task, logType, origin string, offset int64) (io.ReadCloser, error) {
cancel := make(chan struct{})

View File

@ -13,7 +13,7 @@ import (
func TestLogsCommand_Implements(t *testing.T) {
t.Parallel()
var _ cli.Command = &LogsCommand{}
var _ cli.Command = &AllocLogsCommand{}
}
func TestLogsCommand_Fails(t *testing.T) {
@ -22,7 +22,7 @@ func TestLogsCommand_Fails(t *testing.T) {
defer srv.Shutdown()
ui := new(cli.MockUi)
cmd := &LogsCommand{Meta: Meta{Ui: ui}}
cmd := &AllocLogsCommand{Meta: Meta{Ui: ui}}
// Fails on misuse
if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 {
@ -77,7 +77,7 @@ func TestLogsCommand_AutocompleteArgs(t *testing.T) {
defer srv.Shutdown()
ui := new(cli.MockUi)
cmd := &LogsCommand{Meta: Meta{Ui: ui, flagAddress: url}}
cmd := &AllocLogsCommand{Meta: Meta{Ui: ui, flagAddress: url}}
// Create a fake alloc
state := srv.Agent.Server().State()

View File

@ -22,14 +22,14 @@ changed, another user has modified the job and the plan's results are
potentially invalid.`
)
type PlanCommand struct {
type JobPlanCommand struct {
Meta
JobGetter
}
func (c *PlanCommand) Help() string {
func (c *JobPlanCommand) Help() string {
helpText := `
Usage: nomad plan [options] <path>
Usage: nomad job plan [options] <path>
Plan invokes a dry-run of the scheduler to determine the effects of submitting
either a new or updated version of a job. The plan will not result in any
@ -75,11 +75,11 @@ Plan Options:
return strings.TrimSpace(helpText)
}
func (c *PlanCommand) Synopsis() string {
func (c *JobPlanCommand) Synopsis() string {
return "Dry-run a job update to determine its effects"
}
func (c *PlanCommand) AutocompleteFlags() complete.Flags {
func (c *JobPlanCommand) AutocompleteFlags() complete.Flags {
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"-diff": complete.PredictNothing,
@ -88,14 +88,14 @@ func (c *PlanCommand) AutocompleteFlags() complete.Flags {
})
}
func (c *PlanCommand) AutocompleteArgs() complete.Predictor {
func (c *JobPlanCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictOr(complete.PredictFiles("*.nomad"), complete.PredictFiles("*.hcl"))
}
func (c *PlanCommand) Run(args []string) int {
func (c *JobPlanCommand) Run(args []string) int {
var diff, policyOverride, verbose bool
flags := c.Meta.FlagSet("plan", FlagSetClient)
flags := c.Meta.FlagSet("job plan", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&diff, "diff", true, "")
flags.BoolVar(&policyOverride, "policy-override", false, "")

View File

@ -13,13 +13,13 @@ import (
func TestPlanCommand_Implements(t *testing.T) {
t.Parallel()
var _ cli.Command = &RunCommand{}
var _ cli.Command = &JobRunCommand{}
}
func TestPlanCommand_Fails(t *testing.T) {
t.Parallel()
ui := new(cli.MockUi)
cmd := &PlanCommand{Meta: Meta{Ui: ui}}
cmd := &JobPlanCommand{Meta: Meta{Ui: ui}}
// Create a server
s := testutil.NewTestServer(t, nil)
@ -118,7 +118,7 @@ func TestPlanCommand_From_STDIN(t *testing.T) {
}
ui := new(cli.MockUi)
cmd := &PlanCommand{
cmd := &JobPlanCommand{
Meta: Meta{Ui: ui},
JobGetter: JobGetter{testStdin: stdinR},
}
@ -156,7 +156,7 @@ job "job1" {
func TestPlanCommand_From_URL(t *testing.T) {
t.Parallel()
ui := new(cli.MockUi)
cmd := &PlanCommand{
cmd := &JobPlanCommand{
Meta: Meta{Ui: ui},
}

View File

@ -19,14 +19,14 @@ var (
enforceIndexRegex = regexp.MustCompile(`\((Enforcing job modify index.*)\)`)
)
type RunCommand struct {
type JobRunCommand struct {
Meta
JobGetter
}
func (c *RunCommand) Help() string {
func (c *JobRunCommand) Help() string {
helpText := `
Usage: nomad run [options] <path>
Usage: nomad job run [options] <path>
Starts running a new job or updates an existing job using
the specification located at <path>. This is the main command
@ -93,11 +93,11 @@ Run Options:
return strings.TrimSpace(helpText)
}
func (c *RunCommand) Synopsis() string {
func (c *JobRunCommand) Synopsis() string {
return "Run a new job or update an existing job"
}
func (c *RunCommand) AutocompleteFlags() complete.Flags {
func (c *JobRunCommand) AutocompleteFlags() complete.Flags {
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"-check-index": complete.PredictNothing,
@ -109,15 +109,15 @@ func (c *RunCommand) AutocompleteFlags() complete.Flags {
})
}
func (c *RunCommand) AutocompleteArgs() complete.Predictor {
func (c *JobRunCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictOr(complete.PredictFiles("*.nomad"), complete.PredictFiles("*.hcl"))
}
func (c *RunCommand) Run(args []string) int {
func (c *JobRunCommand) Run(args []string) int {
var detach, verbose, output, override bool
var checkIndexStr, vaultToken string
flags := c.Meta.FlagSet("run", FlagSetClient)
flags := c.Meta.FlagSet("job run", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&detach, "detach", false, "")
flags.BoolVar(&verbose, "verbose", false, "")

View File

@ -13,13 +13,13 @@ import (
func TestRunCommand_Implements(t *testing.T) {
t.Parallel()
var _ cli.Command = &RunCommand{}
var _ cli.Command = &JobRunCommand{}
}
func TestRunCommand_Output_Json(t *testing.T) {
t.Parallel()
ui := new(cli.MockUi)
cmd := &RunCommand{Meta: Meta{Ui: ui}}
cmd := &JobRunCommand{Meta: Meta{Ui: ui}}
fh, err := ioutil.TempFile("", "nomad")
if err != nil {
@ -55,7 +55,7 @@ job "job1" {
func TestRunCommand_Fails(t *testing.T) {
t.Parallel()
ui := new(cli.MockUi)
cmd := &RunCommand{Meta: Meta{Ui: ui}}
cmd := &JobRunCommand{Meta: Meta{Ui: ui}}
// Create a server
s := testutil.NewTestServer(t, nil)
@ -164,7 +164,7 @@ func TestRunCommand_From_STDIN(t *testing.T) {
}
ui := new(cli.MockUi)
cmd := &RunCommand{
cmd := &JobRunCommand{
Meta: Meta{Ui: ui},
JobGetter: JobGetter{testStdin: stdinR},
}
@ -202,7 +202,7 @@ job "job1" {
func TestRunCommand_From_URL(t *testing.T) {
t.Parallel()
ui := new(cli.MockUi)
cmd := &RunCommand{
cmd := &JobRunCommand{
Meta: Meta{Ui: ui},
}

19
command/server.go Normal file
View File

@ -0,0 +1,19 @@
package command
import "github.com/mitchellh/cli"
type ServerCommand struct {
Meta
}
func (f *ServerCommand) Help() string {
return "This command is accessed by using one of the subcommands below."
}
func (f *ServerCommand) Synopsis() string {
return "Interact with servers"
}
func (f *ServerCommand) Run(args []string) int {
return cli.RunResultHelp
}

View File

@ -11,7 +11,7 @@ type ServerForceLeaveCommand struct {
func (c *ServerForceLeaveCommand) Help() string {
helpText := `
Usage: nomad server-force-leave [options] <node>
Usage: nomad server force-leave [options] <node>
Forces an server to enter the "left" state. This can be used to
eject nodes which have failed and will not rejoin the cluster.

View File

@ -11,7 +11,7 @@ type ServerJoinCommand struct {
func (c *ServerJoinCommand) Help() string {
helpText := `
Usage: nomad server-join [options] <addr> [<addr>...]
Usage: nomad server join [options] <addr> [<addr>...]
Joins the local server to one or more Nomad servers. Joining is
only required for server nodes, and only needs to succeed

View File

@ -17,7 +17,7 @@ type ServerMembersCommand struct {
func (c *ServerMembersCommand) Help() string {
helpText := `
Usage: nomad server-members [options]
Usage: nomad server members [options]
Display a list of the known servers and their status. Only Nomad servers are
able to service this command.

View File

@ -8,13 +8,13 @@ import (
"github.com/posener/complete"
)
type StopCommand struct {
type JobStopCommand struct {
Meta
}
func (c *StopCommand) Help() string {
func (c *JobStopCommand) Help() string {
helpText := `
Usage: nomad stop [options] <job>
Usage: nomad job stop [options] <job>
Stop an existing job. This command is used to signal allocations
to shut down for the given job ID. Upon successful deregistration,
@ -47,11 +47,11 @@ Stop Options:
return strings.TrimSpace(helpText)
}
func (c *StopCommand) Synopsis() string {
func (c *JobStopCommand) Synopsis() string {
return "Stop a running job"
}
func (c *StopCommand) AutocompleteFlags() complete.Flags {
func (c *JobStopCommand) AutocompleteFlags() complete.Flags {
return mergeAutocompleteFlags(c.Meta.AutocompleteFlags(FlagSetClient),
complete.Flags{
"-detach": complete.PredictNothing,
@ -61,7 +61,7 @@ func (c *StopCommand) AutocompleteFlags() complete.Flags {
})
}
func (c *StopCommand) AutocompleteArgs() complete.Predictor {
func (c *JobStopCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictFunc(func(a complete.Args) []string {
client, err := c.Meta.Client()
if err != nil {
@ -76,10 +76,10 @@ func (c *StopCommand) AutocompleteArgs() complete.Predictor {
})
}
func (c *StopCommand) Run(args []string) int {
func (c *JobStopCommand) Run(args []string) int {
var detach, purge, verbose, autoYes bool
flags := c.Meta.FlagSet("stop", FlagSetClient)
flags := c.Meta.FlagSet("job stop", FlagSetClient)
flags.Usage = func() { c.Ui.Output(c.Help()) }
flags.BoolVar(&detach, "detach", false, "")
flags.BoolVar(&verbose, "verbose", false, "")

View File

@ -12,7 +12,7 @@ import (
func TestStopCommand_Implements(t *testing.T) {
t.Parallel()
var _ cli.Command = &StopCommand{}
var _ cli.Command = &JobStopCommand{}
}
func TestStopCommand_Fails(t *testing.T) {
@ -21,7 +21,7 @@ func TestStopCommand_Fails(t *testing.T) {
defer srv.Shutdown()
ui := new(cli.MockUi)
cmd := &StopCommand{Meta: Meta{Ui: ui}}
cmd := &JobStopCommand{Meta: Meta{Ui: ui}}
// Fails on misuse
if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 {
@ -58,7 +58,7 @@ func TestStopCommand_AutocompleteArgs(t *testing.T) {
defer srv.Shutdown()
ui := new(cli.MockUi)
cmd := &StopCommand{Meta: Meta{Ui: ui, flagAddress: url}}
cmd := &JobStopCommand{Meta: Meta{Ui: ui, flagAddress: url}}
// Create a fake job
state := srv.Agent.Server().State()

View File

@ -11,14 +11,14 @@ import (
"github.com/posener/complete"
)
type ValidateCommand struct {
type JobValidateCommand struct {
Meta
JobGetter
}
func (c *ValidateCommand) Help() string {
func (c *JobValidateCommand) Help() string {
helpText := `
Usage: nomad validate [options] <path>
Usage: nomad job validate [options] <path>
Checks if a given HCL job file has a valid specification. This can be used to
check for any syntax errors or validation problems with a job.
@ -30,20 +30,20 @@ Usage: nomad validate [options] <path>
return strings.TrimSpace(helpText)
}
func (c *ValidateCommand) Synopsis() string {
func (c *JobValidateCommand) Synopsis() string {
return "Checks if a given job specification is valid"
}
func (c *ValidateCommand) AutocompleteFlags() complete.Flags {
func (c *JobValidateCommand) AutocompleteFlags() complete.Flags {
return nil
}
func (c *ValidateCommand) AutocompleteArgs() complete.Predictor {
func (c *JobValidateCommand) AutocompleteArgs() complete.Predictor {
return complete.PredictOr(complete.PredictFiles("*.nomad"), complete.PredictFiles("*.hcl"))
}
func (c *ValidateCommand) Run(args []string) int {
flags := c.Meta.FlagSet("validate", FlagSetNone)
func (c *JobValidateCommand) Run(args []string) int {
flags := c.Meta.FlagSet("job validate", FlagSetNone)
flags.Usage = func() { c.Ui.Output(c.Help()) }
if err := flags.Parse(args); err != nil {
return 1
@ -110,7 +110,7 @@ func (c *ValidateCommand) Run(args []string) int {
}
// validateLocal validates without talking to a Nomad agent
func (c *ValidateCommand) validateLocal(aj *api.Job) (*api.JobValidateResponse, error) {
func (c *JobValidateCommand) validateLocal(aj *api.Job) (*api.JobValidateResponse, error) {
var out api.JobValidateResponse
job := agent.ApiJobToStructJob(aj)

View File

@ -13,13 +13,13 @@ import (
func TestValidateCommand_Implements(t *testing.T) {
t.Parallel()
var _ cli.Command = &ValidateCommand{}
var _ cli.Command = &JobValidateCommand{}
}
func TestValidateCommand(t *testing.T) {
t.Parallel()
ui := new(cli.MockUi)
cmd := &ValidateCommand{Meta: Meta{Ui: ui}}
cmd := &JobValidateCommand{Meta: Meta{Ui: ui}}
// Create a server
s := testutil.NewTestServer(t, nil)
@ -60,7 +60,7 @@ job "job1" {
func TestValidateCommand_Fails(t *testing.T) {
t.Parallel()
ui := new(cli.MockUi)
cmd := &ValidateCommand{Meta: Meta{Ui: ui}}
cmd := &JobValidateCommand{Meta: Meta{Ui: ui}}
// Fails on misuse
if code := cmd.Run([]string{"some", "bad", "args"}); code != 1 {
@ -123,7 +123,7 @@ func TestValidateCommand_From_STDIN(t *testing.T) {
}
ui := new(cli.MockUi)
cmd := &ValidateCommand{
cmd := &JobValidateCommand{
Meta: Meta{Ui: ui},
JobGetter: JobGetter{testStdin: stdinR},
}
@ -164,7 +164,7 @@ job "job1" {
func TestValidateCommand_From_URL(t *testing.T) {
t.Parallel()
ui := new(cli.MockUi)
cmd := &RunCommand{
cmd := &JobRunCommand{
Meta: Meta{Ui: ui},
}

View File

@ -91,6 +91,26 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
Meta: meta,
}, nil
},
"alloc": func() (cli.Command, error) {
return &command.AllocCommand{
Meta: meta,
}, nil
},
"alloc fs": func() (cli.Command, error) {
return &command.AllocFSCommand{
Meta: meta,
}, nil
},
"alloc logs": func() (cli.Command, error) {
return &command.AllocLogsCommand{
Meta: meta,
}, nil
},
"alloc status": func() (cli.Command, error) {
return &command.AllocStatusCommand{
Meta: meta,
}, nil
},
"alloc-status": func() (cli.Command, error) {
return &command.AllocStatusCommand{
Meta: meta,
@ -114,7 +134,7 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
}, nil
},
"client-config": func() (cli.Command, error) {
return &command.ClientConfigCommand{
return &command.NodeConfigCommand{
Meta: meta,
}, nil
},
@ -153,6 +173,16 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
Meta: meta,
}, nil
},
"eval": func() (cli.Command, error) {
return &command.EvalCommand{
Meta: meta,
}, nil
},
"eval status": func() (cli.Command, error) {
return &command.EvalStatusCommand{
Meta: meta,
}, nil
},
"eval-status": func() (cli.Command, error) {
return &command.EvalStatusCommand{
Meta: meta,
@ -164,27 +194,27 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
}, nil
},
"fs": func() (cli.Command, error) {
return &command.FSCommand{
return &command.AllocFSCommand{
Meta: meta,
}, nil
},
"init": func() (cli.Command, error) {
return &command.InitCommand{
return &command.JobInitCommand{
Meta: meta,
}, nil
},
"inspect": func() (cli.Command, error) {
return &command.InspectCommand{
return &command.JobInspectCommand{
Meta: meta,
}, nil
},
"keygen": func() (cli.Command, error) {
return &command.KeygenCommand{
return &command.OperatorKeygenCommand{
Meta: meta,
}, nil
},
"keyring": func() (cli.Command, error) {
return &command.KeyringCommand{
return &command.OperatorKeyringCommand{
Meta: meta,
}, nil
},
@ -208,6 +238,21 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
Meta: meta,
}, nil
},
"job init": func() (cli.Command, error) {
return &command.JobInitCommand{
Meta: meta,
}, nil
},
"job inspect": func() (cli.Command, error) {
return &command.JobInspectCommand{
Meta: meta,
}, nil
},
"job plan": func() (cli.Command, error) {
return &command.JobPlanCommand{
Meta: meta,
}, nil
},
"job promote": func() (cli.Command, error) {
return &command.JobPromoteCommand{
Meta: meta,
@ -218,13 +263,28 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
Meta: meta,
}, nil
},
"job run": func() (cli.Command, error) {
return &command.JobRunCommand{
Meta: meta,
}, nil
},
"job status": func() (cli.Command, error) {
return &command.JobStatusCommand{
Meta: meta,
}, nil
},
"job stop": func() (cli.Command, error) {
return &command.JobStopCommand{
Meta: meta,
}, nil
},
"job validate": func() (cli.Command, error) {
return &command.JobValidateCommand{
Meta: meta,
}, nil
},
"logs": func() (cli.Command, error) {
return &command.LogsCommand{
return &command.AllocLogsCommand{
Meta: meta,
}, nil
},
@ -263,6 +323,11 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
Meta: meta,
}, nil
},
"node config": func() (cli.Command, error) {
return &command.NodeConfigCommand{
Meta: meta,
}, nil
},
"node-drain": func() (cli.Command, error) {
return &command.NodeDrainCommand{
Meta: meta,
@ -311,7 +376,16 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
Meta: meta,
}, nil
},
"operator keygen": func() (cli.Command, error) {
return &command.OperatorKeygenCommand{
Meta: meta,
}, nil
},
"operator keyring": func() (cli.Command, error) {
return &command.OperatorKeyringCommand{
Meta: meta,
}, nil
},
"operator raft": func() (cli.Command, error) {
return &command.OperatorRaftCommand{
Meta: meta,
@ -331,7 +405,7 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
},
"plan": func() (cli.Command, error) {
return &command.PlanCommand{
return &command.JobPlanCommand{
Meta: meta,
}, nil
},
@ -379,7 +453,7 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
},
"run": func() (cli.Command, error) {
return &command.RunCommand{
return &command.JobRunCommand{
Meta: meta,
}, nil
},
@ -408,6 +482,26 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
Meta: meta,
}, nil
},
"server": func() (cli.Command, error) {
return &command.ServerCommand{
Meta: meta,
}, nil
},
"server force-leave": func() (cli.Command, error) {
return &command.ServerForceLeaveCommand{
Meta: meta,
}, nil
},
"server join": func() (cli.Command, error) {
return &command.ServerJoinCommand{
Meta: meta,
}, nil
},
"server members": func() (cli.Command, error) {
return &command.ServerMembersCommand{
Meta: meta,
}, nil
},
"server-force-leave": func() (cli.Command, error) {
return &command.ServerForceLeaveCommand{
Meta: meta,
@ -429,7 +523,7 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
}, nil
},
"stop": func() (cli.Command, error) {
return &command.StopCommand{
return &command.JobStopCommand{
Meta: meta,
}, nil
},
@ -439,7 +533,7 @@ func Commands(metaPtr *command.Meta) map[string]cli.CommandFactory {
}, nil
},
"validate": func() (cli.Command, error) {
return &command.ValidateCommand{
return &command.JobValidateCommand{
Meta: meta,
}, nil
},

24
main.go
View File

@ -47,7 +47,29 @@ func RunCustom(args []string, commands map[string]cli.CommandFactory) int {
// users should not be running should be placed here, versus hiding
// subcommands from the main help, which should be filtered out of the
// commands above.
hidden := []string{"check", "executor", "syslog", "node-drain", "node-status"}
hidden := []string{
"check",
"executor",
"syslog",
"alloc-status",
"eval-status",
"node-drain",
"node-status",
"validate",
"plan",
"init",
"inspect",
"run",
"stop",
"keygen",
"keyring",
"server-force-leave",
"server-join",
"server-members",
"fs",
"logs",
"client-config",
}
cli := &cli.CLI{
Name: "nomad",