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