diff --git a/command/inspect.go b/command/inspect.go index d304c7926..1542e19fc 100644 --- a/command/inspect.go +++ b/command/inspect.go @@ -44,11 +44,10 @@ func (c *InspectCommand) RunContext(ctx context.Context, cla *InspectArgs) int { if ret != 0 { return ret } - diags := packerStarter.Initialize() - ret = writeDiags(c.Ui, nil, diags) - if ret != 0 { - return ret - } + + // here we ignore init diags to allow unknown variables to be used + _ = packerStarter.Initialize() + return packerStarter.InspectConfig(packer.InspectConfigOptions{ Ui: c.Ui, }) diff --git a/command/inspect_test.go b/command/inspect_test.go index 2b31cedcf..73d93b1c2 100644 --- a/command/inspect_test.go +++ b/command/inspect_test.go @@ -15,11 +15,38 @@ func Test_commands(t *testing.T) { env []string expected string }{ + {[]string{"inspect", filepath.Join(testFixture("var-arg"), "fruit_builder.pkr.hcl")}, nil, `Packer Inspect: HCL2 mode + +> input-variables: + +var.fruit: "" + +> local-variables: + +local.fruit: "" + +> builds: + + > : + + sources: + + null.builder + + provisioners: + + shell-local + + post-processors: + + + +`}, {[]string{"inspect", "-var=fruit=banana", filepath.Join(testFixture("var-arg"), "fruit_builder.pkr.hcl")}, nil, `Packer Inspect: HCL2 mode > input-variables: -var.fruit: "banana" [debug: {Type:cty.String,CmdValue:banana,VarfileValue:null,EnvValue:null,DefaultValue:null}] +var.fruit: "banana" > local-variables: @@ -42,11 +69,13 @@ local.fruit: "banana" `}, - {[]string{"inspect", "-var=fruit=peach", filepath.Join(testFixture("hcl"), "inspect", "fruit_string.pkr.hcl")}, nil, `Packer Inspect: HCL2 mode + {[]string{"inspect", "-var=fruit=peach", "-var=unknown_string=also_peach", `-var=unknown_unknown="peach_too"`, filepath.Join(testFixture("hcl"), "inspect", "fruit_string.pkr.hcl")}, nil, `Packer Inspect: HCL2 mode > input-variables: -var.fruit: "peach" [debug: {Type:cty.String,CmdValue:peach,VarfileValue:null,EnvValue:null,DefaultValue:banana}] +var.fruit: "peach" +var.unknown_string: "also_peach" +var.unknown_unknown: "peach_too" > local-variables: @@ -58,7 +87,9 @@ var.fruit: "peach" [debug: {Type:cty.String,CmdValue:peach,VarfileValue:null,Env > input-variables: -var.fruit: "peach" [debug: {Type:cty.String,CmdValue:peach,VarfileValue:null,EnvValue:null,DefaultValue:banana}] +var.fruit: "peach" +var.unknown_string: "" +var.unknown_unknown: "" > local-variables: @@ -94,6 +125,26 @@ Use it at will. manifest shell-local +`}, + {[]string{"inspect", filepath.Join(testFixture("inspect"), "unset_var.json")}, nil, `Packer Inspect: JSON mode +Required variables: + + something + +Optional variables and their defaults: + + +Builders: + + + +Provisioners: + + + +Note: If your build names contain user variables or template +functions such as 'timestamp', these are processed at build time, +and therefore only show in their raw form here. `}, } diff --git a/command/test-fixtures/hcl/inspect/fruit_string.pkr.hcl b/command/test-fixtures/hcl/inspect/fruit_string.pkr.hcl index 3140d12e0..fb285b422 100644 --- a/command/test-fixtures/hcl/inspect/fruit_string.pkr.hcl +++ b/command/test-fixtures/hcl/inspect/fruit_string.pkr.hcl @@ -3,3 +3,10 @@ variable "fruit" { type = string default = "banana" } + +variable "unknown_string" { + type = string +} + +variable "unknown_unknown" { +} diff --git a/command/test-fixtures/inspect/unset_var.json b/command/test-fixtures/inspect/unset_var.json new file mode 100644 index 000000000..f2d2471a5 --- /dev/null +++ b/command/test-fixtures/inspect/unset_var.json @@ -0,0 +1,5 @@ +{ + "variables": { + "something": null + } +} diff --git a/command/test-fixtures/var-arg/fruit_builder.json b/command/test-fixtures/var-arg/fruit_builder.json index abda09077..9d6831c8b 100644 --- a/command/test-fixtures/var-arg/fruit_builder.json +++ b/command/test-fixtures/var-arg/fruit_builder.json @@ -1,6 +1,6 @@ { "variables": { - "fruit": "" + "fruit": null }, "builders": [ { diff --git a/hcl2template/types.packer_config.go b/hcl2template/types.packer_config.go index d07e92ef2..c7f0d0a7f 100644 --- a/hcl2template/types.packer_config.go +++ b/hcl2template/types.packer_config.go @@ -2,6 +2,7 @@ package hcl2template import ( "fmt" + "sort" "strings" "github.com/gobwas/glob" @@ -460,12 +461,18 @@ func (p *PackerConfig) EvaluateExpression(line string) (out string, exit bool, d func (p *PackerConfig) printVariables() string { out := &strings.Builder{} out.WriteString("> input-variables:\n\n") - for _, v := range p.InputVariables { + keys := p.InputVariables.Keys() + sort.Strings(keys) + for _, key := range keys { + v := p.InputVariables[key] val, _ := v.Value() - fmt.Fprintf(out, "var.%s: %q [debug: %#v]\n", v.Name, PrintableCtyValue(val), v) + fmt.Fprintf(out, "var.%s: %q\n", v.Name, PrintableCtyValue(val)) } out.WriteString("\n> local-variables:\n\n") - for _, v := range p.LocalVariables { + keys = p.LocalVariables.Keys() + sort.Strings(keys) + for _, key := range keys { + v := p.LocalVariables[key] val, _ := v.Value() fmt.Fprintf(out, "local.%s: %q\n", v.Name, PrintableCtyValue(val)) } diff --git a/hcl2template/types.variables.go b/hcl2template/types.variables.go index 6a2649083..11f8ba7dc 100644 --- a/hcl2template/types.variables.go +++ b/hcl2template/types.variables.go @@ -72,9 +72,7 @@ func (v *Variable) Value() (cty.Value, *hcl.Diagnostic) { } } - value := cty.NullVal(cty.DynamicPseudoType) - - return value, &hcl.Diagnostic{ + return cty.UnknownVal(v.Type), &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 " + @@ -86,6 +84,14 @@ func (v *Variable) Value() (cty.Value, *hcl.Diagnostic) { type Variables map[string]*Variable +func (variables Variables) Keys() []string { + keys := make([]string, 0, len(variables)) + for key := range variables { + keys = append(keys, key) + } + return keys +} + func (variables Variables) Values() (map[string]cty.Value, hcl.Diagnostics) { res := map[string]cty.Value{} var diags hcl.Diagnostics @@ -93,7 +99,6 @@ func (variables Variables) Values() (map[string]cty.Value, hcl.Diagnostics) { value, diag := v.Value() if diag != nil { diags = append(diags, diag) - continue } res[k] = value } @@ -208,12 +213,11 @@ func (variables *Variables) decodeVariableBlock(block *hcl.Block, ectx *hcl.Eval res.DefaultValue = defaultValue - // It's possible no type attribute was assigned so lets make - // sure we have a valid type otherwise there will be issues parsing the value. + // It's possible no type attribute was assigned so lets make sure we + // have a valid type otherwise there could be issues parsing the value. if res.Type == cty.NilType { res.Type = res.DefaultValue.Type() } - } if len(attrs) > 0 { keys := []string{}