2020-07-02 12:02:19 -04:00
|
|
|
package hcl2template
|
|
|
|
|
|
|
|
import (
|
|
|
|
"context"
|
2020-11-19 14:54:31 -05:00
|
|
|
|
2020-07-02 12:02:19 -04:00
|
|
|
"github.com/hashicorp/hcl/v2"
|
|
|
|
"github.com/hashicorp/hcl/v2/hcldec"
|
2020-12-17 16:29:25 -05:00
|
|
|
packersdk "github.com/hashicorp/packer-plugin-sdk/packer"
|
2021-01-22 08:49:45 -05:00
|
|
|
hcl2shim "github.com/hashicorp/packer/hcl2template/shim"
|
2020-07-02 12:02:19 -04:00
|
|
|
"github.com/zclconf/go-cty/cty"
|
|
|
|
)
|
|
|
|
|
2020-07-06 05:38:12 -04:00
|
|
|
// HCL2Provisioner has a reference to the part of the HCL2 body where it is
|
|
|
|
// defined, allowing to completely reconfigure the Provisioner right before
|
|
|
|
// calling Provision: with contextual variables.
|
|
|
|
// This permits using "${build.ID}" values for example.
|
2020-07-02 12:02:19 -04:00
|
|
|
type HCL2Provisioner struct {
|
2020-12-01 17:25:14 -05:00
|
|
|
Provisioner packersdk.Provisioner
|
2020-07-02 12:02:19 -04:00
|
|
|
provisionerBlock *ProvisionerBlock
|
|
|
|
evalContext *hcl.EvalContext
|
|
|
|
builderVariables map[string]string
|
2020-08-13 13:16:13 -04:00
|
|
|
override map[string]interface{}
|
2020-07-02 12:02:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
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{}
|
2020-10-16 04:57:42 -04:00
|
|
|
if !p.evalContext.Variables[buildAccessor].IsNull() {
|
|
|
|
buildValues = p.evalContext.Variables[buildAccessor].AsValueMap()
|
|
|
|
}
|
2020-07-02 12:02:19 -04:00
|
|
|
for k, v := range buildVars {
|
2021-01-25 15:10:31 -05:00
|
|
|
val, err := ConvertPluginConfigValueToHCLValue(v)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
2020-07-02 12:02:19 -04:00
|
|
|
}
|
2021-01-25 15:10:31 -05:00
|
|
|
|
|
|
|
buildValues[k] = val
|
2020-07-02 12:02:19 -04:00
|
|
|
}
|
|
|
|
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
|
|
|
|
}
|
2021-01-22 08:49:45 -05:00
|
|
|
|
|
|
|
// In case of cty.Unknown values, this will write a equivalent placeholder of the same type
|
|
|
|
// Unknown types are not recognized by the json marshal during the RPC call and we have to do this here
|
|
|
|
// to avoid json parsing failures when running the validate command.
|
|
|
|
// We don't do this before so we can validate if variable types matches correctly on decodeHCL2Spec.
|
|
|
|
flatProvisionerCfg = hcl2shim.WriteUnknownPlaceholderValues(flatProvisionerCfg)
|
|
|
|
|
2020-08-13 13:16:13 -04:00
|
|
|
return p.Provisioner.Prepare(p.builderVariables, flatProvisionerCfg, p.override)
|
2020-07-02 12:02:19 -04:00
|
|
|
}
|
|
|
|
|
|
|
|
func (p *HCL2Provisioner) Prepare(args ...interface{}) error {
|
|
|
|
return p.Provisioner.Prepare(args...)
|
|
|
|
}
|
|
|
|
|
2020-11-19 18:10:00 -05:00
|
|
|
func (p *HCL2Provisioner) Provision(ctx context.Context, ui packersdk.Ui, c packersdk.Communicator, vars map[string]interface{}) error {
|
2020-07-02 12:02:19 -04:00
|
|
|
err := p.HCL2Prepare(vars)
|
|
|
|
if err != nil {
|
|
|
|
return err
|
|
|
|
}
|
|
|
|
return p.Provisioner.Provision(ctx, ui, c, vars)
|
|
|
|
}
|