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