]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blob - vendor/github.com/hashicorp/terraform/terraform/eval_context_builtin.go
Initial transfer of provider code
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / eval_context_builtin.go
1 package terraform
2
3 import (
4 "context"
5 "fmt"
6 "log"
7 "strings"
8 "sync"
9
10 "github.com/hashicorp/terraform/config"
11 )
12
13 // BuiltinEvalContext is an EvalContext implementation that is used by
14 // Terraform by default.
15 type BuiltinEvalContext struct {
16 // StopContext is the context used to track whether we're complete
17 StopContext context.Context
18
19 // PathValue is the Path that this context is operating within.
20 PathValue []string
21
22 // Interpolater setting below affect the interpolation of variables.
23 //
24 // The InterpolaterVars are the exact value for ${var.foo} values.
25 // The map is shared between all contexts and is a mapping of
26 // PATH to KEY to VALUE. Because it is shared by all contexts as well
27 // as the Interpolater itself, it is protected by InterpolaterVarLock
28 // which must be locked during any access to the map.
29 Interpolater *Interpolater
30 InterpolaterVars map[string]map[string]interface{}
31 InterpolaterVarLock *sync.Mutex
32
33 Components contextComponentFactory
34 Hooks []Hook
35 InputValue UIInput
36 ProviderCache map[string]ResourceProvider
37 ProviderConfigCache map[string]*ResourceConfig
38 ProviderInputConfig map[string]map[string]interface{}
39 ProviderLock *sync.Mutex
40 ProvisionerCache map[string]ResourceProvisioner
41 ProvisionerLock *sync.Mutex
42 DiffValue *Diff
43 DiffLock *sync.RWMutex
44 StateValue *State
45 StateLock *sync.RWMutex
46
47 once sync.Once
48 }
49
50 func (ctx *BuiltinEvalContext) Stopped() <-chan struct{} {
51 // This can happen during tests. During tests, we just block forever.
52 if ctx.StopContext == nil {
53 return nil
54 }
55
56 return ctx.StopContext.Done()
57 }
58
59 func (ctx *BuiltinEvalContext) Hook(fn func(Hook) (HookAction, error)) error {
60 for _, h := range ctx.Hooks {
61 action, err := fn(h)
62 if err != nil {
63 return err
64 }
65
66 switch action {
67 case HookActionContinue:
68 continue
69 case HookActionHalt:
70 // Return an early exit error to trigger an early exit
71 log.Printf("[WARN] Early exit triggered by hook: %T", h)
72 return EvalEarlyExitError{}
73 }
74 }
75
76 return nil
77 }
78
79 func (ctx *BuiltinEvalContext) Input() UIInput {
80 return ctx.InputValue
81 }
82
83 func (ctx *BuiltinEvalContext) InitProvider(n string) (ResourceProvider, error) {
84 ctx.once.Do(ctx.init)
85
86 // If we already initialized, it is an error
87 if p := ctx.Provider(n); p != nil {
88 return nil, fmt.Errorf("Provider '%s' already initialized", n)
89 }
90
91 // Warning: make sure to acquire these locks AFTER the call to Provider
92 // above, since it also acquires locks.
93 ctx.ProviderLock.Lock()
94 defer ctx.ProviderLock.Unlock()
95
96 providerPath := make([]string, len(ctx.Path())+1)
97 copy(providerPath, ctx.Path())
98 providerPath[len(providerPath)-1] = n
99 key := PathCacheKey(providerPath)
100
101 typeName := strings.SplitN(n, ".", 2)[0]
102 p, err := ctx.Components.ResourceProvider(typeName, key)
103 if err != nil {
104 return nil, err
105 }
106
107 ctx.ProviderCache[key] = p
108 return p, nil
109 }
110
111 func (ctx *BuiltinEvalContext) Provider(n string) ResourceProvider {
112 ctx.once.Do(ctx.init)
113
114 ctx.ProviderLock.Lock()
115 defer ctx.ProviderLock.Unlock()
116
117 providerPath := make([]string, len(ctx.Path())+1)
118 copy(providerPath, ctx.Path())
119 providerPath[len(providerPath)-1] = n
120
121 return ctx.ProviderCache[PathCacheKey(providerPath)]
122 }
123
124 func (ctx *BuiltinEvalContext) CloseProvider(n string) error {
125 ctx.once.Do(ctx.init)
126
127 ctx.ProviderLock.Lock()
128 defer ctx.ProviderLock.Unlock()
129
130 providerPath := make([]string, len(ctx.Path())+1)
131 copy(providerPath, ctx.Path())
132 providerPath[len(providerPath)-1] = n
133
134 var provider interface{}
135 provider = ctx.ProviderCache[PathCacheKey(providerPath)]
136 if provider != nil {
137 if p, ok := provider.(ResourceProviderCloser); ok {
138 delete(ctx.ProviderCache, PathCacheKey(providerPath))
139 return p.Close()
140 }
141 }
142
143 return nil
144 }
145
146 func (ctx *BuiltinEvalContext) ConfigureProvider(
147 n string, cfg *ResourceConfig) error {
148 p := ctx.Provider(n)
149 if p == nil {
150 return fmt.Errorf("Provider '%s' not initialized", n)
151 }
152
153 if err := ctx.SetProviderConfig(n, cfg); err != nil {
154 return nil
155 }
156
157 return p.Configure(cfg)
158 }
159
160 func (ctx *BuiltinEvalContext) SetProviderConfig(
161 n string, cfg *ResourceConfig) error {
162 providerPath := make([]string, len(ctx.Path())+1)
163 copy(providerPath, ctx.Path())
164 providerPath[len(providerPath)-1] = n
165
166 // Save the configuration
167 ctx.ProviderLock.Lock()
168 ctx.ProviderConfigCache[PathCacheKey(providerPath)] = cfg
169 ctx.ProviderLock.Unlock()
170
171 return nil
172 }
173
174 func (ctx *BuiltinEvalContext) ProviderInput(n string) map[string]interface{} {
175 ctx.ProviderLock.Lock()
176 defer ctx.ProviderLock.Unlock()
177
178 // Make a copy of the path so we can safely edit it
179 path := ctx.Path()
180 pathCopy := make([]string, len(path)+1)
181 copy(pathCopy, path)
182
183 // Go up the tree.
184 for i := len(path) - 1; i >= 0; i-- {
185 pathCopy[i+1] = n
186 k := PathCacheKey(pathCopy[:i+2])
187 if v, ok := ctx.ProviderInputConfig[k]; ok {
188 return v
189 }
190 }
191
192 return nil
193 }
194
195 func (ctx *BuiltinEvalContext) SetProviderInput(n string, c map[string]interface{}) {
196 providerPath := make([]string, len(ctx.Path())+1)
197 copy(providerPath, ctx.Path())
198 providerPath[len(providerPath)-1] = n
199
200 // Save the configuration
201 ctx.ProviderLock.Lock()
202 ctx.ProviderInputConfig[PathCacheKey(providerPath)] = c
203 ctx.ProviderLock.Unlock()
204 }
205
206 func (ctx *BuiltinEvalContext) ParentProviderConfig(n string) *ResourceConfig {
207 ctx.ProviderLock.Lock()
208 defer ctx.ProviderLock.Unlock()
209
210 // Make a copy of the path so we can safely edit it
211 path := ctx.Path()
212 pathCopy := make([]string, len(path)+1)
213 copy(pathCopy, path)
214
215 // Go up the tree.
216 for i := len(path) - 1; i >= 0; i-- {
217 pathCopy[i+1] = n
218 k := PathCacheKey(pathCopy[:i+2])
219 if v, ok := ctx.ProviderConfigCache[k]; ok {
220 return v
221 }
222 }
223
224 return nil
225 }
226
227 func (ctx *BuiltinEvalContext) InitProvisioner(
228 n string) (ResourceProvisioner, error) {
229 ctx.once.Do(ctx.init)
230
231 // If we already initialized, it is an error
232 if p := ctx.Provisioner(n); p != nil {
233 return nil, fmt.Errorf("Provisioner '%s' already initialized", n)
234 }
235
236 // Warning: make sure to acquire these locks AFTER the call to Provisioner
237 // above, since it also acquires locks.
238 ctx.ProvisionerLock.Lock()
239 defer ctx.ProvisionerLock.Unlock()
240
241 provPath := make([]string, len(ctx.Path())+1)
242 copy(provPath, ctx.Path())
243 provPath[len(provPath)-1] = n
244 key := PathCacheKey(provPath)
245
246 p, err := ctx.Components.ResourceProvisioner(n, key)
247 if err != nil {
248 return nil, err
249 }
250
251 ctx.ProvisionerCache[key] = p
252 return p, nil
253 }
254
255 func (ctx *BuiltinEvalContext) Provisioner(n string) ResourceProvisioner {
256 ctx.once.Do(ctx.init)
257
258 ctx.ProvisionerLock.Lock()
259 defer ctx.ProvisionerLock.Unlock()
260
261 provPath := make([]string, len(ctx.Path())+1)
262 copy(provPath, ctx.Path())
263 provPath[len(provPath)-1] = n
264
265 return ctx.ProvisionerCache[PathCacheKey(provPath)]
266 }
267
268 func (ctx *BuiltinEvalContext) CloseProvisioner(n string) error {
269 ctx.once.Do(ctx.init)
270
271 ctx.ProvisionerLock.Lock()
272 defer ctx.ProvisionerLock.Unlock()
273
274 provPath := make([]string, len(ctx.Path())+1)
275 copy(provPath, ctx.Path())
276 provPath[len(provPath)-1] = n
277
278 var prov interface{}
279 prov = ctx.ProvisionerCache[PathCacheKey(provPath)]
280 if prov != nil {
281 if p, ok := prov.(ResourceProvisionerCloser); ok {
282 delete(ctx.ProvisionerCache, PathCacheKey(provPath))
283 return p.Close()
284 }
285 }
286
287 return nil
288 }
289
290 func (ctx *BuiltinEvalContext) Interpolate(
291 cfg *config.RawConfig, r *Resource) (*ResourceConfig, error) {
292 if cfg != nil {
293 scope := &InterpolationScope{
294 Path: ctx.Path(),
295 Resource: r,
296 }
297
298 vs, err := ctx.Interpolater.Values(scope, cfg.Variables)
299 if err != nil {
300 return nil, err
301 }
302
303 // Do the interpolation
304 if err := cfg.Interpolate(vs); err != nil {
305 return nil, err
306 }
307 }
308
309 result := NewResourceConfig(cfg)
310 result.interpolateForce()
311 return result, nil
312 }
313
314 func (ctx *BuiltinEvalContext) Path() []string {
315 return ctx.PathValue
316 }
317
318 func (ctx *BuiltinEvalContext) SetVariables(n string, vs map[string]interface{}) {
319 ctx.InterpolaterVarLock.Lock()
320 defer ctx.InterpolaterVarLock.Unlock()
321
322 path := make([]string, len(ctx.Path())+1)
323 copy(path, ctx.Path())
324 path[len(path)-1] = n
325 key := PathCacheKey(path)
326
327 vars := ctx.InterpolaterVars[key]
328 if vars == nil {
329 vars = make(map[string]interface{})
330 ctx.InterpolaterVars[key] = vars
331 }
332
333 for k, v := range vs {
334 vars[k] = v
335 }
336 }
337
338 func (ctx *BuiltinEvalContext) Diff() (*Diff, *sync.RWMutex) {
339 return ctx.DiffValue, ctx.DiffLock
340 }
341
342 func (ctx *BuiltinEvalContext) State() (*State, *sync.RWMutex) {
343 return ctx.StateValue, ctx.StateLock
344 }
345
346 func (ctx *BuiltinEvalContext) init() {
347 }