diff --git a/command/validate/validate.go b/command/validate/validate.go index 1b3923239c..96a84d6148 100644 --- a/command/validate/validate.go +++ b/command/validate/validate.go @@ -18,12 +18,17 @@ func New(ui cli.Ui) *cmd { type cmd struct { UI cli.Ui flags *flag.FlagSet - quiet bool - help string + // configFormat forces all config files to be interpreted as this + // format independent of their extension. + configFormat string + quiet bool + help string } func (c *cmd) init() { c.flags = flag.NewFlagSet("", flag.ContinueOnError) + c.flags.StringVar(&c.configFormat, "config-format", "", + "Config files are in this format irrespective of their extension. Must be 'hcl' or 'json'") c.flags.BoolVar(&c.quiet, "quiet", false, "When given, a successful run will produce no output.") c.help = flags.Usage(help, c.flags) @@ -40,7 +45,13 @@ func (c *cmd) Run(args []string) int { c.UI.Error("Must specify at least one config file or directory") return 1 } - b, err := config.NewBuilder(config.Flags{ConfigFiles: configFiles}) + + if c.configFormat != "" && c.configFormat != "json" && c.configFormat != "hcl" { + c.UI.Error("-config-format must be either 'hcl' or 'json") + return 1 + } + + b, err := config.NewBuilder(config.Flags{ConfigFiles: configFiles, ConfigFormat: &c.configFormat}) if err != nil { c.UI.Error(fmt.Sprintf("Config validation failed: %v", err.Error())) return 1 diff --git a/command/validate/validate_test.go b/command/validate/validate_test.go index 517e02b620..c3f3dacc61 100644 --- a/command/validate/validate_test.go +++ b/command/validate/validate_test.go @@ -7,6 +7,7 @@ import ( "strings" "testing" + require "github.com/stretchr/testify/require" "github.com/hashicorp/consul/testutil" "github.com/mitchellh/cli" ) @@ -26,9 +27,8 @@ func TestValidateCommand_FailOnEmptyFile(t *testing.T) { cmd := New(cli.NewMockUi()) args := []string{tmpFile.Name()} - if code := cmd.Run(args); code == 0 { - t.Fatalf("bad: %d", code) - } + code := cmd.Run(args) + require.NotEqual(t, 0, code) } func TestValidateCommand_SucceedOnMinimalConfigFile(t *testing.T) { @@ -38,16 +38,62 @@ func TestValidateCommand_SucceedOnMinimalConfigFile(t *testing.T) { fp := filepath.Join(td, "config.json") err := ioutil.WriteFile(fp, []byte(`{"bind_addr":"10.0.0.1", "data_dir":"`+td+`"}`), 0644) - if err != nil { - t.Fatalf("err: %s", err) - } + require.Nilf(t, err, "err: %s", err) cmd := New(cli.NewMockUi()) args := []string{fp} - if code := cmd.Run(args); code != 0 { - t.Fatalf("bad: %d", code) - } + code := cmd.Run(args) + require.Equal(t, 0, code) +} + +func TestValidateCommand_SucceedWithMinimalJSONConfigFormat(t *testing.T) { + t.Parallel() + td := testutil.TempDir(t, "consul") + defer os.RemoveAll(td) + + fp := filepath.Join(td, "json.conf") + err := ioutil.WriteFile(fp, []byte(`{"bind_addr":"10.0.0.1", "data_dir":"`+td+`"}`), 0644) + require.Nilf(t, err, "err: %s", err) + + cmd := New(cli.NewMockUi()) + args := []string{"--config-format", "json", fp} + + code := cmd.Run(args) + require.Equal(t, 0, code) +} + +func TestValidateCommand_SucceedWithMinimalHCLConfigFormat(t *testing.T) { + t.Parallel() + td := testutil.TempDir(t, "consul") + defer os.RemoveAll(td) + + fp := filepath.Join(td, "hcl.conf") + err := ioutil.WriteFile(fp, []byte("bind_addr = \"10.0.0.1\"\ndata_dir = \""+td+"\""), 0644) + require.Nilf(t, err, "err: %s", err) + + + cmd := New(cli.NewMockUi()) + args := []string{"--config-format", "hcl", fp} + + code := cmd.Run(args) + require.Equal(t, 0, code) +} + +func TestValidateCommand_SucceedWithJSONAsHCL(t *testing.T) { + t.Parallel() + td := testutil.TempDir(t, "consul") + defer os.RemoveAll(td) + + fp := filepath.Join(td, "json.conf") + err := ioutil.WriteFile(fp, []byte(`{"bind_addr":"10.0.0.1", "data_dir":"`+td+`"}`), 0644) + require.Nilf(t, err, "err: %s", err) + + cmd := New(cli.NewMockUi()) + args := []string{"--config-format", "hcl", fp} + + code := cmd.Run(args) + require.Equal(t, 0, code) } func TestValidateCommand_SucceedOnMinimalConfigDir(t *testing.T) { @@ -56,16 +102,29 @@ func TestValidateCommand_SucceedOnMinimalConfigDir(t *testing.T) { defer os.RemoveAll(td) err := ioutil.WriteFile(filepath.Join(td, "config.json"), []byte(`{"bind_addr":"10.0.0.1", "data_dir":"`+td+`"}`), 0644) - if err != nil { - t.Fatalf("err: %s", err) - } + require.Nilf(t, err, "err: %s", err) cmd := New(cli.NewMockUi()) args := []string{td} - if code := cmd.Run(args); code != 0 { - t.Fatalf("bad: %d", code) - } + code := cmd.Run(args) + require.Equal(t, 0, code) +} + +func TestValidateCommand_FailForInvalidJSONConfigFormat(t *testing.T) { + t.Parallel() + td := testutil.TempDir(t, "consul") + defer os.RemoveAll(td) + + fp := filepath.Join(td, "hcl.conf") + err := ioutil.WriteFile(fp, []byte(`bind_addr = "10.0.0.1"\ndata_dir = "`+td+`"`), 0644) + require.Nilf(t, err, "err: %s", err) + + cmd := New(cli.NewMockUi()) + args := []string{"--config-format", "json", fp} + + code := cmd.Run(args) + require.NotEqual(t, 0, code) } func TestValidateCommand_Quiet(t *testing.T) { @@ -75,18 +134,13 @@ func TestValidateCommand_Quiet(t *testing.T) { fp := filepath.Join(td, "config.json") err := ioutil.WriteFile(fp, []byte(`{"bind_addr":"10.0.0.1", "data_dir":"`+td+`"}`), 0644) - if err != nil { - t.Fatalf("err: %s", err) - } + require.Nilf(t, err, "err: %s", err) ui := cli.NewMockUi() cmd := New(ui) args := []string{"-quiet", td} - if code := cmd.Run(args); code != 0 { - t.Fatalf("bad: %d, %s", code, ui.ErrorWriter.String()) - } - if ui.OutputWriter.String() != "" { - t.Fatalf("bad: %v", ui.OutputWriter.String()) - } + code := cmd.Run(args) + require.Equalf(t, 0, code, "return code - expected: 0, bad: %d, %s", code, ui.ErrorWriter.String()) + require.Equal(t, "", ui.OutputWriter.String()) }