diff --git a/command/build_test.go b/command/build_test.go index 5cc9ba10a..e464b3401 100644 --- a/command/build_test.go +++ b/command/build_test.go @@ -228,8 +228,8 @@ func TestBuild(t *testing.T) { testFixture("hcl-only-except"), }, fileCheck: fileCheck{ - expected: []string{"chocolate.txt", "vanilla.txt"}, notExpected: []string{"cherry.txt"}, + expected: []string{"chocolate.txt", "vanilla.txt"}, }, }, } @@ -341,109 +341,26 @@ func TestBuildProvisionAndPosProcessWithBuildVariablesSharing(t *testing.T) { c := &BuildCommand{ Meta: testMetaFile(t), } - tc := []struct { - name string - args []string - expectedFiles []string - notExpectedFiles []string - }{ - { - name: "JSON: basic template", - args: []string{ - filepath.Join(testFixture("build-variable-sharing"), "template.json"), - }, - expectedFiles: []string{ - "provisioner.Null.txt", - "post-processor.Null.txt", - }, - notExpectedFiles: []string{}, - }, - { - name: "HCL2: basic template", - args: []string{ - filepath.Join(testFixture("build-variable-sharing"), "basic_template.pkr.hcl"), - }, - expectedFiles: []string{ - "provisioner.Null.txt", - "post-processor.Null.txt", - }, - notExpectedFiles: []string{}, - }, - { - name: "HCL2: basic template with build variables within HCL function", - args: []string{ - filepath.Join(testFixture("build-variable-sharing"), "basic_template_with_hcl_func.pkr.hcl"), - }, - expectedFiles: []string{ - "provisioner.Null.txt", - "provisioner.NULL.txt", - "post-processor.Null.txt", - "post-processor.NULL.txt", - }, - notExpectedFiles: []string{}, - }, - { - name: "HCL2: basic template with named build", - args: []string{ - filepath.Join(testFixture("build-variable-sharing"), "named_build.pkr.hcl"), - }, - expectedFiles: []string{ - "provisioner.Null.txt", - "post-processor.Null.txt", - }, - notExpectedFiles: []string{}, - }, - { - name: "HCL2: multiple build block sharing same sources", - args: []string{ - filepath.Join(testFixture("build-variable-sharing"), "multiple_build_blocks.pkr.hcl"), - }, - expectedFiles: []string{ - "vanilla.chocolate.provisioner.Null.txt", - "vanilla.chocolate.post-processor.Null.txt", - "apple.chocolate.provisioner.Null.txt", - "apple.chocolate.post-processor.Null.txt", - "sugar.banana.provisioner.Null.txt", - "sugar.banana.post-processor.Null.txt", - }, - notExpectedFiles: []string{}, - }, - { - name: "HCL2: multiple sources build with only/except set for provisioner and post-processors", - args: []string{ - filepath.Join(testFixture("build-variable-sharing"), "multiple_source_build.pkr.hcl"), - }, - expectedFiles: []string{ - "all.Null.txt", - }, - notExpectedFiles: []string{ - "chocolate.Null.txt", - "banana.Null.txt", - }, - }, + + args := []string{ + filepath.Join(testFixture("build-variable-sharing"), "template.json"), } - for _, tt := range tc { - t.Run(tt.name, func(t *testing.T) { - defer cleanup(tt.expectedFiles...) - defer cleanup(tt.notExpectedFiles...) + files := []string{ + "provisioner.Null.txt", + "post-processor.Null.txt", + } - if code := c.Run(tt.args); code != 0 { - fatalCommand(t, c.Meta) - } + defer cleanup(files...) - for _, f := range tt.expectedFiles { - if !fileExists(f) { - t.Errorf("Expected to find %s", f) - } - } + if code := c.Run(args); code != 0 { + fatalCommand(t, c.Meta) + } - for _, f := range tt.notExpectedFiles { - if fileExists(f) { - t.Errorf("Not expected to find %s", f) - } - } - }) + for _, f := range files { + if !fileExists(f) { + t.Errorf("Expected to find %s", f) + } } } diff --git a/command/test-fixtures/build-variable-sharing/basic_template.pkr.hcl b/command/test-fixtures/build-variable-sharing/basic_template.pkr.hcl deleted file mode 100644 index 052a9b072..000000000 --- a/command/test-fixtures/build-variable-sharing/basic_template.pkr.hcl +++ /dev/null @@ -1,15 +0,0 @@ -source "null" "chocolate" { - communicator = "none" -} - -build { - sources = ["null.chocolate"] - - provisioner "shell-local" { - inline = ["echo hi > provisioner.${build.ID}.txt"] - } - - post-processor "shell-local" { - inline = ["echo hi > post-processor.${build.ID}.txt"] - } -} \ No newline at end of file diff --git a/command/test-fixtures/build-variable-sharing/basic_template_with_hcl_func.pkr.hcl b/command/test-fixtures/build-variable-sharing/basic_template_with_hcl_func.pkr.hcl deleted file mode 100644 index 218c28f2a..000000000 --- a/command/test-fixtures/build-variable-sharing/basic_template_with_hcl_func.pkr.hcl +++ /dev/null @@ -1,21 +0,0 @@ -source "null" "chocolate" { - communicator = "none" -} - -build { - sources = ["null.chocolate"] - - provisioner "shell-local" { - inline = [ - "echo hi > provisioner.${build.ID}.txt", - "echo hi > provisioner.${upper(build.ID)}.txt" - ] - } - - post-processor "shell-local" { - inline = [ - "echo hi > post-processor.${build.ID}.txt", - "echo hi > post-processor.${upper(build.ID)}.txt" - ] - } -} \ No newline at end of file diff --git a/command/test-fixtures/build-variable-sharing/multiple_build_blocks.pkr.hcl b/command/test-fixtures/build-variable-sharing/multiple_build_blocks.pkr.hcl deleted file mode 100644 index 4af6bcc5b..000000000 --- a/command/test-fixtures/build-variable-sharing/multiple_build_blocks.pkr.hcl +++ /dev/null @@ -1,46 +0,0 @@ -source "null" "chocolate" { - communicator = "none" -} - -source "null" "banana" { - communicator = "none" -} - -build { - name = "vanilla" - sources = ["null.chocolate"] - - provisioner "shell-local" { - inline = ["echo hi > vanilla.chocolate.provisioner.${build.ID}.txt"] - } - - post-processor "shell-local" { - inline = ["echo hi > vanilla.chocolate.post-processor.${build.ID}.txt"] - } -} - -build { - name = "apple" - sources = ["null.chocolate"] - - provisioner "shell-local" { - inline = ["echo hi > apple.chocolate.provisioner.${build.ID}.txt"] - } - - post-processor "shell-local" { - inline = ["echo hi > apple.chocolate.post-processor.${build.ID}.txt"] - } -} - -build { - name = "sugar" - sources = ["null.banana"] - - provisioner "shell-local" { - inline = ["echo hi > sugar.banana.provisioner.${build.ID}.txt"] - } - - post-processor "shell-local" { - inline = ["echo hi > sugar.banana.post-processor.${build.ID}.txt"] - } -} \ No newline at end of file diff --git a/command/test-fixtures/build-variable-sharing/multiple_source_build.pkr.hcl b/command/test-fixtures/build-variable-sharing/multiple_source_build.pkr.hcl deleted file mode 100644 index 8e1f0e97a..000000000 --- a/command/test-fixtures/build-variable-sharing/multiple_source_build.pkr.hcl +++ /dev/null @@ -1,32 +0,0 @@ -source "null" "chocolate" { - communicator = "none" -} - -source "null" "banana" { - communicator = "none" -} - -build { - name = "vanilla" - sources = [ - "null.chocolate", - "null.banana", - ] - - provisioner "shell-local" { - inline = [ - "echo hi > all.${build.ID}.txt", - "echo hi > chocolate.${build.ID}.txt", - "echo hi > banana.${build.ID}.txt" - ] - } - - post-processor "shell-local" { - only = ["null.chocolate"] - inline = ["rm chocolate.${build.ID}.txt"] - } - post-processor "shell-local" { - except = ["null.chocolate"] - inline = ["rm banana.${build.ID}.txt"] - } -} \ No newline at end of file diff --git a/command/test-fixtures/build-variable-sharing/named_build.pkr.hcl b/command/test-fixtures/build-variable-sharing/named_build.pkr.hcl deleted file mode 100644 index 6e110365f..000000000 --- a/command/test-fixtures/build-variable-sharing/named_build.pkr.hcl +++ /dev/null @@ -1,16 +0,0 @@ -source "null" "chocolate" { - communicator = "none" -} - -build { - name = "vanilla" - sources = ["null.chocolate"] - - provisioner "shell-local" { - inline = ["echo hi > provisioner.${build.ID}.txt"] - } - - post-processor "shell-local" { - inline = ["echo hi > post-processor.${build.ID}.txt"] - } -} \ No newline at end of file diff --git a/hcl2template/common_test.go b/hcl2template/common_test.go index 541d077b2..5db6dc6c2 100644 --- a/hcl2template/common_test.go +++ b/hcl2template/common_test.go @@ -121,37 +121,6 @@ func testParse(t *testing.T, tests []parseTest) { if tt.getBuildsWantDiags == (gotDiags == nil) { t.Fatalf("Parser.getBuilds() unexpected diagnostics. %s", gotDiags) } - - // Validates implementation of HCL2ProvisionerPrepare and HCL2PostProcessorsPrepare - for _, build := range gotBuilds { - coreBuild, ok := build.(*packer.CoreBuild) - if !ok { - t.Fatalf("build %s should implement CoreBuild", build.Name()) - } - if coreBuild.HCL2ProvisionerPrepare == nil { - t.Fatalf("build %s should have HCL2ProvisionerPrepare implementation", build.Name()) - } - if coreBuild.HCL2PostProcessorsPrepare == nil { - t.Fatalf("build %s should have HCL2PostProcessorsPrepare implementation", build.Name()) - } - - provisioners, diags := coreBuild.HCL2ProvisionerPrepare(nil) - if diags.HasErrors() { - t.Fatalf("build %s: HCL2ProvisionerPrepare should prepare provisioners", build.Name()) - } - coreBuild.Provisioners = provisioners - - postProcessors, diags := coreBuild.HCL2PostProcessorsPrepare(nil) - if diags.HasErrors() { - t.Fatalf("build %s: HCL2PostProcessorsPrepare should prepare post-processors", build.Name()) - } - if len(postProcessors) > 0 { - coreBuild.PostProcessors = [][]packer.CoreBuildPostProcessor{postProcessors} - } else { - coreBuild.PostProcessors = [][]packer.CoreBuildPostProcessor{} - } - } - if diff := cmp.Diff(tt.getBuildsWantBuilds, gotBuilds, cmpopts.IgnoreUnexported( cty.Value{}, @@ -161,7 +130,6 @@ func testParse(t *testing.T, tests []parseTest) { packer.CoreBuildPostProcessor{}, null.Builder{}, ), - cmpopts.IgnoreFields(packer.CoreBuild{}, "HCL2ProvisionerPrepare", "HCL2PostProcessorsPrepare"), ); diff != "" { t.Fatalf("Parser.getBuilds() wrong packer builds. %s", diff) } diff --git a/hcl2template/types.build.post-processor.go b/hcl2template/types.build.post-processor.go index 6fa249f00..b45b682f5 100644 --- a/hcl2template/types.build.post-processor.go +++ b/hcl2template/types.build.post-processor.go @@ -6,7 +6,6 @@ import ( "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/gohcl" "github.com/hashicorp/packer/packer" - "github.com/zclconf/go-cty/cty" ) // ProvisionerBlock references a detected but unparsed post processor @@ -62,7 +61,7 @@ func (p *Parser) decodePostProcessor(block *hcl.Block) (*PostProcessorBlock, hcl return postProcessor, diags } -func (cfg *PackerConfig) startPostProcessor(source SourceBlock, pp *PostProcessorBlock, ectx *hcl.EvalContext) (packer.PostProcessor, hcl.Diagnostics) { +func (cfg *PackerConfig) startPostProcessor(source SourceBlock, pp *PostProcessorBlock, ectx *hcl.EvalContext, generatedVars map[string]string) (packer.PostProcessor, hcl.Diagnostics) { // ProvisionerBlock represents a detected but unparsed provisioner var diags hcl.Diagnostics @@ -77,7 +76,7 @@ func (cfg *PackerConfig) startPostProcessor(source SourceBlock, pp *PostProcesso } flatProvisinerCfg, moreDiags := decodeHCL2Spec(pp.Rest, ectx, postProcessor) diags = append(diags, moreDiags...) - err = postProcessor.Configure(source.builderVariables(), flatProvisinerCfg) + err = postProcessor.Configure(source.builderVariables(), flatProvisinerCfg, generatedVars) if err != nil { diags = append(diags, &hcl.Diagnostic{ Severity: hcl.DiagError, @@ -89,46 +88,3 @@ func (cfg *PackerConfig) startPostProcessor(source SourceBlock, pp *PostProcesso } return postProcessor, diags } - -type postProcessorsPrepare struct { - cfg *PackerConfig - postProcessorBlock []*PostProcessorBlock - src SourceRef -} - -// HCL2PostProcessorsPrepare is used by the CoreBuild at the runtime, after running the build and before running the post-processors, -// to interpolate any build variable by decoding and preparing it. -func (pp *postProcessorsPrepare) HCL2PostProcessorsPrepare(builderArtifact packer.Artifact) ([]packer.CoreBuildPostProcessor, hcl.Diagnostics) { - src := pp.cfg.Sources[pp.src.Ref()] - - generatedData := make(map[string]interface{}) - if builderArtifact != nil { - artifactStateData := builderArtifact.State("generated_data") - if artifactStateData != nil { - for k, v := range artifactStateData.(map[interface{}]interface{}) { - generatedData[k.(string)] = v - } - } - } - - variables := make(Variables) - for k, v := range generatedData { - if value, ok := v.(string); ok { - variables[k] = &Variable{ - DefaultValue: cty.StringVal(value), - Type: cty.String, - } - } - } - variablesVal, _ := variables.Values() - - generatedVariables := map[string]cty.Value{ - sourcesAccessor: cty.ObjectVal(map[string]cty.Value{ - "type": cty.StringVal(src.Type), - "name": cty.StringVal(src.Name), - }), - buildAccessor: cty.ObjectVal(variablesVal), - } - - return pp.cfg.getCoreBuildPostProcessors(src, pp.postProcessorBlock, pp.cfg.EvalContext(generatedVariables)) -} diff --git a/hcl2template/types.build.provisioners.go b/hcl2template/types.build.provisioners.go index a2eeb2ee9..70756f39e 100644 --- a/hcl2template/types.build.provisioners.go +++ b/hcl2template/types.build.provisioners.go @@ -7,7 +7,6 @@ import ( "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/gohcl" "github.com/hashicorp/packer/packer" - "github.com/zclconf/go-cty/cty" ) // OnlyExcept is a struct that is meant to be embedded that contains the @@ -133,7 +132,7 @@ func (p *Parser) decodeProvisioner(block *hcl.Block) (*ProvisionerBlock, hcl.Dia return provisioner, diags } -func (cfg *PackerConfig) startProvisioner(source SourceBlock, pb *ProvisionerBlock, ectx *hcl.EvalContext) (packer.Provisioner, hcl.Diagnostics) { +func (cfg *PackerConfig) startProvisioner(source SourceBlock, pb *ProvisionerBlock, ectx *hcl.EvalContext, generatedVars map[string]string) (packer.Provisioner, hcl.Diagnostics) { var diags hcl.Diagnostics provisioner, err := cfg.provisionersSchemas.Start(pb.PType) @@ -156,7 +155,7 @@ func (cfg *PackerConfig) startProvisioner(source SourceBlock, pb *ProvisionerBlo // configs := make([]interface{}, 2) // configs = append(, flatProvisionerCfg) // configs = append(configs, generatedVars) - err = provisioner.Prepare(source.builderVariables(), flatProvisionerCfg) + err = provisioner.Prepare(source.builderVariables(), flatProvisionerCfg, generatedVars) if err != nil { diags = append(diags, &hcl.Diagnostic{ Severity: hcl.DiagError, @@ -168,36 +167,3 @@ func (cfg *PackerConfig) startProvisioner(source SourceBlock, pb *ProvisionerBlo } return provisioner, diags } - -type provisionerPrepare struct { - cfg *PackerConfig - provisionerBlock []*ProvisionerBlock - src SourceRef -} - -// HCL2ProvisionerPrepare is used by the ProvisionHook at the runtime in the provision step -// to interpolate any build variable by decoding and preparing it again. -func (pp *provisionerPrepare) HCL2ProvisionerPrepare(data map[string]interface{}) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) { - src := pp.cfg.Sources[pp.src.Ref()] - - variables := make(Variables) - for k, v := range data { - if value, ok := v.(string); ok { - variables[k] = &Variable{ - DefaultValue: cty.StringVal(value), - Type: cty.String, - } - } - } - variablesVal, _ := variables.Values() - - generatedVariables := map[string]cty.Value{ - sourcesAccessor: cty.ObjectVal(map[string]cty.Value{ - "type": cty.StringVal(src.Type), - "name": cty.StringVal(src.Name), - }), - buildAccessor: cty.ObjectVal(variablesVal), - } - - return pp.cfg.getCoreBuildProvisioners(src, pp.provisionerBlock, pp.cfg.EvalContext(generatedVariables)) -} diff --git a/hcl2template/types.packer_config.go b/hcl2template/types.packer_config.go index b791dabd1..2758c5ed1 100644 --- a/hcl2template/types.packer_config.go +++ b/hcl2template/types.packer_config.go @@ -7,6 +7,7 @@ import ( "github.com/gobwas/glob" "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hclsyntax" + "github.com/hashicorp/packer/helper/common" "github.com/hashicorp/packer/packer" "github.com/zclconf/go-cty/cty" ) @@ -40,7 +41,6 @@ type PackerConfig struct { except []glob.Glob only []glob.Glob - debug bool } type ValidationOptions struct { @@ -51,7 +51,6 @@ const ( inputVariablesAccessor = "var" localsAccessor = "local" sourcesAccessor = "source" - buildAccessor = "build" ) // EvalContext returns the *hcl.EvalContext that will be passed to an hcl @@ -199,18 +198,19 @@ func (c *PackerConfig) evaluateLocalVariable(local *Local) hcl.Diagnostics { // getCoreBuildProvisioners takes a list of provisioner block, starts according // provisioners and sends parsed HCL2 over to it. -func (cfg *PackerConfig) getCoreBuildProvisioners(source SourceBlock, blocks []*ProvisionerBlock, ectx *hcl.EvalContext) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) { +func (cfg *PackerConfig) getCoreBuildProvisioners(source SourceBlock, blocks []*ProvisionerBlock, ectx *hcl.EvalContext, generatedVars map[string]string) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) { var diags hcl.Diagnostics res := []packer.CoreBuildProvisioner{} for _, pb := range blocks { if pb.OnlyExcept.Skip(source.String()) { continue } - provisioner, moreDiags := cfg.startProvisioner(source, pb, ectx) + provisioner, moreDiags := cfg.startProvisioner(source, pb, ectx, generatedVars) diags = append(diags, moreDiags...) if moreDiags.HasErrors() { continue } + // If we're pausing, we wrap the provisioner in a special pauser. if pb.PauseBefore != 0 { provisioner = &packer.PausedProvisioner{ @@ -229,11 +229,6 @@ func (cfg *PackerConfig) getCoreBuildProvisioners(source SourceBlock, blocks []* Provisioner: provisioner, } } - if cfg.debug { - provisioner = &packer.DebuggedProvisioner{ - Provisioner: provisioner, - } - } res = append(res, packer.CoreBuildProvisioner{ PType: pb.PType, @@ -246,7 +241,7 @@ func (cfg *PackerConfig) getCoreBuildProvisioners(source SourceBlock, blocks []* // getCoreBuildProvisioners takes a list of post processor block, starts // according provisioners and sends parsed HCL2 over to it. -func (cfg *PackerConfig) getCoreBuildPostProcessors(source SourceBlock, blocks []*PostProcessorBlock, ectx *hcl.EvalContext) ([]packer.CoreBuildPostProcessor, hcl.Diagnostics) { +func (cfg *PackerConfig) getCoreBuildPostProcessors(source SourceBlock, blocks []*PostProcessorBlock, ectx *hcl.EvalContext, generatedVars map[string]string) ([]packer.CoreBuildPostProcessor, hcl.Diagnostics) { var diags hcl.Diagnostics res := []packer.CoreBuildPostProcessor{} for _, ppb := range blocks { @@ -270,7 +265,7 @@ func (cfg *PackerConfig) getCoreBuildPostProcessors(source SourceBlock, blocks [ break } - postProcessor, moreDiags := cfg.startPostProcessor(source, ppb, ectx) + postProcessor, moreDiags := cfg.startPostProcessor(source, ppb, ectx, generatedVars) diags = append(diags, moreDiags...) if moreDiags.HasErrors() { continue @@ -293,8 +288,6 @@ func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packer.Build res := []packer.Build{} var diags hcl.Diagnostics - cfg.debug = opts.Debug - for _, build := range cfg.Builds { for _, from := range build.Sources { src, found := cfg.Sources[from.Ref()] @@ -361,6 +354,13 @@ func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packer.Build continue } + variables := map[string]cty.Value{ + sourcesAccessor: cty.ObjectVal(map[string]cty.Value{ + "type": cty.StringVal(src.Type), + "name": cty.StringVal(src.Name), + }), + } + // 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 @@ -369,42 +369,30 @@ func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packer.Build generatedPlaceholderMap := packer.BasicPlaceholderData() if generatedVars != nil { for _, k := range generatedVars { - generatedPlaceholderMap[k] = "" + generatedPlaceholderMap[k] = fmt.Sprintf("Build_%s. "+ + common.PlaceholderMsg, k) } } - buildVariables, _ := setBuildVariables(generatedPlaceholderMap).Values() - variables := map[string]cty.Value{ - sourcesAccessor: cty.ObjectVal(map[string]cty.Value{ - "type": cty.StringVal(src.Type), - "name": cty.StringVal(src.Name), - }), - buildAccessor: cty.ObjectVal(buildVariables), - } - - _, moreDiags = cfg.getCoreBuildProvisioners(src, build.ProvisionerBlocks, cfg.EvalContext(variables)) + provisioners, moreDiags := cfg.getCoreBuildProvisioners(src, build.ProvisionerBlocks, cfg.EvalContext(variables), generatedPlaceholderMap) diags = append(diags, moreDiags...) if moreDiags.HasErrors() { continue } - _, moreDiags = cfg.getCoreBuildPostProcessors(src, build.PostProcessors, cfg.EvalContext(variables)) + postProcessors, moreDiags := cfg.getCoreBuildPostProcessors(src, build.PostProcessors, cfg.EvalContext(variables), generatedPlaceholderMap) + pps := [][]packer.CoreBuildPostProcessor{} + if len(postProcessors) > 0 { + pps = [][]packer.CoreBuildPostProcessor{postProcessors} + } diags = append(diags, moreDiags...) if moreDiags.HasErrors() { continue } pcb.Builder = builder + pcb.Provisioners = provisioners + pcb.PostProcessors = pps pcb.Prepared = true - pcb.HCL2ProvisionerPrepare = (&provisionerPrepare{ - cfg: cfg, - provisionerBlock: build.ProvisionerBlocks, - src: from, - }).HCL2ProvisionerPrepare - pcb.HCL2PostProcessorsPrepare = (&postProcessorsPrepare{ - cfg: cfg, - postProcessorBlock: build.PostProcessors, - src: from, - }).HCL2PostProcessorsPrepare // Prepare just sets the "prepareCalled" flag on CoreBuild, since // we did all the prep here. @@ -425,17 +413,6 @@ func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packer.Build return res, diags } -func setBuildVariables(generatedVars map[string]string) Variables { - variables := make(Variables) - for k := range generatedVars { - variables[k] = &Variable{ - DefaultValue: cty.StringVal("unknown"), - Type: cty.String, - } - } - return variables -} - var PackerConsoleHelp = strings.TrimSpace(` Packer console HCL2 Mode. The Packer console allows you to experiment with Packer interpolations. diff --git a/packer/build.go b/packer/build.go index 78b16ec3f..ca900797f 100644 --- a/packer/build.go +++ b/packer/build.go @@ -6,7 +6,6 @@ import ( "log" "sync" - "github.com/hashicorp/hcl/v2" "github.com/hashicorp/packer/helper/common" ) @@ -102,11 +101,6 @@ type CoreBuild struct { // Indicates whether the build is already initialized before calling Prepare(..) Prepared bool - // HCL2ProvisionerPrepare and HCL2PostProcessorsPrepare are used to interpolate any build variable by decoding and preparing - // the Provisioners and Post-Processors at runtime for HCL2 templates. - HCL2ProvisionerPrepare func(data map[string]interface{}) ([]CoreBuildProvisioner, hcl.Diagnostics) - HCL2PostProcessorsPrepare func(builderArtifact Artifact) ([]CoreBuildPostProcessor, hcl.Diagnostics) - debug bool force bool onError string @@ -274,12 +268,6 @@ func (b *CoreBuild) Run(ctx context.Context, originalUi Ui) ([]Artifact, error) }) } - if b.HCL2ProvisionerPrepare != nil { - hooks[HookProvision] = append(hooks[HookProvision], &ProvisionHook{ - HCL2Prepare: b.HCL2ProvisionerPrepare, - }) - } - if b.CleanupProvisioner.PType != "" { hookedCleanupProvisioner := &HookedProvisioner{ b.CleanupProvisioner.Provisioner, @@ -315,17 +303,6 @@ func (b *CoreBuild) Run(ctx context.Context, originalUi Ui) ([]Artifact, error) } errors := make([]error, 0) - - if b.HCL2PostProcessorsPrepare != nil { - // For HCL2, decode and prepare Post-Processors to interpolate build variables. - postProcessors, diags := b.HCL2PostProcessorsPrepare(builderArtifact) - if diags.HasErrors() { - errors = append(errors, diags) - } else if len(postProcessors) > 0 { - b.PostProcessors = [][]CoreBuildPostProcessor{postProcessors} - } - } - keepOriginalArtifact := len(b.PostProcessors) == 0 // Run the post-processors diff --git a/packer/provisioner.go b/packer/provisioner.go index d549c431b..905b28971 100644 --- a/packer/provisioner.go +++ b/packer/provisioner.go @@ -7,7 +7,6 @@ import ( "sync" "time" - "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/hcldec" "github.com/hashicorp/packer/helper/common" ) @@ -41,8 +40,6 @@ type ProvisionHook struct { // The provisioners to run as part of the hook. These should already // be prepared (by calling Prepare) at some earlier stage. Provisioners []*HookedProvisioner - - HCL2Prepare func(data map[string]interface{}) ([]CoreBuildProvisioner, hcl.Diagnostics) } // Provisioners interpolate most of their fields in the prepare stage; this @@ -116,7 +113,7 @@ func CastDataToMap(data interface{}) map[string]interface{} { // Runs the provisioners in order. func (h *ProvisionHook) Run(ctx context.Context, name string, ui Ui, comm Communicator, data interface{}) error { // Shortcut - if len(h.Provisioners) == 0 && h.HCL2Prepare == nil { + if len(h.Provisioners) == 0 { return nil } @@ -126,34 +123,10 @@ func (h *ProvisionHook) Run(ctx context.Context, name string, ui Ui, comm Commun "`communicator` config was set to \"none\". If you have any provisioners\n" + "then a communicator is required. Please fix this to continue.") } - - cast := CastDataToMap(data) - - if h.HCL2Prepare != nil { - // For HCL2, decode and prepare Provisioners now to interpolate build variables - coreP, diags := h.HCL2Prepare(cast) - if diags.HasErrors() { - return diags - } - hookedProvisioners := make([]*HookedProvisioner, len(coreP)) - for i, p := range coreP { - var pConfig interface{} - if len(p.config) > 0 { - pConfig = p.config[0] - } - - hookedProvisioners[i] = &HookedProvisioner{ - Provisioner: p.Provisioner, - Config: pConfig, - TypeName: p.PType, - } - } - h.Provisioners = hookedProvisioners - } - for _, p := range h.Provisioners { ts := CheckpointReporter.AddSpan(p.TypeName, "provisioner", p.Config) + cast := CastDataToMap(data) err := p.Provisioner.Provision(ctx, ui, comm, cast) ts.End(err) diff --git a/post-processor/shell-local/post-processor.go b/post-processor/shell-local/post-processor.go index a17ce67e3..0cbf9fe71 100644 --- a/post-processor/shell-local/post-processor.go +++ b/post-processor/shell-local/post-processor.go @@ -42,9 +42,9 @@ func (p *PostProcessor) Configure(raws ...interface{}) error { func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) { generatedData := make(map[string]interface{}) - artifactStateData := artifact.State("generated_data") - if artifactStateData != nil { - for k, v := range artifactStateData.(map[interface{}]interface{}) { + artifactSateData := artifact.State("generated_data") + if artifactSateData != nil { + for k, v := range artifactSateData.(map[interface{}]interface{}) { generatedData[k.(string)] = v } } diff --git a/website/data/docs-navigation.js b/website/data/docs-navigation.js index 0669763f6..a05fe8525 100644 --- a/website/data/docs-navigation.js +++ b/website/data/docs-navigation.js @@ -140,7 +140,6 @@ export default [ }, 'variables', 'locals', - 'contextual-variables', 'syntax', 'onlyexcept', 'expressions', diff --git a/website/pages/docs/builders/amazon/chroot.mdx b/website/pages/docs/builders/amazon/chroot.mdx index 7bf474b22..d5165d6f3 100644 --- a/website/pages/docs/builders/amazon/chroot.mdx +++ b/website/pages/docs/builders/amazon/chroot.mdx @@ -328,52 +328,13 @@ variables are available: - `SourceAMIOwnerName` - The source AMI owner alias/name (for example `amazon`). - `SourceAMITags` - The source AMI Tags, as a `map[string]string` object. -## Build Shared Information Variables +## Build function template engine variables -This builder generates data that are shared with provisioner and post-processor via build function of [template engine](/docs/templates/engine) for JSON and [contextual variables](/docs/from-1.5/contextual-variables) for HCL2. - -The generated variables available for this builder are: +For the build function of [template engine](/docs/templates/engine), the following +variables are available: - `SourceAMIName` - The source AMI Name (for example `ubuntu/images/ebs-ssd/ubuntu-xenial-16.04-amd64-server-20180306`) used to build the AMI. - `Device` - Root device path. - `MountPath` - Device mounting path. - -Usage example: - - - - -```json -"post-processors": [ - { - "type": "manifest", - "output": "manifest.json", - "strip_path": true, - "custom_data": { - "source_ami_name": "{{ build `SourceAMIName` }}", - "device": "{{ build `Device` }}", - "mount_path": "{{ build `MountPath` }}" - } - } -] -``` - - - - -```hcl -post-processor "manifest" { - output = "manifest.json" - strip_path = true - custom_data = { - source_ami_name = "${build.SourceAMIName}" - device = "${build.Device}" - mount_path = "${build.MountPath}" - } -} -``` - - - diff --git a/website/pages/docs/builders/amazon/ebs.mdx b/website/pages/docs/builders/amazon/ebs.mdx index e0db95037..351f97915 100644 --- a/website/pages/docs/builders/amazon/ebs.mdx +++ b/website/pages/docs/builders/amazon/ebs.mdx @@ -235,50 +235,15 @@ variables are available: - `SourceAMIOwnerName` - The source AMI owner alias/name (for example `amazon`). - `SourceAMITags` - The source AMI Tags, as a `map[string]string` object. -## Build Shared Information Variables +## Build function template engine variables -This builder generates data that are shared with provisioner and post-processor via build function of [template engine](/docs/templates/engine) for JSON and [contextual variables](/docs/from-1.5/contextual-variables) for HCL2. - -The generated variables available for this builder are: +For the build function of [template engine](/docs/templates/engine), the following +variables are available: - `SourceAMIName` - The source AMI Name (for example `ubuntu/images/ebs-ssd/ubuntu-xenial-16.04-amd64-server-20180306`) used to build the AMI. -Usage example: - - - - -```json -"post-processors": [ - { - "type": "manifest", - "output": "manifest.json", - "strip_path": true, - "custom_data": { - "source_ami_name": "{{ build `SourceAMIName` }}" - } - } -] -``` - - - - -```hcl -post-processor "manifest" { - output = "manifest.json" - strip_path = true - custom_data = { - source_ami_name = "${build.SourceAMIName}" - } -} -``` - - - - ## Tag Example Here is an example using the optional AMI tags. This will add the tags diff --git a/website/pages/docs/builders/amazon/ebssurrogate.mdx b/website/pages/docs/builders/amazon/ebssurrogate.mdx index 529db51e0..deb506e13 100644 --- a/website/pages/docs/builders/amazon/ebssurrogate.mdx +++ b/website/pages/docs/builders/amazon/ebssurrogate.mdx @@ -207,50 +207,15 @@ variables are available: - `SourceAMIOwnerName` - The source AMI owner alias/name (for example `amazon`). - `SourceAMITags` - The source AMI Tags, as a `map[string]string` object. -## Build Shared Information Variables +## Build function template engine variables -This builder generates data that are shared with provisioner and post-processor via build function of [template engine](/docs/templates/engine) for JSON and [contextual variables](/docs/from-1.5/contextual-variables) for HCL2. - -The generated variables available for this builder are: +For the build function of [template engine](/docs/templates/engine), the following +variables are available: - `SourceAMIName` - The source AMI Name (for example `ubuntu/images/ebs-ssd/ubuntu-xenial-16.04-amd64-server-20180306`) used to build the AMI. -Usage example: - - - - -```json -"post-processors": [ - { - "type": "manifest", - "output": "manifest.json", - "strip_path": true, - "custom_data": { - "source_ami_name": "{{ build `SourceAMIName` }}" - } - } -] -``` - - - - -```hcl -post-processor "manifest" { - output = "manifest.json" - strip_path = true - custom_data = { - source_ami_name = "${build.SourceAMIName}" - } -} -``` - - - - -> **Note:** Packer uses pre-built AMIs as the source for building images. These source AMIs may include volumes that are not flagged to be destroyed on termination of the instance building the new image. In addition to those diff --git a/website/pages/docs/builders/amazon/ebsvolume.mdx b/website/pages/docs/builders/amazon/ebsvolume.mdx index 4e25e3dcf..1b5b6aabc 100644 --- a/website/pages/docs/builders/amazon/ebsvolume.mdx +++ b/website/pages/docs/builders/amazon/ebsvolume.mdx @@ -243,48 +243,13 @@ termination of the instance building the new image. In addition to those volumes created by this builder, any volumes in the source AMI which are not marked for deletion on termination will remain in your account. -## Build Shared Information Variables +## Build function template engine variables -This builder generates data that are shared with provisioner and post-processor via build function of [template engine](/docs/templates/engine) for JSON and [contextual variables](/docs/from-1.5/contextual-variables) for HCL2. - -The generated variables available for this builder are: +For the build function of [template engine](/docs/templates/engine), the following +variables are available: - `SourceAMIName` - The source AMI Name (for example `ubuntu/images/ebs-ssd/ubuntu-xenial-16.04-amd64-server-20180306`) used to build the AMI. -Usage example: - - - - -```json -"post-processors": [ - { - "type": "manifest", - "output": "manifest.json", - "strip_path": true, - "custom_data": { - "source_ami_name": "{{ build `SourceAMIName` }}" - } - } -] -``` - - - - -```hcl -post-processor "manifest" { - output = "manifest.json" - strip_path = true - custom_data = { - source_ami_name = "${build.SourceAMIName}" - } -} -``` - - - - @include 'builders/aws-ssh-differentiation-table.mdx' diff --git a/website/pages/docs/builders/amazon/instance.mdx b/website/pages/docs/builders/amazon/instance.mdx index 9abf80da1..69410bbcf 100644 --- a/website/pages/docs/builders/amazon/instance.mdx +++ b/website/pages/docs/builders/amazon/instance.mdx @@ -199,50 +199,15 @@ variables are available: - `SourceAMIOwnerName` - The source AMI owner alias/name (for example `amazon`). - `SourceAMITags` - The source AMI Tags, as a `map[string]string` object. -## Build Shared Information Variables +## Build function template engine variables -This builder generates data that are shared with provisioner and post-processor via build function of [template engine](/docs/templates/engine) for JSON and [contextual variables](/docs/from-1.5/contextual-variables) for HCL2. - -The generated variables available for this builder are: +For the build function of [template engine](/docs/templates/engine), the following +variables are available: - `SourceAMIName` - The source AMI Name (for example `ubuntu/images/ebs-ssd/ubuntu-xenial-16.04-amd64-server-20180306`) used to build the AMI. -Usage example: - - - - -```json -"post-processors": [ - { - "type": "manifest", - "output": "manifest.json", - "strip_path": true, - "custom_data": { - "source_ami_name": "{{ build `SourceAMIName` }}" - } - } -] -``` - - - - -```hcl -post-processor "manifest" { - output = "manifest.json" - strip_path = true - custom_data = { - source_ami_name = "${build.SourceAMIName}" - } -} -``` - - - - ## Custom Bundle Commands A lot of the process required for creating an instance-store backed AMI diff --git a/website/pages/docs/from-1.5/blocks/build/post-processor.mdx b/website/pages/docs/from-1.5/blocks/build/post-processor.mdx index cb94f1ef9..47fccaabb 100644 --- a/website/pages/docs/from-1.5/blocks/build/post-processor.mdx +++ b/website/pages/docs/from-1.5/blocks/build/post-processor.mdx @@ -71,8 +71,3 @@ build { ``` The values within `only` or `except` are _source names_, not builder types. - -## Build Contextual Variables - -Packer allows to access connection information and basic instance state information from a post-processor. These information are stored in the `build` variable. -Check out the [Contextual Variables](/docs/from-1.5/contextual-variables) documentation to learn more about and see some examples of how to use them. diff --git a/website/pages/docs/from-1.5/blocks/build/provisioner.mdx b/website/pages/docs/from-1.5/blocks/build/provisioner.mdx index 5ab488405..0c06e36f8 100644 --- a/website/pages/docs/from-1.5/blocks/build/provisioner.mdx +++ b/website/pages/docs/from-1.5/blocks/build/provisioner.mdx @@ -59,7 +59,7 @@ build { ] provisioner "shell" { # This provisioner only runs for the 'first-example' source. - only = ["source.amazon-ebs.first-example"] + only = ["source.amazon-ebs.first-example"] inline = [ "echo provisioning all the things", @@ -160,8 +160,3 @@ For the above provisioner, Packer will cancel the script if it takes more than 5 minutes. Timeout has no effect in debug mode. - -## Build Contextual Variables - -Packer allows to access connection information and basic instance state information from a provisioner. These information are stored in the `build` variable. -Check out the [Contextual Variables](/docs/from-1.5/contextual-variables) documentation to learn more about and see some examples of how to use them. diff --git a/website/pages/docs/from-1.5/contextual-variables.mdx b/website/pages/docs/from-1.5/contextual-variables.mdx deleted file mode 100644 index 48c91472d..000000000 --- a/website/pages/docs/from-1.5/contextual-variables.mdx +++ /dev/null @@ -1,71 +0,0 @@ ---- -layout: docs -page_title: Contextual Variables - HCL Configuration Language -sidebar_title: Contextual Variables -description: |- - Special variables provide connection information and basic instance state information. - This page covers all existing special variables. ---- - -# Build Variables - -`@include 'from-1.5/beta-hcl2-note.mdx'` - -Build variables will allow you to access connection information and basic instance state information for a builder. -All special build variables are stored in the `build` variable: - -```hcl - provisioner "shell" { - environment_vars = ["TESTVAR=${build.PackerRunUUID}"] - inline = ["echo $TESTVAR"] - } -``` - -Here is the list of available build variables: - -- **ID**: Represents the vm being provisioned. For example, in Amazon it is the instance id; in digitalocean, - it is the droplet id; in Vmware, it is the vm name. - -- **Host**, **Port**, **User** and **Password**: The host, port, user, and password that Packer uses to access the machine. - Useful for using the shell local provisioner to run Ansible or Inspec against the provisioned instance. - -- **ConnType**: Type of communicator being used. For example, for SSH communicator this will be "ssh". - -- **PackerRunUUID**: Current build's unique id. Can be used to specify build artifacts. - An example of that, is when multiple builds runs at the same time producing the same artifact. - It's possible to differentiate these artifacts by naming them with the builds' unique ids. - -- **PackerHTTPIP**, **PackerHTTPPort**, and **PackerHTTPAddr**: HTTP IP, port, and address of the file server Packer creates to serve items in the "http" dir to the vm. The HTTP address is displayed in the format `IP:PORT`. - -- **SSHPublicKey** and **SSHPrivateKey**: The public and private key that Packer uses to connect to the instance. - These are unique to the SSH communicator and are unset when using other communicators. - **SSHPublicKey** and **SSHPrivateKey** can have escape sequences and special characters so their output should be single quoted to avoid surprises. For example: - - ```hcl - provisioner "shell" { - inline = ["echo '${build.SSHPrivateKey}' > /tmp/packer-session.pem"] - } - ``` - -For backwards compatibility, `WinRMPassword` is also available through this -engine, though it is no different than using the more general `Password`. - -All build variables are valid to use with any of the [HCL2 functions](/docs/from-1.5/functions). -Example of using [upper](/docs/from-1.5/functions/string/upper) to upper case the build ID: - -```hcl - post-processor "shell-local" { - inline = ["echo ${upper(build.ID)}"] - } -``` - -For builder-specific builder variables, please also refer to the builder docs: - - - Amazon EC2: [chroot](/docs/builders/amazon/chroot#build-shared-information-variables), - [EBS Volume](/docs/builders/amazon/ebsvolume#build-shared-information-variables), - [EBS](/docs/builders/amazon/ebs#build-shared-information-variables), - [EBS Surrogate](/docs/builders/amazon/ebssurrogate#build-shared-information-variables), - [Instance](/docs/builders/amazon/instance#build-shared-information-variables). - -The HCL2 Special Build Variables is in beta; please report any issues or requests on the Packer -issue tracker on GitHub. diff --git a/website/pages/docs/templates/engine.mdx b/website/pages/docs/templates/engine.mdx index 11ec5f9f2..ebf50fd2e 100644 --- a/website/pages/docs/templates/engine.mdx +++ b/website/pages/docs/templates/engine.mdx @@ -83,8 +83,6 @@ Here is a full list of the available functions for reference. - **ConnType**: Type of communicator being used. For example, for SSH communicator this will be "ssh". - **PackerRunUUID**: Current build's unique id. Can be used to specify build artifacts. - An example of that, is when multiple builds runs at the same time producing the same artifact. - It's possible to differentiate these artifacts by naming them with the builds' unique ids. - **PackerHTTPIP**, **PackerHTTPPort**, and **PackerHTTPAddr**: HTTP IP, port, and address of the file server Packer creates to serve items in the "http" dir to the vm. The HTTP address is displayed in the format `IP:PORT`. @@ -100,20 +98,16 @@ Here is a full list of the available functions for reference. } ``` - For backwards compatibility, `WinRMPassword` is also available through this + For backwards compatability, `WinRMPassword` is also available through this engine, though it is no different than using the more general `Password`. This function is only for use within specific options inside of _provisioners_ -- these options will be listed as being template engines - in the provisioner documentation. + in the provisioner documentation. This feature does not yet work + if the provisioners are being used in conjunction with our chroot builders + or with lxc/lxd builders. - For builder-specific builder variables, please also refer to the builder docs: - - - Amazon EC2: [chroot](/docs/builders/amazon/chroot#build-shared-information-variables), - [EBS Volume](/docs/builders/amazon/ebsvolume#build-shared-information-variables), - [EBS](/docs/builders/amazon/ebs#build-shared-information-variables), - [EBS Surrogate](/docs/builders/amazon/ebssurrogate#build-shared-information-variables), - [Instance](/docs/builders/amazon/instance#build-shared-information-variables). + For builder-specific engine variables, please also refer to the builder docs. This engine is in beta; please report any issues or requests on the Packer issue tracker on GitHub.