diff --git a/command/commands.go b/command/commands.go index b735839568..a934fd2922 100644 --- a/command/commands.go +++ b/command/commands.go @@ -8,6 +8,7 @@ import ( "strings" "syscall" + "github.com/hashicorp/consul/command/validate" "github.com/hashicorp/consul/version" "github.com/mitchellh/cli" ) @@ -349,12 +350,7 @@ func init() { }, "validate": func() (cli.Command, error) { - return &ValidateCommand{ - BaseCommand: BaseCommand{ - Flags: FlagSetNone, - UI: ui, - }, - }, nil + return validate.New(ui), nil }, "version": func() (cli.Command, error) { diff --git a/command/validate.go b/command/validate/validate.go similarity index 64% rename from command/validate.go rename to command/validate/validate.go index 971627013c..c94d0500f4 100644 --- a/command/validate.go +++ b/command/validate/validate.go @@ -1,55 +1,43 @@ -package command +package validate import ( + "flag" "fmt" "github.com/hashicorp/consul/agent/config" + "github.com/hashicorp/consul/command/flags" + "github.com/mitchellh/cli" ) -// ValidateCommand is a Command implementation that is used to -// verify config files -type ValidateCommand struct { - BaseCommand +func New(ui cli.Ui) *cmd { + c := &cmd{UI: ui} + c.initFlags() + return c +} - // flags +type cmd struct { + UI cli.Ui + flags *flag.FlagSet quiet bool } -func (c *ValidateCommand) initFlags() { - c.InitFlagSet() - c.FlagSet.BoolVar(&c.quiet, "quiet", false, +func (c *cmd) initFlags() { + c.flags = flag.NewFlagSet("", flag.ContinueOnError) + c.flags.BoolVar(&c.quiet, "quiet", false, "When given, a successful run will produce no output.") } -func (c *ValidateCommand) Help() string { - c.initFlags() - return c.HelpCommand(` -Usage: consul validate [options] FILE_OR_DIRECTORY... - - Performs a basic sanity test on Consul configuration files. For each file - or directory given, the validate command will attempt to parse the - contents just as the "consul agent" command would, and catch any errors. - This is useful to do a test of the configuration only, without actually - starting the agent. - - Returns 0 if the configuration is valid, or 1 if there are problems. - -`) -} - -func (c *ValidateCommand) Run(args []string) int { - c.initFlags() - if err := c.FlagSet.Parse(args); err != nil { +func (c *cmd) Run(args []string) int { + if err := c.flags.Parse(args); err != nil { c.UI.Error(err.Error()) return 1 } - configFiles := c.FlagSet.Args() + configFiles := c.flags.Args() if len(configFiles) < 1 { c.UI.Error("Must specify at least one config file or directory") return 1 } - b, err := config.NewBuilder(config.Flags{ConfigFiles: configFiles}) if err != nil { c.UI.Error(fmt.Sprintf("Config validation failed: %v", err.Error())) @@ -59,13 +47,26 @@ func (c *ValidateCommand) Run(args []string) int { c.UI.Error(fmt.Sprintf("Config validation failed: %v", err.Error())) return 1 } - if !c.quiet { c.UI.Output("Configuration is valid!") } return 0 } -func (c *ValidateCommand) Synopsis() string { +func (c *cmd) Synopsis() string { return "Validate config files/directories" } + +func (c *cmd) Help() string { + s := `Usage: consul validate [options] FILE_OR_DIRECTORY... + + Performs a basic sanity test on Consul configuration files. For each file + or directory given, the validate command will attempt to parse the + contents just as the "consul agent" command would, and catch any errors. + This is useful to do a test of the configuration only, without actually + starting the agent. + + Returns 0 if the configuration is valid, or 1 if there are problems.` + + return flags.Usage(s, c.flags, nil, nil) +} diff --git a/command/validate_test.go b/command/validate/validate_test.go similarity index 79% rename from command/validate_test.go rename to command/validate/validate_test.go index d49914b952..7767e9201b 100644 --- a/command/validate_test.go +++ b/command/validate/validate_test.go @@ -1,37 +1,28 @@ -package command +package validate import ( "io/ioutil" "os" "path/filepath" + "strings" "testing" "github.com/hashicorp/consul/testutil" "github.com/mitchellh/cli" ) -func testValidateCommand(t *testing.T) (*cli.MockUi, *ValidateCommand) { - ui := cli.NewMockUi() - return ui, &ValidateCommand{ - BaseCommand: BaseCommand{ - UI: ui, - Flags: FlagSetNone, - }, +func TestValidateCommand_noTabs(t *testing.T) { + if strings.ContainsRune(New(nil).Help(), '\t') { + t.Fatal("usage has tabs") } } -func TestValidateCommand_implements(t *testing.T) { - t.Parallel() - var _ cli.Command = &ValidateCommand{} -} - func TestValidateCommandFailOnEmptyFile(t *testing.T) { t.Parallel() tmpFile := testutil.TempFile(t, "consul") defer os.RemoveAll(tmpFile.Name()) - _, cmd := testValidateCommand(t) - + cmd := New(cli.NewMockUi()) args := []string{tmpFile.Name()} if code := cmd.Run(args); code == 0 { @@ -49,8 +40,7 @@ func TestValidateCommandSucceedOnMinimalConfigFile(t *testing.T) { t.Fatalf("err: %s", err) } - _, cmd := testValidateCommand(t) - + cmd := New(cli.NewMockUi()) args := []string{fp} if code := cmd.Run(args); code != 0 { @@ -67,8 +57,7 @@ func TestValidateCommandSucceedOnMinimalConfigDir(t *testing.T) { t.Fatalf("err: %s", err) } - _, cmd := testValidateCommand(t) - + cmd := New(cli.NewMockUi()) args := []string{td} if code := cmd.Run(args); code != 0 { @@ -87,8 +76,8 @@ func TestValidateCommandQuiet(t *testing.T) { t.Fatalf("err: %s", err) } - ui, cmd := testValidateCommand(t) - + ui := cli.NewMockUi() + cmd := New(ui) args := []string{"-quiet", td} if code := cmd.Run(args); code != 0 {