hcl2: allow to optionnaly name provisioners and post-processors

This commit is contained in:
Adrien Delorme 2020-01-16 12:08:39 +01:00
parent b5075a35c0
commit 2d1a67c6cb
10 changed files with 146 additions and 39 deletions

View File

@ -10,6 +10,6 @@ type Decodable interface {
ConfigSpec() hcldec.ObjectSpec
}
func decodeHCL2Spec(block *hcl.Block, ctx *hcl.EvalContext, dec Decodable) (cty.Value, hcl.Diagnostics) {
return hcldec.Decode(block.Body, dec.ConfigSpec(), ctx)
func decodeHCL2Spec(body hcl.Body, ctx *hcl.EvalContext, dec Decodable) (cty.Value, hcl.Diagnostics) {
return hcldec.Decode(body, dec.ConfigSpec(), ctx)
}

View File

@ -6,6 +6,7 @@ build {
]
provisioner "shell" {
name = "provisioner that does something"
string = "string"
int = 42
int64 = 43
@ -83,6 +84,46 @@ build {
}
}
post-processor "amazon-import" {
name = "something"
string = "string"
int = 42
int64 = 43
bool = true
trilean = true
duration = "10s"
map_string_string {
a = "b"
c = "d"
}
slice_string = [
"a",
"b",
"c",
]
nested {
string = "string"
int = 42
int64 = 43
bool = true
trilean = true
duration = "10s"
map_string_string {
a = "b"
c = "d"
}
slice_string = [
"a",
"b",
"c",
]
}
nested_slice {
}
}
post-processor "amazon-import" {
string = "string"
int = 42

View File

@ -78,7 +78,7 @@ func (p *Parser) decodeBuildConfig(block *hcl.Block) (*BuildBlock, hcl.Diagnosti
}
build.ProvisionerBlocks = append(build.ProvisionerBlocks, p)
case buildPostProcessorLabel:
pp, moreDiags := p.decodePostProcessorGroup(block)
pp, moreDiags := p.decodePostProcessor(block)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {
continue

View File

@ -4,27 +4,43 @@ import (
"fmt"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/gohcl"
"github.com/hashicorp/packer/packer"
)
// PostProcessorBlock represents a parsed PostProcessorBlock
type PostProcessorBlock struct {
PType string
block *hcl.Block
PName string
HCL2Ref
}
func (p *PostProcessorBlock) String() string {
return fmt.Sprintf(buildPostProcessorLabel+"-block %q %q", p.PType, p.PName)
}
func (p *Parser) decodePostProcessor(block *hcl.Block) (*PostProcessorBlock, hcl.Diagnostics) {
var b struct {
Name string `hcl:"name,optional"`
Rest hcl.Body `hcl:",remain"`
}
diags := gohcl.DecodeBody(block.Body, nil, &b)
if diags.HasErrors() {
return nil, diags
}
func (p *Parser) decodePostProcessorGroup(block *hcl.Block) (*PostProcessorBlock, hcl.Diagnostics) {
postProcessor := &PostProcessorBlock{
PType: block.Labels[0],
block: block,
PName: b.Name,
HCL2Ref: newHCL2Ref(block, b.Rest),
}
var diags hcl.Diagnostics
if !p.PostProcessorsSchemas.Has(postProcessor.PType) {
diags = append(diags, &hcl.Diagnostic{
Summary: "Unknown " + buildPostProcessorLabel + " type " + postProcessor.PType,
Summary: fmt.Sprintf("Unknown "+buildPostProcessorLabel+" type %q", postProcessor.PType),
Subject: block.LabelRanges[0].Ptr(),
Detail: fmt.Sprintf("known provisioners: %v", p.ProvisionersSchemas.List()),
Detail: fmt.Sprintf("known "+buildPostProcessorLabel+"s: %v", p.PostProcessorsSchemas.List()),
Severity: hcl.DiagError,
})
return nil, diags
@ -39,21 +55,21 @@ func (p *Parser) StartPostProcessor(pp *PostProcessorBlock) (packer.PostProcesso
postProcessor, err := p.PostProcessorsSchemas.Start(pp.PType)
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Summary: "Failed loading " + pp.block.Type,
Subject: pp.block.LabelRanges[0].Ptr(),
Summary: fmt.Sprintf("Failed loading %s", pp.PType),
Subject: pp.DefRange.Ptr(),
Detail: err.Error(),
})
return nil, diags
}
flatProvisinerCfg, moreDiags := decodeHCL2Spec(pp.block, nil, postProcessor)
flatProvisinerCfg, moreDiags := decodeHCL2Spec(pp.Rest, nil, postProcessor)
diags = append(diags, moreDiags...)
err = postProcessor.Configure(flatProvisinerCfg)
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Failed preparing " + pp.block.Type,
Summary: fmt.Sprintf("Failed preparing %s", pp),
Detail: err.Error(),
Subject: pp.block.DefRange.Ptr(),
Subject: pp.DefRange.Ptr(),
})
return nil, diags
}

View File

@ -2,7 +2,9 @@ package hcl2template
import (
"fmt"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/hcl/v2/gohcl"
"github.com/hashicorp/packer/helper/common"
"github.com/hashicorp/packer/packer"
)
@ -10,21 +12,34 @@ import (
// ProvisionerBlock represents a parsed provisioner
type ProvisionerBlock struct {
PType string
block *hcl.Block
PName string
HCL2Ref
}
func (p *ProvisionerBlock) String() string {
return fmt.Sprintf(buildProvisionerLabel+"-block %q %q", p.PType, p.PName)
}
func (p *Parser) decodeProvisioner(block *hcl.Block) (*ProvisionerBlock, hcl.Diagnostics) {
var b struct {
Name string `hcl:"name,optional"`
Rest hcl.Body `hcl:",remain"`
}
diags := gohcl.DecodeBody(block.Body, nil, &b)
if diags.HasErrors() {
return nil, diags
}
provisioner := &ProvisionerBlock{
PType: block.Labels[0],
block: block,
PName: b.Name,
HCL2Ref: newHCL2Ref(block, b.Rest),
}
var diags hcl.Diagnostics
if !p.ProvisionersSchemas.Has(provisioner.PType) {
diags = append(diags, &hcl.Diagnostic{
Summary: "Unknown " + buildProvisionerLabel + " type " + provisioner.PType,
Summary: fmt.Sprintf("Unknown "+buildProvisionerLabel+" type %q", provisioner.PType),
Subject: block.LabelRanges[0].Ptr(),
Detail: fmt.Sprintf("known provisioners: %v", p.ProvisionersSchemas.List()),
Detail: fmt.Sprintf("known "+buildProvisionerLabel+"s: %v", p.ProvisionersSchemas.List()),
Severity: hcl.DiagError,
})
return nil, diags
@ -38,13 +53,13 @@ func (p *Parser) StartProvisioner(pb *ProvisionerBlock, generatedVars []string)
provisioner, err := p.ProvisionersSchemas.Start(pb.PType)
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Summary: "Failed loading " + pb.block.Type,
Subject: pb.block.LabelRanges[0].Ptr(),
Summary: fmt.Sprintf("failed loading %s", pb.PType),
Subject: pb.HCL2Ref.LabelsRanges[0].Ptr(),
Detail: err.Error(),
})
return nil, diags
}
flatProvisionerCfg, moreDiags := decodeHCL2Spec(pb.block, nil, provisioner)
flatProvisionerCfg, moreDiags := decodeHCL2Spec(pb.HCL2Ref.Rest, nil, provisioner)
diags = append(diags, moreDiags...)
if diags.HasErrors() {
return nil, diags
@ -71,9 +86,9 @@ func (p *Parser) StartProvisioner(pb *ProvisionerBlock, generatedVars []string)
if err != nil {
diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Failed preparing " + pb.block.Type,
Summary: fmt.Sprintf("Failed preparing %s", pb),
Detail: err.Error(),
Subject: pb.block.DefRange.Ptr(),
Subject: pb.HCL2Ref.DefRange.Ptr(),
})
return nil, diags
}

