get rid of the NodeOutputOrphan

We don't need another node type for orphaned outptus, they are just
outputs being removed for a different reason than destroy. Use the
NodeDestroyableOutput implementation.

Destroy outputs also don't need to be referencers, since they are being
removed.

Rename DestroyOutputTransformer to destroyRootOutputTransformer, and add
an explanation as to why it is the only transformer that requires an
exception to know when it's involved from the destroy command.
This commit is contained in:
James Bardin 2020-05-22 09:51:25 -04:00
parent dc1b133831
commit 48757bcbe0
5 changed files with 14 additions and 65 deletions

View File

@ -160,8 +160,16 @@ func (b *ApplyGraphBuilder) Steps() []GraphTransformer {
Schemas: b.Schemas,
},
// Create a destroy node for outputs to remove them from the state.
&DestroyOutputTransformer{Destroy: b.Destroy},
// Create a destroy node for root outputs to remove them from the
// state. This does nothing unless invoked via the destroy command
// directly. A destroy is identical to a normal apply, except for the
// fact that we also have configuration to evaluate. While the rest of
// the unused nodes can be programmatically pruned (via
// pruneUnusedNodesTransformer), root module outputs only have an
// implied dependency on remote state. This means that if they exist in
// the configuration, the only signal to remove them is via the destroy
// command itself.
&destroyRootOutputTransformer{Destroy: b.Destroy},
// We need to remove configuration nodes that are not used at all, as
// they may not be able to evaluate, especially during destroy.

View File

@ -257,7 +257,6 @@ type NodeDestroyableOutput struct {
var (
_ RemovableIfNotTargeted = (*NodeDestroyableOutput)(nil)
_ GraphNodeTargetDownstream = (*NodeDestroyableOutput)(nil)
_ GraphNodeReferencer = (*NodeDestroyableOutput)(nil)
_ GraphNodeEvalable = (*NodeDestroyableOutput)(nil)
_ dag.GraphNodeDotter = (*NodeDestroyableOutput)(nil)
)
@ -284,11 +283,6 @@ func (n *NodeDestroyableOutput) TargetDownstream(targetedDeps, untargetedDeps da
return true
}
// GraphNodeReferencer
func (n *NodeDestroyableOutput) References() []*addrs.Reference {
return referencesForOutput(n.Config)
}
// GraphNodeEvalable
func (n *NodeDestroyableOutput) EvalTree() EvalNode {
return &EvalDeleteOutput{

View File

@ -1,53 +0,0 @@
package terraform
import (
"fmt"
"github.com/hashicorp/terraform/addrs"
)
// NodeOutputOrphan represents an output that is an orphan.
type NodeOutputOrphan struct {
Addr addrs.AbsOutputValue
}
var (
_ GraphNodeModuleInstance = (*NodeOutputOrphan)(nil)
_ GraphNodeReferenceable = (*NodeOutputOrphan)(nil)
_ GraphNodeReferenceOutside = (*NodeOutputOrphan)(nil)
_ GraphNodeEvalable = (*NodeOutputOrphan)(nil)
)
func (n *NodeOutputOrphan) Name() string {
return fmt.Sprintf("%s (orphan)", n.Addr.String())
}
// GraphNodeReferenceOutside implementation
func (n *NodeOutputOrphan) ReferenceOutside() (selfPath, referencePath addrs.Module) {
return referenceOutsideForOutput(n.Addr)
}
// GraphNodeReferenceable
func (n *NodeOutputOrphan) ReferenceableAddrs() []addrs.Referenceable {
return referenceableAddrsForOutput(n.Addr)
}
// GraphNodeModuleInstance
func (n *NodeOutputOrphan) Path() addrs.ModuleInstance {
return n.Addr.Module
}
// GraphNodeModulePath
func (n *NodeOutputOrphan) ModulePath() addrs.Module {
return n.Addr.Module.Module()
}
// GraphNodeEvalable
func (n *NodeOutputOrphan) EvalTree() EvalNode {
return &EvalOpFilter{
Ops: []walkOperation{walkRefresh, walkApply, walkDestroy},
Node: &EvalDeleteOutput{
Addr: n.Addr,
},
}
}

View File

@ -51,7 +51,7 @@ func (t *OrphanOutputTransformer) transform(g *Graph, ms *states.Module) error {
continue
}
g.Add(&NodeOutputOrphan{
g.Add(&NodeDestroyableOutput{
Addr: addrs.OutputValue{Name: name}.Absolute(moduleAddr),
})
}

View File

@ -53,14 +53,14 @@ func (t *OutputTransformer) transform(g *Graph, c *configs.Config) error {
return nil
}
// DestroyOutputTransformer is a GraphTransformer that adds nodes to delete
// destroyRootOutputTransformer is a GraphTransformer that adds nodes to delete
// outputs during destroy. We need to do this to ensure that no stale outputs
// are ever left in the state.
type DestroyOutputTransformer struct {
type destroyRootOutputTransformer struct {
Destroy bool
}
func (t *DestroyOutputTransformer) Transform(g *Graph) error {
func (t *destroyRootOutputTransformer) Transform(g *Graph) error {
// Only clean root outputs on a full destroy
if !t.Destroy {
return nil