]>
Commit | Line | Data |
---|---|---|
bae9f6d2 JC |
1 | package terraform |
2 | ||
3 | import ( | |
107c1cdb ND |
4 | "github.com/hashicorp/hcl2/hcl" |
5 | "github.com/hashicorp/terraform/addrs" | |
6 | "github.com/hashicorp/terraform/configs" | |
7 | "github.com/hashicorp/terraform/dag" | |
8 | "github.com/hashicorp/terraform/lang" | |
9 | "github.com/zclconf/go-cty/cty" | |
bae9f6d2 JC |
10 | ) |
11 | ||
12 | // NodeApplyableModuleVariable represents a module variable input during | |
13 | // the apply step. | |
14 | type NodeApplyableModuleVariable struct { | |
107c1cdb ND |
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 | |
bae9f6d2 JC |
18 | } |
19 | ||
107c1cdb ND |
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 | ) | |
bae9f6d2 | 31 | |
107c1cdb ND |
32 | func (n *NodeApplyableModuleVariable) Name() string { |
33 | return n.Addr.String() | |
bae9f6d2 JC |
34 | } |
35 | ||
36 | // GraphNodeSubPath | |
107c1cdb ND |
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() | |
bae9f6d2 JC |
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 | ||
107c1cdb ND |
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 | |
bae9f6d2 JC |
62 | } |
63 | ||
64 | // GraphNodeReferenceable | |
107c1cdb ND |
65 | func (n *NodeApplyableModuleVariable) ReferenceableAddrs() []addrs.Referenceable { |
66 | return []addrs.Referenceable{n.Addr.Variable} | |
bae9f6d2 JC |
67 | } |
68 | ||
69 | // GraphNodeReferencer | |
107c1cdb | 70 | func (n *NodeApplyableModuleVariable) References() []*addrs.Reference { |
bae9f6d2 | 71 | |
107c1cdb ND |
72 | // If we have no value expression, we cannot depend on anything. |
73 | if n.Expr == nil { | |
bae9f6d2 JC |
74 | return nil |
75 | } | |
76 | ||
107c1cdb ND |
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 | |
bae9f6d2 JC |
81 | } |
82 | ||
107c1cdb ND |
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 | |
bae9f6d2 JC |
95 | } |
96 | ||
97 | // GraphNodeEvalable | |
98 | func (n *NodeApplyableModuleVariable) EvalTree() EvalNode { | |
99 | // If we have no value, do nothing | |
107c1cdb | 100 | if n.Expr == nil { |
bae9f6d2 JC |
101 | return &EvalNoop{} |
102 | } | |
103 | ||
104 | // Otherwise, interpolate the value of this variable and set it | |
105 | // within the variables mapping. | |
107c1cdb ND |
106 | vals := make(map[string]cty.Value) |
107 | ||
108 | _, call := n.Addr.Module.CallInstance() | |
15c0b25d | 109 | |
bae9f6d2 JC |
110 | return &EvalSequence{ |
111 | Nodes: []EvalNode{ | |
15c0b25d AP |
112 | &EvalOpFilter{ |
113 | Ops: []walkOperation{walkRefresh, walkPlan, walkApply, | |
114 | walkDestroy, walkValidate}, | |
107c1cdb ND |
115 | Node: &EvalModuleCallArgument{ |
116 | Addr: n.Addr.Variable, | |
117 | Config: n.Config, | |
118 | Expr: n.Expr, | |
119 | Values: vals, | |
bae9f6d2 | 120 | |
107c1cdb ND |
121 | IgnoreDiagnostics: false, |
122 | }, | |
bae9f6d2 JC |
123 | }, |
124 | ||
107c1cdb ND |
125 | &EvalSetModuleCallArguments{ |
126 | Module: call, | |
127 | Values: vals, | |
bae9f6d2 | 128 | }, |
107c1cdb ND |
129 | }, |
130 | } | |
131 | } | |
bae9f6d2 | 132 | |
107c1cdb ND |
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", | |
bae9f6d2 JC |
140 | }, |
141 | } | |
142 | } |