View File

@ -7,8 +7,19 @@ import (
// reference to the source definition in configuration text file
type HCL2Ref struct {
// reference to the source definition in configuration text file
DeclRange hcl.Range
DefRange hcl.Range
TypeRange hcl.Range
LabelsRanges []hcl.Range
// remainder of unparsed body
Remain hcl.Body
Rest hcl.Body
}
func newHCL2Ref(block *hcl.Block, rest hcl.Body) HCL2Ref {
return HCL2Ref{
Rest: rest,
DefRange: block.DefRange,
TypeRange: block.TypeRange,
LabelsRanges: block.LabelRanges,
}
}

View File

@ -25,6 +25,7 @@ func (p *Parser) CoreBuildProvisioners(blocks []*ProvisionerBlock, generatedVars
}
res = append(res, packer.CoreBuildProvisioner{
PType: pb.PType,
PName: pb.PName,
Provisioner: provisioner,
})
}
@ -34,15 +35,16 @@ func (p *Parser) CoreBuildProvisioners(blocks []*ProvisionerBlock, generatedVars
func (p *Parser) CoreBuildPostProcessors(blocks []*PostProcessorBlock) ([]packer.CoreBuildPostProcessor, hcl.Diagnostics) {
var diags hcl.Diagnostics
res := []packer.CoreBuildPostProcessor{}
for _, pp := range blocks {
postProcessor, moreDiags := p.StartPostProcessor(pp)
for _, ppb := range blocks {
postProcessor, moreDiags := p.StartPostProcessor(ppb)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {
continue
}
res = append(res, packer.CoreBuildPostProcessor{
PostProcessor: postProcessor,
PType: pp.PType,
PName: ppb.PName,
PType: ppb.PType,
})
}
@ -59,7 +61,7 @@ func (p *Parser) getBuilds(cfg *PackerConfig) ([]packer.Build, hcl.Diagnostics)
if !found {
diags = append(diags, &hcl.Diagnostic{
Summary: "Unknown " + sourceLabel + " " + from.String(),
Subject: build.HCL2Ref.DeclRange.Ptr(),
Subject: build.HCL2Ref.DefRange.Ptr(),
Severity: hcl.DiagError,
})
continue

View File

@ -26,11 +26,20 @@ func TestParser_complete(t *testing.T) {
&BuildBlock{
Froms: []SourceRef{refVBIsoUbuntu1204},
ProvisionerBlocks: []*ProvisionerBlock{
{PType: "shell"},
{
PType: "shell",
PName: "provisioner that does something",
},
{PType: "file"},
},
PostProcessors: []*PostProcessorBlock{
{PType: "amazon-import"},
{
PType: "amazon-import",
PName: "something",
},
{
PType: "amazon-import",
},
},
},
},
@ -41,12 +50,24 @@ func TestParser_complete(t *testing.T) {
Type: "virtualbox-iso",
Builder: basicMockBuilder,
Provisioners: []packer.CoreBuildProvisioner{
{PType: "shell", Provisioner: basicMockProvisioner},
{
PType: "shell",
PName: "provisioner that does something",
Provisioner: basicMockProvisioner,
},
{PType: "file", Provisioner: basicMockProvisioner},
},
PostProcessors: [][]packer.CoreBuildPostProcessor{
{
{PType: "amazon-import", PostProcessor: basicMockPostProcessor},
{
PType: "amazon-import",
PName: "something",
PostProcessor: basicMockPostProcessor,
},
{
PType: "amazon-import",
PostProcessor: basicMockPostProcessor,
},
},
},
},

View File

@ -52,7 +52,7 @@ func (p *Parser) StartBuilder(source *Source) (packer.Builder, hcl.Diagnostics,
return builder, diags, nil
}
decoded, moreDiags := decodeHCL2Spec(source.block, nil, builder)
decoded, moreDiags := decodeHCL2Spec(source.block.Body, nil, builder)
diags = append(diags, moreDiags...)
if moreDiags.HasErrors() {
return nil, diags, nil

View File

@ -118,6 +118,7 @@ type CoreBuildPostProcessor struct {
// the provisioner within the build.
type CoreBuildProvisioner struct {
PType string
PName string
Provisioner Provisioner
config []interface{}
}