mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-26 17:01:04 -06:00
2555f6f988
If we're adding a node to remove a root output from the state, the output itself does not need to be re-evaluated. The exception for root outputs caused them to be missed when we refactored resource destruction to only use the existing state.
102 lines
2.5 KiB
Go
102 lines
2.5 KiB
Go
package terraform
|
|
|
|
import (
|
|
"log"
|
|
|
|
"github.com/hashicorp/terraform/addrs"
|
|
"github.com/hashicorp/terraform/configs"
|
|
"github.com/hashicorp/terraform/dag"
|
|
)
|
|
|
|
// OutputTransformer is a GraphTransformer that adds all the outputs
|
|
// in the configuration to the graph.
|
|
//
|
|
// This is done for the apply graph builder even if dependent nodes
|
|
// aren't changing since there is no downside: the state will be available
|
|
// even if the dependent items aren't changing.
|
|
type OutputTransformer struct {
|
|
Config *configs.Config
|
|
}
|
|
|
|
func (t *OutputTransformer) Transform(g *Graph) error {
|
|
return t.transform(g, t.Config)
|
|
}
|
|
|
|
func (t *OutputTransformer) transform(g *Graph, c *configs.Config) error {
|
|
// If we have no config then there can be no outputs.
|
|
if c == nil {
|
|
return nil
|
|
}
|
|
|
|
// Transform all the children. We must do this first because
|
|
// we can reference module outputs and they must show up in the
|
|
// reference map.
|
|
for _, cc := range c.Children {
|
|
if err := t.transform(g, cc); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// Add plannable outputs to the graph, which will be dynamically expanded
|
|
// into NodeApplyableOutputs to reflect possible expansion
|
|
// through the presence of "count" or "for_each" on the modules.
|
|
for _, o := range c.Module.Outputs {
|
|
node := &nodeExpandOutput{
|
|
Addr: addrs.OutputValue{Name: o.Name},
|
|
Module: c.Path,
|
|
Config: o,
|
|
}
|
|
log.Printf("[TRACE] OutputTransformer: adding %s as %T", o.Name, node)
|
|
g.Add(node)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// 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 destroyRootOutputTransformer struct {
|
|
Destroy bool
|
|
}
|
|
|
|
func (t *destroyRootOutputTransformer) Transform(g *Graph) error {
|
|
// Only clean root outputs on a full destroy
|
|
if !t.Destroy {
|
|
return nil
|
|
}
|
|
|
|
for _, v := range g.Vertices() {
|
|
output, ok := v.(*nodeExpandOutput)
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
// We only destroy root outputs
|
|
if !output.Module.Equal(addrs.RootModule) {
|
|
continue
|
|
}
|
|
|
|
// create the destroy node for this output
|
|
node := &NodeDestroyableOutput{
|
|
Addr: output.Addr.Absolute(addrs.RootModuleInstance),
|
|
Config: output.Config,
|
|
}
|
|
|
|
log.Printf("[TRACE] creating %s", node.Name())
|
|
g.Add(node)
|
|
|
|
deps := g.UpEdges(v)
|
|
|
|
for _, d := range deps {
|
|
log.Printf("[TRACE] %s depends on %s", node.Name(), dag.VertexName(d))
|
|
g.Connect(dag.BasicEdge(node, d))
|
|
}
|
|
|
|
// We no longer need the expand node, since we intend to remove this
|
|
// output from the state.
|
|
g.Remove(v)
|
|
}
|
|
return nil
|
|
}
|