all variables must have a value.

A variable's default value can be set to null to force user to set it.
This commit is contained in:
Adrien Delorme 2020-03-09 17:25:56 +01:00
parent 6d8cce501e
commit 0ccff0d5b9
6 changed files with 34 additions and 18 deletions

View File

@ -126,6 +126,11 @@ func (p *Parser) parse(filename string, vars map[string]string) (*PackerConfig,
diags = append(diags, cfg.collectInputVariableValues(os.Environ(), varFiles, vars)...)
}
_, moreDiags := cfg.InputVariables.Values()
diags = append(diags, moreDiags...)
_, moreDiags = cfg.LocalVariables.Values()
diags = append(diags, moreDiags...)
// decode the actual content
for _, file := range files {
diags = append(diags, p.decodeConfig(file, cfg)...)

View File

@ -29,6 +29,7 @@ variable "super_secret_password" {
description = <<IMSENSIBLE
Handle with care plz
IMSENSIBLE
default = null
}
locals {

View File

@ -1,4 +1,5 @@
variable "broken_type" {
variable "broken_variable" {
invalid = true
default = true
}

View File

@ -39,11 +39,13 @@ type ValidationOptions struct {
// decoder in order to tell what is the actual value of a var or a local and
// the list of defined functions.
func (cfg *PackerConfig) EvalContext() *hcl.EvalContext {
inputVariables, _ := cfg.InputVariables.Values()
localVariables, _ := cfg.LocalVariables.Values()
ectx := &hcl.EvalContext{
Functions: Functions(cfg.Basedir),
Variables: map[string]cty.Value{
"var": cty.ObjectVal(cfg.InputVariables.Values()),
"local": cty.ObjectVal(cfg.LocalVariables.Values()),
"var": cty.ObjectVal(inputVariables),
"local": cty.ObjectVal(localVariables),
},
}
return ectx

View File

@ -62,7 +62,7 @@ func (v *Variable) Value() (cty.Value, *hcl.Diagnostic) {
v.EnvValue,
v.DefaultValue,
} {
if !value.IsNull() {
if value != cty.NilVal {
return value, nil
}
}
@ -73,23 +73,26 @@ func (v *Variable) Value() (cty.Value, *hcl.Diagnostic) {
Severity: hcl.DiagError,
Summary: fmt.Sprintf("Unset variable %q", v.Name),
Detail: "A used variable must be set or have a default value; see " +
"https://packer.io/docs/configuration/from-1.5/syntax.html for details.",
"https://packer.io/docs/configuration/from-1.5/syntax.html for " +
"details.",
Context: v.Range.Ptr(),
}
}
type Variables map[string]*Variable
func (variables Variables) Values() map[string]cty.Value {
func (variables Variables) Values() (map[string]cty.Value, hcl.Diagnostics) {
res := map[string]cty.Value{}
var diags hcl.Diagnostics
for k, v := range variables {
res[k], _ = v.Value()
// here the value might not be used and in that case we don't want to
// force users to set it. So this error is ignored. we still set it as
// it can be a `cty.NullVal(cty.DynamicPseudoType)`, which is the go
// cty value for 'unknown value' and should error when used.
value, diag := v.Value()
if diag != nil {
diags = append(diags, diag)
continue
}
return res
res[k] = value
}
return res, diags
}
// decodeVariable decodes a variable key and value into Variables

View File

@ -54,6 +54,7 @@ func TestParse_variables(t *testing.T) {
"super_secret_password": &Variable{
Name: "super_secret_password",
Sensitive: true,
DefaultValue: cty.NullVal(cty.String),
Description: fmt.Sprintln("Handle with care plz"),
},
},
@ -117,14 +118,16 @@ func TestParse_variables(t *testing.T) {
[]packer.Build{},
false,
},
{"unknown key",
defaultParser,
parseTestArgs{"testdata/variables/unknown_key.pkr.hcl", nil},
&PackerConfig{
Basedir: filepath.Join("testdata", "variables"),
InputVariables: Variables{
"broken_type": &Variable{
Name: "broken_type",
"broken_variable": &Variable{
Name: "broken_variable",
DefaultValue: cty.BoolVal(true),
},
},
},
@ -132,6 +135,7 @@ func TestParse_variables(t *testing.T) {
[]packer.Build{},
false,
},
{"unset used variable",
defaultParser,
parseTestArgs{"testdata/variables/unset_used_string_variable.pkr.hcl", nil},
@ -170,7 +174,7 @@ func TestParse_variables(t *testing.T) {
},
},
},
false, false,
true, true,
[]packer.Build{
&packer.CoreBuild{
Type: "null",