diff options
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.go | 347 |
1 files changed, 347 insertions, 0 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 new file mode 100644 index 0000000..3dcfb22 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/terraform/eval_context_builtin.go | |||
@@ -0,0 +1,347 @@ | |||
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 | } | ||