diff --git a/command/build_test.go b/command/build_test.go index dc906a80e..812b5c4e2 100644 --- a/command/build_test.go +++ b/command/build_test.go @@ -12,6 +12,7 @@ import ( "testing" "github.com/google/go-cmp/cmp" + "github.com/hashicorp/go-uuid" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" "github.com/hashicorp/packer/builder/file" "github.com/hashicorp/packer/builder/null" @@ -695,6 +696,79 @@ func testHCLOnlyExceptFlags(t *testing.T, args, present, notPresent []string) { } } +func TestHCL2PostProcessorForceFlag(t *testing.T) { + t.Helper() + + UUID, _ := uuid.GenerateUUID() + // Manifest will only clean with force if the build's PACKER_RUN_UUID are different + os.Setenv("PACKER_RUN_UUID", UUID) + defer os.Unsetenv("PACKER_RUN_UUID") + + args := []string{ + filepath.Join(testFixture("hcl"), "force.pkr.hcl"), + } + fCheck := fileCheck{ + expectedContent: map[string]string{ + "manifest.json": fmt.Sprintf(`{ + "builds": [ + { + "name": "potato", + "builder_type": "null", + "files": null, + "artifact_id": "Null", + "packer_run_uuid": %q, + "custom_data": null + } + ], + "last_run_uuid": %q +}`, UUID, UUID), + }, + } + defer fCheck.cleanup(t) + + c := &BuildCommand{ + Meta: testMetaFile(t), + } + if code := c.Run(args); code != 0 { + fatalCommand(t, c.Meta) + } + fCheck.verify(t) + + // Second build should override previous manifest + UUID, _ = uuid.GenerateUUID() + os.Setenv("PACKER_RUN_UUID", UUID) + + args = []string{ + "-force", + filepath.Join(testFixture("hcl"), "force.pkr.hcl"), + } + fCheck = fileCheck{ + expectedContent: map[string]string{ + "manifest.json": fmt.Sprintf(`{ + "builds": [ + { + "name": "potato", + "builder_type": "null", + "files": null, + "artifact_id": "Null", + "packer_run_uuid": %q, + "custom_data": null + } + ], + "last_run_uuid": %q +}`, UUID, UUID), + }, + } + + c = &BuildCommand{ + Meta: testMetaFile(t), + } + if code := c.Run(args); code != 0 { + fatalCommand(t, c.Meta) + } + fCheck.verify(t) +} + func TestBuildCommand_HCLOnlyExceptOptions(t *testing.T) { tests := []struct { args []string diff --git a/command/test-fixtures/build-only/template.pkr.hcl b/command/test-fixtures/build-only/template.pkr.hcl index 3d8423dff..934d028c0 100644 --- a/command/test-fixtures/build-only/template.pkr.hcl +++ b/command/test-fixtures/build-only/template.pkr.hcl @@ -42,13 +42,13 @@ build { } post-processor "shell-local" { - only = ["sources.file.vanilla"] + only = ["file.vanilla"] name = "tomato" inline = [ "echo apple > tomato.txt" ] } post-processor "shell-local" { - only = ["sources.file.chocolate"] + only = ["file.chocolate"] inline = [ "echo apple > unnamed.txt" ] } } diff --git a/command/test-fixtures/hcl/force.pkr.hcl b/command/test-fixtures/hcl/force.pkr.hcl new file mode 100644 index 000000000..98b31b0fa --- /dev/null +++ b/command/test-fixtures/hcl/force.pkr.hcl @@ -0,0 +1,12 @@ +source "null" "potato" { + communicator = "none" +} + +build { + sources = ["sources.null.potato"] + + post-processor "manifest" { + output = "manifest.json" + strip_time = true + } +} \ No newline at end of file diff --git a/hcl2template/types.build.post-processor.go b/hcl2template/types.build.post-processor.go index 7df22fc43..e79f808e5 100644 --- a/hcl2template/types.build.post-processor.go +++ b/hcl2template/types.build.post-processor.go @@ -2,6 +2,7 @@ package hcl2template import ( "fmt" + "strconv" "github.com/hashicorp/hcl/v2" "github.com/hashicorp/hcl/v2/gohcl" @@ -64,11 +65,17 @@ func (cfg *PackerConfig) startPostProcessor(source SourceUseBlock, pp *PostProce }) return nil, diags } + + builderVars := source.builderVariables() + builderVars["packer_debug"] = strconv.FormatBool(cfg.debug) + builderVars["packer_force"] = strconv.FormatBool(cfg.force) + builderVars["packer_on_error"] = cfg.onError + hclPostProcessor := &HCL2PostProcessor{ PostProcessor: postProcessor, postProcessorBlock: pp, evalContext: ectx, - builderVariables: source.builderVariables(), + builderVariables: builderVars, } err = hclPostProcessor.HCL2Prepare(nil) if err != nil { diff --git a/hcl2template/types.build.provisioners.go b/hcl2template/types.build.provisioners.go index 17adb7c83..96f975a0b 100644 --- a/hcl2template/types.build.provisioners.go +++ b/hcl2template/types.build.provisioners.go @@ -2,6 +2,7 @@ package hcl2template import ( "fmt" + "strconv" "time" "github.com/hashicorp/hcl/v2" @@ -152,11 +153,16 @@ func (cfg *PackerConfig) startProvisioner(source SourceUseBlock, pb *Provisioner return nil, diags } + builderVars := source.builderVariables() + builderVars["packer_debug"] = strconv.FormatBool(cfg.debug) + builderVars["packer_force"] = strconv.FormatBool(cfg.force) + builderVars["packer_on_error"] = cfg.onError + hclProvisioner := &HCL2Provisioner{ Provisioner: provisioner, provisionerBlock: pb, evalContext: ectx, - builderVariables: source.builderVariables(), + builderVariables: builderVars, } if pb.Override != nil { diff --git a/hcl2template/types.packer_config.go b/hcl2template/types.packer_config.go index 159d3e5a9..1e458d1a6 100644 --- a/hcl2template/types.packer_config.go +++ b/hcl2template/types.packer_config.go @@ -52,11 +52,15 @@ type PackerConfig struct { // Builds is the list of Build blocks defined in the config files. Builds Builds - except []glob.Glob - only []glob.Glob - parser *Parser files []*hcl.File + + // Fields passed as command line flags + except []glob.Glob + only []glob.Glob + force bool + debug bool + onError string } type ValidationOptions struct { @@ -408,6 +412,10 @@ func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packersdk.Bu res := []packersdk.Build{} var diags hcl.Diagnostics + cfg.debug = opts.Debug + cfg.force = opts.Force + cfg.onError = opts.OnError + for _, build := range cfg.Builds { for _, srcUsage := range build.Sources { src, found := cfg.Sources[srcUsage.SourceRef] @@ -466,7 +474,7 @@ func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packersdk.Bu } } - builder, moreDiags, generatedVars := cfg.startBuilder(srcUsage, cfg.EvalContext(BuildContext, nil), opts) + builder, moreDiags, generatedVars := cfg.startBuilder(srcUsage, cfg.EvalContext(BuildContext, nil)) diags = append(diags, moreDiags...) if moreDiags.HasErrors() { continue diff --git a/hcl2template/types.source.go b/hcl2template/types.source.go index 7ff9ca992..cbdd54277 100644 --- a/hcl2template/types.source.go +++ b/hcl2template/types.source.go @@ -8,7 +8,6 @@ import ( "github.com/hashicorp/hcl/v2/gohcl" packersdk "github.com/hashicorp/packer-plugin-sdk/packer" hcl2shim "github.com/hashicorp/packer/hcl2template/shim" - "github.com/hashicorp/packer/packer" "github.com/zclconf/go-cty/cty" ) @@ -96,7 +95,7 @@ func (p *Parser) decodeSource(block *hcl.Block) (SourceBlock, hcl.Diagnostics) { return source, diags } -func (cfg *PackerConfig) startBuilder(source SourceUseBlock, ectx *hcl.EvalContext, opts packer.GetBuildsOptions) (packersdk.Builder, hcl.Diagnostics, []string) { +func (cfg *PackerConfig) startBuilder(source SourceUseBlock, ectx *hcl.EvalContext) (packersdk.Builder, hcl.Diagnostics, []string) { var diags hcl.Diagnostics builder, err := cfg.parser.PluginConfig.Builders.Start(source.Type) @@ -127,9 +126,9 @@ func (cfg *PackerConfig) startBuilder(source SourceUseBlock, ectx *hcl.EvalConte // prepare at a later step, to make builds from different template types // easier to reason about. builderVars := source.builderVariables() - builderVars["packer_debug"] = strconv.FormatBool(opts.Debug) - builderVars["packer_force"] = strconv.FormatBool(opts.Force) - builderVars["packer_on_error"] = opts.OnError + builderVars["packer_debug"] = strconv.FormatBool(cfg.debug) + builderVars["packer_force"] = strconv.FormatBool(cfg.force) + builderVars["packer_on_error"] = cfg.onError generatedVars, warning, err := builder.Prepare(builderVars, decoded) moreDiags = warningErrorsToDiags(cfg.Sources[source.SourceRef].block, warning, err) diff --git a/website/content/docs/templates/hcl_templates/blocks/build/post-processor.mdx b/website/content/docs/templates/hcl_templates/blocks/build/post-processor.mdx index 0ac71453e..b7447ff9c 100644 --- a/website/content/docs/templates/hcl_templates/blocks/build/post-processor.mdx +++ b/website/content/docs/templates/hcl_templates/blocks/build/post-processor.mdx @@ -72,7 +72,7 @@ build { post-processor "checksum" { checksum_types = [ "md5", "sha512" ] keep_input_artifact = true - only = ["source.amazon-ebs.example"] + only = ["amazon-ebs.example"] } } ``` diff --git a/website/content/docs/templates/hcl_templates/blocks/build/provisioner.mdx b/website/content/docs/templates/hcl_templates/blocks/build/provisioner.mdx index 89e749b40..eab09a689 100644 --- a/website/content/docs/templates/hcl_templates/blocks/build/provisioner.mdx +++ b/website/content/docs/templates/hcl_templates/blocks/build/provisioner.mdx @@ -58,7 +58,7 @@ build { ] provisioner "shell" { # This provisioner only runs for the 'first-example' source. - only = ["source.amazon-ebs.first-example"] + only = ["amazon-ebs.first-example"] inline = [ "echo provisioning all the things", diff --git a/website/content/docs/templates/hcl_templates/onlyexcept.mdx b/website/content/docs/templates/hcl_templates/onlyexcept.mdx index 91c4b6309..3f38f9ec5 100644 --- a/website/content/docs/templates/hcl_templates/onlyexcept.mdx +++ b/website/content/docs/templates/hcl_templates/onlyexcept.mdx @@ -32,12 +32,12 @@ build { } provisioner "shell-local" { - only = ["source.amazon-ebs.first-example"] + only = ["amazon-ebs.first-example"] inline = ["echo I will only run for the second example source"] } provisioner "shell-local" { - except = ["source.amazon-ebs.second-example-local-name"] + except = ["amazon-ebs.second-example-local-name"] inline = ["echo I will never run for the second example source"] } }