aboutsummaryrefslogtreecommitdiffhomepage
path: root/vendor/github.com/hashicorp/terraform/terraform/eval_context_builtin.go
diff options
context:
space:
mode:
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/terraform/eval_context_builtin.go')
-rw-r--r--vendor/github.com/hashicorp/terraform/terraform/eval_context_builtin.go292
1 files changed, 150 insertions, 142 deletions
diff --git a/vendor/github.com/hashicorp/terraform/terraform/eval_context_builtin.go b/vendor/github.com/hashicorp/terraform/terraform/eval_context_builtin.go
index 1b6ee5a..20b3793 100644
--- a/vendor/github.com/hashicorp/terraform/terraform/eval_context_builtin.go
+++ b/vendor/github.com/hashicorp/terraform/terraform/eval_context_builtin.go
@@ -6,7 +6,20 @@ import (
6 "log" 6 "log"
7 "sync" 7 "sync"
8 8
9 "github.com/hashicorp/terraform/config" 9 "github.com/hashicorp/terraform/plans"
10 "github.com/hashicorp/terraform/providers"
11 "github.com/hashicorp/terraform/provisioners"
12 "github.com/hashicorp/terraform/version"
13
14 "github.com/hashicorp/terraform/states"
15
16 "github.com/hashicorp/hcl2/hcl"
17 "github.com/hashicorp/terraform/configs/configschema"
18 "github.com/hashicorp/terraform/lang"
19 "github.com/hashicorp/terraform/tfdiags"
20
21 "github.com/hashicorp/terraform/addrs"
22 "github.com/zclconf/go-cty/cty"
10) 23)
11 24
12// BuiltinEvalContext is an EvalContext implementation that is used by 25// BuiltinEvalContext is an EvalContext implementation that is used by
@@ -16,35 +29,47 @@ type BuiltinEvalContext struct {
16 StopContext context.Context 29 StopContext context.Context
17 30
18 // PathValue is the Path that this context is operating within. 31 // PathValue is the Path that this context is operating within.
19 PathValue []string 32 PathValue addrs.ModuleInstance
20 33
21 // Interpolater setting below affect the interpolation of variables. 34 // Evaluator is used for evaluating expressions within the scope of this
35 // eval context.
36 Evaluator *Evaluator
37
38 // Schemas is a repository of all of the schemas we should need to
39 // decode configuration blocks and expressions. This must be constructed by
40 // the caller to include schemas for all of the providers, resource types,
41 // data sources and provisioners used by the given configuration and
42 // state.
22 // 43 //
23 // The InterpolaterVars are the exact value for ${var.foo} values. 44 // This must not be mutated during evaluation.
24 // The map is shared between all contexts and is a mapping of 45 Schemas *Schemas
25 // PATH to KEY to VALUE. Because it is shared by all contexts as well 46
26 // as the Interpolater itself, it is protected by InterpolaterVarLock 47 // VariableValues contains the variable values across all modules. This
27 // which must be locked during any access to the map. 48 // structure is shared across the entire containing context, and so it
28 Interpolater *Interpolater 49 // may be accessed only when holding VariableValuesLock.
29 InterpolaterVars map[string]map[string]interface{} 50 // The keys of the first level of VariableValues are the string
30 InterpolaterVarLock *sync.Mutex 51 // representations of addrs.ModuleInstance values. The second-level keys
52 // are variable names within each module instance.
53 VariableValues map[string]map[string]cty.Value
54 VariableValuesLock *sync.Mutex
31 55
32 Components contextComponentFactory 56 Components contextComponentFactory
33 Hooks []Hook 57 Hooks []Hook
34 InputValue UIInput 58 InputValue UIInput
35 ProviderCache map[string]ResourceProvider 59 ProviderCache map[string]providers.Interface
36 ProviderInputConfig map[string]map[string]interface{} 60 ProviderInputConfig map[string]map[string]cty.Value
37 ProviderLock *sync.Mutex 61 ProviderLock *sync.Mutex
38 ProvisionerCache map[string]ResourceProvisioner 62 ProvisionerCache map[string]provisioners.Interface
39 ProvisionerLock *sync.Mutex 63 ProvisionerLock *sync.Mutex
40 DiffValue *Diff 64 ChangesValue *plans.ChangesSync
41 DiffLock *sync.RWMutex 65 StateValue *states.SyncState
42 StateValue *State
43 StateLock *sync.RWMutex
44 66
45 once sync.Once 67 once sync.Once
46} 68}
47 69
70// BuiltinEvalContext implements EvalContext
71var _ EvalContext = (*BuiltinEvalContext)(nil)
72
48func (ctx *BuiltinEvalContext) Stopped() <-chan struct{} { 73func (ctx *BuiltinEvalContext) Stopped() <-chan struct{} {
49 // This can happen during tests. During tests, we just block forever. 74 // This can happen during tests. During tests, we just block forever.
50 if ctx.StopContext == nil { 75 if ctx.StopContext == nil {
@@ -78,12 +103,13 @@ func (ctx *BuiltinEvalContext) Input() UIInput {
78 return ctx.InputValue 103 return ctx.InputValue
79} 104}
80 105
81func (ctx *BuiltinEvalContext) InitProvider(typeName, name string) (ResourceProvider, error) { 106func (ctx *BuiltinEvalContext) InitProvider(typeName string, addr addrs.ProviderConfig) (providers.Interface, error) {
82 ctx.once.Do(ctx.init) 107 ctx.once.Do(ctx.init)
108 absAddr := addr.Absolute(ctx.Path())
83 109
84 // If we already initialized, it is an error 110 // If we already initialized, it is an error
85 if p := ctx.Provider(name); p != nil { 111 if p := ctx.Provider(absAddr); p != nil {
86 return nil, fmt.Errorf("Provider '%s' already initialized", name) 112 return nil, fmt.Errorf("%s is already initialized", addr)
87 } 113 }
88 114
89 // Warning: make sure to acquire these locks AFTER the call to Provider 115 // Warning: make sure to acquire these locks AFTER the call to Provider
@@ -91,85 +117,102 @@ func (ctx *BuiltinEvalContext) InitProvider(typeName, name string) (ResourceProv
91 ctx.ProviderLock.Lock() 117 ctx.ProviderLock.Lock()
92 defer ctx.ProviderLock.Unlock() 118 defer ctx.ProviderLock.Unlock()
93 119
94 p, err := ctx.Components.ResourceProvider(typeName, name) 120 key := absAddr.String()
121
122 p, err := ctx.Components.ResourceProvider(typeName, key)
95 if err != nil { 123 if err != nil {
96 return nil, err 124 return nil, err
97 } 125 }
98 126
99 ctx.ProviderCache[name] = p 127 log.Printf("[TRACE] BuiltinEvalContext: Initialized %q provider for %s", typeName, absAddr)
128 ctx.ProviderCache[key] = p
129
100 return p, nil 130 return p, nil
101} 131}
102 132
103func (ctx *BuiltinEvalContext) Provider(n string) ResourceProvider { 133func (ctx *BuiltinEvalContext) Provider(addr addrs.AbsProviderConfig) providers.Interface {
104 ctx.once.Do(ctx.init) 134 ctx.once.Do(ctx.init)
105 135
106 ctx.ProviderLock.Lock() 136 ctx.ProviderLock.Lock()
107 defer ctx.ProviderLock.Unlock() 137 defer ctx.ProviderLock.Unlock()
108 138
109 return ctx.ProviderCache[n] 139 return ctx.ProviderCache[addr.String()]
140}
141
142func (ctx *BuiltinEvalContext) ProviderSchema(addr addrs.AbsProviderConfig) *ProviderSchema {
143 ctx.once.Do(ctx.init)
144
145 return ctx.Schemas.ProviderSchema(addr.ProviderConfig.Type)
110} 146}
111 147
112func (ctx *BuiltinEvalContext) CloseProvider(n string) error { 148func (ctx *BuiltinEvalContext) CloseProvider(addr addrs.ProviderConfig) error {
113 ctx.once.Do(ctx.init) 149 ctx.once.Do(ctx.init)
114 150
115 ctx.ProviderLock.Lock() 151 ctx.ProviderLock.Lock()
116 defer ctx.ProviderLock.Unlock() 152 defer ctx.ProviderLock.Unlock()
117 153
118 var provider interface{} 154 key := addr.Absolute(ctx.Path()).String()
119 provider = ctx.ProviderCache[n] 155 provider := ctx.ProviderCache[key]
120 if provider != nil { 156 if provider != nil {
121 if p, ok := provider.(ResourceProviderCloser); ok { 157 delete(ctx.ProviderCache, key)
122 delete(ctx.ProviderCache, n) 158 return provider.Close()
123 return p.Close()
124 }
125 } 159 }
126 160
127 return nil 161 return nil
128} 162}
129 163
130func (ctx *BuiltinEvalContext) ConfigureProvider( 164func (ctx *BuiltinEvalContext) ConfigureProvider(addr addrs.ProviderConfig, cfg cty.Value) tfdiags.Diagnostics {
131 n string, cfg *ResourceConfig) error { 165 var diags tfdiags.Diagnostics
132 p := ctx.Provider(n) 166 absAddr := addr.Absolute(ctx.Path())
167 p := ctx.Provider(absAddr)
133 if p == nil { 168 if p == nil {
134 return fmt.Errorf("Provider '%s' not initialized", n) 169 diags = diags.Append(fmt.Errorf("%s not initialized", addr))
170 return diags
135 } 171 }
136 return p.Configure(cfg) 172
173 providerSchema := ctx.ProviderSchema(absAddr)
174 if providerSchema == nil {
175 diags = diags.Append(fmt.Errorf("schema for %s is not available", absAddr))
176 return diags
177 }
178
179 req := providers.ConfigureRequest{
180 TerraformVersion: version.String(),
181 Config: cfg,
182 }
183
184 resp := p.Configure(req)
185 return resp.Diagnostics
137} 186}
138 187
139func (ctx *BuiltinEvalContext) ProviderInput(n string) map[string]interface{} { 188func (ctx *BuiltinEvalContext) ProviderInput(pc addrs.ProviderConfig) map[string]cty.Value {
140 ctx.ProviderLock.Lock() 189 ctx.ProviderLock.Lock()
141 defer ctx.ProviderLock.Unlock() 190 defer ctx.ProviderLock.Unlock()
142 191
143 // Make a copy of the path so we can safely edit it 192 if !ctx.Path().IsRoot() {
144 path := ctx.Path() 193 // Only root module provider configurations can have input.
145 pathCopy := make([]string, len(path)+1) 194 return nil
146 copy(pathCopy, path)
147
148 // Go up the tree.
149 for i := len(path) - 1; i >= 0; i-- {
150 pathCopy[i+1] = n
151 k := PathCacheKey(pathCopy[:i+2])
152 if v, ok := ctx.ProviderInputConfig[k]; ok {
153 return v
154 }
155 } 195 }
156 196
157 return nil 197 return ctx.ProviderInputConfig[pc.String()]
158} 198}
159 199
160func (ctx *BuiltinEvalContext) SetProviderInput(n string, c map[string]interface{}) { 200func (ctx *BuiltinEvalContext) SetProviderInput(pc addrs.ProviderConfig, c map[string]cty.Value) {
161 providerPath := make([]string, len(ctx.Path())+1) 201 absProvider := pc.Absolute(ctx.Path())
162 copy(providerPath, ctx.Path()) 202
163 providerPath[len(providerPath)-1] = n 203 if !ctx.Path().IsRoot() {
204 // Only root module provider configurations can have input.
205 log.Printf("[WARN] BuiltinEvalContext: attempt to SetProviderInput for non-root module")
206 return
207 }
164 208
165 // Save the configuration 209 // Save the configuration
166 ctx.ProviderLock.Lock() 210 ctx.ProviderLock.Lock()
167 ctx.ProviderInputConfig[PathCacheKey(providerPath)] = c 211 ctx.ProviderInputConfig[absProvider.String()] = c
168 ctx.ProviderLock.Unlock() 212 ctx.ProviderLock.Unlock()
169} 213}
170 214
171func (ctx *BuiltinEvalContext) InitProvisioner( 215func (ctx *BuiltinEvalContext) InitProvisioner(n string) (provisioners.Interface, error) {
172 n string) (ResourceProvisioner, error) {
173 ctx.once.Do(ctx.init) 216 ctx.once.Do(ctx.init)
174 217
175 // If we already initialized, it is an error 218 // If we already initialized, it is an error
@@ -182,10 +225,7 @@ func (ctx *BuiltinEvalContext) InitProvisioner(
182 ctx.ProvisionerLock.Lock() 225 ctx.ProvisionerLock.Lock()
183 defer ctx.ProvisionerLock.Unlock() 226 defer ctx.ProvisionerLock.Unlock()
184 227
185 provPath := make([]string, len(ctx.Path())+1) 228 key := PathObjectCacheKey(ctx.Path(), n)
186 copy(provPath, ctx.Path())
187 provPath[len(provPath)-1] = n
188 key := PathCacheKey(provPath)
189 229
190 p, err := ctx.Components.ResourceProvisioner(n, key) 230 p, err := ctx.Components.ResourceProvisioner(n, key)
191 if err != nil { 231 if err != nil {
@@ -193,20 +233,24 @@ func (ctx *BuiltinEvalContext) InitProvisioner(
193 } 233 }
194 234
195 ctx.ProvisionerCache[key] = p 235 ctx.ProvisionerCache[key] = p
236
196 return p, nil 237 return p, nil
197} 238}
198 239
199func (ctx *BuiltinEvalContext) Provisioner(n string) ResourceProvisioner { 240func (ctx *BuiltinEvalContext) Provisioner(n string) provisioners.Interface {
200 ctx.once.Do(ctx.init) 241 ctx.once.Do(ctx.init)
201 242
202 ctx.ProvisionerLock.Lock() 243 ctx.ProvisionerLock.Lock()
203 defer ctx.ProvisionerLock.Unlock() 244 defer ctx.ProvisionerLock.Unlock()
204 245
205 provPath := make([]string, len(ctx.Path())+1) 246 key := PathObjectCacheKey(ctx.Path(), n)
206 copy(provPath, ctx.Path()) 247 return ctx.ProvisionerCache[key]
207 provPath[len(provPath)-1] = n 248}
249
250func (ctx *BuiltinEvalContext) ProvisionerSchema(n string) *configschema.Block {
251 ctx.once.Do(ctx.init)
208 252
209 return ctx.ProvisionerCache[PathCacheKey(provPath)] 253 return ctx.Schemas.ProvisionerConfig(n)
210} 254}
211 255
212func (ctx *BuiltinEvalContext) CloseProvisioner(n string) error { 256func (ctx *BuiltinEvalContext) CloseProvisioner(n string) error {
@@ -215,106 +259,70 @@ func (ctx *BuiltinEvalContext) CloseProvisioner(n string) error {
215 ctx.ProvisionerLock.Lock() 259 ctx.ProvisionerLock.Lock()
216 defer ctx.ProvisionerLock.Unlock() 260 defer ctx.ProvisionerLock.Unlock()
217 261
218 provPath := make([]string, len(ctx.Path())+1) 262 key := PathObjectCacheKey(ctx.Path(), n)
219 copy(provPath, ctx.Path())
220 provPath[len(provPath)-1] = n
221 263
222 var prov interface{} 264 prov := ctx.ProvisionerCache[key]
223 prov = ctx.ProvisionerCache[PathCacheKey(provPath)]
224 if prov != nil { 265 if prov != nil {
225 if p, ok := prov.(ResourceProvisionerCloser); ok { 266 return prov.Close()
226 delete(ctx.ProvisionerCache, PathCacheKey(provPath))
227 return p.Close()
228 }
229 } 267 }
230 268
231 return nil 269 return nil
232} 270}
233 271
234func (ctx *BuiltinEvalContext) Interpolate( 272func (ctx *BuiltinEvalContext) EvaluateBlock(body hcl.Body, schema *configschema.Block, self addrs.Referenceable, keyData InstanceKeyEvalData) (cty.Value, hcl.Body, tfdiags.Diagnostics) {
235 cfg *config.RawConfig, r *Resource) (*ResourceConfig, error) { 273 var diags tfdiags.Diagnostics
236 274 scope := ctx.EvaluationScope(self, keyData)
237 if cfg != nil { 275 body, evalDiags := scope.ExpandBlock(body, schema)
238 scope := &InterpolationScope{ 276 diags = diags.Append(evalDiags)
239 Path: ctx.Path(), 277 val, evalDiags := scope.EvalBlock(body, schema)
240 Resource: r, 278 diags = diags.Append(evalDiags)
241 } 279 return val, body, diags
242
243 vs, err := ctx.Interpolater.Values(scope, cfg.Variables)
244 if err != nil {
245 return nil, err
246 }
247
248 // Do the interpolation
249 if err := cfg.Interpolate(vs); err != nil {
250 return nil, err
251 }
252 }
253
254 result := NewResourceConfig(cfg)
255 result.interpolateForce()
256 return result, nil
257} 280}
258 281
259func (ctx *BuiltinEvalContext) InterpolateProvider( 282func (ctx *BuiltinEvalContext) EvaluateExpr(expr hcl.Expression, wantType cty.Type, self addrs.Referenceable) (cty.Value, tfdiags.Diagnostics) {
260 pc *config.ProviderConfig, r *Resource) (*ResourceConfig, error) { 283 scope := ctx.EvaluationScope(self, EvalDataForNoInstanceKey)
261 284 return scope.EvalExpr(expr, wantType)
262 var cfg *config.RawConfig 285}
263
264 if pc != nil && pc.RawConfig != nil {
265 scope := &InterpolationScope{
266 Path: ctx.Path(),
267 Resource: r,
268 }
269
270 cfg = pc.RawConfig
271
272 vs, err := ctx.Interpolater.Values(scope, cfg.Variables)
273 if err != nil {
274 return nil, err
275 }
276 286
277 // Do the interpolation 287func (ctx *BuiltinEvalContext) EvaluationScope(self addrs.Referenceable, keyData InstanceKeyEvalData) *lang.Scope {
278 if err := cfg.Interpolate(vs); err != nil { 288 data := &evaluationStateData{
279 return nil, err 289 Evaluator: ctx.Evaluator,
280 } 290 ModulePath: ctx.PathValue,
291 InstanceKeyData: keyData,
292 Operation: ctx.Evaluator.Operation,
281 } 293 }
282 294 return ctx.Evaluator.Scope(data, self)
283 result := NewResourceConfig(cfg)
284 result.interpolateForce()
285 return result, nil
286} 295}
287 296
288func (ctx *BuiltinEvalContext) Path() []string { 297func (ctx *BuiltinEvalContext) Path() addrs.ModuleInstance {
289 return ctx.PathValue 298 return ctx.PathValue
290} 299}
291 300
292func (ctx *BuiltinEvalContext) SetVariables(n string, vs map[string]interface{}) { 301func (ctx *BuiltinEvalContext) SetModuleCallArguments(n addrs.ModuleCallInstance, vals map[string]cty.Value) {
293 ctx.InterpolaterVarLock.Lock() 302 ctx.VariableValuesLock.Lock()
294 defer ctx.InterpolaterVarLock.Unlock() 303 defer ctx.VariableValuesLock.Unlock()
295 304
296 path := make([]string, len(ctx.Path())+1) 305 childPath := n.ModuleInstance(ctx.PathValue)
297 copy(path, ctx.Path()) 306 key := childPath.String()
298 path[len(path)-1] = n
299 key := PathCacheKey(path)
300 307
301 vars := ctx.InterpolaterVars[key] 308 args := ctx.VariableValues[key]
302 if vars == nil { 309 if args == nil {
303 vars = make(map[string]interface{}) 310 args = make(map[string]cty.Value)
304 ctx.InterpolaterVars[key] = vars 311 ctx.VariableValues[key] = vals
312 return
305 } 313 }
306 314
307 for k, v := range vs { 315 for k, v := range vals {
308 vars[k] = v 316 args[k] = v
309 } 317 }
310} 318}
311 319
312func (ctx *BuiltinEvalContext) Diff() (*Diff, *sync.RWMutex) { 320func (ctx *BuiltinEvalContext) Changes() *plans.ChangesSync {
313 return ctx.DiffValue, ctx.DiffLock 321 return ctx.ChangesValue
314} 322}
315 323
316func (ctx *BuiltinEvalContext) State() (*State, *sync.RWMutex) { 324func (ctx *BuiltinEvalContext) State() *states.SyncState {
317 return ctx.StateValue, ctx.StateLock 325 return ctx.StateValue
318} 326}
319 327
320func (ctx *BuiltinEvalContext) init() { 328func (ctx *BuiltinEvalContext) init() {