diff --git a/terraform/graph_builder_apply.go b/terraform/graph_builder_apply.go index f40827859..5b96d6af6 100644 --- a/terraform/graph_builder_apply.go +++ b/terraform/graph_builder_apply.go @@ -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. diff --git a/terraform/node_output.go b/terraform/node_output.go index ef5e6cd5e..729710f22 100644 --- a/terraform/node_output.go +++ b/terraform/node_output.go @@ -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{ diff --git a/terraform/node_output_orphan.go b/terraform/node_output_orphan.go deleted file mode 100644 index bb13234b6..000000000 --- a/terraform/node_output_orphan.go +++ /dev/null @@ -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, - }, - } -} diff --git a/terraform/transform_orphan_output.go b/terraform/transform_orphan_output.go index c67540934..ba1bce932 100644 --- a/terraform/transform_orphan_output.go +++ b/terraform/transform_orphan_output.go @@ -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), }) } diff --git a/terraform/transform_output.go b/terraform/transform_output.go index 2582448c9..4d51dabd6 100644 --- a/terraform/transform_output.go +++ b/terraform/transform_output.go @@ -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