From 9002ac263fe98f1972684244eda5ae44b2f231c3 Mon Sep 17 00:00:00 2001 From: Wilken Rivera Date: Tue, 20 Dec 2022 15:37:59 -0500 Subject: [PATCH] Update BuildBlock with valid HCL2Ref (#12167) While looking into #11932 I found that Packer will throw an error when an unknown source is referenced from within the sources attribute for a build block. The hcl.Diagnostics error includes a Subject, which should highlight where in the HCL2 configuration file the unknown source resides. But when creating the BuildBlock no HCL2Ref data is copied over, thus the Subject is displayed with with zero value for an hcl.Range type. This change updates the build creation logic to copy the HCL2Ref data from the build block at decode time so that it can be properly referenced downstream. Closes #11932 Failure due to change in output ``` --- FAIL: TestValidateCommand_ShowLineNumForMissing (0.00s) --- FAIL: TestValidateCommand_ShowLineNumForMissing/test-fixtures/validate-invalid/missing_build_block.pkr.hcl (0.00s) validate_test.go:377: Unexpected output: ( """ Error: Unknown source file.cho - on line 0: + on test-fixtures/validate-invalid/missing_build_block.pkr.hcl line 6: (source code not available) ... // 4 identical lines """ ) validate_test.go:379: FAIL FAIL github.com/hashicorp/packer/command 1.002s ``` --- command/validate_test.go | 40 +++++++++++++++++++++++++++++++++++++ hcl2template/types.build.go | 10 +++++++--- 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/command/validate_test.go b/command/validate_test.go index 3a2c6b20a..d4188c497 100644 --- a/command/validate_test.go +++ b/command/validate_test.go @@ -1,6 +1,7 @@ package command import ( + "fmt" "path/filepath" "testing" @@ -341,3 +342,42 @@ func TestValidateCommand_VarFilesDisableWarnOnUndeclared(t *testing.T) { }) } } + +func TestValidateCommand_ShowLineNumForMissing(t *testing.T) { + tt := []struct { + path string + exitCode int + extraArgs []string + }{ + {path: filepath.Join(testFixture("validate-invalid"), "missing_build_block.pkr.hcl"), exitCode: 1}, + } + + for _, tc := range tt { + t.Run(tc.path, func(t *testing.T) { + c := &ValidateCommand{ + Meta: TestMetaFile(t), + } + tc := tc + args := tc.extraArgs + args = append(args, tc.path) + if code := c.Run(args); code != tc.exitCode { + fatalCommand(t, c.Meta) + } + + stdout, stderr := GetStdoutAndErrFromTestMeta(t, c.Meta) + expected := fmt.Sprintf(`Error: Unknown source file.cho + + on %s line 6: + (source code not available) + +Known: [file.chocolate] + + +`, tc.path) + if diff := cmp.Diff(expected, stderr); diff != "" { + t.Errorf("Unexpected output: %s", diff) + } + t.Log(stdout) + }) + } +} diff --git a/hcl2template/types.build.go b/hcl2template/types.build.go index 3bb54b20c..73ae957d3 100644 --- a/hcl2template/types.build.go +++ b/hcl2template/types.build.go @@ -87,22 +87,26 @@ type Builds []*BuildBlock // decodeBuildConfig is called when a 'build' block has been detected. It will // load the references to the contents of the build block. func (p *Parser) decodeBuildConfig(block *hcl.Block, cfg *PackerConfig) (*BuildBlock, hcl.Diagnostics) { - build := &BuildBlock{} - body := block.Body - var b struct { Name string `hcl:"name,optional"` Description string `hcl:"description,optional"` FromSources []string `hcl:"sources,optional"` Config hcl.Body `hcl:",remain"` } + + body := block.Body diags := gohcl.DecodeBody(body, cfg.EvalContext(LocalContext, nil), &b) if diags.HasErrors() { return nil, diags } + build := &BuildBlock{ + HCL2Ref: newHCL2Ref(block, b.Config), + } + build.Name = b.Name build.Description = b.Description + build.HCL2Ref.DefRange = block.DefRange // Expose build.name during parsing of pps and provisioners ectx := cfg.EvalContext(BuildContext, nil)