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  }