Avoid calling CoreBuild.Prepare(...) for HCL2 templates (#8742)

This commit is contained in:
Sylvia Moss 2020-02-14 17:39:32 +01:00 committed by GitHub
parent 7254b04129
commit 2981fd627d
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 51 additions and 25 deletions

View File

@ -49,7 +49,7 @@ func (p *Parser) decodePostProcessor(block *hcl.Block) (*PostProcessorBlock, hcl
return postProcessor, diags 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 // ProvisionerBlock represents a detected but unparsed provisioner
var diags hcl.Diagnostics var diags hcl.Diagnostics
@ -64,7 +64,7 @@ func (p *Parser) startPostProcessor(pp *PostProcessorBlock, ectx *hcl.EvalContex
} }
flatProvisinerCfg, moreDiags := decodeHCL2Spec(pp.Rest, ectx, postProcessor) flatProvisinerCfg, moreDiags := decodeHCL2Spec(pp.Rest, ectx, postProcessor)
diags = append(diags, moreDiags...) diags = append(diags, moreDiags...)
err = postProcessor.Configure(flatProvisinerCfg) err = postProcessor.Configure(flatProvisinerCfg, generatedVars)
if err != nil { if err != nil {
diags = append(diags, &hcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError, Severity: hcl.DiagError,

View File

@ -5,7 +5,6 @@ import (
"github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/gohcl" "github.com/hashicorp/hcl/v2/gohcl"
"github.com/hashicorp/packer/helper/common"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
) )
@ -47,7 +46,7 @@ func (p *Parser) decodeProvisioner(block *hcl.Block) (*ProvisionerBlock, hcl.Dia
return provisioner, diags 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 var diags hcl.Diagnostics
provisioner, err := p.ProvisionersSchemas.Start(pb.PType) provisioner, err := p.ProvisionersSchemas.Start(pb.PType)
@ -67,22 +66,10 @@ func (p *Parser) startProvisioner(pb *ProvisionerBlock, ectx *hcl.EvalContext, g
// manipulate generatedVars from builder to add to the interfaces being // manipulate generatedVars from builder to add to the interfaces being
// passed to the provisioner Prepare() // 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 := make([]interface{}, 2)
// configs = append(, flatProvisionerCfg) // configs = append(, flatProvisionerCfg)
// configs = append(configs, generatedPlaceholderMap) // configs = append(configs, generatedVars)
err = provisioner.Prepare(flatProvisionerCfg, generatedPlaceholderMap) err = provisioner.Prepare(flatProvisionerCfg, generatedVars)
if err != nil { if err != nil {
diags = append(diags, &hcl.Diagnostic{ diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError, Severity: hcl.DiagError,

View File

@ -1,7 +1,9 @@
package hcl2template package hcl2template
import ( import (
"fmt"
"github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2"
"github.com/hashicorp/packer/helper/common"
"github.com/hashicorp/packer/packer" "github.com/hashicorp/packer/packer"
"github.com/zclconf/go-cty/cty" "github.com/zclconf/go-cty/cty"
) )
@ -42,7 +44,7 @@ func (cfg *PackerConfig) EvalContext() *hcl.EvalContext {
// getCoreBuildProvisioners takes a list of provisioner block, starts according // getCoreBuildProvisioners takes a list of provisioner block, starts according
// provisioners and sends parsed HCL2 over to it. // 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 var diags hcl.Diagnostics
res := []packer.CoreBuildProvisioner{} res := []packer.CoreBuildProvisioner{}
for _, pb := range blocks { for _, pb := range blocks {
@ -62,11 +64,11 @@ func (p *Parser) getCoreBuildProvisioners(blocks []*ProvisionerBlock, ectx *hcl.
// getCoreBuildProvisioners takes a list of post processor block, starts // getCoreBuildProvisioners takes a list of post processor block, starts
// according provisioners and sends parsed HCL2 over to it. // 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 var diags hcl.Diagnostics
res := []packer.CoreBuildPostProcessor{} res := []packer.CoreBuildPostProcessor{}
for _, ppb := range blocks { for _, ppb := range blocks {
postProcessor, moreDiags := p.startPostProcessor(ppb, ectx) postProcessor, moreDiags := p.startPostProcessor(ppb, ectx, generatedVars)
diags = append(diags, moreDiags...) diags = append(diags, moreDiags...)
if moreDiags.HasErrors() { if moreDiags.HasErrors() {
continue continue
@ -104,12 +106,26 @@ func (p *Parser) getBuilds(cfg *PackerConfig) ([]packer.Build, hcl.Diagnostics)
if moreDiags.HasErrors() { if moreDiags.HasErrors() {
continue 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...) diags = append(diags, moreDiags...)
if moreDiags.HasErrors() { if moreDiags.HasErrors() {
continue continue
} }
postProcessors, moreDiags := p.getCoreBuildPostProcessors(build.PostProcessors, cfg.EvalContext()) postProcessors, moreDiags := p.getCoreBuildPostProcessors(build.PostProcessors, cfg.EvalContext(), generatedPlaceholderMap)
pps := [][]packer.CoreBuildPostProcessor{} pps := [][]packer.CoreBuildPostProcessor{}
if len(postProcessors) > 0 { if len(postProcessors) > 0 {
pps = [][]packer.CoreBuildPostProcessor{postProcessors} pps = [][]packer.CoreBuildPostProcessor{postProcessors}
@ -124,6 +140,7 @@ func (p *Parser) getBuilds(cfg *PackerConfig) ([]packer.Build, hcl.Diagnostics)
Builder: builder, Builder: builder,
Provisioners: provisioners, Provisioners: provisioners,
PostProcessors: pps, PostProcessors: pps,
Prepared: true,
} }
res = append(res, pcb) res = append(res, pcb)
} }

View File

@ -58,6 +58,7 @@ func TestParser_complete(t *testing.T) {
[]packer.Build{ []packer.Build{
&packer.CoreBuild{ &packer.CoreBuild{
Type: "virtualbox-iso", Type: "virtualbox-iso",
Prepared: true,
Builder: basicMockBuilder, Builder: basicMockBuilder,
Provisioners: []packer.CoreBuildProvisioner{ Provisioners: []packer.CoreBuildProvisioner{
{ {

View File

@ -97,6 +97,9 @@ type CoreBuild struct {
TemplatePath string TemplatePath string
Variables map[string]string Variables map[string]string
// Indicates whether the build is already initialized before calling Prepare(..)
Prepared bool
debug bool debug bool
force bool force bool
onError string onError string
@ -132,6 +135,13 @@ func (b *CoreBuild) Name() string {
// and any hooks. This _must_ be called prior to Run. The parameter is the // and any hooks. This _must_ be called prior to Run. The parameter is the
// overrides for the variables within the template (if any). // overrides for the variables within the template (if any).
func (b *CoreBuild) Prepare() (warn []string, err error) { 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() b.l.Lock()
defer b.l.Unlock() defer b.l.Unlock()

View File

@ -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) { func TestBuild_Prepare_Twice(t *testing.T) {
build := testBuild() build := testBuild()
warn, err := build.Prepare() warn, err := build.Prepare()