mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-28 01:41:48 -06:00
89f7e3b79f
Fixes #10711 The `ModuleVariablesTransformer` only adds module variables in use. This was missing module variables used by providers since we ran the provider too late. This moves the transformer and adds a test for this.
121 lines
3.2 KiB
Go
121 lines
3.2 KiB
Go
package terraform
|
|
|
|
import (
|
|
"log"
|
|
|
|
"github.com/hashicorp/terraform/config"
|
|
"github.com/hashicorp/terraform/config/module"
|
|
"github.com/hashicorp/terraform/dag"
|
|
)
|
|
|
|
// ModuleVariableTransformer is a GraphTransformer that adds all the variables
|
|
// in the configuration to the graph.
|
|
//
|
|
// This only adds variables that are referenced by other things in the graph.
|
|
// If a module variable is not referenced, it won't be added to the graph.
|
|
type ModuleVariableTransformer struct {
|
|
Module *module.Tree
|
|
|
|
DisablePrune bool // True if pruning unreferenced should be disabled
|
|
}
|
|
|
|
func (t *ModuleVariableTransformer) Transform(g *Graph) error {
|
|
return t.transform(g, nil, t.Module)
|
|
}
|
|
|
|
func (t *ModuleVariableTransformer) transform(g *Graph, parent, m *module.Tree) error {
|
|
// If no config, no variables
|
|
if m == nil {
|
|
return nil
|
|
}
|
|
|
|
// Transform all the children. This must be done BEFORE the transform
|
|
// above since child module variables can reference parent module variables.
|
|
for _, c := range m.Children() {
|
|
if err := t.transform(g, m, c); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
// If we have a parent, we can determine if a module variable is being
|
|
// used, so we transform this.
|
|
if parent != nil {
|
|
if err := t.transformSingle(g, parent, m); err != nil {
|
|
return err
|
|
}
|
|
}
|
|
|
|
return nil
|
|
}
|
|
|
|
func (t *ModuleVariableTransformer) transformSingle(g *Graph, parent, m *module.Tree) error {
|
|
// If we have no vars, we're done!
|
|
vars := m.Config().Variables
|
|
if len(vars) == 0 {
|
|
log.Printf("[TRACE] Module %#v has no variables, skipping.", m.Path())
|
|
return nil
|
|
}
|
|
|
|
// Look for usage of this module
|
|
var mod *config.Module
|
|
for _, modUse := range parent.Config().Modules {
|
|
if modUse.Name == m.Name() {
|
|
mod = modUse
|
|
break
|
|
}
|
|
}
|
|
if mod == nil {
|
|
log.Printf("[INFO] Module %#v not used, not adding variables", m.Path())
|
|
return nil
|
|
}
|
|
|
|
// Build the reference map so we can determine if we're referencing things.
|
|
refMap := NewReferenceMap(g.Vertices())
|
|
|
|
// Add all variables here
|
|
for _, v := range vars {
|
|
// Determine the value of the variable. If it isn't in the
|
|
// configuration then it was never set and that's not a problem.
|
|
var value *config.RawConfig
|
|
if raw, ok := mod.RawConfig.Raw[v.Name]; ok {
|
|
var err error
|
|
value, err = config.NewRawConfig(map[string]interface{}{
|
|
v.Name: raw,
|
|
})
|
|
if err != nil {
|
|
// This shouldn't happen because it is already in
|
|
// a RawConfig above meaning it worked once before.
|
|
panic(err)
|
|
}
|
|
}
|
|
|
|
// Build the node.
|
|
//
|
|
// NOTE: For now this is just an "applyable" variable. As we build
|
|
// new graph builders for the other operations I suspect we'll
|
|
// find a way to parameterize this, require new transforms, etc.
|
|
node := &NodeApplyableModuleVariable{
|
|
PathValue: normalizeModulePath(m.Path()),
|
|
Config: v,
|
|
Value: value,
|
|
Module: t.Module,
|
|
}
|
|
|
|
if !t.DisablePrune {
|
|
// If the node is not referenced by anything, then we don't need
|
|
// to include it since it won't be used.
|
|
if matches := refMap.ReferencedBy(node); len(matches) == 0 {
|
|
log.Printf(
|
|
"[INFO] Not including %q in graph, nothing depends on it",
|
|
dag.VertexName(node))
|
|
continue
|
|
}
|
|
}
|
|
|
|
// Add it!
|
|
g.Add(node)
|
|
}
|
|
|
|
return nil
|
|
}
|