From 2af40c762b372ecd45e5384b0686dd38c45359ea Mon Sep 17 00:00:00 2001 From: Adrien Delorme Date: Thu, 9 Apr 2020 11:14:37 +0200 Subject: [PATCH] HCL2: pass on builder type and name (#8956) * sets `packer_build_name` and `packer_builder_type` variables for builder provisioners and post-processors in HCL2 * allows to use the new `${source.type}` and `${source.name}` variables in HCL2 * fixes #8932 Note that the common.PackerConfig is used everywhere and was not set for HCL2, this had some implications: For #8923 you can see the issue here: https://github.com/hashicorp/packer/blob/dde74232f251434715cb76664426d9c1e1c91bd8/builder/lxd/config.go#L61-L63 More random examples of where this could cause an issue : https://github.com/hashicorp/packer/blob/0785c2f6fca9c22bf25528e0176042799dd79df9/provisioner/ansible-local/provisioner.go#L380-L381 https://github.com/hashicorp/packer/blob/b4efd13a4d69a937a22caa5dd84eb98f7fdce5cf/builder/amazon/ebs/builder.go#L232-L236 * [All references to PackerConfig.PackerBuildName](https://sourcegraph.com/github.com/hashicorp/packer@ff6a039d5bb45e34ff761d9c52e8b98972288447/-/blob/common/packer_config.go#L7:2&tab=references) * [All references to PackerConfig.PackerBuilderType](https://sourcegraph.com/github.com/hashicorp/packer@ff6a039d5bb45e34ff761d9c52e8b98972288447/-/blob/common/packer_config.go#L8:2&tab=references) --- command/build_test.go | 145 ++++++++++++++++-- .../build-name-and-type/all.json | 21 +++ .../build-name-and-type/all.pkr.hcl | 25 +++ hcl2template/parser.go | 2 +- hcl2template/types.build.post-processor.go | 4 +- hcl2template/types.build.provisioners.go | 4 +- hcl2template/types.packer_config.go | 42 +++-- hcl2template/types.source.go | 9 +- post-processor/manifest/artifact.go | 2 +- post-processor/manifest/post-processor.go | 17 +- .../manifest/post-processor.hcl2spec.go | 2 + .../pages/docs/post-processors/manifest.mdx | 20 +-- .../manifest/Config-not-required.mdx | 14 ++ 13 files changed, 262 insertions(+), 45 deletions(-) create mode 100644 command/test-fixtures/build-name-and-type/all.json create mode 100644 command/test-fixtures/build-name-and-type/all.pkr.hcl create mode 100644 website/pages/partials/post-processor/manifest/Config-not-required.mdx diff --git a/command/build_test.go b/command/build_test.go index 9d23bb197..697bcd20e 100644 --- a/command/build_test.go +++ b/command/build_test.go @@ -3,6 +3,7 @@ package command import ( "bytes" "fmt" + "io/ioutil" "math" "os" "path/filepath" @@ -12,12 +13,14 @@ import ( "github.com/hashicorp/packer/builder/file" "github.com/hashicorp/packer/builder/null" "github.com/hashicorp/packer/packer" + "github.com/hashicorp/packer/post-processor/manifest" shell_local_pp "github.com/hashicorp/packer/post-processor/shell-local" + filep "github.com/hashicorp/packer/provisioner/file" "github.com/hashicorp/packer/provisioner/shell" shell_local "github.com/hashicorp/packer/provisioner/shell-local" ) -func TestBuild_VarArgs(t *testing.T) { +func TestBuild(t *testing.T) { tc := []struct { name string args []string @@ -25,7 +28,7 @@ func TestBuild_VarArgs(t *testing.T) { fileCheck }{ { - name: "json - json varfile sets an apple env var", + name: "var-args: json - json varfile sets an apple env var", args: []string{ "-var-file=" + filepath.Join(testFixture("var-arg"), "apple.json"), filepath.Join(testFixture("var-arg"), "fruit_builder.json"), @@ -43,7 +46,7 @@ func TestBuild_VarArgs(t *testing.T) { fileCheck: fileCheck{expected: []string{"banana.txt"}}, }, { - name: "json - arg sets a pear env var", + name: "var-args: json - arg sets a pear env var", args: []string{ "-var=fruit=pear", filepath.Join(testFixture("var-arg"), "fruit_builder.json"), @@ -52,7 +55,7 @@ func TestBuild_VarArgs(t *testing.T) { }, { - name: "json - inexistent var file errs", + name: "var-args: json - inexistent var file errs", args: []string{ "-var-file=" + filepath.Join(testFixture("var-arg"), "potato.json"), filepath.Join(testFixture("var-arg"), "fruit_builder.json"), @@ -62,7 +65,7 @@ func TestBuild_VarArgs(t *testing.T) { }, { - name: "hcl - inexistent json var file errs", + name: "var-args: hcl - inexistent json var file errs", args: []string{ "-var-file=" + filepath.Join(testFixture("var-arg"), "potato.json"), testFixture("var-arg"), @@ -72,7 +75,7 @@ func TestBuild_VarArgs(t *testing.T) { }, { - name: "hcl - inexistent hcl var file errs", + name: "var-args: hcl - inexistent hcl var file errs", args: []string{ "-var-file=" + filepath.Join(testFixture("var-arg"), "potato.hcl"), testFixture("var-arg"), @@ -82,7 +85,7 @@ func TestBuild_VarArgs(t *testing.T) { }, { - name: "hcl - auto varfile sets a chocolate env var", + name: "var-args: hcl - auto varfile sets a chocolate env var", args: []string{ testFixture("var-arg"), }, @@ -90,7 +93,7 @@ func TestBuild_VarArgs(t *testing.T) { }, { - name: "hcl - hcl varfile sets a apple env var", + name: "var-args: hcl - hcl varfile sets a apple env var", args: []string{ "-var-file=" + filepath.Join(testFixture("var-arg"), "apple.hcl"), testFixture("var-arg"), @@ -99,7 +102,7 @@ func TestBuild_VarArgs(t *testing.T) { }, { - name: "hcl - json varfile sets a apple env var", + name: "var-args: hcl - json varfile sets a apple env var", args: []string{ "-var-file=" + filepath.Join(testFixture("var-arg"), "apple.json"), testFixture("var-arg"), @@ -108,19 +111,108 @@ func TestBuild_VarArgs(t *testing.T) { }, { - name: "hcl - arg sets a tomato env var", + name: "var-args: hcl - arg sets a tomato env var", args: []string{ "-var=fruit=tomato", testFixture("var-arg"), }, fileCheck: fileCheck{expected: []string{"tomato.txt"}}, }, + + { + name: "build name: HCL", + args: []string{ + "-parallel-builds=1", // to ensure order is kept + testFixture("build-name-and-type"), + }, + fileCheck: fileCheck{ + expectedContent: map[string]string{ + "manifest.json": `{ + "builds": [ + { + "name": "test", + "builder_type": "null", + "files": null, + "artifact_id": "Null", + "packer_run_uuid": "", + "custom_data": null + }, + { + "name": "potato", + "builder_type": "null", + "files": null, + "artifact_id": "Null", + "packer_run_uuid": "", + "custom_data": null + } + ], + "last_run_uuid": "" +}`, + }, + }, + }, + + { + name: "build name: JSON except potato", + args: []string{ + "-except=potato", + "-parallel-builds=1", // to ensure order is kept + filepath.Join(testFixture("build-name-and-type"), "all.json"), + }, + fileCheck: fileCheck{ + expected: []string{ + "null.test.txt", + "null.potato.txt", + }, + expectedContent: map[string]string{ + "manifest.json": `{ + "builds": [ + { + "name": "test", + "builder_type": "null", + "files": null, + "artifact_id": "Null", + "packer_run_uuid": "", + "custom_data": null + } + ], + "last_run_uuid": "" +}`, + }, + }, + }, + + { + name: "build name: JSON only potato", + args: []string{ + "-only=potato", + "-parallel-builds=1", // to ensure order is kept + filepath.Join(testFixture("build-name-and-type"), "all.json"), + }, + fileCheck: fileCheck{ + expectedContent: map[string]string{ + "manifest.json": `{ + "builds": [ + { + "name": "potato", + "builder_type": "null", + "files": null, + "artifact_id": "Null", + "packer_run_uuid": "", + "custom_data": null + } + ], + "last_run_uuid": "" +}`, + }, + }, + }, } for _, tt := range tc { t.Run(tt.name, func(t *testing.T) { + defer tt.cleanup(t) run(t, tt.args, tt.expectedCode) - defer cleanup() tt.fileCheck.verify(t) }) } @@ -340,10 +432,28 @@ func run(t *testing.T, args []string, expectedCode int) { type fileCheck struct { expected, notExpected []string + expectedContent map[string]string +} + +func (fc fileCheck) cleanup(t *testing.T) { + for _, file := range fc.expectedFiles() { + t.Logf("removing %v", file) + if err := os.Remove(file); err != nil { + t.Errorf("failed to remove file %s: %v", file, err) + } + } +} + +func (fc fileCheck) expectedFiles() []string { + expected := fc.expected + for file := range fc.expectedContent { + expected = append(expected, file) + } + return expected } func (fc fileCheck) verify(t *testing.T) { - for _, f := range fc.expected { + for _, f := range fc.expectedFiles() { if !fileExists(f) { t.Errorf("Expected to find %s", f) } @@ -353,6 +463,15 @@ func (fc fileCheck) verify(t *testing.T) { t.Errorf("Expected to not find %s", f) } } + for file, expectedContent := range fc.expectedContent { + content, err := ioutil.ReadFile(file) + if err != nil { + t.Fatalf("ioutil.ReadFile: %v", err) + } + if diff := cmp.Diff(expectedContent, string(content)); diff != "" { + t.Errorf("content of %s differs: %s", file, diff) + } + } } // fileExists returns true if the filename is found @@ -374,9 +493,11 @@ func testCoreConfigBuilder(t *testing.T) *packer.CoreConfig { ProvisionerStore: packer.MapOfProvisioner{ "shell-local": func() (packer.Provisioner, error) { return &shell_local.Provisioner{}, nil }, "shell": func() (packer.Provisioner, error) { return &shell.Provisioner{}, nil }, + "file": func() (packer.Provisioner, error) { return &filep.Provisioner{}, nil }, }, PostProcessorStore: packer.MapOfPostProcessor{ "shell-local": func() (packer.PostProcessor, error) { return &shell_local_pp.PostProcessor{}, nil }, + "manifest": func() (packer.PostProcessor, error) { return &manifest.PostProcessor{}, nil }, }, } return &packer.CoreConfig{ diff --git a/command/test-fixtures/build-name-and-type/all.json b/command/test-fixtures/build-name-and-type/all.json new file mode 100644 index 000000000..e0150f90f --- /dev/null +++ b/command/test-fixtures/build-name-and-type/all.json @@ -0,0 +1,21 @@ +{ + "builders": [ + { + "name": "test", + "communicator": "none", + "type": "null" + }, + { + "name": "potato", + "communicator": "none", + "type": "null" + } + ], + "post-processors": [ + { + "type": "manifest", + "output": "manifest.json", + "strip_time": true + } + ] +} diff --git a/command/test-fixtures/build-name-and-type/all.pkr.hcl b/command/test-fixtures/build-name-and-type/all.pkr.hcl new file mode 100644 index 000000000..b0dbf2bd0 --- /dev/null +++ b/command/test-fixtures/build-name-and-type/all.pkr.hcl @@ -0,0 +1,25 @@ +source "null" "test" { + communicator = "none" +} + +source "null" "potato" { + communicator = "none" +} + +build { + sources = [ + "sources.null.test", + "sources.null.potato", + ] + + provisioner "shell-local" { + inline = [ + "echo '' > ${source.type}.${source.name}.txt" + ] + } + + post-processor "manifest" { + output = "manifest.json" + strip_time = true + } +} diff --git a/hcl2template/parser.go b/hcl2template/parser.go index 5ea9a18a5..d27ee74a0 100644 --- a/hcl2template/parser.go +++ b/hcl2template/parser.go @@ -166,7 +166,7 @@ func (p *Parser) parse(filename string, varFiles []string, argVars map[string]st func (p *Parser) decodeConfig(f *hcl.File, cfg *PackerConfig) hcl.Diagnostics { var diags hcl.Diagnostics - body := dynblock.Expand(f.Body, cfg.EvalContext()) + body := dynblock.Expand(f.Body, cfg.EvalContext(nil)) content, moreDiags := body.Content(configSchema) diags = append(diags, moreDiags...) diff --git a/hcl2template/types.build.post-processor.go b/hcl2template/types.build.post-processor.go index 890f2d8d3..5c0c7004d 100644 --- a/hcl2template/types.build.post-processor.go +++ b/hcl2template/types.build.post-processor.go @@ -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, generatedVars map[string]string) (packer.PostProcessor, hcl.Diagnostics) { +func (p *Parser) 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 @@ -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, generatedVars) + err = postProcessor.Configure(source.builderVariables(), flatProvisinerCfg, generatedVars) if err != nil { diags = append(diags, &hcl.Diagnostic{ Severity: hcl.DiagError, diff --git a/hcl2template/types.build.provisioners.go b/hcl2template/types.build.provisioners.go index 862b13ca2..49fbb5c42 100644 --- a/hcl2template/types.build.provisioners.go +++ b/hcl2template/types.build.provisioners.go @@ -46,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 map[string]string) (packer.Provisioner, hcl.Diagnostics) { +func (p *Parser) startProvisioner(source *SourceBlock, pb *ProvisionerBlock, ectx *hcl.EvalContext, generatedVars map[string]string) (packer.Provisioner, hcl.Diagnostics) { var diags hcl.Diagnostics provisioner, err := p.ProvisionersSchemas.Start(pb.PType) @@ -69,7 +69,7 @@ func (p *Parser) startProvisioner(pb *ProvisionerBlock, ectx *hcl.EvalContext, g // configs := make([]interface{}, 2) // configs = append(, flatProvisionerCfg) // configs = append(configs, generatedVars) - err = provisioner.Prepare(flatProvisionerCfg, generatedVars) + err = provisioner.Prepare(source.builderVariables(), flatProvisionerCfg, generatedVars) if err != nil { diags = append(diags, &hcl.Diagnostic{ Severity: hcl.DiagError, diff --git a/hcl2template/types.packer_config.go b/hcl2template/types.packer_config.go index 3f52092d7..f6d4a99b6 100644 --- a/hcl2template/types.packer_config.go +++ b/hcl2template/types.packer_config.go @@ -35,19 +35,32 @@ type ValidationOptions struct { Strict bool } +const ( + inputVariablesAccessor = "var" + localsAccessor = "local" + sourcesAccessor = "source" +) + // EvalContext returns the *hcl.EvalContext that will be passed to an hcl // decoder in order to tell what is the actual value of a var or a local and // the list of defined functions. -func (cfg *PackerConfig) EvalContext() *hcl.EvalContext { +func (cfg *PackerConfig) EvalContext(variables map[string]cty.Value) *hcl.EvalContext { inputVariables, _ := cfg.InputVariables.Values() localVariables, _ := cfg.LocalVariables.Values() ectx := &hcl.EvalContext{ Functions: Functions(cfg.Basedir), Variables: map[string]cty.Value{ - "var": cty.ObjectVal(inputVariables), - "local": cty.ObjectVal(localVariables), + inputVariablesAccessor: cty.ObjectVal(inputVariables), + localsAccessor: cty.ObjectVal(localVariables), + sourcesAccessor: cty.ObjectVal(map[string]cty.Value{ + "type": cty.UnknownVal(cty.String), + "name": cty.UnknownVal(cty.String), + }), }, } + for k, v := range variables { + ectx.Variables[k] = v + } return ectx } @@ -157,7 +170,7 @@ func (c *PackerConfig) evaluateLocalVariables(locals []*Local) hcl.Diagnostics { func (c *PackerConfig) evaluateLocalVariable(local *Local) hcl.Diagnostics { var diags hcl.Diagnostics - value, moreDiags := local.Expr.Value(c.EvalContext()) + value, moreDiags := local.Expr.Value(c.EvalContext(nil)) diags = append(diags, moreDiags...) if moreDiags.HasErrors() { return diags @@ -173,11 +186,11 @@ 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 (p *Parser) getCoreBuildProvisioners(blocks []*ProvisionerBlock, ectx *hcl.EvalContext, generatedVars map[string]string) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) { +func (p *Parser) 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 { - provisioner, moreDiags := p.startProvisioner(pb, ectx, generatedVars) + provisioner, moreDiags := p.startProvisioner(source, pb, ectx, generatedVars) diags = append(diags, moreDiags...) if moreDiags.HasErrors() { continue @@ -193,11 +206,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, generatedVars map[string]string) ([]packer.CoreBuildPostProcessor, hcl.Diagnostics) { +func (p *Parser) 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 { - postProcessor, moreDiags := p.startPostProcessor(ppb, ectx, generatedVars) + postProcessor, moreDiags := p.startPostProcessor(source, ppb, ectx, generatedVars) diags = append(diags, moreDiags...) if moreDiags.HasErrors() { continue @@ -230,12 +243,19 @@ func (p *Parser) getBuilds(cfg *PackerConfig) ([]packer.Build, hcl.Diagnostics) }) continue } - builder, moreDiags, generatedVars := p.startBuilder(src, cfg.EvalContext()) + builder, moreDiags, generatedVars := p.startBuilder(src, cfg.EvalContext(nil)) diags = append(diags, moreDiags...) if moreDiags.HasErrors() { 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 @@ -249,12 +269,12 @@ func (p *Parser) getBuilds(cfg *PackerConfig) ([]packer.Build, hcl.Diagnostics) } } - provisioners, moreDiags := p.getCoreBuildProvisioners(build.ProvisionerBlocks, cfg.EvalContext(), generatedPlaceholderMap) + provisioners, moreDiags := p.getCoreBuildProvisioners(src, build.ProvisionerBlocks, cfg.EvalContext(variables), generatedPlaceholderMap) diags = append(diags, moreDiags...) if moreDiags.HasErrors() { continue } - postProcessors, moreDiags := p.getCoreBuildPostProcessors(build.PostProcessors, cfg.EvalContext(), generatedPlaceholderMap) + postProcessors, moreDiags := p.getCoreBuildPostProcessors(src, build.PostProcessors, cfg.EvalContext(variables), generatedPlaceholderMap) pps := [][]packer.CoreBuildPostProcessor{} if len(postProcessors) > 0 { pps = [][]packer.CoreBuildPostProcessor{postProcessors} diff --git a/hcl2template/types.source.go b/hcl2template/types.source.go index a351c0686..f81dd768b 100644 --- a/hcl2template/types.source.go +++ b/hcl2template/types.source.go @@ -57,12 +57,19 @@ func (p *Parser) startBuilder(source *SourceBlock, ectx *hcl.EvalContext) (packe return nil, diags, nil } - generatedVars, warning, err := builder.Prepare(decoded) + generatedVars, warning, err := builder.Prepare(source.builderVariables(), decoded) moreDiags = warningErrorsToDiags(source.block, warning, err) diags = append(diags, moreDiags...) return builder, diags, generatedVars } +func (source *SourceBlock) builderVariables() map[string]string { + return map[string]string{ + "packer_build_name": source.Name, + "packer_builder_type": source.Type, + } +} + func (source *SourceBlock) Ref() SourceRef { return SourceRef{ Type: source.Type, diff --git a/post-processor/manifest/artifact.go b/post-processor/manifest/artifact.go index 59d6110eb..61f11bb85 100644 --- a/post-processor/manifest/artifact.go +++ b/post-processor/manifest/artifact.go @@ -12,7 +12,7 @@ type ArtifactFile struct { type Artifact struct { BuildName string `json:"name"` BuilderType string `json:"builder_type"` - BuildTime int64 `json:"build_time"` + BuildTime int64 `json:"build_time,omitempty"` ArtifactFiles []ArtifactFile `json:"files"` ArtifactId string `json:"artifact_id"` PackerRunUUID string `json:"packer_run_uuid"` diff --git a/post-processor/manifest/post-processor.go b/post-processor/manifest/post-processor.go index 4a7221998..b6d396c2d 100644 --- a/post-processor/manifest/post-processor.go +++ b/post-processor/manifest/post-processor.go @@ -1,4 +1,5 @@ //go:generate mapstructure-to-hcl2 -type Config +//go:generate struct-markdown package manifest @@ -22,8 +23,17 @@ import ( type Config struct { common.PackerConfig `mapstructure:",squash"` - OutputPath string `mapstructure:"output"` - StripPath bool `mapstructure:"strip_path"` + // The manifest will be written to this file. This defaults to + // `packer-manifest.json`. + OutputPath string `mapstructure:"output"` + // Write only filename without the path to the manifest file. This defaults + // to false. + StripPath bool `mapstructure:"strip_path"` + // Don't write the `build_time` field from the output. + StripTime bool `mapstructure:"strip_time"` + // Arbitrary data to add to the manifest. This is a [template + // engine](https://packer.io/docs/templates/engine.html). Therefore, you + // may use user variables and template functions in this field. CustomData map[string]string `mapstructure:"custom_data"` ctx interpolate.Context } @@ -101,6 +111,9 @@ func (p *PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, source pa artifact.BuilderType = p.config.PackerBuilderType artifact.BuildName = p.config.PackerBuildName artifact.BuildTime = time.Now().Unix() + if p.config.StripTime { + artifact.BuildTime = 0 + } // Since each post-processor runs in a different process we need a way to // coordinate between various post-processors in a single packer run. We do // this by setting a UUID per run and tracking this in the manifest file. diff --git a/post-processor/manifest/post-processor.hcl2spec.go b/post-processor/manifest/post-processor.hcl2spec.go index 08be1e1e9..54cf2ba86 100644 --- a/post-processor/manifest/post-processor.hcl2spec.go +++ b/post-processor/manifest/post-processor.hcl2spec.go @@ -18,6 +18,7 @@ type FlatConfig struct { PackerSensitiveVars []string `mapstructure:"packer_sensitive_variables" cty:"packer_sensitive_variables"` OutputPath *string `mapstructure:"output" cty:"output"` StripPath *bool `mapstructure:"strip_path" cty:"strip_path"` + StripTime *bool `mapstructure:"strip_time" cty:"strip_time"` CustomData map[string]string `mapstructure:"custom_data" cty:"custom_data"` } @@ -42,6 +43,7 @@ func (*FlatConfig) HCL2Spec() map[string]hcldec.Spec { "packer_sensitive_variables": &hcldec.AttrSpec{Name: "packer_sensitive_variables", Type: cty.List(cty.String), Required: false}, "output": &hcldec.AttrSpec{Name: "output", Type: cty.String, Required: false}, "strip_path": &hcldec.AttrSpec{Name: "strip_path", Type: cty.Bool, Required: false}, + "strip_time": &hcldec.AttrSpec{Name: "strip_time", Type: cty.Bool, Required: false}, "custom_data": &hcldec.BlockAttrsSpec{TypeName: "custom_data", ElementType: cty.String, Required: false}, } return s diff --git a/website/pages/docs/post-processors/manifest.mdx b/website/pages/docs/post-processors/manifest.mdx index 76e994a37..afe8741f3 100644 --- a/website/pages/docs/post-processors/manifest.mdx +++ b/website/pages/docs/post-processors/manifest.mdx @@ -36,19 +36,13 @@ post-processors such as Docker and Artifice. ### Optional: -- `output` (string) The manifest will be written to this file. This defaults - to `packer-manifest.json`. -- `strip_path` (boolean) Write only filename without the path to the manifest - file. This defaults to false. -- `custom_data` (map of strings) Arbitrary data to add to the manifest. - This is a [template engine](/docs/templates/engine). Therefore, you - may use user variables and template functions in this field. -- `keep_input_artifact` (boolean) - Unlike most other post-processors, the - keep_input_artifact option will have no effect for the manifest - post-processor. We will always retain the input artifact for manifest, - since deleting the files we just recorded is not a behavior anyone should - ever expect. `keep_input_artifact will` therefore always be evaluated as - true, regardless of the value you enter into this field. +@include 'post-processor/manifest/Config-not-required.mdx' +- `keep_input_artifact` (boolean) - Unlike most other post-processors, the + keep_input_artifact option will have no effect for the manifest + post-processor. We will always retain the input artifact for manifest, + since deleting the files we just recorded is not a behavior anyone should + ever expect. `keep_input_artifact will` therefore always be evaluated as + true, regardless of the value you enter into this field. ### Example Configuration diff --git a/website/pages/partials/post-processor/manifest/Config-not-required.mdx b/website/pages/partials/post-processor/manifest/Config-not-required.mdx new file mode 100644 index 000000000..f94208521 --- /dev/null +++ b/website/pages/partials/post-processor/manifest/Config-not-required.mdx @@ -0,0 +1,14 @@ + + +- `output` (string) - The manifest will be written to this file. This defaults to + `packer-manifest.json`. + +- `strip_path` (bool) - Write only filename without the path to the manifest file. This defaults + to false. + +- `strip_time` (bool) - Don't write the `build_time` field from the output. + +- `custom_data` (map[string]string) - Arbitrary data to add to the manifest. This is a [template + engine](https://packer.io/docs/templates/engine.html). Therefore, you + may use user variables and template functions in this field. + \ No newline at end of file