outputs should not be checked during destroy

Module output may need to be evaluated during destroy in order to
possibly be used by providers. The final state however is that all
objects are destroyed, so preconditions should not be evaluated.
This commit is contained in:
James Bardin 2022-10-14 18:08:18 -04:00
parent 71837d187b
commit 8a24d73d15
2 changed files with 45 additions and 31 deletions

View File

@ -23,7 +23,8 @@ type nodeExpandOutput struct {
Addr addrs.OutputValue
Module addrs.Module
Config *configs.Output
Destroy bool
DestroyPlan bool
DestroyApply bool
RefreshOnly bool
// Planning is set to true when this node is in a graph that was produced
@ -52,7 +53,7 @@ func (n *nodeExpandOutput) temporaryValue() bool {
}
func (n *nodeExpandOutput) DynamicExpand(ctx EvalContext) (*Graph, error) {
if n.Destroy {
if n.DestroyPlan {
// if we're planning a destroy, we only need to handle the root outputs.
// The destroy plan doesn't evaluate any other config, so we can skip
// the rest of the outputs.
@ -109,6 +110,7 @@ func (n *nodeExpandOutput) DynamicExpand(ctx EvalContext) (*Graph, error) {
Config: n.Config,
Change: change,
RefreshOnly: n.RefreshOnly,
DestroyApply: n.DestroyApply,
}
log.Printf("[TRACE] Expanding output: adding %s as %T", o.Addr.String(), o)
g.Add(o)
@ -192,8 +194,11 @@ func (n *nodeExpandOutput) ReferenceOutside() (selfPath, referencePath addrs.Mod
// GraphNodeReferencer
func (n *nodeExpandOutput) References() []*addrs.Reference {
// root outputs might be destroyable, and may not reference anything in
// that case
// DestroyNodes do not reference anything.
if n.Module.IsRoot() && n.DestroyApply {
return nil
}
return referencesForOutput(n.Config)
}
@ -208,6 +213,10 @@ type NodeApplyableOutput struct {
// Refresh-only mode means that any failing output preconditions are
// reported as warnings rather than errors
RefreshOnly bool
// DestroyApply indicates that we are applying a destroy plan, and do not
// need to account for conditional blocks.
DestroyApply bool
}
var (
@ -321,6 +330,9 @@ func (n *NodeApplyableOutput) Execute(ctx EvalContext, op walkOperation) (diags
}
}
// Checks are not evaluated during a destroy. The checks may fail, may not
// be valid, or may not have been registered at all.
if !n.DestroyApply {
checkRuleSeverity := tfdiags.Error
if n.RefreshOnly {
checkRuleSeverity = tfdiags.Warning
@ -335,6 +347,7 @@ func (n *NodeApplyableOutput) Execute(ctx EvalContext, op walkOperation) (diags
if diags.HasErrors() {
return diags // failed preconditions prevent further evaluation
}
}
// If there was no change recorded, or the recorded change was not wholly
// known, then we need to re-evaluate the output

View File

@ -95,7 +95,8 @@ func (t *OutputTransformer) transform(g *Graph, c *configs.Config) error {
Addr: addr,
Module: c.Path,
Config: o,
Destroy: t.removeRootOutputs,
DestroyPlan: t.removeRootOutputs,
DestroyApply: t.destroyApply,
RefreshOnly: t.RefreshOnly,
Planning: t.Planning,
}