mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-29 10:21:01 -06:00
40f09027f0
While the Expander itself now handles the recursive expansion of modules, Resources themselves still need to be expanded twice, because the evaluation of the Resource, which entails evaluating the for_each or count expressions, is separate from the ResourceInstance expansion. Add a nodeExpandPlannableResource to do handle this expansion to allow all NodePlannableResources to call EvalWriteResourceState with an absolute address.
104 lines
2.5 KiB
Go
104 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 := &NodePlannableOutput{
|
|
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
|
|
}
|
|
|
|
// 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 {
|
|
Destroy bool
|
|
}
|
|
|
|
func (t *DestroyOutputTransformer) 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.(*NodePlannableOutput)
|
|
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, 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 {
|
|
log.Printf("[TRACE] %s depends on %s", node.Name(), dag.VertexName(d))
|
|
g.Connect(dag.BasicEdge(node, d))
|
|
}
|
|
}
|
|
return nil
|
|
}
|