From 3dc4ba2d6889e28a4e46aef53fb30342ce3df51f Mon Sep 17 00:00:00 2001 From: Megan Marsh Date: Thu, 28 May 2020 01:43:58 -0700 Subject: [PATCH] Json vs HCL2 parity refactor (#9301) * refactor so that json and hcl2 templates are both prepared in the same place in the build call, to make code easier to reason about. Remove overly verbose error output which isn't useful in vast majority of cases * fix tests * check err msg * hcl2template.PackerConfig.GetBuilds: raise a diagnostic in case the packer core build perpare call errors Co-authored-by: Adrien Delorme --- command/build.go | 25 ------------------------- hcl2template/types.packer_config.go | 13 +++++++++++++ helper/config/decode.go | 2 +- packer/build.go | 6 ++++-- packer/core.go | 26 ++++++++++++++++++++++++++ 5 files changed, 44 insertions(+), 28 deletions(-) diff --git a/command/build.go b/command/build.go index 410f1889d..72c3e3512 100644 --- a/command/build.go +++ b/command/build.go @@ -188,31 +188,6 @@ func (c *BuildCommand) RunContext(buildCtx context.Context, cla *BuildArgs) int log.Printf("Force build: %v", cla.Force) log.Printf("On error: %v", cla.OnError) - // Set the debug and force mode and prepare all the builds - // This is only affects json templates, because HCL2 - // templates have already been prepared in GetBuilds() above. - for i := range builds { - b := builds[i] - log.Printf("Preparing build: %s", b.Name()) - b.SetDebug(cla.Debug) - b.SetForce(cla.Force) - b.SetOnError(cla.OnError) - - warnings, err := b.Prepare() - if err != nil { - c.Ui.Error(err.Error()) - return 1 - } - if len(warnings) > 0 { - ui := buildUis[b] - ui.Say(fmt.Sprintf("Warnings for build '%s':\n", b.Name())) - for _, warning := range warnings { - ui.Say(fmt.Sprintf("* %s", warning)) - } - ui.Say("") - } - } - // Run all the builds in parallel and wait for them to complete var wg sync.WaitGroup var artifacts = struct { diff --git a/hcl2template/types.packer_config.go b/hcl2template/types.packer_config.go index 41580d3af..a5dd4e3ee 100644 --- a/hcl2template/types.packer_config.go +++ b/hcl2template/types.packer_config.go @@ -359,6 +359,19 @@ func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packer.Build PostProcessors: pps, Prepared: true, } + // Prepare just sets the "prepareCalled" flag on CoreBuild, since + // we did all the prep here. + _, err := pcb.Prepare() + if err != nil { + diags = append(diags, &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: fmt.Sprintf("Preparing packer core build %s failed", src.Ref().String()), + Detail: err.Error(), + Subject: build.HCL2Ref.DefRange.Ptr(), + }) + continue + } + res = append(res, pcb) } } diff --git a/helper/config/decode.go b/helper/config/decode.go index ba022e7e3..327241619 100644 --- a/helper/config/decode.go +++ b/helper/config/decode.go @@ -144,7 +144,7 @@ func Decode(target interface{}, config *DecodeOpts, raws ...interface{}) error { for _, unused := range md.Unused { if unused != "type" && !strings.HasPrefix(unused, "packer_") { err = multierror.Append(err, fmt.Errorf( - "unknown configuration key: %q; raws is %#v \n\n and ctx data is %#v", unused, raws, ctxData)) + "unknown configuration key: %q", unused)) } } if err != nil { diff --git a/packer/build.go b/packer/build.go index 007c6ed3b..53c90490f 100644 --- a/packer/build.go +++ b/packer/build.go @@ -135,8 +135,8 @@ func (b *CoreBuild) Name() string { // and any hooks. This _must_ be called prior to Run. The parameter is the // overrides for the variables within the template (if any). func (b *CoreBuild) Prepare() (warn []string, err error) { - // For HCL2 templates, the builder and hooks are initialized when the template is parsed. - // Calling Prepare(...) is not necessary + // For HCL2 templates, the builder and hooks are initialized when the + // template is parsed. Calling Prepare(...) is not necessary if b.Prepared { b.prepareCalled = true return @@ -149,6 +149,8 @@ func (b *CoreBuild) Prepare() (warn []string, err error) { panic("prepare already called") } + // Templates loaded from HCL2 will never get here. TODO: move this code into + // a custom json area instead of just aborting early for HCL. b.prepareCalled = true packerConfig := map[string]interface{}{ diff --git a/packer/core.go b/packer/core.go index fcf72a6c5..011a21a96 100644 --- a/packer/core.go +++ b/packer/core.go @@ -216,6 +216,32 @@ func (c *Core) GetBuilds(opts GetBuildsOptions) ([]Build, hcl.Diagnostics) { continue } builds = append(builds, b) + + // Now that build plugin has been launched, call Prepare() + log.Printf("Preparing build: %s", b.Name()) + b.SetDebug(opts.Debug) + b.SetForce(opts.Force) + b.SetOnError(opts.OnError) + + warnings, err := b.Prepare() + if err != nil { + diags = append(diags, &hcl.Diagnostic{ + Severity: hcl.DiagError, + Summary: fmt.Sprintf("Failed to prepare build: %q", n), + Detail: err.Error(), + }) + continue + } + + if len(warnings) > 0 { + for _, warning := range warnings { + diags = append(diags, &hcl.Diagnostic{ + Severity: hcl.DiagWarning, + Summary: fmt.Sprintf("Warning when preparing build: %q", n), + Detail: warning, + }) + } + } } return builds, diags }