terrafrom: create CheckPreventDestroy method on NodeAbstractResource

This will eventually replace all uses of EvalCheckPreventDestroy.
This commit is contained in:
Kristin Laemmert 2020-09-25 12:37:23 -04:00
parent ab5bf50fc3
commit f835841c28
3 changed files with 30 additions and 9 deletions

View File

@ -45,5 +45,3 @@ func (n *EvalCheckPreventDestroy) Eval(ctx EvalContext) (interface{}, error) {
return nil, nil
}
const preventDestroyErrStr = `%s: the plan would destroy this resource, but it currently has lifecycle.prevent_destroy set to true. To avoid this error and continue with the plan, either disable lifecycle.prevent_destroy or adjust the scope of the plan using the -target flag.`

View File

@ -4,11 +4,13 @@ import (
"fmt"
"log"
"github.com/hashicorp/hcl/v2"
"github.com/hashicorp/terraform/addrs"
"github.com/hashicorp/terraform/configs"
"github.com/hashicorp/terraform/configs/configschema"
"github.com/hashicorp/terraform/dag"
"github.com/hashicorp/terraform/lang"
"github.com/hashicorp/terraform/plans"
"github.com/hashicorp/terraform/states"
"github.com/hashicorp/terraform/tfdiags"
)
@ -450,7 +452,7 @@ func (n *NodeAbstractResource) DotNode(name string, opts *dag.DotOpts) *dag.DotN
// WriteResourceState ensures that a suitable resource-level state record is
// present in the state, if that's required for the "each mode" of that
// resource.
//å
//
// This is important primarily for the situation where count = 0, since this
// eval is the only change we get to set the resource "each mode" to list
// in that case, allowing expression evaluation to see it as a zero-element list
@ -538,6 +540,31 @@ func (n *NodeAbstractResource) ReadResourceInstanceState(ctx EvalContext, addr a
return obj, nil
}
// CheckPreventDestroy returns an error if a resource has PreventDestroy
// configured and the diff would destroy the resource.
func (n *NodeAbstractResource) CheckPreventDestroy(addr addrs.AbsResourceInstance, change *plans.ResourceInstanceChange) error {
if change == nil || n.Config == nil || n.Config.Managed == nil {
return nil
}
preventDestroy := n.Config.Managed.PreventDestroy
if (change.Action == plans.Delete || change.Action.IsReplace()) && preventDestroy {
var diags tfdiags.Diagnostics
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Instance cannot be destroyed",
Detail: fmt.Sprintf(
"Resource %s has lifecycle.prevent_destroy set, but the plan calls for this resource to be destroyed. To avoid this error and continue with the plan, either disable lifecycle.prevent_destroy or reduce the scope of the plan using the -target flag.",
addr,
),
Subject: &n.Config.DeclRange,
})
return diags.Err()
}
return nil
}
// graphNodesAreResourceInstancesInDifferentInstancesOfSameModule is an
// annoyingly-task-specific helper function that returns true if and only if
// the following conditions hold:

View File

@ -57,12 +57,7 @@ func (n *NodePlannableResourceInstanceOrphan) Execute(ctx EvalContext, op walkOp
return err
}
checkPreventDestroy := &EvalCheckPreventDestroy{
Addr: addr.Resource,
Config: n.Config,
Change: &change,
}
_, err = checkPreventDestroy.Eval(ctx)
err = n.CheckPreventDestroy(addr, change)
if err != nil {
return err
}
@ -76,6 +71,7 @@ func (n *NodePlannableResourceInstanceOrphan) Execute(ctx EvalContext, op walkOp
if err != nil {
return err
}
writeState := &EvalWriteState{
Addr: addr.Resource,
ProviderAddr: n.ResolvedProvider,