use EvalSelfBlock for destroy provisioners
Evaluate destroy provisioner configurations using only the last resource state value, and the static instance key data.
This commit is contained in:
parent
64c3a8f550
commit
95197f0324
|
@ -11,6 +11,7 @@ import (
|
|||
|
||||
"github.com/hashicorp/terraform/addrs"
|
||||
"github.com/hashicorp/terraform/configs"
|
||||
"github.com/hashicorp/terraform/configs/configschema"
|
||||
"github.com/hashicorp/terraform/plans"
|
||||
"github.com/hashicorp/terraform/plans/objchange"
|
||||
"github.com/hashicorp/terraform/providers"
|
||||
|
@ -504,6 +505,9 @@ type EvalApplyProvisioners struct {
|
|||
|
||||
// When is the type of provisioner to run at this point
|
||||
When configs.ProvisionerWhen
|
||||
|
||||
// We use the stored change to get the previous resource values in the case of a destroy provisioner
|
||||
Change *plans.ResourceInstanceChange
|
||||
}
|
||||
|
||||
// TODO: test
|
||||
|
@ -600,6 +604,18 @@ func (n *EvalApplyProvisioners) apply(ctx EvalContext, provs []*configs.Provisio
|
|||
instanceAddr := n.Addr
|
||||
absAddr := instanceAddr.Absolute(ctx.Path())
|
||||
|
||||
// this self is only used for destroy provisioner evaluation, and must
|
||||
// refer to the last known value of the resource.
|
||||
self := n.Change.Before
|
||||
|
||||
var evalScope func(EvalContext, hcl.Body, cty.Value, *configschema.Block) (cty.Value, tfdiags.Diagnostics)
|
||||
switch n.When {
|
||||
case configs.ProvisionerWhenDestroy:
|
||||
evalScope = n.evalDestroyProvisionerConfig
|
||||
default:
|
||||
evalScope = n.evalProvisionerConfig
|
||||
}
|
||||
|
||||
// If there's a connection block defined directly inside the resource block
|
||||
// then it'll serve as a base connection configuration for all of the
|
||||
// provisioners.
|
||||
|
@ -615,25 +631,8 @@ func (n *EvalApplyProvisioners) apply(ctx EvalContext, provs []*configs.Provisio
|
|||
provisioner := ctx.Provisioner(prov.Type)
|
||||
schema := ctx.ProvisionerSchema(prov.Type)
|
||||
|
||||
var forEach map[string]cty.Value
|
||||
|
||||
// For a destroy-time provisioner forEach is intentionally nil here,
|
||||
// which EvalDataForInstanceKey responds to by not populating EachValue
|
||||
// in its result. That's okay because each.value is prohibited for
|
||||
// destroy-time provisioners.
|
||||
if n.When != configs.ProvisionerWhenDestroy {
|
||||
m, forEachDiags := evaluateForEachExpression(n.ResourceConfig.ForEach, ctx)
|
||||
diags = diags.Append(forEachDiags)
|
||||
forEach = m
|
||||
}
|
||||
|
||||
keyData := EvalDataForInstanceKey(instanceAddr.Key, forEach)
|
||||
|
||||
// Evaluate the main provisioner configuration.
|
||||
config, _, configDiags := ctx.EvaluateBlock(prov.Config, schema, instanceAddr, keyData)
|
||||
config, configDiags := evalScope(ctx, prov.Config, self, schema)
|
||||
diags = diags.Append(configDiags)
|
||||
|
||||
// we can't apply the provisioner if the config has errors
|
||||
if diags.HasErrors() {
|
||||
return diags.Err()
|
||||
}
|
||||
|
@ -664,11 +663,9 @@ func (n *EvalApplyProvisioners) apply(ctx EvalContext, provs []*configs.Provisio
|
|||
|
||||
if connBody != nil {
|
||||
var connInfoDiags tfdiags.Diagnostics
|
||||
connInfo, _, connInfoDiags = ctx.EvaluateBlock(connBody, connectionBlockSupersetSchema, instanceAddr, keyData)
|
||||
connInfo, connInfoDiags = evalScope(ctx, connBody, self, connectionBlockSupersetSchema)
|
||||
diags = diags.Append(connInfoDiags)
|
||||
if diags.HasErrors() {
|
||||
// "on failure continue" setting only applies to failures of the
|
||||
// provisioner itself, not to invalid configuration.
|
||||
return diags.Err()
|
||||
}
|
||||
}
|
||||
|
@ -728,3 +725,34 @@ func (n *EvalApplyProvisioners) apply(ctx EvalContext, provs []*configs.Provisio
|
|||
|
||||
return diags.ErrWithWarnings()
|
||||
}
|
||||
|
||||
func (n *EvalApplyProvisioners) evalProvisionerConfig(ctx EvalContext, body hcl.Body, self cty.Value, schema *configschema.Block) (cty.Value, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
forEach, forEachDiags := evaluateForEachExpression(n.ResourceConfig.ForEach, ctx)
|
||||
diags = diags.Append(forEachDiags)
|
||||
|
||||
keyData := EvalDataForInstanceKey(n.Addr.Key, forEach)
|
||||
|
||||
config, _, configDiags := ctx.EvaluateBlock(body, schema, n.Addr, keyData)
|
||||
diags = diags.Append(configDiags)
|
||||
|
||||
return config, diags
|
||||
}
|
||||
|
||||
// during destroy a provisioner can only evaluate within the scope of the parent resource
|
||||
func (n *EvalApplyProvisioners) evalDestroyProvisionerConfig(ctx EvalContext, body hcl.Body, self cty.Value, schema *configschema.Block) (cty.Value, tfdiags.Diagnostics) {
|
||||
var diags tfdiags.Diagnostics
|
||||
|
||||
// For a destroy-time provisioner forEach is intentionally nil here,
|
||||
// which EvalDataForInstanceKey responds to by not populating EachValue
|
||||
// in its result. That's okay because each.value is prohibited for
|
||||
// destroy-time provisioners.
|
||||
keyData := EvalDataForInstanceKey(n.Addr.Key, nil)
|
||||
|
||||
evalScope := ctx.EvaluationScope(n.Addr, keyData)
|
||||
config, evalDiags := evalScope.EvalSelfBlock(body, self, schema, keyData)
|
||||
diags = diags.Append(evalDiags)
|
||||
|
||||
return config, diags
|
||||
}
|
||||
|
|
|
@ -352,6 +352,18 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext)
|
|||
return err
|
||||
}
|
||||
|
||||
// We clear the change out here so that future nodes don't see a change
|
||||
// that is already complete.
|
||||
writeDiff := &EvalWriteDiff{
|
||||
Addr: addr,
|
||||
ProviderSchema: &providerSchema,
|
||||
Change: nil,
|
||||
}
|
||||
_, err = writeDiff.Eval(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
evalMaybeTainted := &EvalMaybeTainted{
|
||||
Addr: addr,
|
||||
State: &state,
|
||||
|
@ -382,6 +394,7 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext)
|
|||
CreateNew: &createNew,
|
||||
Error: &applyError,
|
||||
When: configs.ProvisionerWhenCreate,
|
||||
Change: diffApply,
|
||||
}
|
||||
_, err = applyProvisioners.Eval(ctx)
|
||||
if err != nil {
|
||||
|
@ -423,20 +436,6 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext)
|
|||
}
|
||||
}
|
||||
|
||||
// We clear the diff out here so that future nodes don't see a diff that is
|
||||
// already complete. There is no longer a diff!
|
||||
if !diff.Action.IsReplace() || !n.CreateBeforeDestroy() {
|
||||
writeDiff := &EvalWriteDiff{
|
||||
Addr: addr,
|
||||
ProviderSchema: &providerSchema,
|
||||
Change: nil,
|
||||
}
|
||||
_, err := writeDiff.Eval(ctx)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
|
||||
applyPost := &EvalApplyPost{
|
||||
Addr: addr,
|
||||
State: &state,
|
||||
|
|
|
@ -193,6 +193,7 @@ func (n *NodeDestroyResourceInstance) Execute(ctx EvalContext, op walkOperation)
|
|||
ResourceConfig: n.Config,
|
||||
Error: &provisionerErr,
|
||||
When: configs.ProvisionerWhenDestroy,
|
||||
Change: changeApply,
|
||||
}
|
||||
_, err := evalApplyProvisioners.Eval(ctx)
|
||||
if err != nil {
|
||||
|
|
Loading…
Reference in New Issue