add hcl2 provisioner type that reprepares itself
This commit is contained in:
parent
c88cb098a1
commit
db6c3adbba
|
@ -129,6 +129,7 @@ func testParse(t *testing.T, tests []parseTest) {
|
|||
packer.CoreBuildProvisioner{},
|
||||
packer.CoreBuildPostProcessor{},
|
||||
null.Builder{},
|
||||
HCL2Provisioner{},
|
||||
),
|
||||
); diff != "" {
|
||||
t.Fatalf("Parser.getBuilds() wrong packer builds. %s", diff)
|
||||
|
@ -176,7 +177,7 @@ var (
|
|||
|
||||
basicMockProvisioner = &MockProvisioner{
|
||||
Config: MockConfig{
|
||||
NotSquashed: "value",
|
||||
NotSquashed: "value <UNKNOWN>",
|
||||
NestedMockConfig: basicNestedMockConfig,
|
||||
Nested: basicNestedMockConfig,
|
||||
NestedSlice: []NestedMockConfig{
|
||||
|
|
|
@ -11,7 +11,7 @@ build {
|
|||
|
||||
provisioner "shell" {
|
||||
name = "provisioner that does something"
|
||||
not_squashed = "${var.foo} ${lower(build.ID)}"
|
||||
not_squashed = "${var.foo} ${upper(build.ID)}"
|
||||
string = "string"
|
||||
int = "${41 + 1}"
|
||||
int64 = "${42 + 1}"
|
||||
|
@ -62,7 +62,7 @@ build {
|
|||
}
|
||||
|
||||
provisioner "file" {
|
||||
not_squashed = "${var.foo}"
|
||||
not_squashed = "${var.foo} ${upper(build.ID)}"
|
||||
string = "string"
|
||||
int = 42
|
||||
int64 = 43
|
||||
|
|
|
@ -61,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, generatedVars map[string]string) (packer.PostProcessor, hcl.Diagnostics) {
|
||||
func (cfg *PackerConfig) startPostProcessor(source SourceBlock, pp *PostProcessorBlock, ectx *hcl.EvalContext, generatedVars map[string]interface{}) (packer.PostProcessor, hcl.Diagnostics) {
|
||||
// ProvisionerBlock represents a detected but unparsed provisioner
|
||||
var diags hcl.Diagnostics
|
||||
|
||||
|
@ -76,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, generatedVars)
|
||||
err = postProcessor.Configure(source.builderVariables(), flatProvisinerCfg)
|
||||
if err != nil {
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
|
|
|
@ -132,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, generatedVars map[string]string) (packer.Provisioner, hcl.Diagnostics) {
|
||||
func (cfg *PackerConfig) startProvisioner(source SourceBlock, pb *ProvisionerBlock, ectx *hcl.EvalContext, generatedVars map[string]interface{}) (packer.Provisioner, hcl.Diagnostics) {
|
||||
var diags hcl.Diagnostics
|
||||
|
||||
provisioner, err := cfg.provisionersSchemas.Start(pb.PType)
|
||||
|
@ -144,18 +144,13 @@ func (cfg *PackerConfig) startProvisioner(source SourceBlock, pb *ProvisionerBlo
|
|||
})
|
||||
return nil, diags
|
||||
}
|
||||
flatProvisionerCfg, moreDiags := decodeHCL2Spec(pb.HCL2Ref.Rest, ectx, provisioner)
|
||||
diags = append(diags, moreDiags...)
|
||||
if diags.HasErrors() {
|
||||
return nil, diags
|
||||
p := &HCL2Provisioner{
|
||||
Provisioner: provisioner,
|
||||
provisionerBlock: pb,
|
||||
evalContext: ectx,
|
||||
builderVariables: source.builderVariables(),
|
||||
}
|
||||
// manipulate generatedVars from builder to add to the interfaces being
|
||||
// passed to the provisioner Prepare()
|
||||
|
||||
// configs := make([]interface{}, 2)
|
||||
// configs = append(, flatProvisionerCfg)
|
||||
// configs = append(configs, generatedVars)
|
||||
err = provisioner.Prepare(source.builderVariables(), flatProvisionerCfg, generatedVars)
|
||||
err = p.HCL2Prepare(generatedVars)
|
||||
if err != nil {
|
||||
diags = append(diags, &hcl.Diagnostic{
|
||||
Severity: hcl.DiagError,
|
||||
|
@ -165,5 +160,5 @@ func (cfg *PackerConfig) startProvisioner(source SourceBlock, pb *ProvisionerBlo
|
|||
})
|
||||
return nil, diags
|
||||
}
|
||||
return provisioner, diags
|
||||
return p, diags
|
||||
}
|
||||
|
|
|
@ -266,19 +266,23 @@ func TestParse_build(t *testing.T) {
|
|||
Provisioners: []packer.CoreBuildProvisioner{
|
||||
{
|
||||
PType: "shell",
|
||||
Provisioner: &MockProvisioner{
|
||||
Config: MockConfig{
|
||||
NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
|
||||
NestedSlice: []NestedMockConfig{},
|
||||
Provisioner: &HCL2Provisioner{
|
||||
Provisioner: &MockProvisioner{
|
||||
Config: MockConfig{
|
||||
NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
|
||||
NestedSlice: []NestedMockConfig{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
PType: "file",
|
||||
Provisioner: &MockProvisioner{
|
||||
Config: MockConfig{
|
||||
NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
|
||||
NestedSlice: []NestedMockConfig{},
|
||||
Provisioner: &HCL2Provisioner{
|
||||
Provisioner: &MockProvisioner{
|
||||
Config: MockConfig{
|
||||
NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
|
||||
NestedSlice: []NestedMockConfig{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
@ -292,19 +296,23 @@ func TestParse_build(t *testing.T) {
|
|||
Provisioners: []packer.CoreBuildProvisioner{
|
||||
{
|
||||
PType: "file",
|
||||
Provisioner: &MockProvisioner{
|
||||
Config: MockConfig{
|
||||
NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
|
||||
NestedSlice: []NestedMockConfig{},
|
||||
Provisioner: &HCL2Provisioner{
|
||||
Provisioner: &MockProvisioner{
|
||||
Config: MockConfig{
|
||||
NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
|
||||
NestedSlice: []NestedMockConfig{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
PType: "shell",
|
||||
Provisioner: &MockProvisioner{
|
||||
Config: MockConfig{
|
||||
NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
|
||||
NestedSlice: []NestedMockConfig{},
|
||||
Provisioner: &HCL2Provisioner{
|
||||
Provisioner: &MockProvisioner{
|
||||
Config: MockConfig{
|
||||
NestedMockConfig: NestedMockConfig{Tags: []MockTag{}},
|
||||
NestedSlice: []NestedMockConfig{},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
|
@ -0,0 +1,61 @@
|
|||
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 HCL2Provisioner struct {
|
||||
Provisioner packer.Provisioner
|
||||
provisionerBlock *ProvisionerBlock
|
||||
evalContext *hcl.EvalContext
|
||||
builderVariables map[string]string
|
||||
}
|
||||
|
||||
func (p *HCL2Provisioner) ConfigSpec() hcldec.ObjectSpec {
|
||||
return p.Provisioner.ConfigSpec()
|
||||
}
|
||||
|
||||
func (p *HCL2Provisioner) 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),
|
||||
}
|
||||
}
|
||||
|
||||
flatProvisionerCfg, moreDiags := decodeHCL2Spec(p.provisionerBlock.HCL2Ref.Rest, ectx, p.Provisioner)
|
||||
diags = append(diags, moreDiags...)
|
||||
if diags.HasErrors() {
|
||||
return diags
|
||||
}
|
||||
return p.Provisioner.Prepare(p.builderVariables, flatProvisionerCfg)
|
||||
}
|
||||
|
||||
func (p *HCL2Provisioner) Prepare(args ...interface{}) error {
|
||||
return p.Provisioner.Prepare(args...)
|
||||
}
|
||||
|
||||
func (p *HCL2Provisioner) Provision(ctx context.Context, ui packer.Ui, c packer.Communicator, vars map[string]interface{}) error {
|
||||
err := p.HCL2Prepare(vars)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
return p.Provisioner.Provision(ctx, ui, c, vars)
|
||||
}
|
|
@ -199,7 +199,7 @@ 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, generatedVars map[string]string) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) {
|
||||
func (cfg *PackerConfig) getCoreBuildProvisioners(source SourceBlock, blocks []*ProvisionerBlock, ectx *hcl.EvalContext, generatedVars map[string]interface{}) ([]packer.CoreBuildProvisioner, hcl.Diagnostics) {
|
||||
var diags hcl.Diagnostics
|
||||
res := []packer.CoreBuildProvisioner{}
|
||||
for _, pb := range blocks {
|
||||
|
@ -242,7 +242,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, generatedVars map[string]string) ([]packer.CoreBuildPostProcessor, hcl.Diagnostics) {
|
||||
func (cfg *PackerConfig) getCoreBuildPostProcessors(source SourceBlock, blocks []*PostProcessorBlock, ectx *hcl.EvalContext, generatedVars map[string]interface{}) ([]packer.CoreBuildPostProcessor, hcl.Diagnostics) {
|
||||
var diags hcl.Diagnostics
|
||||
res := []packer.CoreBuildPostProcessor{}
|
||||
for _, ppb := range blocks {
|
||||
|
@ -365,7 +365,7 @@ func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packer.Build
|
|||
for _, k := range generatedVars {
|
||||
generatedPlaceholderMap[k] = fmt.Sprintf("Build_%s. "+
|
||||
common.PlaceholderMsg, k)
|
||||
unknownBuildValues[k] = cty.StringVal("<unknown_value>")
|
||||
unknownBuildValues[k] = cty.StringVal("<unknown>")
|
||||
}
|
||||
|
||||
variables := map[string]cty.Value{
|
||||
|
@ -376,16 +376,16 @@ func (cfg *PackerConfig) GetBuilds(opts packer.GetBuildsOptions) ([]packer.Build
|
|||
buildAccessor: cty.ObjectVal(unknownBuildValues),
|
||||
}
|
||||
|
||||
provisioners, moreDiags := cfg.getCoreBuildProvisioners(src, build.ProvisionerBlocks, cfg.EvalContext(variables), generatedPlaceholderMap)
|
||||
provisioners, moreDiags := cfg.getCoreBuildProvisioners(src, build.ProvisionerBlocks, cfg.EvalContext(variables), nil)
|
||||
diags = append(diags, moreDiags...)
|
||||
if moreDiags.HasErrors() {
|
||||
continue
|
||||
}
|
||||
postProcessors, moreDiags := cfg.getCoreBuildPostProcessors(src, build.PostProcessors, cfg.EvalContext(variables), generatedPlaceholderMap)
|
||||
postProcessors, moreDiags := cfg.getCoreBuildPostProcessors(src, build.PostProcessors, cfg.EvalContext(variables), nil)
|
||||
pps := [][]packer.CoreBuildPostProcessor{}
|
||||
if len(postProcessors) > 0 {
|
||||
pps = [][]packer.CoreBuildPostProcessor{postProcessors}
|
||||
}
|
||||
} // TODO(azr): remove this
|
||||
diags = append(diags, moreDiags...)
|
||||
if moreDiags.HasErrors() {
|
||||
continue
|
||||
|
|
|
@ -110,11 +110,18 @@ func TestParser_complete(t *testing.T) {
|
|||
Builder: basicMockBuilder,
|
||||
Provisioners: []packer.CoreBuildProvisioner{
|
||||
{
|
||||
PType: "shell",
|
||||
PName: "provisioner that does something",
|
||||
Provisioner: basicMockProvisioner,
|
||||
PType: "shell",
|
||||
PName: "provisioner that does something",
|
||||
Provisioner: &HCL2Provisioner{
|
||||
Provisioner: basicMockProvisioner,
|
||||
},
|
||||
},
|
||||
{
|
||||
PType: "file",
|
||||
Provisioner: &HCL2Provisioner{
|
||||
Provisioner: basicMockProvisioner,
|
||||
},
|
||||
},
|
||||
{PType: "file", Provisioner: basicMockProvisioner},
|
||||
},
|
||||
PostProcessors: [][]packer.CoreBuildPostProcessor{
|
||||
{
|
||||
|
@ -146,11 +153,18 @@ func TestParser_complete(t *testing.T) {
|
|||
},
|
||||
Provisioners: []packer.CoreBuildProvisioner{
|
||||
{
|
||||
PType: "shell",
|
||||
PName: "provisioner that does something",
|
||||
Provisioner: basicMockProvisioner,
|
||||
PType: "shell",
|
||||
PName: "provisioner that does something",
|
||||
Provisioner: &HCL2Provisioner{
|
||||
Provisioner: basicMockProvisioner,
|
||||
},
|
||||
},
|
||||
{
|
||||
PType: "file",
|
||||
Provisioner: &HCL2Provisioner{
|
||||
Provisioner: basicMockProvisioner,
|
||||
},
|
||||
},
|
||||
{PType: "file", Provisioner: basicMockProvisioner},
|
||||
},
|
||||
PostProcessors: [][]packer.CoreBuildPostProcessor{
|
||||
{
|
||||
|
|
|
@ -51,8 +51,8 @@ type ProvisionHook struct {
|
|||
// custom generated data could be passed into provisioners from builders to
|
||||
// enable specialized builder-specific (but still validated!!) access to builder
|
||||
// data.
|
||||
func BasicPlaceholderData() map[string]string {
|
||||
placeholderData := map[string]string{}
|
||||
func BasicPlaceholderData() map[string]interface{} {
|
||||
placeholderData := map[string]interface{}{}
|
||||
msg := "Build_%s. " + common.PlaceholderMsg
|
||||
placeholderData["ID"] = fmt.Sprintf(msg, "ID")
|
||||
// The following correspond to communicator-agnostic functions that are
|
||||
|
|
Loading…
Reference in New Issue