]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/hashicorp/terraform/terraform/eval_context_builtin.go
Upgrade to 0.12
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / eval_context_builtin.go
CommitLineData
bae9f6d2
JC
1package terraform
2
3import (
4 "context"
5 "fmt"
6 "log"
bae9f6d2
JC
7 "sync"
8
107c1cdb
ND
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"
bae9f6d2
JC
23)
24
25// BuiltinEvalContext is an EvalContext implementation that is used by
26// Terraform by default.
27type BuiltinEvalContext struct {
28 // StopContext is the context used to track whether we're complete
29 StopContext context.Context
30
31 // PathValue is the Path that this context is operating within.
107c1cdb 32 PathValue addrs.ModuleInstance
bae9f6d2 33
107c1cdb
ND
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.
bae9f6d2 43 //
107c1cdb
ND
44 // This must not be mutated during evaluation.
45 Schemas *Schemas
46
47 // VariableValues contains the variable values across all modules. This
48 // structure is shared across the entire containing context, and so it
49 // may be accessed only when holding VariableValuesLock.
50 // The keys of the first level of VariableValues are the string
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
bae9f6d2
JC
55
56 Components contextComponentFactory
57 Hooks []Hook
58 InputValue UIInput
107c1cdb
ND
59 ProviderCache map[string]providers.Interface
60 ProviderInputConfig map[string]map[string]cty.Value
bae9f6d2 61 ProviderLock *sync.Mutex
107c1cdb 62 ProvisionerCache map[string]provisioners.Interface
bae9f6d2 63 ProvisionerLock *sync.Mutex
107c1cdb
ND
64 ChangesValue *plans.ChangesSync
65 StateValue *states.SyncState
bae9f6d2
JC
66
67 once sync.Once
68}
69
107c1cdb
ND
70// BuiltinEvalContext implements EvalContext
71var _ EvalContext = (*BuiltinEvalContext)(nil)
72
bae9f6d2
JC
73func (ctx *BuiltinEvalContext) Stopped() <-chan struct{} {
74 // This can happen during tests. During tests, we just block forever.
75 if ctx.StopContext == nil {
76 return nil
77 }
78
79 return ctx.StopContext.Done()
80}
81
82func (ctx *BuiltinEvalContext) Hook(fn func(Hook) (HookAction, error)) error {
83 for _, h := range ctx.Hooks {
84 action, err := fn(h)
85 if err != nil {
86 return err
87 }
88
89 switch action {
90 case HookActionContinue:
91 continue
92 case HookActionHalt:
93 // Return an early exit error to trigger an early exit
94 log.Printf("[WARN] Early exit triggered by hook: %T", h)
95 return EvalEarlyExitError{}
96 }
97 }
98
99 return nil
100}
101
102func (ctx *BuiltinEvalContext) Input() UIInput {
103 return ctx.InputValue
104}
105
107c1cdb 106func (ctx *BuiltinEvalContext) InitProvider(typeName string, addr addrs.ProviderConfig) (providers.Interface, error) {
bae9f6d2 107 ctx.once.Do(ctx.init)
107c1cdb 108 absAddr := addr.Absolute(ctx.Path())
bae9f6d2
JC
109
110 // If we already initialized, it is an error
107c1cdb
ND
111 if p := ctx.Provider(absAddr); p != nil {
112 return nil, fmt.Errorf("%s is already initialized", addr)
bae9f6d2
JC
113 }
114
115 // Warning: make sure to acquire these locks AFTER the call to Provider
116 // above, since it also acquires locks.
117 ctx.ProviderLock.Lock()
118 defer ctx.ProviderLock.Unlock()
119
107c1cdb
ND
120 key := absAddr.String()
121
122 p, err := ctx.Components.ResourceProvider(typeName, key)
bae9f6d2
JC
123 if err != nil {
124 return nil, err
125 }
126
107c1cdb
ND
127 log.Printf("[TRACE] BuiltinEvalContext: Initialized %q provider for %s", typeName, absAddr)
128 ctx.ProviderCache[key] = p
129
bae9f6d2
JC
130 return p, nil
131}
132
107c1cdb 133func (ctx *BuiltinEvalContext) Provider(addr addrs.AbsProviderConfig) providers.Interface {
bae9f6d2
JC
134 ctx.once.Do(ctx.init)
135
136 ctx.ProviderLock.Lock()
137 defer ctx.ProviderLock.Unlock()
138
107c1cdb
ND
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)
bae9f6d2
JC
146}
147
107c1cdb 148func (ctx *BuiltinEvalContext) CloseProvider(addr addrs.ProviderConfig) error {
bae9f6d2
JC
149 ctx.once.Do(ctx.init)
150
151 ctx.ProviderLock.Lock()
152 defer ctx.ProviderLock.Unlock()
153
107c1cdb
ND
154 key := addr.Absolute(ctx.Path()).String()
155 provider := ctx.ProviderCache[key]
bae9f6d2 156 if provider != nil {
107c1cdb
ND
157 delete(ctx.ProviderCache, key)
158 return provider.Close()
bae9f6d2
JC
159 }
160
161 return nil
162}
163
107c1cdb
ND
164func (ctx *BuiltinEvalContext) ConfigureProvider(addr addrs.ProviderConfig, cfg cty.Value) tfdiags.Diagnostics {
165 var diags tfdiags.Diagnostics
166 absAddr := addr.Absolute(ctx.Path())
167 p := ctx.Provider(absAddr)
bae9f6d2 168 if p == nil {
107c1cdb
ND
169 diags = diags.Append(fmt.Errorf("%s not initialized", addr))
170 return diags
bae9f6d2 171 }
107c1cdb
ND
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
bae9f6d2
JC
186}
187
107c1cdb 188func (ctx *BuiltinEvalContext) ProviderInput(pc addrs.ProviderConfig) map[string]cty.Value {
bae9f6d2
JC
189 ctx.ProviderLock.Lock()
190 defer ctx.ProviderLock.Unlock()
191
107c1cdb
ND
192 if !ctx.Path().IsRoot() {
193 // Only root module provider configurations can have input.
194 return nil
bae9f6d2
JC
195 }
196
107c1cdb 197 return ctx.ProviderInputConfig[pc.String()]
bae9f6d2
JC
198}
199
107c1cdb
ND
200func (ctx *BuiltinEvalContext) SetProviderInput(pc addrs.ProviderConfig, c map[string]cty.Value) {
201 absProvider := pc.Absolute(ctx.Path())
202
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 }
bae9f6d2
JC
208
209 // Save the configuration
210 ctx.ProviderLock.Lock()
107c1cdb 211 ctx.ProviderInputConfig[absProvider.String()] = c
bae9f6d2
JC
212 ctx.ProviderLock.Unlock()
213}
214
107c1cdb 215func (ctx *BuiltinEvalContext) InitProvisioner(n string) (provisioners.Interface, error) {
bae9f6d2
JC
216 ctx.once.Do(ctx.init)
217
218 // If we already initialized, it is an error
219 if p := ctx.Provisioner(n); p != nil {
220 return nil, fmt.Errorf("Provisioner '%s' already initialized", n)
221 }
222
223 // Warning: make sure to acquire these locks AFTER the call to Provisioner
224 // above, since it also acquires locks.
225 ctx.ProvisionerLock.Lock()
226 defer ctx.ProvisionerLock.Unlock()
227
107c1cdb 228 key := PathObjectCacheKey(ctx.Path(), n)
bae9f6d2
JC
229
230 p, err := ctx.Components.ResourceProvisioner(n, key)
231 if err != nil {
232 return nil, err
233 }
234
235 ctx.ProvisionerCache[key] = p
107c1cdb 236
bae9f6d2
JC
237 return p, nil
238}
239
107c1cdb 240func (ctx *BuiltinEvalContext) Provisioner(n string) provisioners.Interface {
bae9f6d2
JC
241 ctx.once.Do(ctx.init)
242
243 ctx.ProvisionerLock.Lock()
244 defer ctx.ProvisionerLock.Unlock()
245
107c1cdb
ND
246 key := PathObjectCacheKey(ctx.Path(), n)
247 return ctx.ProvisionerCache[key]
248}
249
250func (ctx *BuiltinEvalContext) ProvisionerSchema(n string) *configschema.Block {
251 ctx.once.Do(ctx.init)
bae9f6d2 252
107c1cdb 253 return ctx.Schemas.ProvisionerConfig(n)
bae9f6d2
JC
254}
255
256func (ctx *BuiltinEvalContext) CloseProvisioner(n string) error {
257 ctx.once.Do(ctx.init)
258
259 ctx.ProvisionerLock.Lock()
260 defer ctx.ProvisionerLock.Unlock()
261
107c1cdb 262 key := PathObjectCacheKey(ctx.Path(), n)
bae9f6d2 263
107c1cdb 264 prov := ctx.ProvisionerCache[key]
bae9f6d2 265 if prov != nil {
107c1cdb 266 return prov.Close()
bae9f6d2
JC
267 }
268
269 return nil
270}
271
107c1cdb
ND
272func (ctx *BuiltinEvalContext) EvaluateBlock(body hcl.Body, schema *configschema.Block, self addrs.Referenceable, keyData InstanceKeyEvalData) (cty.Value, hcl.Body, tfdiags.Diagnostics) {
273 var diags tfdiags.Diagnostics
274 scope := ctx.EvaluationScope(self, keyData)
275 body, evalDiags := scope.ExpandBlock(body, schema)
276 diags = diags.Append(evalDiags)
277 val, evalDiags := scope.EvalBlock(body, schema)
278 diags = diags.Append(evalDiags)
279 return val, body, diags
15c0b25d
AP
280}
281
107c1cdb
ND
282func (ctx *BuiltinEvalContext) EvaluateExpr(expr hcl.Expression, wantType cty.Type, self addrs.Referenceable) (cty.Value, tfdiags.Diagnostics) {
283 scope := ctx.EvaluationScope(self, EvalDataForNoInstanceKey)
284 return scope.EvalExpr(expr, wantType)
285}
bae9f6d2 286
107c1cdb
ND
287func (ctx *BuiltinEvalContext) EvaluationScope(self addrs.Referenceable, keyData InstanceKeyEvalData) *lang.Scope {
288 data := &evaluationStateData{
289 Evaluator: ctx.Evaluator,
290 ModulePath: ctx.PathValue,
291 InstanceKeyData: keyData,
292 Operation: ctx.Evaluator.Operation,
bae9f6d2 293 }
107c1cdb 294 return ctx.Evaluator.Scope(data, self)
bae9f6d2
JC
295}
296
107c1cdb 297func (ctx *BuiltinEvalContext) Path() addrs.ModuleInstance {
bae9f6d2
JC
298 return ctx.PathValue
299}
300
107c1cdb
ND
301func (ctx *BuiltinEvalContext) SetModuleCallArguments(n addrs.ModuleCallInstance, vals map[string]cty.Value) {
302 ctx.VariableValuesLock.Lock()
303 defer ctx.VariableValuesLock.Unlock()
bae9f6d2 304
107c1cdb
ND
305 childPath := n.ModuleInstance(ctx.PathValue)
306 key := childPath.String()
bae9f6d2 307
107c1cdb
ND
308 args := ctx.VariableValues[key]
309 if args == nil {
310 args = make(map[string]cty.Value)
311 ctx.VariableValues[key] = vals
312 return
bae9f6d2
JC
313 }
314
107c1cdb
ND
315 for k, v := range vals {
316 args[k] = v
bae9f6d2
JC
317 }
318}
319
107c1cdb
ND
320func (ctx *BuiltinEvalContext) Changes() *plans.ChangesSync {
321 return ctx.ChangesValue
bae9f6d2
JC
322}
323
107c1cdb
ND
324func (ctx *BuiltinEvalContext) State() *states.SyncState {
325 return ctx.StateValue
bae9f6d2
JC
326}
327
328func (ctx *BuiltinEvalContext) init() {
329}