tweak validation & add tests

This commit is contained in:
Adrien Delorme 2020-03-09 16:16:59 +01:00
parent e195c627fb
commit 6d8cce501e
5 changed files with 89 additions and 26 deletions

View File

@ -123,7 +123,7 @@ func (p *Parser) parse(filename string, vars map[string]string) (*PackerConfig,
varFiles = append(varFiles, f) varFiles = append(varFiles, f)
} }
diags = append(diags, cfg.InputVariables.collectVariableValues(os.Environ(), varFiles, vars)...) diags = append(diags, cfg.collectInputVariableValues(os.Environ(), varFiles, vars)...)
} }
// decode the actual content // decode the actual content

View File

View File

@ -25,10 +25,16 @@ type PackerConfig struct {
InputVariables Variables InputVariables Variables
LocalVariables Variables LocalVariables Variables
ValidationOptions
// Builds is the list of Build blocks defined in the config files. // Builds is the list of Build blocks defined in the config files.
Builds Builds Builds Builds
} }
type ValidationOptions struct {
Strict bool
}
// EvalContext returns the *hcl.EvalContext that will be passed to an hcl // EvalContext returns the *hcl.EvalContext that will be passed to an hcl
// decoder in order to tell what is the actual value of a var or a local and // decoder in order to tell what is the actual value of a var or a local and
// the list of defined functions. // the list of defined functions.

View File

