mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-30 10:47:14 -06:00
d31fe5ab9d
Now that outputs are always evaluated, we still need a way to remove them from state when they are destroyed. Previously, outputs were removed during destroy from the same "Applyable" node type that evaluates them. Now that we need to possibly both evaluate and remove output during an apply, we add a new node - NodeDestroyableOutput. This new node is added to the graph by the DestroyOutputTransformer, which make the new destroy node depend on all descendants of the output node. This ensures that the output remains in the state as long as everything which may interpolate the output still exists.
96 lines
2.1 KiB
Go
96 lines
2.1 KiB
Go
package terraform
|
|
|
|
import (
|
|
"log"
|
|
|
|
"github.com/hashicorp/terraform/config/module"
|
|
"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 {
|
|
Module *module.Tree
|
|
}
|
|
|
|
func (t *OutputTransformer) Transform(g *Graph) error {
|
|
return t.transform(g, t.Module)
|
|
}
|
|
|
|
func (t *OutputTransformer) transform(g *Graph, m *module.Tree) error {
|
|
// If no config, no outputs
|
|
if m == 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 _, c := range m.Children() {
|
|
if err := t.transform(g, c); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// If we have no outputs, we're done!
|
|
os := m.Config().Outputs
|
|
if len(os) == 0 {
|
|
return nil
|
|
}
|
|
|
|
// Add all outputs here
|
|
for _, o := range os {
|
|
node := &NodeApplyableOutput{
|
|
PathValue: normalizeModulePath(m.Path()),
|
|
Config: o,
|
|
}
|
|
|
|
// Add it!
|
|
g.Add(node)
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
// DestroyOutputTransformer 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 {
|
|
}
|
|
|
|
func (t *DestroyOutputTransformer) Transform(g *Graph) error {
|
|
for _, v := range g.Vertices() {
|
|
output, ok := v.(*NodeApplyableOutput)
|
|
if !ok {
|
|
continue
|
|
}
|
|
|
|
// create the destroy node for this output
|
|
node := &NodeDestroyableOutput{
|
|
PathValue: output.PathValue,
|
|
Config: output.Config,
|
|
}
|
|
|
|
log.Printf("[TRACE] creating %s", node.Name())
|
|
g.Add(node)
|
|
|
|
deps, err := g.Descendents(v)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
|
|
// the destroy node must depend on the eval node
|
|
deps.Add(v)
|
|
|
|
for _, d := range deps.List() {
|
|
log.Printf("[TRACE] %s depends on %s", node.Name(), dag.VertexName(d))
|
|
g.Connect(dag.BasicEdge(node, d))
|
|
}
|
|
}
|
|
return nil
|
|
}
|