github.com/hashicorp/terraform-plugin-sdk@v1.17.2/terraform/node_module_variable.go (about) 1 package terraform 2 3 import ( 4 "github.com/hashicorp/hcl/v2" 5 "github.com/hashicorp/terraform-plugin-sdk/internal/addrs" 6 "github.com/hashicorp/terraform-plugin-sdk/internal/configs" 7 "github.com/hashicorp/terraform-plugin-sdk/internal/dag" 8 "github.com/hashicorp/terraform-plugin-sdk/internal/lang" 9 "github.com/zclconf/go-cty/cty" 10 ) 11 12 // NodeApplyableModuleVariable represents a module variable input during 13 // the apply step. 14 type NodeApplyableModuleVariable struct { 15 Addr addrs.AbsInputVariableInstance 16 Config *configs.Variable // Config is the var in the config 17 Expr hcl.Expression // Expr is the value expression given in the call 18 } 19 20 // Ensure that we are implementing all of the interfaces we think we are 21 // implementing. 22 var ( 23 _ GraphNodeSubPath = (*NodeApplyableModuleVariable)(nil) 24 _ RemovableIfNotTargeted = (*NodeApplyableModuleVariable)(nil) 25 _ GraphNodeReferenceOutside = (*NodeApplyableModuleVariable)(nil) 26 _ GraphNodeReferenceable = (*NodeApplyableModuleVariable)(nil) 27 _ GraphNodeReferencer = (*NodeApplyableModuleVariable)(nil) 28 _ GraphNodeEvalable = (*NodeApplyableModuleVariable)(nil) 29 _ dag.GraphNodeDotter = (*NodeApplyableModuleVariable)(nil) 30 ) 31 32 func (n *NodeApplyableModuleVariable) Name() string { 33 return n.Addr.String() 34 } 35 36 // GraphNodeSubPath 37 func (n *NodeApplyableModuleVariable) Path() addrs.ModuleInstance { 38 // We execute in the parent scope (above our own module) because 39 // expressions in our value are resolved in that context. 40 return n.Addr.Module.Parent() 41 } 42 43 // RemovableIfNotTargeted 44 func (n *NodeApplyableModuleVariable) RemoveIfNotTargeted() bool { 45 // We need to add this so that this node will be removed if 46 // it isn't targeted or a dependency of a target. 47 return true 48 } 49 50 // GraphNodeReferenceOutside implementation 51 func (n *NodeApplyableModuleVariable) ReferenceOutside() (selfPath, referencePath addrs.ModuleInstance) { 52 53 // Module input variables have their value expressions defined in the 54 // context of their calling (parent) module, and so references from 55 // a node of this type should be resolved in the parent module instance. 56 referencePath = n.Addr.Module.Parent() 57 58 // Input variables are _referenced_ from their own module, though. 59 selfPath = n.Addr.Module 60 61 return // uses named return values 62 } 63 64 // GraphNodeReferenceable 65 func (n *NodeApplyableModuleVariable) ReferenceableAddrs() []addrs.Referenceable { 66 return []addrs.Referenceable{n.Addr.Variable} 67 } 68 69 // GraphNodeReferencer 70 func (n *NodeApplyableModuleVariable) References() []*addrs.Reference { 71 72 // If we have no value expression, we cannot depend on anything. 73 if n.Expr == nil { 74 return nil 75 } 76 77 // Variables in the root don't depend on anything, because their values 78 // are gathered prior to the graph walk and recorded in the context. 79 if len(n.Addr.Module) == 0 { 80 return nil 81 } 82 83 // Otherwise, we depend on anything referenced by our value expression. 84 // We ignore diagnostics here under the assumption that we'll re-eval 85 // all these things later and catch them then; for our purposes here, 86 // we only care about valid references. 87 // 88 // Due to our GraphNodeReferenceOutside implementation, the addresses 89 // returned by this function are interpreted in the _parent_ module from 90 // where our associated variable was declared, which is correct because 91 // our value expression is assigned within a "module" block in the parent 92 // module. 93 refs, _ := lang.ReferencesInExpr(n.Expr) 94 return refs 95 } 96 97 // GraphNodeEvalable 98 func (n *NodeApplyableModuleVariable) EvalTree() EvalNode { 99 // If we have no value, do nothing 100 if n.Expr == nil { 101 return &EvalNoop{} 102 } 103 104 // Otherwise, interpolate the value of this variable and set it 105 // within the variables mapping. 106 vals := make(map[string]cty.Value) 107 108 _, call := n.Addr.Module.CallInstance() 109 110 return &EvalSequence{ 111 Nodes: []EvalNode{ 112 &EvalOpFilter{ 113 Ops: []walkOperation{walkRefresh, walkPlan, walkApply, 114 walkDestroy, walkValidate}, 115 Node: &EvalModuleCallArgument{ 116 Addr: n.Addr.Variable, 117 Config: n.Config, 118 Expr: n.Expr, 119 Values: vals, 120 121 IgnoreDiagnostics: false, 122 }, 123 }, 124 125 &EvalSetModuleCallArguments{ 126 Module: call, 127 Values: vals, 128 }, 129 }, 130 } 131 } 132 133 // dag.GraphNodeDotter impl. 134 func (n *NodeApplyableModuleVariable) DotNode(name string, opts *dag.DotOpts) *dag.DotNode { 135 return &dag.DotNode{ 136 Name: name, 137 Attrs: map[string]string{ 138 "label": n.Name(), 139 "shape": "note", 140 }, 141 } 142 }