command: Add vars to validate command

pull/38288/head
Daniel Banck 2 months ago committed by Daniel Banck
parent ad270d952d
commit 4b132a4879

@ -27,6 +27,8 @@ type Validate struct {
// Query indicates that Terraform should also validate .tfquery files.
Query bool
Vars *Vars
}
// ParseValidate processes CLI arguments, returning a Validate value and errors.
@ -36,10 +38,11 @@ func ParseValidate(args []string) (*Validate, tfdiags.Diagnostics) {
var diags tfdiags.Diagnostics
validate := &Validate{
Path: ".",
Vars: &Vars{},
}
var jsonOutput bool
cmdFlags := defaultFlagSet("validate")
cmdFlags := extendedFlagSet("validate", nil, nil, validate.Vars)
cmdFlags.BoolVar(&jsonOutput, "json", false, "json")
cmdFlags.StringVar(&validate.TestDirectory, "test-directory", "tests", "test-directory")
cmdFlags.BoolVar(&validate.NoTests, "no-tests", false, "no-tests")

@ -6,6 +6,8 @@ package arguments
import (
"testing"
"github.com/google/go-cmp/cmp"
"github.com/google/go-cmp/cmp/cmpopts"
"github.com/hashicorp/terraform/internal/tfdiags"
)
@ -19,6 +21,7 @@ func TestParseValidate_valid(t *testing.T) {
&Validate{
Path: ".",
TestDirectory: "tests",
Vars: &Vars{},
ViewType: ViewHuman,
},
},
@ -27,6 +30,7 @@ func TestParseValidate_valid(t *testing.T) {
&Validate{
Path: ".",
TestDirectory: "tests",
Vars: &Vars{},
ViewType: ViewJSON,
},
},
@ -35,6 +39,7 @@ func TestParseValidate_valid(t *testing.T) {
&Validate{
Path: "foo",
TestDirectory: "tests",
Vars: &Vars{},
ViewType: ViewJSON,
},
},
@ -43,6 +48,7 @@ func TestParseValidate_valid(t *testing.T) {
&Validate{
Path: ".",
TestDirectory: "other",
Vars: &Vars{},
ViewType: ViewHuman,
},
},
@ -51,25 +57,72 @@ func TestParseValidate_valid(t *testing.T) {
&Validate{
Path: ".",
TestDirectory: "tests",
Vars: &Vars{},
ViewType: ViewHuman,
NoTests: true,
},
},
}
cmpOpts := cmpopts.IgnoreUnexported(Vars{})
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
got, diags := ParseValidate(tc.args)
if len(diags) > 0 {
t.Fatalf("unexpected diags: %v", diags)
}
if *got != *tc.want {
if diff := cmp.Diff(tc.want, got, cmpOpts); diff != "" {
t.Fatalf("unexpected result\n got: %#v\nwant: %#v", got, tc.want)
}
})
}
}
func TestParseValidate_vars(t *testing.T) {
testCases := map[string]struct {
args []string
want []FlagNameValue
}{
"var": {
args: []string{"-var", "foo=bar"},
want: []FlagNameValue{
{Name: "-var", Value: "foo=bar"},
},
},
"var-file": {
args: []string{"-var-file", "cool.tfvars"},
want: []FlagNameValue{
{Name: "-var-file", Value: "cool.tfvars"},
},
},
"both": {
args: []string{
"-var", "foo=bar",
"-var-file", "cool.tfvars",
"-var", "boop=beep",
},
want: []FlagNameValue{
{Name: "-var", Value: "foo=bar"},
{Name: "-var-file", Value: "cool.tfvars"},
{Name: "-var", Value: "boop=beep"},
},
},
}
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
got, diags := ParseValidate(tc.args)
if len(diags) > 0 {
t.Fatalf("unexpected diags: %v", diags)
}
if vars := got.Vars.All(); !cmp.Equal(vars, tc.want) {
t.Fatalf("unexpected vars: %#v", vars)
}
})
}
}
func TestParseValidate_invalid(t *testing.T) {
testCases := map[string]struct {
args []string
@ -81,6 +134,7 @@ func TestParseValidate_invalid(t *testing.T) {
&Validate{
Path: ".",
TestDirectory: "tests",
Vars: &Vars{},
ViewType: ViewHuman,
},
tfdiags.Diagnostics{
@ -96,6 +150,7 @@ func TestParseValidate_invalid(t *testing.T) {
&Validate{
Path: "bar",
TestDirectory: "tests",
Vars: &Vars{},
ViewType: ViewJSON,
},
tfdiags.Diagnostics{
@ -108,10 +163,12 @@ func TestParseValidate_invalid(t *testing.T) {
},
}
cmpOpts := cmpopts.IgnoreUnexported(Vars{})
for name, tc := range testCases {
t.Run(name, func(t *testing.T) {
got, gotDiags := ParseValidate(tc.args)
if *got != *tc.want {
if diff := cmp.Diff(tc.want, got, cmpOpts); diff != "" {
t.Fatalf("unexpected result\n got: %#v\nwant: %#v", got, tc.want)
}
tfdiags.AssertDiagnosticsMatch(t, gotDiags, tc.wantDiags)

@ -47,6 +47,26 @@ func (c *ValidateCommand) Run(rawArgs []string) int {
c.ParsedArgs = args
view := views.NewValidate(args.ViewType, c.View)
// If the query flag is set, include query files in the validation.
c.includeQueryFiles = c.ParsedArgs.Query
loader, err := c.initConfigLoader()
if err != nil {
diags = diags.Append(err)
view.Diagnostics(diags)
return 1
}
var varDiags tfdiags.Diagnostics
c.VariableValues, varDiags = args.Vars.CollectValues(func(filename string, src []byte) {
loader.Parser().ForceFileSource(filename, src)
})
diags = diags.Append(varDiags)
if diags.HasErrors() {
view.Diagnostics(diags)
return 1
}
// After this point, we must only produce JSON output if JSON mode is
// enabled, so all errors should be accumulated into diags and we'll
// print out a suitable result at the end, depending on the format
@ -81,9 +101,6 @@ func (c *ValidateCommand) validate(dir string) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
var cfg *configs.Config
// If the query flag is set, include query files in the validation.
c.includeQueryFiles = c.ParsedArgs.Query
if c.ParsedArgs.NoTests {
cfg, diags = c.loadConfig(dir)
} else {
@ -360,9 +377,19 @@ Options:
-no-tests If specified, Terraform will not validate test files.
-test-directory=path Set the Terraform test directory, defaults to "tests".
-test-directory=path Set the Terraform test directory, defaults to "tests".
-query If specified, the command will also validate .tfquery.hcl files.
-var 'foo=bar' Set a value for one of the input variables in the root
module of the configuration. Use this option more than
once to set more than one variable.
-var-file=filename Load variable values from the given file, in addition
to the default files terraform.tfvars and *.auto.tfvars.
Use this option more than once to include more than one
variables file.
`
return strings.TrimSpace(helpText)
}

Loading…
Cancel
Save