@ -223,8 +223,9 @@ func (variables *Variables) decodeVariableBlock(block *hcl.Block, ectx *hcl.Eval
// them. // them.
const VarEnvPrefix = "PKR_VAR_" const VarEnvPrefix = "PKR_VAR_"
func (variables Variables) collectVariableValues(env []string, files []*hcl.File, argv map[string]string) hcl.Diagnostics { func (cfg *PackerConfig) collectInputVariableValues(env []string, files []*hcl.File, argv map[string]string) hcl.Diagnostics {
var diags hcl.Diagnostics var diags hcl.Diagnostics
variables := cfg.InputVariables
for _, raw := range env { for _, raw := range env {
if !strings.HasPrefix(raw, VarEnvPrefix) { if !strings.HasPrefix(raw, VarEnvPrefix) {
@ -321,7 +322,20 @@ func (variables Variables) collectVariableValues(env []string, files []*hcl.File
for name, attr := range attrs { for name, attr := range attrs {
variable, found := variables[name] variable, found := variables[name]
if !found { if !found {
// No file defines this variable; let's skip it sev := hcl.DiagWarning
if cfg.ValidationOptions.Strict {
sev = hcl.DiagError
}
diags = append(diags, &hcl.Diagnostic{
Severity: sev,
Summary: "Undefined variable",
Detail: fmt.Sprintf("A %q variable was set but was "+
"not found in known variables. To declare "+
"variable %q, place this block in one of your"+
".pkr files, such as variables.pkr.hcl",
name, name),
Context: attr.Range.Ptr(),
})
continue continue
} }
@ -351,8 +365,8 @@ func (variables Variables) collectVariableValues(env []string, files []*hcl.File
variable, found := variables[name] variable, found := variables[name]
if !found { if !found {
diags = append(diags, &hcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagWarning, Severity: hcl.DiagError,
Summary: "Unknown -var variable", Summary: "Undefined -var variable",
Detail: fmt.Sprintf("A %q variable was passed in the command "+ Detail: fmt.Sprintf("A %q variable was passed in the command "+
"line but was not found in known variables."+ "line but was not found in known variables."+
"To declare variable %q, place this block in one of your"+ "To declare variable %q, place this block in one of your"+

View File

@ -249,8 +249,10 @@ func TestVariables_collectVariableValues(t *testing.T) {
tests := []struct { tests := []struct {
name string name string
variables Variables variables Variables
validationOptions ValidationOptions
args args args args
wantDiags bool wantDiags bool
wantDiagsHasError bool
wantVariables Variables wantVariables Variables
wantValues map[string]cty.Value wantValues map[string]cty.Value
}{ }{
@ -333,11 +335,39 @@ func TestVariables_collectVariableValues(t *testing.T) {
}, },
}, },
{name: "undefined but set value", {name: "undefined but set value - pkrvar file - normal mode",
variables: Variables{}, variables: Variables{},
args: args{ args: args{
env: []string{`PKR_VAR_unused_string=value`}, hclFiles: []string{`undefined_string="value"`},
hclFiles: []string{`unused_string="value"`}, },
// output
wantDiags: true,
wantDiagsHasError: false,
wantVariables: Variables{},
wantValues: map[string]cty.Value{},
},
{name: "undefined but set value - pkrvar file - strict mode",
variables: Variables{},
validationOptions: ValidationOptions{
Strict: true,
},
args: args{
hclFiles: []string{`undefined_string="value"`},
},
// output
wantDiags: true,
wantDiagsHasError: true,
wantVariables: Variables{},
wantValues: map[string]cty.Value{},
},
{name: "undefined but set value - env",
variables: Variables{},
args: args{
env: []string{`PKR_VAR_undefined_string=value`},
}, },
// output // output
@ -346,16 +376,17 @@ func TestVariables_collectVariableValues(t *testing.T) {
wantValues: map[string]cty.Value{}, wantValues: map[string]cty.Value{},
}, },
{name: "undefined but set value - args", {name: "undefined but set value - argv",
variables: Variables{}, variables: Variables{},
args: args{ args: args{
argv: map[string]string{ argv: map[string]string{
"unused_string": "value", "undefined_string": "value",
}, },
}, },
// output // output
wantDiags: true, wantDiags: true,
wantDiagsHasError: true,
wantVariables: Variables{}, wantVariables: Variables{},
wantValues: map[string]cty.Value{}, wantValues: map[string]cty.Value{},
}, },
@ -372,6 +403,7 @@ func TestVariables_collectVariableValues(t *testing.T) {
// output // output
wantDiags: true, wantDiags: true,
wantDiagsHasError: true,
wantVariables: Variables{ wantVariables: Variables{
"used_string": &Variable{ "used_string": &Variable{
Type: cty.String, Type: cty.String,
@ -395,6 +427,7 @@ func TestVariables_collectVariableValues(t *testing.T) {
// output // output
wantDiags: true, wantDiags: true,
wantDiagsHasError: true,
wantVariables: Variables{ wantVariables: Variables{
"used_string": &Variable{ "used_string": &Variable{
Type: cty.String, Type: cty.String,
@ -420,6 +453,7 @@ func TestVariables_collectVariableValues(t *testing.T) {
// output // output
wantDiags: true, wantDiags: true,
wantDiagsHasError: true,
wantVariables: Variables{ wantVariables: Variables{
"used_string": &Variable{ "used_string": &Variable{
Type: cty.String, Type: cty.String,
@ -439,6 +473,7 @@ func TestVariables_collectVariableValues(t *testing.T) {
// output // output
wantDiags: true, wantDiags: true,
wantDiagsHasError: true,
wantVariables: Variables{}, wantVariables: Variables{},
wantValues: map[string]cty.Value{}, wantValues: map[string]cty.Value{},
}, },
@ -454,9 +489,17 @@ func TestVariables_collectVariableValues(t *testing.T) {
} }
files = append(files, file) files = append(files, file)
} }
if gotDiags := tt.variables.collectVariableValues(tt.args.env, files, tt.args.argv); (gotDiags == nil) == tt.wantDiags { cfg := &PackerConfig{
InputVariables: tt.variables,
ValidationOptions: tt.validationOptions,
}
gotDiags := cfg.collectInputVariableValues(tt.args.env, files, tt.args.argv)
if (gotDiags == nil) == tt.wantDiags {
t.Fatalf("Variables.collectVariableValues() = %v, want %v", gotDiags, tt.wantDiags) t.Fatalf("Variables.collectVariableValues() = %v, want %v", gotDiags, tt.wantDiags)
} }
if tt.wantDiagsHasError != gotDiags.HasErrors() {
t.Fatalf("Variables.collectVariableValues() unexpected diagnostics HasErrors. %s", gotDiags)
}
if diff := cmp.Diff(fmt.Sprintf("%#v", tt.wantVariables), fmt.Sprintf("%#v", tt.variables)); diff != "" { if diff := cmp.Diff(fmt.Sprintf("%#v", tt.wantVariables), fmt.Sprintf("%#v", tt.variables)); diff != "" {
t.Fatalf("didn't get expected variables: %s", diff) t.Fatalf("didn't get expected variables: %s", diff)
} }