]>
Commit | Line | Data |
---|---|---|
1 | package terraform | |
2 | ||
3 | import ( | |
4 | "github.com/hashicorp/hcl2/hcl" | |
5 | "github.com/hashicorp/hcl2/hcldec" | |
6 | "github.com/zclconf/go-cty/cty" | |
7 | "github.com/zclconf/go-cty/cty/convert" | |
8 | ||
9 | "github.com/hashicorp/terraform/addrs" | |
10 | "github.com/hashicorp/terraform/config" | |
11 | "github.com/hashicorp/terraform/configs/configschema" | |
12 | "github.com/hashicorp/terraform/lang" | |
13 | "github.com/hashicorp/terraform/plans" | |
14 | "github.com/hashicorp/terraform/providers" | |
15 | "github.com/hashicorp/terraform/provisioners" | |
16 | "github.com/hashicorp/terraform/states" | |
17 | "github.com/hashicorp/terraform/tfdiags" | |
18 | ) | |
19 | ||
20 | // MockEvalContext is a mock version of EvalContext that can be used | |
21 | // for tests. | |
22 | type MockEvalContext struct { | |
23 | StoppedCalled bool | |
24 | StoppedValue <-chan struct{} | |
25 | ||
26 | HookCalled bool | |
27 | HookHook Hook | |
28 | HookError error | |
29 | ||
30 | InputCalled bool | |
31 | InputInput UIInput | |
32 | ||
33 | InitProviderCalled bool | |
34 | InitProviderType string | |
35 | InitProviderAddr addrs.ProviderConfig | |
36 | InitProviderProvider providers.Interface | |
37 | InitProviderError error | |
38 | ||
39 | ProviderCalled bool | |
40 | ProviderAddr addrs.AbsProviderConfig | |
41 | ProviderProvider providers.Interface | |
42 | ||
43 | ProviderSchemaCalled bool | |
44 | ProviderSchemaAddr addrs.AbsProviderConfig | |
45 | ProviderSchemaSchema *ProviderSchema | |
46 | ||
47 | CloseProviderCalled bool | |
48 | CloseProviderAddr addrs.ProviderConfig | |
49 | CloseProviderProvider providers.Interface | |
50 | ||
51 | ProviderInputCalled bool | |
52 | ProviderInputAddr addrs.ProviderConfig | |
53 | ProviderInputValues map[string]cty.Value | |
54 | ||
55 | SetProviderInputCalled bool | |
56 | SetProviderInputAddr addrs.ProviderConfig | |
57 | SetProviderInputValues map[string]cty.Value | |
58 | ||
59 | ConfigureProviderCalled bool | |
60 | ConfigureProviderAddr addrs.ProviderConfig | |
61 | ConfigureProviderConfig cty.Value | |
62 | ConfigureProviderDiags tfdiags.Diagnostics | |
63 | ||
64 | InitProvisionerCalled bool | |
65 | InitProvisionerName string | |
66 | InitProvisionerProvisioner provisioners.Interface | |
67 | InitProvisionerError error | |
68 | ||
69 | ProvisionerCalled bool | |
70 | ProvisionerName string | |
71 | ProvisionerProvisioner provisioners.Interface | |
72 | ||
73 | ProvisionerSchemaCalled bool | |
74 | ProvisionerSchemaName string | |
75 | ProvisionerSchemaSchema *configschema.Block | |
76 | ||
77 | CloseProvisionerCalled bool | |
78 | CloseProvisionerName string | |
79 | CloseProvisionerProvisioner provisioners.Interface | |
80 | ||
81 | EvaluateBlockCalled bool | |
82 | EvaluateBlockBody hcl.Body | |
83 | EvaluateBlockSchema *configschema.Block | |
84 | EvaluateBlockSelf addrs.Referenceable | |
85 | EvaluateBlockKeyData InstanceKeyEvalData | |
86 | EvaluateBlockResultFunc func( | |
87 | body hcl.Body, | |
88 | schema *configschema.Block, | |
89 | self addrs.Referenceable, | |
90 | keyData InstanceKeyEvalData, | |
91 | ) (cty.Value, hcl.Body, tfdiags.Diagnostics) // overrides the other values below, if set | |
92 | EvaluateBlockResult cty.Value | |
93 | EvaluateBlockExpandedBody hcl.Body | |
94 | EvaluateBlockDiags tfdiags.Diagnostics | |
95 | ||
96 | EvaluateExprCalled bool | |
97 | EvaluateExprExpr hcl.Expression | |
98 | EvaluateExprWantType cty.Type | |
99 | EvaluateExprSelf addrs.Referenceable | |
100 | EvaluateExprResultFunc func( | |
101 | expr hcl.Expression, | |
102 | wantType cty.Type, | |
103 | self addrs.Referenceable, | |
104 | ) (cty.Value, tfdiags.Diagnostics) // overrides the other values below, if set | |
105 | EvaluateExprResult cty.Value | |
106 | EvaluateExprDiags tfdiags.Diagnostics | |
107 | ||
108 | EvaluationScopeCalled bool | |
109 | EvaluationScopeSelf addrs.Referenceable | |
110 | EvaluationScopeKeyData InstanceKeyEvalData | |
111 | EvaluationScopeScope *lang.Scope | |
112 | ||
113 | InterpolateCalled bool | |
114 | InterpolateConfig *config.RawConfig | |
115 | InterpolateResource *Resource | |
116 | InterpolateConfigResult *ResourceConfig | |
117 | InterpolateError error | |
118 | ||
119 | InterpolateProviderCalled bool | |
120 | InterpolateProviderConfig *config.ProviderConfig | |
121 | InterpolateProviderResource *Resource | |
122 | InterpolateProviderConfigResult *ResourceConfig | |
123 | InterpolateProviderError error | |
124 | ||
125 | PathCalled bool | |
126 | PathPath addrs.ModuleInstance | |
127 | ||
128 | SetModuleCallArgumentsCalled bool | |
129 | SetModuleCallArgumentsModule addrs.ModuleCallInstance | |
130 | SetModuleCallArgumentsValues map[string]cty.Value | |
131 | ||
132 | ChangesCalled bool | |
133 | ChangesChanges *plans.ChangesSync | |
134 | ||
135 | StateCalled bool | |
136 | StateState *states.SyncState | |
137 | } | |
138 | ||
139 | // MockEvalContext implements EvalContext | |
140 | var _ EvalContext = (*MockEvalContext)(nil) | |
141 | ||
142 | func (c *MockEvalContext) Stopped() <-chan struct{} { | |
143 | c.StoppedCalled = true | |
144 | return c.StoppedValue | |
145 | } | |
146 | ||
147 | func (c *MockEvalContext) Hook(fn func(Hook) (HookAction, error)) error { | |
148 | c.HookCalled = true | |
149 | if c.HookHook != nil { | |
150 | if _, err := fn(c.HookHook); err != nil { | |
151 | return err | |
152 | } | |
153 | } | |
154 | ||
155 | return c.HookError | |
156 | } | |
157 | ||
158 | func (c *MockEvalContext) Input() UIInput { | |
159 | c.InputCalled = true | |
160 | return c.InputInput | |
161 | } | |
162 | ||
163 | func (c *MockEvalContext) InitProvider(t string, addr addrs.ProviderConfig) (providers.Interface, error) { | |
164 | c.InitProviderCalled = true | |
165 | c.InitProviderType = t | |
166 | c.InitProviderAddr = addr | |
167 | return c.InitProviderProvider, c.InitProviderError | |
168 | } | |
169 | ||
170 | func (c *MockEvalContext) Provider(addr addrs.AbsProviderConfig) providers.Interface { | |
171 | c.ProviderCalled = true | |
172 | c.ProviderAddr = addr | |
173 | return c.ProviderProvider | |
174 | } | |
175 | ||
176 | func (c *MockEvalContext) ProviderSchema(addr addrs.AbsProviderConfig) *ProviderSchema { | |
177 | c.ProviderSchemaCalled = true | |
178 | c.ProviderSchemaAddr = addr | |
179 | return c.ProviderSchemaSchema | |
180 | } | |
181 | ||
182 | func (c *MockEvalContext) CloseProvider(addr addrs.ProviderConfig) error { | |
183 | c.CloseProviderCalled = true | |
184 | c.CloseProviderAddr = addr | |
185 | return nil | |
186 | } | |
187 | ||
188 | func (c *MockEvalContext) ConfigureProvider(addr addrs.ProviderConfig, cfg cty.Value) tfdiags.Diagnostics { | |
189 | c.ConfigureProviderCalled = true | |
190 | c.ConfigureProviderAddr = addr | |
191 | c.ConfigureProviderConfig = cfg | |
192 | return c.ConfigureProviderDiags | |
193 | } | |
194 | ||
195 | func (c *MockEvalContext) ProviderInput(addr addrs.ProviderConfig) map[string]cty.Value { | |
196 | c.ProviderInputCalled = true | |
197 | c.ProviderInputAddr = addr | |
198 | return c.ProviderInputValues | |
199 | } | |
200 | ||
201 | func (c *MockEvalContext) SetProviderInput(addr addrs.ProviderConfig, vals map[string]cty.Value) { | |
202 | c.SetProviderInputCalled = true | |
203 | c.SetProviderInputAddr = addr | |
204 | c.SetProviderInputValues = vals | |
205 | } | |
206 | ||
207 | func (c *MockEvalContext) InitProvisioner(n string) (provisioners.Interface, error) { | |
208 | c.InitProvisionerCalled = true | |
209 | c.InitProvisionerName = n | |
210 | return c.InitProvisionerProvisioner, c.InitProvisionerError | |
211 | } | |
212 | ||
213 | func (c *MockEvalContext) Provisioner(n string) provisioners.Interface { | |
214 | c.ProvisionerCalled = true | |
215 | c.ProvisionerName = n | |
216 | return c.ProvisionerProvisioner | |
217 | } | |
218 | ||
219 | func (c *MockEvalContext) ProvisionerSchema(n string) *configschema.Block { | |
220 | c.ProvisionerSchemaCalled = true | |
221 | c.ProvisionerSchemaName = n | |
222 | return c.ProvisionerSchemaSchema | |
223 | } | |
224 | ||
225 | func (c *MockEvalContext) CloseProvisioner(n string) error { | |
226 | c.CloseProvisionerCalled = true | |
227 | c.CloseProvisionerName = n | |
228 | return nil | |
229 | } | |
230 | ||
231 | func (c *MockEvalContext) EvaluateBlock(body hcl.Body, schema *configschema.Block, self addrs.Referenceable, keyData InstanceKeyEvalData) (cty.Value, hcl.Body, tfdiags.Diagnostics) { | |
232 | c.EvaluateBlockCalled = true | |
233 | c.EvaluateBlockBody = body | |
234 | c.EvaluateBlockSchema = schema | |
235 | c.EvaluateBlockSelf = self | |
236 | c.EvaluateBlockKeyData = keyData | |
237 | if c.EvaluateBlockResultFunc != nil { | |
238 | return c.EvaluateBlockResultFunc(body, schema, self, keyData) | |
239 | } | |
240 | return c.EvaluateBlockResult, c.EvaluateBlockExpandedBody, c.EvaluateBlockDiags | |
241 | } | |
242 | ||
243 | func (c *MockEvalContext) EvaluateExpr(expr hcl.Expression, wantType cty.Type, self addrs.Referenceable) (cty.Value, tfdiags.Diagnostics) { | |
244 | c.EvaluateExprCalled = true | |
245 | c.EvaluateExprExpr = expr | |
246 | c.EvaluateExprWantType = wantType | |
247 | c.EvaluateExprSelf = self | |
248 | if c.EvaluateExprResultFunc != nil { | |
249 | return c.EvaluateExprResultFunc(expr, wantType, self) | |
250 | } | |
251 | return c.EvaluateExprResult, c.EvaluateExprDiags | |
252 | } | |
253 | ||
254 | // installSimpleEval is a helper to install a simple mock implementation of | |
255 | // both EvaluateBlock and EvaluateExpr into the receiver. | |
256 | // | |
257 | // These default implementations will either evaluate the given input against | |
258 | // the scope in field EvaluationScopeScope or, if it is nil, with no eval | |
259 | // context at all so that only constant values may be used. | |
260 | // | |
261 | // This function overwrites any existing functions installed in fields | |
262 | // EvaluateBlockResultFunc and EvaluateExprResultFunc. | |
263 | func (c *MockEvalContext) installSimpleEval() { | |
264 | c.EvaluateBlockResultFunc = func(body hcl.Body, schema *configschema.Block, self addrs.Referenceable, keyData InstanceKeyEvalData) (cty.Value, hcl.Body, tfdiags.Diagnostics) { | |
265 | if scope := c.EvaluationScopeScope; scope != nil { | |
266 | // Fully-functional codepath. | |
267 | var diags tfdiags.Diagnostics | |
268 | body, diags = scope.ExpandBlock(body, schema) | |
269 | if diags.HasErrors() { | |
270 | return cty.DynamicVal, body, diags | |
271 | } | |
272 | val, evalDiags := c.EvaluationScopeScope.EvalBlock(body, schema) | |
273 | diags = diags.Append(evalDiags) | |
274 | if evalDiags.HasErrors() { | |
275 | return cty.DynamicVal, body, diags | |
276 | } | |
277 | return val, body, diags | |
278 | } | |
279 | ||
280 | // Fallback codepath supporting constant values only. | |
281 | val, hclDiags := hcldec.Decode(body, schema.DecoderSpec(), nil) | |
282 | return val, body, tfdiags.Diagnostics(nil).Append(hclDiags) | |
283 | } | |
284 | c.EvaluateExprResultFunc = func(expr hcl.Expression, wantType cty.Type, self addrs.Referenceable) (cty.Value, tfdiags.Diagnostics) { | |
285 | if scope := c.EvaluationScopeScope; scope != nil { | |
286 | // Fully-functional codepath. | |
287 | return scope.EvalExpr(expr, wantType) | |
288 | } | |
289 | ||
290 | // Fallback codepath supporting constant values only. | |
291 | var diags tfdiags.Diagnostics | |
292 | val, hclDiags := expr.Value(nil) | |
293 | diags = diags.Append(hclDiags) | |
294 | if hclDiags.HasErrors() { | |
295 | return cty.DynamicVal, diags | |
296 | } | |
297 | var err error | |
298 | val, err = convert.Convert(val, wantType) | |
299 | if err != nil { | |
300 | diags = diags.Append(err) | |
301 | return cty.DynamicVal, diags | |
302 | } | |
303 | return val, diags | |
304 | } | |
305 | } | |
306 | ||
307 | func (c *MockEvalContext) EvaluationScope(self addrs.Referenceable, keyData InstanceKeyEvalData) *lang.Scope { | |
308 | c.EvaluationScopeCalled = true | |
309 | c.EvaluationScopeSelf = self | |
310 | c.EvaluationScopeKeyData = keyData | |
311 | return c.EvaluationScopeScope | |
312 | } | |
313 | ||
314 | func (c *MockEvalContext) Interpolate( | |
315 | config *config.RawConfig, resource *Resource) (*ResourceConfig, error) { | |
316 | c.InterpolateCalled = true | |
317 | c.InterpolateConfig = config | |
318 | c.InterpolateResource = resource | |
319 | return c.InterpolateConfigResult, c.InterpolateError | |
320 | } | |
321 | ||
322 | func (c *MockEvalContext) InterpolateProvider( | |
323 | config *config.ProviderConfig, resource *Resource) (*ResourceConfig, error) { | |
324 | c.InterpolateProviderCalled = true | |
325 | c.InterpolateProviderConfig = config | |
326 | c.InterpolateProviderResource = resource | |
327 | return c.InterpolateProviderConfigResult, c.InterpolateError | |
328 | } | |
329 | ||
330 | func (c *MockEvalContext) Path() addrs.ModuleInstance { | |
331 | c.PathCalled = true | |
332 | return c.PathPath | |
333 | } | |
334 | ||
335 | func (c *MockEvalContext) SetModuleCallArguments(n addrs.ModuleCallInstance, values map[string]cty.Value) { | |
336 | c.SetModuleCallArgumentsCalled = true | |
337 | c.SetModuleCallArgumentsModule = n | |
338 | c.SetModuleCallArgumentsValues = values | |
339 | } | |
340 | ||
341 | func (c *MockEvalContext) Changes() *plans.ChangesSync { | |
342 | c.ChangesCalled = true | |
343 | return c.ChangesChanges | |
344 | } | |
345 | ||
346 | func (c *MockEvalContext) State() *states.SyncState { | |
347 | c.StateCalled = true | |
348 | return c.StateState | |
349 | } |