mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-30 10:47:14 -06:00
97bb7cb65c
Allow module variables to fail interpolation during input. This is OK since they will be verified again during Plan. Because Input happens before Refresh, module variable interpolation can fail when referencing values that aren't yet in the state, but are expected after Refresh.
141 lines
3.2 KiB
Go
141 lines
3.2 KiB
Go
package terraform
|
|
|
|
import (
|
|
"fmt"
|
|
|
|
"github.com/hashicorp/terraform/config"
|
|
"github.com/hashicorp/terraform/config/module"
|
|
)
|
|
|
|
// NodeApplyableModuleVariable represents a module variable input during
|
|
// the apply step.
|
|
type NodeApplyableModuleVariable struct {
|
|
PathValue []string
|
|
Config *config.Variable // Config is the var in the config
|
|
Value *config.RawConfig // Value is the value that is set
|
|
|
|
Module *module.Tree // Antiquated, want to remove
|
|
|
|
// Input is set if this graph was created for the Input operation.
|
|
Input bool
|
|
}
|
|
|
|
func (n *NodeApplyableModuleVariable) Name() string {
|
|
result := fmt.Sprintf("var.%s", n.Config.Name)
|
|
if len(n.PathValue) > 1 {
|
|
result = fmt.Sprintf("%s.%s", modulePrefixStr(n.PathValue), result)
|
|
}
|
|
|
|
return result
|
|
}
|
|
|
|
// GraphNodeSubPath
|
|
func (n *NodeApplyableModuleVariable) Path() []string {
|
|
// We execute in the parent scope (above our own module) so that
|
|
// we can access the proper interpolations.
|
|
if len(n.PathValue) > 2 {
|
|
return n.PathValue[:len(n.PathValue)-1]
|
|
}
|
|
|
|
return rootModulePath
|
|
}
|
|
|
|
// RemovableIfNotTargeted
|
|
func (n *NodeApplyableModuleVariable) RemoveIfNotTargeted() bool {
|
|
// We need to add this so that this node will be removed if
|
|
// it isn't targeted or a dependency of a target.
|
|
return true
|
|
}
|
|
|
|
// GraphNodeReferenceGlobal
|
|
func (n *NodeApplyableModuleVariable) ReferenceGlobal() bool {
|
|
// We have to create fully qualified references because we cross
|
|
// boundaries here: our ReferenceableName is in one path and our
|
|
// References are from another path.
|
|
return true
|
|
}
|
|
|
|
// GraphNodeReferenceable
|
|
func (n *NodeApplyableModuleVariable) ReferenceableName() []string {
|
|
return []string{n.Name()}
|
|
}
|
|
|
|
// GraphNodeReferencer
|
|
func (n *NodeApplyableModuleVariable) References() []string {
|
|
// If we have no value set, we depend on nothing
|
|
if n.Value == nil {
|
|
return nil
|
|
}
|
|
|
|
// Can't depend on anything if we're in the root
|
|
if len(n.PathValue) < 2 {
|
|
return nil
|
|
}
|
|
|
|
// Otherwise, we depend on anything that is in our value, but
|
|
// specifically in the namespace of the parent path.
|
|
// Create the prefix based on the path
|
|
var prefix string
|
|
if p := n.Path(); len(p) > 0 {
|
|
prefix = modulePrefixStr(p)
|
|
}
|
|
|
|
result := ReferencesFromConfig(n.Value)
|
|
return modulePrefixList(result, prefix)
|
|
}
|
|
|
|
// GraphNodeEvalable
|
|
func (n *NodeApplyableModuleVariable) EvalTree() EvalNode {
|
|
// If we have no value, do nothing
|
|
if n.Value == nil {
|
|
return &EvalNoop{}
|
|
}
|
|
|
|
// Otherwise, interpolate the value of this variable and set it
|
|
// within the variables mapping.
|
|
var config *ResourceConfig
|
|
variables := make(map[string]interface{})
|
|
|
|
var interpolate EvalNode
|
|
|
|
if n.Input {
|
|
interpolate = &EvalTryInterpolate{
|
|
Config: n.Value,
|
|
Output: &config,
|
|
}
|
|
} else {
|
|
interpolate = &EvalInterpolate{
|
|
Config: n.Value,
|
|
Output: &config,
|
|
}
|
|
}
|
|
|
|
return &EvalSequence{
|
|
Nodes: []EvalNode{
|
|
interpolate,
|
|
|
|
&EvalVariableBlock{
|
|
Config: &config,
|
|
VariableValues: variables,
|
|
},
|
|
|
|
&EvalCoerceMapVariable{
|
|
Variables: variables,
|
|
ModulePath: n.PathValue,
|
|
ModuleTree: n.Module,
|
|
},
|
|
|
|
&EvalTypeCheckVariable{
|
|
Variables: variables,
|
|
ModulePath: n.PathValue,
|
|
ModuleTree: n.Module,
|
|
},
|
|
|
|
&EvalSetVariables{
|
|
Module: &n.PathValue[len(n.PathValue)-1],
|
|
Variables: variables,
|
|
},
|
|
},
|
|
}
|
|
}
|