github.com/opentofu/opentofu@v1.7.1/internal/tofu/eval_context_mock.go (about) 1 // Copyright (c) The OpenTofu Authors 2 // SPDX-License-Identifier: MPL-2.0 3 // Copyright (c) 2023 HashiCorp, Inc. 4 // SPDX-License-Identifier: MPL-2.0 5 6 package tofu 7 8 import ( 9 "github.com/hashicorp/hcl/v2" 10 "github.com/hashicorp/hcl/v2/hcldec" 11 "github.com/opentofu/opentofu/internal/addrs" 12 "github.com/opentofu/opentofu/internal/checks" 13 "github.com/opentofu/opentofu/internal/configs/configschema" 14 "github.com/opentofu/opentofu/internal/encryption" 15 "github.com/opentofu/opentofu/internal/instances" 16 "github.com/opentofu/opentofu/internal/lang" 17 "github.com/opentofu/opentofu/internal/plans" 18 "github.com/opentofu/opentofu/internal/providers" 19 "github.com/opentofu/opentofu/internal/provisioners" 20 "github.com/opentofu/opentofu/internal/refactoring" 21 "github.com/opentofu/opentofu/internal/states" 22 "github.com/opentofu/opentofu/internal/tfdiags" 23 "github.com/zclconf/go-cty/cty" 24 "github.com/zclconf/go-cty/cty/convert" 25 ) 26 27 // MockEvalContext is a mock version of EvalContext that can be used 28 // for tests. 29 type MockEvalContext struct { 30 StoppedCalled bool 31 StoppedValue <-chan struct{} 32 33 HookCalled bool 34 HookHook Hook 35 HookError error 36 37 InputCalled bool 38 InputInput UIInput 39 40 InitProviderCalled bool 41 InitProviderType string 42 InitProviderAddr addrs.AbsProviderConfig 43 InitProviderProvider providers.Interface 44 InitProviderError error 45 46 ProviderCalled bool 47 ProviderAddr addrs.AbsProviderConfig 48 ProviderProvider providers.Interface 49 50 ProviderSchemaCalled bool 51 ProviderSchemaAddr addrs.AbsProviderConfig 52 ProviderSchemaSchema providers.ProviderSchema 53 ProviderSchemaError error 54 55 CloseProviderCalled bool 56 CloseProviderAddr addrs.AbsProviderConfig 57 CloseProviderProvider providers.Interface 58 59 ProviderInputCalled bool 60 ProviderInputAddr addrs.AbsProviderConfig 61 ProviderInputValues map[string]cty.Value 62 63 SetProviderInputCalled bool 64 SetProviderInputAddr addrs.AbsProviderConfig 65 SetProviderInputValues map[string]cty.Value 66 67 ConfigureProviderFn func( 68 addr addrs.AbsProviderConfig, 69 cfg cty.Value) tfdiags.Diagnostics // overrides the other values below, if set 70 ConfigureProviderCalled bool 71 ConfigureProviderAddr addrs.AbsProviderConfig 72 ConfigureProviderConfig cty.Value 73 ConfigureProviderDiags tfdiags.Diagnostics 74 75 ProvisionerCalled bool 76 ProvisionerName string 77 ProvisionerProvisioner provisioners.Interface 78 79 ProvisionerSchemaCalled bool 80 ProvisionerSchemaName string 81 ProvisionerSchemaSchema *configschema.Block 82 ProvisionerSchemaError error 83 84 CloseProvisionersCalled bool 85 86 EvaluateBlockCalled bool 87 EvaluateBlockBody hcl.Body 88 EvaluateBlockSchema *configschema.Block 89 EvaluateBlockSelf addrs.Referenceable 90 EvaluateBlockKeyData InstanceKeyEvalData 91 EvaluateBlockResultFunc func( 92 body hcl.Body, 93 schema *configschema.Block, 94 self addrs.Referenceable, 95 keyData InstanceKeyEvalData, 96 ) (cty.Value, hcl.Body, tfdiags.Diagnostics) // overrides the other values below, if set 97 EvaluateBlockResult cty.Value 98 EvaluateBlockExpandedBody hcl.Body 99 EvaluateBlockDiags tfdiags.Diagnostics 100 101 EvaluateExprCalled bool 102 EvaluateExprExpr hcl.Expression 103 EvaluateExprWantType cty.Type 104 EvaluateExprSelf addrs.Referenceable 105 EvaluateExprResultFunc func( 106 expr hcl.Expression, 107 wantType cty.Type, 108 self addrs.Referenceable, 109 ) (cty.Value, tfdiags.Diagnostics) // overrides the other values below, if set 110 EvaluateExprResult cty.Value 111 EvaluateExprDiags tfdiags.Diagnostics 112 113 EvaluationScopeCalled bool 114 EvaluationScopeSelf addrs.Referenceable 115 EvaluationScopeKeyData InstanceKeyEvalData 116 EvaluationScopeScope *lang.Scope 117 118 PathCalled bool 119 PathPath addrs.ModuleInstance 120 121 SetRootModuleArgumentCalled bool 122 SetRootModuleArgumentAddr addrs.InputVariable 123 SetRootModuleArgumentValue cty.Value 124 SetRootModuleArgumentFunc func(addr addrs.InputVariable, v cty.Value) 125 126 SetModuleCallArgumentCalled bool 127 SetModuleCallArgumentModuleCall addrs.ModuleCallInstance 128 SetModuleCallArgumentVariable addrs.InputVariable 129 SetModuleCallArgumentValue cty.Value 130 SetModuleCallArgumentFunc func(callAddr addrs.ModuleCallInstance, varAddr addrs.InputVariable, v cty.Value) 131 132 GetVariableValueCalled bool 133 GetVariableValueAddr addrs.AbsInputVariableInstance 134 GetVariableValueValue cty.Value 135 GetVariableValueFunc func(addr addrs.AbsInputVariableInstance) cty.Value // supersedes GetVariableValueValue 136 137 ChangesCalled bool 138 ChangesChanges *plans.ChangesSync 139 140 StateCalled bool 141 StateState *states.SyncState 142 143 ChecksCalled bool 144 ChecksState *checks.State 145 146 RefreshStateCalled bool 147 RefreshStateState *states.SyncState 148 149 PrevRunStateCalled bool 150 PrevRunStateState *states.SyncState 151 152 MoveResultsCalled bool 153 MoveResultsResults refactoring.MoveResults 154 155 ImportResolverCalled bool 156 ImportResolverResults *ImportResolver 157 158 InstanceExpanderCalled bool 159 InstanceExpanderExpander *instances.Expander 160 } 161 162 // MockEvalContext implements EvalContext 163 var _ EvalContext = (*MockEvalContext)(nil) 164 165 func (c *MockEvalContext) Stopped() <-chan struct{} { 166 c.StoppedCalled = true 167 return c.StoppedValue 168 } 169 170 func (c *MockEvalContext) Hook(fn func(Hook) (HookAction, error)) error { 171 c.HookCalled = true 172 if c.HookHook != nil { 173 if _, err := fn(c.HookHook); err != nil { 174 return err 175 } 176 } 177 178 return c.HookError 179 } 180 181 func (c *MockEvalContext) Input() UIInput { 182 c.InputCalled = true 183 return c.InputInput 184 } 185 186 func (c *MockEvalContext) InitProvider(addr addrs.AbsProviderConfig) (providers.Interface, error) { 187 c.InitProviderCalled = true 188 c.InitProviderType = addr.String() 189 c.InitProviderAddr = addr 190 return c.InitProviderProvider, c.InitProviderError 191 } 192 193 func (c *MockEvalContext) Provider(addr addrs.AbsProviderConfig) providers.Interface { 194 c.ProviderCalled = true 195 c.ProviderAddr = addr 196 return c.ProviderProvider 197 } 198 199 func (c *MockEvalContext) ProviderSchema(addr addrs.AbsProviderConfig) (providers.ProviderSchema, error) { 200 c.ProviderSchemaCalled = true 201 c.ProviderSchemaAddr = addr 202 return c.ProviderSchemaSchema, c.ProviderSchemaError 203 } 204 205 func (c *MockEvalContext) CloseProvider(addr addrs.AbsProviderConfig) error { 206 c.CloseProviderCalled = true 207 c.CloseProviderAddr = addr 208 return nil 209 } 210 211 func (c *MockEvalContext) ConfigureProvider(addr addrs.AbsProviderConfig, cfg cty.Value) tfdiags.Diagnostics { 212 213 c.ConfigureProviderCalled = true 214 c.ConfigureProviderAddr = addr 215 c.ConfigureProviderConfig = cfg 216 if c.ConfigureProviderFn != nil { 217 return c.ConfigureProviderFn(addr, cfg) 218 } 219 return c.ConfigureProviderDiags 220 } 221 222 func (c *MockEvalContext) ProviderInput(addr addrs.AbsProviderConfig) map[string]cty.Value { 223 c.ProviderInputCalled = true 224 c.ProviderInputAddr = addr 225 return c.ProviderInputValues 226 } 227 228 func (c *MockEvalContext) SetProviderInput(addr addrs.AbsProviderConfig, vals map[string]cty.Value) { 229 c.SetProviderInputCalled = true 230 c.SetProviderInputAddr = addr 231 c.SetProviderInputValues = vals 232 } 233 234 func (c *MockEvalContext) Provisioner(n string) (provisioners.Interface, error) { 235 c.ProvisionerCalled = true 236 c.ProvisionerName = n 237 return c.ProvisionerProvisioner, nil 238 } 239 240 func (c *MockEvalContext) ProvisionerSchema(n string) (*configschema.Block, error) { 241 c.ProvisionerSchemaCalled = true 242 c.ProvisionerSchemaName = n 243 return c.ProvisionerSchemaSchema, c.ProvisionerSchemaError 244 } 245 246 func (c *MockEvalContext) CloseProvisioners() error { 247 c.CloseProvisionersCalled = true 248 return nil 249 } 250 251 func (c *MockEvalContext) EvaluateBlock(body hcl.Body, schema *configschema.Block, self addrs.Referenceable, keyData InstanceKeyEvalData) (cty.Value, hcl.Body, tfdiags.Diagnostics) { 252 c.EvaluateBlockCalled = true 253 c.EvaluateBlockBody = body 254 c.EvaluateBlockSchema = schema 255 c.EvaluateBlockSelf = self 256 c.EvaluateBlockKeyData = keyData 257 if c.EvaluateBlockResultFunc != nil { 258 return c.EvaluateBlockResultFunc(body, schema, self, keyData) 259 } 260 return c.EvaluateBlockResult, c.EvaluateBlockExpandedBody, c.EvaluateBlockDiags 261 } 262 263 func (c *MockEvalContext) EvaluateExpr(expr hcl.Expression, wantType cty.Type, self addrs.Referenceable) (cty.Value, tfdiags.Diagnostics) { 264 c.EvaluateExprCalled = true 265 c.EvaluateExprExpr = expr 266 c.EvaluateExprWantType = wantType 267 c.EvaluateExprSelf = self 268 if c.EvaluateExprResultFunc != nil { 269 return c.EvaluateExprResultFunc(expr, wantType, self) 270 } 271 return c.EvaluateExprResult, c.EvaluateExprDiags 272 } 273 274 func (c *MockEvalContext) EvaluateReplaceTriggeredBy(hcl.Expression, instances.RepetitionData) (*addrs.Reference, bool, tfdiags.Diagnostics) { 275 return nil, false, nil 276 } 277 278 func (c *MockEvalContext) EvaluateImportAddress(expression hcl.Expression, keyData instances.RepetitionData) (addrs.AbsResourceInstance, tfdiags.Diagnostics) { 279 return addrs.AbsResourceInstance{}, nil 280 } 281 282 // installSimpleEval is a helper to install a simple mock implementation of 283 // both EvaluateBlock and EvaluateExpr into the receiver. 284 // 285 // These default implementations will either evaluate the given input against 286 // the scope in field EvaluationScopeScope or, if it is nil, with no eval 287 // context at all so that only constant values may be used. 288 // 289 // This function overwrites any existing functions installed in fields 290 // EvaluateBlockResultFunc and EvaluateExprResultFunc. 291 func (c *MockEvalContext) installSimpleEval() { 292 c.EvaluateBlockResultFunc = func(body hcl.Body, schema *configschema.Block, self addrs.Referenceable, keyData InstanceKeyEvalData) (cty.Value, hcl.Body, tfdiags.Diagnostics) { 293 if scope := c.EvaluationScopeScope; scope != nil { 294 // Fully-functional codepath. 295 var diags tfdiags.Diagnostics 296 body, diags = scope.ExpandBlock(body, schema) 297 if diags.HasErrors() { 298 return cty.DynamicVal, body, diags 299 } 300 val, evalDiags := c.EvaluationScopeScope.EvalBlock(body, schema) 301 diags = diags.Append(evalDiags) 302 if evalDiags.HasErrors() { 303 return cty.DynamicVal, body, diags 304 } 305 return val, body, diags 306 } 307 308 // Fallback codepath supporting constant values only. 309 val, hclDiags := hcldec.Decode(body, schema.DecoderSpec(), nil) 310 return val, body, tfdiags.Diagnostics(nil).Append(hclDiags) 311 } 312 c.EvaluateExprResultFunc = func(expr hcl.Expression, wantType cty.Type, self addrs.Referenceable) (cty.Value, tfdiags.Diagnostics) { 313 if scope := c.EvaluationScopeScope; scope != nil { 314 // Fully-functional codepath. 315 return scope.EvalExpr(expr, wantType) 316 } 317 318 // Fallback codepath supporting constant values only. 319 var diags tfdiags.Diagnostics 320 val, hclDiags := expr.Value(nil) 321 diags = diags.Append(hclDiags) 322 if hclDiags.HasErrors() { 323 return cty.DynamicVal, diags 324 } 325 var err error 326 val, err = convert.Convert(val, wantType) 327 if err != nil { 328 diags = diags.Append(err) 329 return cty.DynamicVal, diags 330 } 331 return val, diags 332 } 333 } 334 335 func (c *MockEvalContext) EvaluationScope(self addrs.Referenceable, source addrs.Referenceable, keyData InstanceKeyEvalData) *lang.Scope { 336 c.EvaluationScopeCalled = true 337 c.EvaluationScopeSelf = self 338 c.EvaluationScopeKeyData = keyData 339 return c.EvaluationScopeScope 340 } 341 342 func (c *MockEvalContext) WithPath(path addrs.ModuleInstance) EvalContext { 343 newC := *c 344 newC.PathPath = path 345 return &newC 346 } 347 348 func (c *MockEvalContext) Path() addrs.ModuleInstance { 349 c.PathCalled = true 350 return c.PathPath 351 } 352 353 func (c *MockEvalContext) SetRootModuleArgument(addr addrs.InputVariable, v cty.Value) { 354 c.SetRootModuleArgumentCalled = true 355 c.SetRootModuleArgumentAddr = addr 356 c.SetRootModuleArgumentValue = v 357 if c.SetRootModuleArgumentFunc != nil { 358 c.SetRootModuleArgumentFunc(addr, v) 359 } 360 } 361 362 func (c *MockEvalContext) SetModuleCallArgument(callAddr addrs.ModuleCallInstance, varAddr addrs.InputVariable, v cty.Value) { 363 c.SetModuleCallArgumentCalled = true 364 c.SetModuleCallArgumentModuleCall = callAddr 365 c.SetModuleCallArgumentVariable = varAddr 366 c.SetModuleCallArgumentValue = v 367 if c.SetModuleCallArgumentFunc != nil { 368 c.SetModuleCallArgumentFunc(callAddr, varAddr, v) 369 } 370 } 371 372 func (c *MockEvalContext) GetVariableValue(addr addrs.AbsInputVariableInstance) cty.Value { 373 c.GetVariableValueCalled = true 374 c.GetVariableValueAddr = addr 375 if c.GetVariableValueFunc != nil { 376 return c.GetVariableValueFunc(addr) 377 } 378 return c.GetVariableValueValue 379 } 380 381 func (c *MockEvalContext) Changes() *plans.ChangesSync { 382 c.ChangesCalled = true 383 return c.ChangesChanges 384 } 385 386 func (c *MockEvalContext) State() *states.SyncState { 387 c.StateCalled = true 388 return c.StateState 389 } 390 391 func (c *MockEvalContext) Checks() *checks.State { 392 c.ChecksCalled = true 393 return c.ChecksState 394 } 395 396 func (c *MockEvalContext) RefreshState() *states.SyncState { 397 c.RefreshStateCalled = true 398 return c.RefreshStateState 399 } 400 401 func (c *MockEvalContext) PrevRunState() *states.SyncState { 402 c.PrevRunStateCalled = true 403 return c.PrevRunStateState 404 } 405 406 func (c *MockEvalContext) MoveResults() refactoring.MoveResults { 407 c.MoveResultsCalled = true 408 return c.MoveResultsResults 409 } 410 411 func (c *MockEvalContext) ImportResolver() *ImportResolver { 412 c.ImportResolverCalled = true 413 return c.ImportResolverResults 414 } 415 416 func (c *MockEvalContext) InstanceExpander() *instances.Expander { 417 c.InstanceExpanderCalled = true 418 return c.InstanceExpanderExpander 419 } 420 421 func (c *MockEvalContext) GetEncryption() encryption.Encryption { 422 return encryption.Disabled() 423 }