diff --git a/hcl2template/common_test.go b/hcl2template/common_test.go index 610e178ce..4a4889e8b 100644 --- a/hcl2template/common_test.go +++ b/hcl2template/common_test.go @@ -130,6 +130,7 @@ func testParse(t *testing.T, tests []parseTest) { packer.CoreBuildPostProcessor{}, null.Builder{}, HCL2Provisioner{}, + HCL2PostProcessor{}, ), ); 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 f80b40ecf..c54626639 100644 --- a/hcl2template/types.build.post-processor.go +++ b/hcl2template/types.build.post-processor.go @@ -74,9 +74,13 @@ func (cfg *PackerConfig) startPostProcessor(source SourceBlock, pp *PostProcesso }) return nil, diags } - flatProvisinerCfg, moreDiags := decodeHCL2Spec(pp.Rest, ectx, postProcessor) - diags = append(diags, moreDiags...) - err = postProcessor.Configure(source.builderVariables(), flatProvisinerCfg) + hclPostProcessor := &HCL2PostProcessor{ + PostProcessor: postProcessor, + postProcessorBlock: pp, + evalContext: ectx, + builderVariables: source.builderVariables(), + } + err = hclPostProcessor.HCL2Prepare(generatedVars) if err != nil { diags = append(diags, &hcl.Diagnostic{ Severity: hcl.DiagError, @@ -86,5 +90,5 @@ func (cfg *PackerConfig) startPostProcessor(source SourceBlock, pp *PostProcesso }) return nil, diags } - return postProcessor, diags + return hclPostProcessor, diags } diff --git a/hcl2template/types.build.provisioners.go b/hcl2template/types.build.provisioners.go index 19b699155..ebc89600b 100644 --- a/hcl2template/types.build.provisioners.go +++ b/hcl2template/types.build.provisioners.go @@ -144,13 +144,13 @@ func (cfg *PackerConfig) startProvisioner(source SourceBlock, pb *ProvisionerBlo }) return nil, diags } - p := &HCL2Provisioner{ + hclProvisioner := &HCL2Provisioner{ Provisioner: provisioner, provisionerBlock: pb, evalContext: ectx, builderVariables: source.builderVariables(), } - err = p.HCL2Prepare(generatedVars) + err = hclProvisioner.HCL2Prepare(generatedVars) if err != nil { diags = append(diags, &hcl.Diagnostic{ Severity: hcl.DiagError, @@ -160,5 +160,5 @@ func (cfg *PackerConfig) startProvisioner(source SourceBlock, pb *ProvisionerBlo }) return nil, diags } - return p, diags + return hclProvisioner, diags } diff --git a/hcl2template/types.build_test.go b/hcl2template/types.build_test.go index f7a69e844..658c79c68 100644 --- a/hcl2template/types.build_test.go +++ b/hcl2template/types.build_test.go @@ -171,19 +171,23 @@ func TestParse_build(t *testing.T) { { { PType: "amazon-import", - PostProcessor: &MockPostProcessor{ - Config: MockConfig{ - NestedMockConfig: NestedMockConfig{Tags: []MockTag{}}, - NestedSlice: []NestedMockConfig{}, + PostProcessor: &HCL2PostProcessor{ + PostProcessor: &MockPostProcessor{ + Config: MockConfig{ + NestedMockConfig: NestedMockConfig{Tags: []MockTag{}}, + NestedSlice: []NestedMockConfig{}, + }, }, }, }, { PType: "manifest", - PostProcessor: &MockPostProcessor{ - Config: MockConfig{ - NestedMockConfig: NestedMockConfig{Tags: []MockTag{}}, - NestedSlice: []NestedMockConfig{}, + PostProcessor: &HCL2PostProcessor{ + PostProcessor: &MockPostProcessor{ + Config: MockConfig{ + NestedMockConfig: NestedMockConfig{Tags: []MockTag{}}, + NestedSlice: []NestedMockConfig{}, + }, }, }, }, @@ -199,19 +203,23 @@ func TestParse_build(t *testing.T) { { { PType: "manifest", - PostProcessor: &MockPostProcessor{ - Config: MockConfig{ - NestedMockConfig: NestedMockConfig{Tags: []MockTag{}}, - NestedSlice: []NestedMockConfig{}, + PostProcessor: &HCL2PostProcessor{ + PostProcessor: &MockPostProcessor{ + Config: MockConfig{ + NestedMockConfig: NestedMockConfig{Tags: []MockTag{}}, + NestedSlice: []NestedMockConfig{}, + }, }, }, }, { PType: "amazon-import", - PostProcessor: &MockPostProcessor{ - Config: MockConfig{ - NestedMockConfig: NestedMockConfig{Tags: []MockTag{}}, - NestedSlice: []NestedMockConfig{}, + PostProcessor: &HCL2PostProcessor{ + PostProcessor: &MockPostProcessor{ + Config: MockConfig{ + NestedMockConfig: NestedMockConfig{Tags: []MockTag{}}, + NestedSlice: []NestedMockConfig{}, + }, }, }, }, diff --git a/hcl2template/types.hcl_post-processor.go b/hcl2template/types.hcl_post-processor.go new file mode 100644 index 000000000..6698b3f5a --- /dev/null +++ b/hcl2template/types.hcl_post-processor.go @@ -0,0 +1,68 @@ +package hcl2template + +import ( + "context" + "fmt" + + "github.com/hashicorp/hcl/v2" + "github.com/hashicorp/hcl/v2/hcldec" + "github.com/hashicorp/packer/packer" + "github.com/zclconf/go-cty/cty" +) + +type HCL2PostProcessor struct { + PostProcessor packer.PostProcessor + postProcessorBlock *PostProcessorBlock + evalContext *hcl.EvalContext + builderVariables map[string]string +} + +func (p *HCL2PostProcessor) ConfigSpec() hcldec.ObjectSpec { + return p.PostProcessor.ConfigSpec() +} + +func (p *HCL2PostProcessor) HCL2Prepare(buildVars map[string]interface{}) error { + var diags hcl.Diagnostics + ectx := p.evalContext + if len(buildVars) > 0 { + ectx = p.evalContext.NewChild() + buildValues := map[string]cty.Value{} + for k, v := range buildVars { + switch v := v.(type) { + case string: + buildValues[k] = cty.StringVal(v) + default: + return fmt.Errorf("unhandled builvar type: %T", v) + } + } + ectx.Variables = map[string]cty.Value{ + buildAccessor: cty.ObjectVal(buildValues), + } + } + + flatPostProcessorCfg, moreDiags := decodeHCL2Spec(p.postProcessorBlock.HCL2Ref.Rest, ectx, p.PostProcessor) + diags = append(diags, moreDiags...) + if diags.HasErrors() { + return diags + } + return p.PostProcessor.Configure(p.builderVariables, flatPostProcessorCfg) +} + +func (p *HCL2PostProcessor) Configure(args ...interface{}) error { + return p.PostProcessor.Configure(args...) +} + +func (p *HCL2PostProcessor) PostProcess(ctx context.Context, ui packer.Ui, artifact packer.Artifact) (packer.Artifact, bool, bool, error) { + generatedData := make(map[string]interface{}) + if artifactStateData, ok := artifact.State("generated_data").(map[interface{}]interface{}); ok { + for k, v := range artifactStateData { + generatedData[k.(string)] = v + } + } + + err := p.HCL2Prepare(generatedData) + if err != nil { + return nil, false, false, err + } + return p.PostProcessor.PostProcess(ctx, ui, artifact) +} diff --git a/hcl2template/types.packer_config_test.go b/hcl2template/types.packer_config_test.go index 9849f06df..09efb0b3b 100644 --- a/hcl2template/types.packer_config_test.go +++ b/hcl2template/types.packer_config_test.go @@ -126,14 +126,18 @@ func TestParser_complete(t *testing.T) { PostProcessors: [][]packer.CoreBuildPostProcessor{ { { - PType: "amazon-import", - PName: "something", - PostProcessor: basicMockPostProcessor, + PType: "amazon-import", + PName: "something", + PostProcessor: &HCL2PostProcessor{ + PostProcessor: basicMockPostProcessor, + }, KeepInputArtifact: pTrue, }, { - PType: "amazon-import", - PostProcessor: basicMockPostProcessor, + PType: "amazon-import", + PostProcessor: &HCL2PostProcessor{ + PostProcessor: basicMockPostProcessor, + }, }, }, }, @@ -169,14 +173,18 @@ func TestParser_complete(t *testing.T) { PostProcessors: [][]packer.CoreBuildPostProcessor{ { { - PType: "amazon-import", - PName: "something", - PostProcessor: basicMockPostProcessor, + PType: "amazon-import", + PName: "something", + PostProcessor: &HCL2PostProcessor{ + PostProcessor: basicMockPostProcessor, + }, KeepInputArtifact: pTrue, }, { - PType: "amazon-import", - PostProcessor: basicMockPostProcessor, + PType: "amazon-import", + PostProcessor: &HCL2PostProcessor{ + PostProcessor: basicMockPostProcessor, + }, }, }, },