Skip to content

Commit

Permalink
Avoid calling CoreBuild.Prepare(...) for HCL2 templates (hashicorp#8742)
Browse files Browse the repository at this point in the history
  • Loading branch information
sylviamoss authored Feb 14, 2020
1 parent 7254b04 commit 2981fd6
Show file tree
Hide file tree
Showing 6 changed files with 51 additions and 25 deletions.
4 changes: 2 additions & 2 deletions hcl2template/types.build.post-processor.go
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ func (p *Parser) decodePostProcessor(block *hcl.Block) (*PostProcessorBlock, hcl
return postProcessor, diags
}

func (p *Parser) startPostProcessor(pp *PostProcessorBlock, ectx *hcl.EvalContext) (packer.PostProcessor, hcl.Diagnostics) {
func (p *Parser) startPostProcessor(pp *PostProcessorBlock, ectx *hcl.EvalContext, generatedVars map[string]string) (packer.PostProcessor, hcl.Diagnostics) {
// ProvisionerBlock represents a detected but unparsed provisioner
var diags hcl.Diagnostics

Expand All @@ -64,7 +64,7 @@ func (p *Parser) startPostProcessor(pp *PostProcessorBlock, ectx *hcl.EvalContex
}
flatProvisinerCfg, moreDiags := decodeHCL2Spec(pp.Rest, ectx, postProcessor)
diags = append(diags, moreDiags...)
err = postProcessor.Configure(flatProvisinerCfg)
err = postProcessor.Configure(flatProvisinerCfg, generatedVars)
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Expand Down
19 changes: 3 additions & 16 deletions hcl2template/types.build.provisioners.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (

"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/gohcl"
"github.com/hashicorp/packer/helper/common"
"github.com/hashicorp/packer/packer"
)

Expand Down Expand Up @@ -47,7 +46,7 @@ func (p *Parser) decodeProvisioner(block *hcl.Block) (*ProvisionerBlock, hcl.Dia
return provisioner, diags
}

func (p *Parser) startProvisioner(pb *ProvisionerBlock, ectx *hcl.EvalContext, generatedVars []string) (packer.Provisioner, hcl.Diagnostics) {
func (p *Parser) startProvisioner(pb *ProvisionerBlock, ectx *hcl.EvalContext, generatedVars map[string]string) (packer.Provisioner, hcl.Diagnostics) {
var diags hcl.Diagnostics

provisioner, err := p.ProvisionersSchemas.Start(pb.PType)
Expand All @@ -67,22 +66,10 @@ func (p *Parser) startProvisioner(pb *ProvisionerBlock, ectx *hcl.EvalContext, g
// manipulate generatedVars from builder to add to the interfaces being
// passed to the provisioner Prepare()

// If the builder has provided a list of to-be-generated variables that
// should be made accessible to provisioners, pass that list into
// the provisioner prepare() so that the provisioner can appropriately
// validate user input against what will become available. Otherwise,
// only pass the default variables, using the basic placeholder data.
generatedPlaceholderMap := packer.BasicPlaceholderData()
if generatedVars != nil {
for _, k := range generatedVars {
generatedPlaceholderMap[k] = fmt.Sprintf("Generated_%s. "+
common.PlaceholderMsg, k)
}
}
// configs := make([]interface{}, 2)
// configs = append(, flatProvisionerCfg)
// configs = append(configs, generatedPlaceholderMap)
err = provisioner.Prepare(flatProvisionerCfg, generatedPlaceholderMap)
// configs = append(configs, generatedVars)
err = provisioner.Prepare(flatProvisionerCfg, generatedVars)
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Expand Down
27 changes: 22 additions & 5 deletions hcl2template/types.packer_config.go
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
package hcl2template

import (
"fmt"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/packer/helper/common"
"github.com/hashicorp/packer/packer"
"github.com/zclconf/go-cty/cty"
)
Expand Down Expand Up @@ -42,7 +44,7 @@ func (cfg *PackerConfig) EvalContext() *hcl.EvalContext {

// getCoreBuildProvisioners takes a list of provisioner block, starts according
// provisioners and sends parsed HCL2 over to it.
func (p *Parser) getCoreBuildProvisioners(blocks []*ProvisionerBlock, ectx *hcl.EvalContext, generatedVars []string) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) {
func (p *Parser) getCoreBuildProvisioners(blocks []*ProvisionerBlock, ectx *hcl.EvalContext, generatedVars map[string]string) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) {
var diags hcl.Diagnostics
res := []packer.CoreBuildProvisioner{}
for _, pb := range blocks {
Expand All @@ -62,11 +64,11 @@ func (p *Parser) getCoreBuildProvisioners(blocks []*ProvisionerBlock, ectx *hcl.

// getCoreBuildProvisioners takes a list of post processor block, starts
// according provisioners and sends parsed HCL2 over to it.
func (p *Parser) getCoreBuildPostProcessors(blocks []*PostProcessorBlock, ectx *hcl.EvalContext) ([]packer.CoreBuildPostProcessor, hcl.Diagnostics) {
func (p *Parser) getCoreBuildPostProcessors(blocks []*PostProcessorBlock, ectx *hcl.EvalContext, generatedVars map[string]string) ([]packer.CoreBuildPostProcessor, hcl.Diagnostics) {
var diags hcl.Diagnostics
res := []packer.CoreBuildPostProcessor{}
for _, ppb := range blocks {
postProcessor, moreDiags := p.startPostProcessor(ppb, ectx)
postProcessor, moreDiags := p.startPostProcessor(ppb, ectx, generatedVars)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {
continue
Expand Down Expand Up @@ -104,12 +106,26 @@ func (p *Parser) getBuilds(cfg *PackerConfig) ([]packer.Build, hcl.Diagnostics)
if moreDiags.HasErrors() {
continue
}
provisioners, moreDiags := p.getCoreBuildProvisioners(build.ProvisionerBlocks, cfg.EvalContext(), generatedVars)

// If the builder has provided a list of to-be-generated variables that
// should be made accessible to provisioners, pass that list into
// the provisioner prepare() so that the provisioner can appropriately
// validate user input against what will become available. Otherwise,
// only pass the default variables, using the basic placeholder data.
generatedPlaceholderMap := packer.BasicPlaceholderData()
if generatedVars != nil {
for _, k := range generatedVars {
generatedPlaceholderMap[k] = fmt.Sprintf("Build_%s. "+
common.PlaceholderMsg, k)
}
}

provisioners, moreDiags := p.getCoreBuildProvisioners(build.ProvisionerBlocks, cfg.EvalContext(), generatedPlaceholderMap)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {
continue
}
postProcessors, moreDiags := p.getCoreBuildPostProcessors(build.PostProcessors, cfg.EvalContext())
postProcessors, moreDiags := p.getCoreBuildPostProcessors(build.PostProcessors, cfg.EvalContext(), generatedPlaceholderMap)
pps := [][]packer.CoreBuildPostProcessor{}
if len(postProcessors) > 0 {
pps = [][]packer.CoreBuildPostProcessor{postProcessors}
Expand All @@ -124,6 +140,7 @@ func (p *Parser) getBuilds(cfg *PackerConfig) ([]packer.Build, hcl.Diagnostics)
Builder: builder,
Provisioners: provisioners,
PostProcessors: pps,
Prepared: true,
}
res = append(res, pcb)
}
Expand Down
5 changes: 3 additions & 2 deletions hcl2template/types.packer_config_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,8 +57,9 @@ func TestParser_complete(t *testing.T) {
false, false,
[]packer.Build{
&packer.CoreBuild{
Type: "virtualbox-iso",
Builder: basicMockBuilder,
Type: "virtualbox-iso",
Prepared: true,
Builder: basicMockBuilder,
Provisioners: []packer.CoreBuildProvisioner{
{
PType: "shell",
Expand Down
10 changes: 10 additions & 0 deletions packer/build.go
Original file line number Diff line number Diff line change
Expand Up @@ -97,6 +97,9 @@ type CoreBuild struct {
TemplatePath string
Variables map[string]string

// Indicates whether the build is already initialized before calling Prepare(..)
Prepared bool

debug bool
force bool
onError string
Expand Down Expand Up @@ -132,6 +135,13 @@ 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
if b.Prepared {
b.prepareCalled = true
return
}

b.l.Lock()
defer b.l.Unlock()

Expand Down
11 changes: 11 additions & 0 deletions packer/build_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,17 @@ func TestBuild_Prepare(t *testing.T) {
}
}

func TestBuild_Prepare_SkipWhenBuilderAlreadyInitialized(t *testing.T) {
build := testBuild()
builder := build.Builder.(*MockBuilder)

build.Prepared = true
build.Prepare()
if builder.PrepareCalled {
t.Fatal("should not be called")
}
}

func TestBuild_Prepare_Twice(t *testing.T) {
build := testBuild()
warn, err := build.Prepare()
Expand Down

0 comments on commit 2981fd6

Please sign in to comment.