tofu: GraphNodeExecutable interface takes context.Context

In order to generate OpenTelemetry traces of the main work that OpenTofu
Core does we'll need to be able to propagate the active trace context into
the main "Execute" method of each graph node, since that's where we
typically make requests to providers, and other such work that could take
a noticeable amount of time.

Changing these frequently-used interfaces is always a noisy diff, so this
commit intentionally focuses only on changing the signature of that
interface and its one caller, and then dealing with all of the fallout of
that on existing unit test code.

For any use of Execute that was affected by this change we'll also switch
to our newer naming scheme of using "evalCtx" as the name of the
tofu.EvalContext variable, in preparation for using "ctx" idiomatically to
refer to context.Context. However, the implementations currently don't yet
name their context.Context argument because the method bodies don't yet
make use of it. We'll name each of those arguments to "ctx" individually
as we gradually add tracing support to each graph node type.

Signed-off-by: Martin Atkins <mart@degeneration.co.uk>
This commit is contained in:
Martin Atkins
2025-05-01 10:32:44 -07:00
parent 89296b438a
commit 84147b50e9
35 changed files with 305 additions and 271 deletions

View File

@@ -5,10 +5,14 @@
package tofu
import "github.com/opentofu/opentofu/internal/tfdiags"
import (
"context"
"github.com/opentofu/opentofu/internal/tfdiags"
)
// GraphNodeExecutable is the interface that graph nodes must implement to
// enable execution.
type GraphNodeExecutable interface {
Execute(EvalContext, walkOperation) tfdiags.Diagnostics
Execute(context.Context, EvalContext, walkOperation) tfdiags.Diagnostics
}

View File

@@ -82,7 +82,7 @@ func (g *Graph) walk(ctx context.Context, walker GraphWalker) tfdiags.Diagnostic
// If the node is exec-able, then execute it.
if ev, ok := v.(GraphNodeExecutable); ok {
diags = diags.Append(walker.Execute(vertexCtx, ev))
diags = diags.Append(walker.Execute(ctx, vertexCtx, ev))
if diags.HasErrors() {
return
}

View File

@@ -6,6 +6,8 @@
package tofu
import (
"context"
"github.com/opentofu/opentofu/internal/addrs"
"github.com/opentofu/opentofu/internal/tfdiags"
)
@@ -16,7 +18,7 @@ type GraphWalker interface {
EvalContext() EvalContext
EnterPath(addrs.ModuleInstance) EvalContext
ExitPath(addrs.ModuleInstance)
Execute(EvalContext, GraphNodeExecutable) tfdiags.Diagnostics
Execute(context.Context, EvalContext, GraphNodeExecutable) tfdiags.Diagnostics
}
// NullGraphWalker is a GraphWalker implementation that does nothing.
@@ -24,7 +26,9 @@ type GraphWalker interface {
// implementing all the required functions.
type NullGraphWalker struct{}
func (NullGraphWalker) EvalContext() EvalContext { return new(MockEvalContext) }
func (NullGraphWalker) EnterPath(addrs.ModuleInstance) EvalContext { return new(MockEvalContext) }
func (NullGraphWalker) ExitPath(addrs.ModuleInstance) {}
func (NullGraphWalker) Execute(EvalContext, GraphNodeExecutable) tfdiags.Diagnostics { return nil }
func (NullGraphWalker) EvalContext() EvalContext { return new(MockEvalContext) }
func (NullGraphWalker) EnterPath(addrs.ModuleInstance) EvalContext { return new(MockEvalContext) }
func (NullGraphWalker) ExitPath(addrs.ModuleInstance) {}
func (NullGraphWalker) Execute(context.Context, EvalContext, GraphNodeExecutable) tfdiags.Diagnostics {
return nil
}

View File

@@ -66,6 +66,8 @@ type ContextGraphWalker struct {
provisionerCache map[string]provisioners.Interface
}
var _ GraphWalker = (*ContextGraphWalker)(nil)
func (w *ContextGraphWalker) EnterPath(path addrs.ModuleInstance) EvalContext {
w.contextLock.Lock()
defer w.contextLock.Unlock()
@@ -141,10 +143,10 @@ func (w *ContextGraphWalker) init() {
}
}
func (w *ContextGraphWalker) Execute(ctx EvalContext, n GraphNodeExecutable) tfdiags.Diagnostics {
func (w *ContextGraphWalker) Execute(ctx context.Context, evalCtx EvalContext, n GraphNodeExecutable) tfdiags.Diagnostics {
// Acquire a lock on the semaphore
w.Context.parallelSem.Acquire()
defer w.Context.parallelSem.Release()
return n.Execute(ctx, w.Operation)
return n.Execute(ctx, evalCtx, w.Operation)
}

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"log"
"github.com/hashicorp/hcl/v2/hclsyntax"
@@ -40,15 +41,15 @@ func (n *nodeReportCheck) ModulePath() addrs.Module {
return n.addr.Module
}
func (n *nodeReportCheck) Execute(ctx EvalContext, _ walkOperation) tfdiags.Diagnostics {
exp := ctx.InstanceExpander()
func (n *nodeReportCheck) Execute(_ context.Context, evalCtx EvalContext, _ walkOperation) tfdiags.Diagnostics {
exp := evalCtx.InstanceExpander()
modInsts := exp.ExpandModule(n.ModulePath())
instAddrs := addrs.MakeSet[addrs.Checkable]()
for _, modAddr := range modInsts {
instAddrs.Add(n.addr.Check.Absolute(modAddr))
}
ctx.Checks().ReportCheckableObjects(n.addr, instAddrs)
evalCtx.Checks().ReportCheckableObjects(n.addr, instAddrs)
return nil
}
@@ -150,12 +151,12 @@ func (n *nodeCheckAssert) Path() addrs.ModuleInstance {
return n.addr.Module
}
func (n *nodeCheckAssert) Execute(ctx EvalContext, _ walkOperation) tfdiags.Diagnostics {
func (n *nodeCheckAssert) Execute(_ context.Context, evalCtx EvalContext, _ walkOperation) tfdiags.Diagnostics {
// We only want to actually execute the checks during specific
// operations, such as plan and applies.
if n.executeChecks {
if status := ctx.Checks().ObjectCheckStatus(n.addr); status == checks.StatusFail || status == checks.StatusError {
if status := evalCtx.Checks().ObjectCheckStatus(n.addr); status == checks.StatusFail || status == checks.StatusError {
// This check is already failing, so we won't try and evaluate it.
// This typically means there was an error in a data block within
// the check block.
@@ -165,7 +166,7 @@ func (n *nodeCheckAssert) Execute(ctx EvalContext, _ walkOperation) tfdiags.Diag
return evalCheckRules(
addrs.CheckAssertion,
n.config.Asserts,
ctx,
evalCtx,
n.addr,
EvalDataForNoInstanceKey,
tfdiags.Warning)
@@ -176,7 +177,7 @@ func (n *nodeCheckAssert) Execute(ctx EvalContext, _ walkOperation) tfdiags.Diag
// diagnostics if references do not exist etc.
var diags tfdiags.Diagnostics
for ix, assert := range n.config.Asserts {
_, _, moreDiags := validateCheckRule(addrs.NewCheckRule(n.addr, addrs.CheckAssertion, ix), assert, ctx, EvalDataForNoInstanceKey)
_, _, moreDiags := validateCheckRule(addrs.NewCheckRule(n.addr, addrs.CheckAssertion, ix), assert, evalCtx, EvalDataForNoInstanceKey)
diags = diags.Append(moreDiags)
}
return diags
@@ -195,7 +196,7 @@ var (
// dependency that can enforce this ordering.
type nodeCheckStart struct{}
func (n *nodeCheckStart) Execute(context EvalContext, operation walkOperation) tfdiags.Diagnostics {
func (n *nodeCheckStart) Execute(_ context.Context, _ EvalContext, _ walkOperation) tfdiags.Diagnostics {
// This node doesn't actually do anything, except simplify the underlying
// graph structure.
return nil

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"log"
"github.com/opentofu/opentofu/internal/tfdiags"
@@ -22,8 +23,8 @@ var (
)
// GraphNodeExecutable
func (n *NodeDestroyableDataResourceInstance) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics {
func (n *NodeDestroyableDataResourceInstance) Execute(ctx context.Context, evalCtx EvalContext, op walkOperation) tfdiags.Diagnostics {
log.Printf("[TRACE] NodeDestroyableDataResourceInstance: removing state object for %s", n.Addr)
ctx.State().SetResourceInstanceCurrent(n.Addr, nil, n.ResolvedProvider.ProviderConfig, nil)
evalCtx.State().SetResourceInstanceCurrent(n.Addr, nil, n.ResolvedProvider.ProviderConfig, nil)
return nil
}

View File

@@ -30,7 +30,7 @@ func TestNodeDataDestroyExecute(t *testing.T) {
},
addrs.NoKey,
)
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
StateState: state.SyncWrapper(),
}
@@ -42,7 +42,7 @@ func TestNodeDataDestroyExecute(t *testing.T) {
}.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance),
}}
diags := node.Execute(ctx, walkApply)
diags := node.Execute(t.Context(), evalCtx, walkApply)
if diags.HasErrors() {
t.Fatalf("unexpected error: %v", diags.Err())
}

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"fmt"
"log"
@@ -135,7 +136,7 @@ func (n *NodeLocal) References() []*addrs.Reference {
// NodeLocal.Execute is an Execute implementation that evaluates the
// expression for a local value and writes it into a transient part of
// the state.
func (n *NodeLocal) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
func (n *NodeLocal) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
expr := n.Config.Expr
addr := n.Addr.LocalValue
@@ -157,19 +158,19 @@ func (n *NodeLocal) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Di
return diags
}
val, moreDiags := ctx.EvaluateExpr(expr, cty.DynamicPseudoType, nil)
val, moreDiags := evalCtx.EvaluateExpr(expr, cty.DynamicPseudoType, nil)
diags = diags.Append(moreDiags)
if moreDiags.HasErrors() {
return diags
}
state := ctx.State()
state := evalCtx.State()
if state == nil {
diags = diags.Append(fmt.Errorf("cannot write local value to nil state"))
return diags
}
state.SetLocalValue(addr.Absolute(ctx.Path()), val)
state.SetLocalValue(addr.Absolute(evalCtx.Path()), val)
return diags
}

View File

@@ -56,13 +56,13 @@ func TestNodeLocalExecute(t *testing.T) {
Expr: expr,
},
}
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
StateState: states.NewState().SyncWrapper(),
EvaluateExprResult: hcl2shim.HCL2ValueFromConfigValue(test.Want),
}
err := n.Execute(ctx, walkApply)
err := n.Execute(t.Context(), evalCtx, walkApply)
if (err != nil) != test.Err {
if err != nil {
t.Errorf("unexpected error: %s", err)
@@ -71,7 +71,7 @@ func TestNodeLocalExecute(t *testing.T) {
}
}
ms := ctx.StateState.Module(addrs.RootModuleInstance)
ms := evalCtx.StateState.Module(addrs.RootModuleInstance)
gotLocals := ms.LocalValues
wantLocals := map[string]cty.Value{}
if test.Want != nil {

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"log"
"github.com/opentofu/opentofu/internal/addrs"
@@ -112,18 +113,18 @@ func (n *nodeExpandModule) ReferenceOutside() (selfPath, referencePath addrs.Mod
}
// GraphNodeExecutable
func (n *nodeExpandModule) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
expander := ctx.InstanceExpander()
func (n *nodeExpandModule) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
expander := evalCtx.InstanceExpander()
_, call := n.Addr.Call()
// nodeExpandModule itself does not have visibility into how its ancestors
// were expanded, so we use the expander here to provide all possible paths
// to our module, and register module instances with each of them.
for _, module := range expander.ExpandModule(n.Addr.Parent()) {
ctx = ctx.WithPath(module)
evalCtx = evalCtx.WithPath(module)
switch {
case n.ModuleCall.Count != nil:
count, ctDiags := evaluateCountExpression(n.ModuleCall.Count, ctx, module)
count, ctDiags := evaluateCountExpression(n.ModuleCall.Count, evalCtx, module)
diags = diags.Append(ctDiags)
if diags.HasErrors() {
return diags
@@ -131,7 +132,7 @@ func (n *nodeExpandModule) Execute(ctx EvalContext, op walkOperation) (diags tfd
expander.SetModuleCount(module, call, count)
case n.ModuleCall.ForEach != nil:
forEach, feDiags := evaluateForEachExpression(n.ModuleCall.ForEach, ctx, module)
forEach, feDiags := evaluateForEachExpression(n.ModuleCall.ForEach, evalCtx, module)
diags = diags.Append(feDiags)
if diags.HasErrors() {
return diags
@@ -202,19 +203,19 @@ func (n *nodeCloseModule) IsOverridden(addr addrs.Module) bool {
return modConfig.Module.IsOverridden
}
func (n *nodeCloseModule) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
func (n *nodeCloseModule) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
if !n.Addr.IsRoot() {
return
}
// If this is the root module, we are cleaning up the walk, so close
// any running provisioners
diags = diags.Append(ctx.CloseProvisioners())
diags = diags.Append(evalCtx.CloseProvisioners())
switch op {
case walkApply, walkDestroy:
state := ctx.State().Lock()
defer ctx.State().Unlock()
state := evalCtx.State().Lock()
defer evalCtx.State().Unlock()
for modKey, mod := range state.Modules {
// clean out any empty resources
@@ -246,33 +247,33 @@ type nodeValidateModule struct {
var _ GraphNodeExecutable = (*nodeValidateModule)(nil)
// GraphNodeEvalable
func (n *nodeValidateModule) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
func (n *nodeValidateModule) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
_, call := n.Addr.Call()
expander := ctx.InstanceExpander()
expander := evalCtx.InstanceExpander()
// Modules all evaluate to single instances during validation, only to
// create a proper context within which to evaluate. All parent modules
// will be a single instance, but still get our address in the expected
// manner anyway to ensure they've been registered correctly.
for _, module := range expander.ExpandModule(n.Addr.Parent()) {
ctx = ctx.WithPath(module)
evalCtx = evalCtx.WithPath(module)
// Validate our for_each and count expressions at a basic level
// We skip validation on known, because there will be unknown values before
// a full expansion, presuming these errors will be caught in later steps
switch {
case n.ModuleCall.Count != nil:
_, countDiags := evaluateCountExpressionValue(n.ModuleCall.Count, ctx)
_, countDiags := evaluateCountExpressionValue(n.ModuleCall.Count, evalCtx)
diags = diags.Append(countDiags)
case n.ModuleCall.ForEach != nil:
const unknownsAllowed = true
const tupleNotAllowed = false
_, forEachDiags := evaluateForEachExpressionValue(n.ModuleCall.ForEach, ctx, unknownsAllowed, tupleNotAllowed, module)
_, forEachDiags := evaluateForEachExpressionValue(n.ModuleCall.ForEach, evalCtx, unknownsAllowed, tupleNotAllowed, module)
diags = diags.Append(forEachDiags)
}
diags = diags.Append(validateDependsOn(ctx, n.ModuleCall.DependsOn))
diags = diags.Append(validateDependsOn(evalCtx, n.ModuleCall.DependsOn))
// now set our own mode to single
expander.SetModuleSingle(module, call)

View File

@@ -17,10 +17,10 @@ import (
)
func TestNodeExpandModuleExecute(t *testing.T) {
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
InstanceExpanderExpander: instances.NewExpander(),
}
ctx.installSimpleEval()
evalCtx.installSimpleEval()
node := nodeExpandModule{
Addr: addrs.Module{"child"},
@@ -29,12 +29,12 @@ func TestNodeExpandModuleExecute(t *testing.T) {
},
}
err := node.Execute(ctx, walkApply)
err := node.Execute(t.Context(), evalCtx, walkApply)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
if !ctx.InstanceExpanderCalled {
if !evalCtx.InstanceExpanderCalled {
t.Fatal("did not expand")
}
}
@@ -43,11 +43,11 @@ func TestNodeCloseModuleExecute(t *testing.T) {
t.Run("walkApply", func(t *testing.T) {
state := states.NewState()
state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey))
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
StateState: state.SyncWrapper(),
}
node := nodeCloseModule{Addr: addrs.Module{"child"}}
diags := node.Execute(ctx, walkApply)
diags := node.Execute(t.Context(), evalCtx, walkApply)
if diags.HasErrors() {
t.Fatalf("unexpected error: %s", diags.Err())
}
@@ -59,7 +59,7 @@ func TestNodeCloseModuleExecute(t *testing.T) {
// the root module should do all the module cleanup
node = nodeCloseModule{Addr: addrs.RootModule}
diags = node.Execute(ctx, walkApply)
diags = node.Execute(t.Context(), evalCtx, walkApply)
if diags.HasErrors() {
t.Fatalf("unexpected error: %s", diags.Err())
}
@@ -74,12 +74,12 @@ func TestNodeCloseModuleExecute(t *testing.T) {
t.Run("walkImport", func(t *testing.T) {
state := states.NewState()
state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey))
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
StateState: state.SyncWrapper(),
}
node := nodeCloseModule{Addr: addrs.Module{"child"}}
diags := node.Execute(ctx, walkImport)
diags := node.Execute(t.Context(), evalCtx, walkImport)
if diags.HasErrors() {
t.Fatalf("unexpected error: %s", diags.Err())
}
@@ -91,10 +91,10 @@ func TestNodeCloseModuleExecute(t *testing.T) {
func TestNodeValidateModuleExecute(t *testing.T) {
t.Run("success", func(t *testing.T) {
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
InstanceExpanderExpander: instances.NewExpander(),
}
ctx.installSimpleEval()
evalCtx.installSimpleEval()
node := nodeValidateModule{
nodeExpandModule{
Addr: addrs.Module{"child"},
@@ -104,17 +104,17 @@ func TestNodeValidateModuleExecute(t *testing.T) {
},
}
diags := node.Execute(ctx, walkApply)
diags := node.Execute(t.Context(), evalCtx, walkApply)
if diags.HasErrors() {
t.Fatalf("unexpected error: %v", diags.Err())
}
})
t.Run("invalid count", func(t *testing.T) {
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
InstanceExpanderExpander: instances.NewExpander(),
}
ctx.installSimpleEval()
evalCtx.installSimpleEval()
node := nodeValidateModule{
nodeExpandModule{
Addr: addrs.Module{"child"},
@@ -124,7 +124,7 @@ func TestNodeValidateModuleExecute(t *testing.T) {
},
}
err := node.Execute(ctx, walkApply)
err := node.Execute(t.Context(), evalCtx, walkApply)
if err == nil {
t.Fatal("expected error, got success")
}

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"fmt"
"log"
@@ -150,10 +151,10 @@ func (n *nodeModuleVariable) ModulePath() addrs.Module {
}
// GraphNodeExecutable
func (n *nodeModuleVariable) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
func (n *nodeModuleVariable) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
log.Printf("[TRACE] nodeModuleVariable: evaluating %s", n.Addr)
val, err := n.evalModuleVariable(ctx, op == walkValidate)
val, err := n.evalModuleVariable(evalCtx, op == walkValidate)
diags = diags.Append(err)
if diags.HasErrors() {
return diags
@@ -162,7 +163,7 @@ func (n *nodeModuleVariable) Execute(ctx EvalContext, op walkOperation) (diags t
// Set values for arguments of a child module call, for later retrieval
// during expression evaluation.
_, call := n.Addr.Module.CallInstance()
ctx.SetModuleCallArgument(call, n.Addr.Variable, val)
evalCtx.SetModuleCallArgument(call, n.Addr.Variable, val)
return diags
}

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"fmt"
"log"
@@ -302,13 +303,13 @@ func (n *NodeApplyableOutput) References() []*addrs.Reference {
}
// GraphNodeExecutable
func (n *NodeApplyableOutput) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
state := ctx.State()
func (n *NodeApplyableOutput) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
state := evalCtx.State()
if state == nil {
return
}
changes := ctx.Changes() // may be nil, if we're not working on a changeset
changes := evalCtx.Changes() // may be nil, if we're not working on a changeset
val := cty.UnknownVal(cty.DynamicPseudoType)
changeRecorded := n.Change != nil
@@ -332,7 +333,7 @@ func (n *NodeApplyableOutput) Execute(ctx EvalContext, op walkOperation) (diags
checkDiags := evalCheckRules(
addrs.OutputPrecondition,
n.Config.Preconditions,
ctx, n.Addr, EvalDataForNoInstanceKey,
evalCtx, n.Addr, EvalDataForNoInstanceKey,
checkRuleSeverity,
)
diags = diags.Append(checkDiags)
@@ -350,7 +351,7 @@ func (n *NodeApplyableOutput) Execute(ctx EvalContext, op walkOperation) (diags
// This has to run before we have a state lock, since evaluation also
// reads the state
var evalDiags tfdiags.Diagnostics
val, evalDiags = ctx.EvaluateExpr(n.Config.Expr, cty.DynamicPseudoType, nil)
val, evalDiags = evalCtx.EvaluateExpr(n.Config.Expr, cty.DynamicPseudoType, nil)
diags = diags.Append(evalDiags)
// If the module is being overridden and we have a value to use,
@@ -367,7 +368,7 @@ func (n *NodeApplyableOutput) Execute(ctx EvalContext, op walkOperation) (diags
// We'll handle errors below, after we have loaded the module.
// Outputs don't have a separate mode for validation, so validate
// depends_on expressions here too
diags = diags.Append(validateDependsOn(ctx, n.Config.DependsOn))
diags = diags.Append(validateDependsOn(evalCtx, n.Config.DependsOn))
// For root module outputs in particular, an output value must be
// statically declared as sensitive in order to dynamically return
@@ -419,7 +420,7 @@ If you do intend to export this data, annotate the output value as sensitive by
// If we were able to evaluate a new value, we can update that in the
// refreshed state as well.
if state = ctx.RefreshState(); state != nil && val.IsWhollyKnown() {
if state = evalCtx.RefreshState(); state != nil && val.IsWhollyKnown() {
// we only need to update the state, do not pass in the changes again
n.setValue(state, nil, val)
}
@@ -465,8 +466,8 @@ func (n *NodeDestroyableOutput) temporaryValue() bool {
}
// GraphNodeExecutable
func (n *NodeDestroyableOutput) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics {
state := ctx.State()
func (n *NodeDestroyableOutput) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) tfdiags.Diagnostics {
state := evalCtx.State()
if state == nil {
return nil
}
@@ -488,7 +489,7 @@ func (n *NodeDestroyableOutput) Execute(ctx EvalContext, op walkOperation) tfdia
}
}
changes := ctx.Changes()
changes := evalCtx.Changes()
if changes != nil && n.Planning {
change := &plans.OutputChange{
Addr: n.Addr,

View File

@@ -20,10 +20,10 @@ import (
)
func TestNodeApplyableOutputExecute_knownValue(t *testing.T) {
ctx := new(MockEvalContext)
ctx.StateState = states.NewState().SyncWrapper()
ctx.RefreshStateState = states.NewState().SyncWrapper()
ctx.ChecksState = checks.NewState(nil)
evalCtx := new(MockEvalContext)
evalCtx.StateState = states.NewState().SyncWrapper()
evalCtx.RefreshStateState = states.NewState().SyncWrapper()
evalCtx.ChecksState = checks.NewState(nil)
config := &configs.Output{Name: "map-output"}
addr := addrs.OutputValue{Name: config.Name}.Absolute(addrs.RootModuleInstance)
@@ -31,29 +31,29 @@ func TestNodeApplyableOutputExecute_knownValue(t *testing.T) {
val := cty.MapVal(map[string]cty.Value{
"a": cty.StringVal("b"),
})
ctx.EvaluateExprResult = val
evalCtx.EvaluateExprResult = val
err := node.Execute(ctx, walkApply)
err := node.Execute(t.Context(), evalCtx, walkApply)
if err != nil {
t.Fatalf("unexpected execute error: %s", err)
}
outputVal := ctx.StateState.OutputValue(addr)
outputVal := evalCtx.StateState.OutputValue(addr)
if got, want := outputVal.Value, val; !got.RawEquals(want) {
t.Errorf("wrong output value in state\n got: %#v\nwant: %#v", got, want)
}
if !ctx.RefreshStateCalled {
if !evalCtx.RefreshStateCalled {
t.Fatal("should have called RefreshState, but didn't")
}
refreshOutputVal := ctx.RefreshStateState.OutputValue(addr)
refreshOutputVal := evalCtx.RefreshStateState.OutputValue(addr)
if got, want := refreshOutputVal.Value, val; !got.RawEquals(want) {
t.Fatalf("wrong output value in refresh state\n got: %#v\nwant: %#v", got, want)
}
}
func TestNodeApplyableOutputExecute_noState(t *testing.T) {
ctx := new(MockEvalContext)
evalCtx := new(MockEvalContext)
config := &configs.Output{Name: "map-output"}
addr := addrs.OutputValue{Name: config.Name}.Absolute(addrs.RootModuleInstance)
@@ -61,18 +61,18 @@ func TestNodeApplyableOutputExecute_noState(t *testing.T) {
val := cty.MapVal(map[string]cty.Value{
"a": cty.StringVal("b"),
})
ctx.EvaluateExprResult = val
evalCtx.EvaluateExprResult = val
err := node.Execute(ctx, walkApply)
err := node.Execute(t.Context(), evalCtx, walkApply)
if err != nil {
t.Fatalf("unexpected execute error: %s", err)
}
}
func TestNodeApplyableOutputExecute_invalidDependsOn(t *testing.T) {
ctx := new(MockEvalContext)
ctx.StateState = states.NewState().SyncWrapper()
ctx.ChecksState = checks.NewState(nil)
evalCtx := new(MockEvalContext)
evalCtx.StateState = states.NewState().SyncWrapper()
evalCtx.ChecksState = checks.NewState(nil)
config := &configs.Output{
Name: "map-output",
@@ -89,9 +89,9 @@ func TestNodeApplyableOutputExecute_invalidDependsOn(t *testing.T) {
val := cty.MapVal(map[string]cty.Value{
"a": cty.StringVal("b"),
})
ctx.EvaluateExprResult = val
evalCtx.EvaluateExprResult = val
diags := node.Execute(ctx, walkApply)
diags := node.Execute(t.Context(), evalCtx, walkApply)
if !diags.HasErrors() {
t.Fatal("expected execute error, but there was none")
}
@@ -101,9 +101,9 @@ func TestNodeApplyableOutputExecute_invalidDependsOn(t *testing.T) {
}
func TestNodeApplyableOutputExecute_sensitiveValueNotOutput(t *testing.T) {
ctx := new(MockEvalContext)
ctx.StateState = states.NewState().SyncWrapper()
ctx.ChecksState = checks.NewState(nil)
evalCtx := new(MockEvalContext)
evalCtx.StateState = states.NewState().SyncWrapper()
evalCtx.ChecksState = checks.NewState(nil)
config := &configs.Output{Name: "map-output"}
addr := addrs.OutputValue{Name: config.Name}.Absolute(addrs.RootModuleInstance)
@@ -111,9 +111,9 @@ func TestNodeApplyableOutputExecute_sensitiveValueNotOutput(t *testing.T) {
val := cty.MapVal(map[string]cty.Value{
"a": cty.StringVal("b").Mark(marks.Sensitive),
})
ctx.EvaluateExprResult = val
evalCtx.EvaluateExprResult = val
diags := node.Execute(ctx, walkApply)
diags := node.Execute(t.Context(), evalCtx, walkApply)
if !diags.HasErrors() {
t.Fatal("expected execute error, but there was none")
}
@@ -123,9 +123,9 @@ func TestNodeApplyableOutputExecute_sensitiveValueNotOutput(t *testing.T) {
}
func TestNodeApplyableOutputExecute_deprecatedOutput(t *testing.T) {
ctx := new(MockEvalContext)
ctx.StateState = states.NewState().SyncWrapper()
ctx.ChecksState = checks.NewState(nil)
evalCtx := new(MockEvalContext)
evalCtx.StateState = states.NewState().SyncWrapper()
evalCtx.ChecksState = checks.NewState(nil)
config := &configs.Output{Name: "map-output"}
addr := addrs.OutputValue{Name: config.Name}.Absolute(addrs.RootModuleInstance)
@@ -133,13 +133,13 @@ func TestNodeApplyableOutputExecute_deprecatedOutput(t *testing.T) {
val := cty.MapVal(map[string]cty.Value{
"a": marks.Deprecated(cty.StringVal("b"), marks.DeprecationCause{}),
})
ctx.EvaluateExprResult = val
evalCtx.EvaluateExprResult = val
// We set a value with no deprecation marks to check if the marks
// will be updated in the state.
ctx.StateState.SetOutputValue(addr, marks.RemoveDeepDeprecated(val), false, "")
evalCtx.StateState.SetOutputValue(addr, marks.RemoveDeepDeprecated(val), false, "")
diags := node.Execute(ctx, walkApply)
diags := node.Execute(t.Context(), evalCtx, walkApply)
if diags.HasErrors() {
t.Fatalf("Got unexpected error: %v", diags)
}
@@ -149,7 +149,7 @@ func TestNodeApplyableOutputExecute_deprecatedOutput(t *testing.T) {
t.Fatalf("Invalid mod addr in test: %v", diags)
}
stateVal := ctx.StateState.OutputValue(modOutputAddr)
stateVal := evalCtx.StateState.OutputValue(modOutputAddr)
_, pvms := stateVal.Value.UnmarkDeepWithPaths()
if len(pvms) != 1 {
@@ -162,9 +162,9 @@ func TestNodeApplyableOutputExecute_deprecatedOutput(t *testing.T) {
}
func TestNodeApplyableOutputExecute_alternativelyMarkedValue(t *testing.T) {
ctx := new(MockEvalContext)
ctx.StateState = states.NewState().SyncWrapper()
ctx.ChecksState = checks.NewState(nil)
evalCtx := new(MockEvalContext)
evalCtx.StateState = states.NewState().SyncWrapper()
evalCtx.ChecksState = checks.NewState(nil)
config := &configs.Output{Name: "map-output"}
addr := addrs.OutputValue{Name: config.Name}.Absolute(addrs.RootModuleInstance)
@@ -172,9 +172,9 @@ func TestNodeApplyableOutputExecute_alternativelyMarkedValue(t *testing.T) {
val := cty.MapVal(map[string]cty.Value{
"a": cty.StringVal("b").Mark("alternative-mark"),
})
ctx.EvaluateExprResult = val
evalCtx.EvaluateExprResult = val
diags := node.Execute(ctx, walkApply)
diags := node.Execute(t.Context(), evalCtx, walkApply)
if diags.HasErrors() {
t.Fatalf("Got unexpected error: %v", diags)
}
@@ -184,7 +184,7 @@ func TestNodeApplyableOutputExecute_alternativelyMarkedValue(t *testing.T) {
t.Fatalf("Invalid mod addr in test: %v", diags)
}
stateVal := ctx.StateState.OutputValue(modOutputAddr)
stateVal := evalCtx.StateState.OutputValue(modOutputAddr)
_, pvms := stateVal.Value.UnmarkDeepWithPaths()
if len(pvms) != 1 {
@@ -199,9 +199,9 @@ func TestNodeApplyableOutputExecute_alternativelyMarkedValue(t *testing.T) {
}
func TestNodeApplyableOutputExecute_sensitiveValueAndOutput(t *testing.T) {
ctx := new(MockEvalContext)
ctx.StateState = states.NewState().SyncWrapper()
ctx.ChecksState = checks.NewState(nil)
evalCtx := new(MockEvalContext)
evalCtx.StateState = states.NewState().SyncWrapper()
evalCtx.ChecksState = checks.NewState(nil)
config := &configs.Output{
Name: "map-output",
@@ -212,15 +212,15 @@ func TestNodeApplyableOutputExecute_sensitiveValueAndOutput(t *testing.T) {
val := cty.MapVal(map[string]cty.Value{
"a": cty.StringVal("b").Mark(marks.Sensitive),
})
ctx.EvaluateExprResult = val
evalCtx.EvaluateExprResult = val
err := node.Execute(ctx, walkApply)
err := node.Execute(t.Context(), evalCtx, walkApply)
if err != nil {
t.Fatalf("unexpected execute error: %s", err)
}
// Unmarked value should be stored in state
outputVal := ctx.StateState.OutputValue(addr)
outputVal := evalCtx.StateState.OutputValue(addr)
want, _ := val.UnmarkDeep()
if got := outputVal.Value; !got.RawEquals(want) {
t.Errorf("wrong output value in state\n got: %#v\nwant: %#v", got, want)
@@ -234,12 +234,12 @@ func TestNodeDestroyableOutputExecute(t *testing.T) {
state.Module(addrs.RootModuleInstance).SetOutputValue("foo", cty.StringVal("bar"), false, "")
state.OutputValue(outputAddr)
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
StateState: state.SyncWrapper(),
}
node := NodeDestroyableOutput{Addr: outputAddr}
diags := node.Execute(ctx, walkApply)
diags := node.Execute(t.Context(), evalCtx, walkApply)
if diags.HasErrors() {
t.Fatalf("Unexpected error: %s", diags.Err())
}
@@ -253,12 +253,12 @@ func TestNodeDestroyableOutputExecute_notInState(t *testing.T) {
state := states.NewState()
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
StateState: state.SyncWrapper(),
}
node := NodeDestroyableOutput{Addr: outputAddr}
diags := node.Execute(ctx, walkApply)
diags := node.Execute(t.Context(), evalCtx, walkApply)
if diags.HasErrors() {
t.Fatalf("Unexpected error: %s", diags.Err())
}

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"fmt"
"log"
@@ -27,11 +28,11 @@ var (
)
// GraphNodeExecutable
func (n *NodeApplyableProvider) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics {
instances, diags := n.initInstances(ctx, op)
func (n *NodeApplyableProvider) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) tfdiags.Diagnostics {
instances, diags := n.initInstances(evalCtx, op)
for key, provider := range instances {
diags = diags.Append(n.executeInstance(ctx, op, key, provider))
diags = diags.Append(n.executeInstance(evalCtx, op, key, provider))
}
return diags

View File

@@ -6,6 +6,8 @@
package tofu
import (
"context"
"github.com/opentofu/opentofu/internal/addrs"
"github.com/opentofu/opentofu/internal/tfdiags"
)
@@ -21,7 +23,7 @@ type NodeEvalableProvider struct {
var _ GraphNodeExecutable = (*NodeEvalableProvider)(nil)
// GraphNodeExecutable
func (n *NodeEvalableProvider) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
_, err := ctx.InitProvider(n.Addr, addrs.NoKey)
func (n *NodeEvalableProvider) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
_, err := evalCtx.InitProvider(n.Addr, addrs.NoKey)
return diags.Append(err)
}

View File

@@ -51,21 +51,21 @@ func TestNodeApplyableProviderExecute(t *testing.T) {
Config: config,
}}
ctx := &MockEvalContext{ProviderProvider: provider}
ctx.installSimpleEval()
ctx.ProviderInputValues = map[string]cty.Value{
evalCtx := &MockEvalContext{ProviderProvider: provider}
evalCtx.installSimpleEval()
evalCtx.ProviderInputValues = map[string]cty.Value{
"pw": cty.StringVal("so secret"),
}
if diags := n.Execute(ctx, walkApply); diags.HasErrors() {
if diags := n.Execute(t.Context(), evalCtx, walkApply); diags.HasErrors() {
t.Fatalf("err: %s", diags.Err())
}
if !ctx.ConfigureProviderCalled {
if !evalCtx.ConfigureProviderCalled {
t.Fatal("should be called")
}
gotObj := ctx.ConfigureProviderConfig
gotObj := evalCtx.ConfigureProviderConfig
if !gotObj.Type().HasAttribute("user") {
t.Fatal("configuration object does not have \"user\" attribute")
}
@@ -98,10 +98,10 @@ func TestNodeApplyableProviderExecute_unknownImport(t *testing.T) {
Config: config,
}}
ctx := &MockEvalContext{ProviderProvider: provider}
ctx.installSimpleEval()
evalCtx := &MockEvalContext{ProviderProvider: provider}
evalCtx.installSimpleEval()
diags := n.Execute(ctx, walkImport)
diags := n.Execute(t.Context(), evalCtx, walkImport)
if !diags.HasErrors() {
t.Fatal("expected error, got success")
}
@@ -111,7 +111,7 @@ func TestNodeApplyableProviderExecute_unknownImport(t *testing.T) {
t.Errorf("wrong diagnostic detail\n got: %q\nwant: %q", got, want)
}
if ctx.ConfigureProviderCalled {
if evalCtx.ConfigureProviderCalled {
t.Fatal("should not be called")
}
}
@@ -132,18 +132,18 @@ func TestNodeApplyableProviderExecute_unknownApply(t *testing.T) {
Addr: providerAddr,
Config: config,
}}
ctx := &MockEvalContext{ProviderProvider: provider}
ctx.installSimpleEval()
evalCtx := &MockEvalContext{ProviderProvider: provider}
evalCtx.installSimpleEval()
if err := n.Execute(ctx, walkApply); err != nil {
if err := n.Execute(t.Context(), evalCtx, walkApply); err != nil {
t.Fatalf("err: %s", err)
}
if !ctx.ConfigureProviderCalled {
if !evalCtx.ConfigureProviderCalled {
t.Fatal("should be called")
}
gotObj := ctx.ConfigureProviderConfig
gotObj := evalCtx.ConfigureProviderConfig
if !gotObj.Type().HasAttribute("test_string") {
t.Fatal("configuration object does not have \"test_string\" attribute")
}
@@ -170,17 +170,17 @@ func TestNodeApplyableProviderExecute_sensitive(t *testing.T) {
Config: config,
}}
ctx := &MockEvalContext{ProviderProvider: provider}
ctx.installSimpleEval()
if err := n.Execute(ctx, walkApply); err != nil {
evalCtx := &MockEvalContext{ProviderProvider: provider}
evalCtx.installSimpleEval()
if err := n.Execute(t.Context(), evalCtx, walkApply); err != nil {
t.Fatalf("err: %s", err)
}
if !ctx.ConfigureProviderCalled {
if !evalCtx.ConfigureProviderCalled {
t.Fatal("should be called")
}
gotObj := ctx.ConfigureProviderConfig
gotObj := evalCtx.ConfigureProviderConfig
if !gotObj.Type().HasAttribute("test_string") {
t.Fatal("configuration object does not have \"test_string\" attribute")
}
@@ -207,9 +207,9 @@ func TestNodeApplyableProviderExecute_sensitiveValidate(t *testing.T) {
Config: config,
}}
ctx := &MockEvalContext{ProviderProvider: provider}
ctx.installSimpleEval()
if err := n.Execute(ctx, walkValidate); err != nil {
evalCtx := &MockEvalContext{ProviderProvider: provider}
evalCtx.installSimpleEval()
if err := n.Execute(t.Context(), evalCtx, walkValidate); err != nil {
t.Fatalf("err: %s", err)
}
@@ -249,13 +249,13 @@ func TestNodeApplyableProviderExecute_emptyValidate(t *testing.T) {
Config: config,
}}
ctx := &MockEvalContext{ProviderProvider: provider}
ctx.installSimpleEval()
if err := n.Execute(ctx, walkValidate); err != nil {
evalCtx := &MockEvalContext{ProviderProvider: provider}
evalCtx.installSimpleEval()
if err := n.Execute(t.Context(), evalCtx, walkValidate); err != nil {
t.Fatalf("err: %s", err)
}
if ctx.ConfigureProviderCalled {
if evalCtx.ConfigureProviderCalled {
t.Fatal("should not be called")
}
}

View File

@@ -6,6 +6,8 @@
package tofu
import (
"context"
"github.com/opentofu/opentofu/internal/addrs"
"github.com/opentofu/opentofu/internal/tfdiags"
)
@@ -19,6 +21,7 @@ type nodeExpandApplyableResource struct {
}
var (
_ GraphNodeExecutable = (*nodeExpandApplyableResource)(nil)
_ GraphNodeReferenceable = (*nodeExpandApplyableResource)(nil)
_ GraphNodeReferencer = (*nodeExpandApplyableResource)(nil)
_ GraphNodeConfigResource = (*nodeExpandApplyableResource)(nil)
@@ -48,13 +51,13 @@ func (n *nodeExpandApplyableResource) Name() string {
return n.NodeAbstractResource.Name() + " (expand)"
}
func (n *nodeExpandApplyableResource) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics {
func (n *nodeExpandApplyableResource) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
expander := ctx.InstanceExpander()
expander := evalCtx.InstanceExpander()
moduleInstances := expander.ExpandModule(n.Addr.Module)
for _, module := range moduleInstances {
ctx = ctx.WithPath(module)
diags = diags.Append(n.writeResourceState(ctx, n.Addr.Resource.Absolute(module)))
evalCtx = evalCtx.WithPath(module)
diags = diags.Append(n.writeResourceState(evalCtx, n.Addr.Resource.Absolute(module)))
}
return diags

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"fmt"
"log"
@@ -116,14 +117,14 @@ func (n *NodeApplyableResourceInstance) AttachDependencies(deps []addrs.ConfigRe
}
// GraphNodeExecutable
func (n *NodeApplyableResourceInstance) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
func (n *NodeApplyableResourceInstance) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
addr := n.ResourceInstanceAddr()
if n.Config == nil {
// If there is no config, and there is no change, then we have nothing
// to do and the change was left in the plan for informational
// purposes only.
changes := ctx.Changes()
changes := evalCtx.Changes()
csrc := changes.GetResourceInstanceChange(n.ResourceInstanceAddr(), states.CurrentGen)
if csrc == nil || csrc.Action == plans.NoOp {
log.Printf("[DEBUG] NodeApplyableResourceInstance: No config or planned change recorded for %s", n.Addr)
@@ -141,7 +142,7 @@ func (n *NodeApplyableResourceInstance) Execute(ctx EvalContext, op walkOperatio
return diags
}
diags = n.resolveProvider(ctx, true, states.NotDeposed)
diags = n.resolveProvider(evalCtx, true, states.NotDeposed)
if diags.HasErrors() {
return diags
}
@@ -149,9 +150,9 @@ func (n *NodeApplyableResourceInstance) Execute(ctx EvalContext, op walkOperatio
// Eval info is different depending on what kind of resource this is
switch n.Config.Mode {
case addrs.ManagedResourceMode:
return n.managedResourceExecute(ctx)
return n.managedResourceExecute(evalCtx)
case addrs.DataResourceMode:
return n.dataResourceExecute(ctx)
return n.dataResourceExecute(evalCtx)
default:
panic(fmt.Errorf("unsupported resource mode %s", n.Config.Mode))
}

View File

@@ -17,7 +17,7 @@ import (
func TestNodeExpandApplyableResourceExecute(t *testing.T) {
state := states.NewState()
t.Run("no config", func(t *testing.T) {
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
StateState: state.SyncWrapper(),
InstanceExpanderExpander: instances.NewExpander(),
}
@@ -28,7 +28,7 @@ func TestNodeExpandApplyableResourceExecute(t *testing.T) {
Config: nil,
},
}
diags := node.Execute(ctx, walkApply)
diags := node.Execute(t.Context(), evalCtx, walkApply)
if diags.HasErrors() {
t.Fatalf("unexpected error: %s", diags.Err())
}
@@ -40,7 +40,7 @@ func TestNodeExpandApplyableResourceExecute(t *testing.T) {
})
t.Run("simple", func(t *testing.T) {
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
StateState: state.SyncWrapper(),
InstanceExpanderExpander: instances.NewExpander(),
}
@@ -59,7 +59,7 @@ func TestNodeExpandApplyableResourceExecute(t *testing.T) {
}},
},
}
diags := node.Execute(ctx, walkApply)
diags := node.Execute(t.Context(), evalCtx, walkApply)
if diags.HasErrors() {
t.Fatalf("unexpected error: %s", diags.Err())
}

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"fmt"
"log"
@@ -86,16 +87,16 @@ func (n *NodePlanDeposedResourceInstanceObject) References() []*addrs.Reference
}
// GraphNodeEvalable impl.
func (n *NodePlanDeposedResourceInstanceObject) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
func (n *NodePlanDeposedResourceInstanceObject) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
log.Printf("[TRACE] NodePlanDeposedResourceInstanceObject: planning %s deposed object %s", n.Addr, n.DeposedKey)
diags = n.resolveProvider(ctx, false, n.DeposedKey)
diags = n.resolveProvider(evalCtx, false, n.DeposedKey)
if diags.HasErrors() {
return diags
}
// Read the state for the deposed resource instance
state, err := n.readResourceInstanceStateDeposed(ctx, n.Addr, n.DeposedKey)
state, err := n.readResourceInstanceStateDeposed(evalCtx, n.Addr, n.DeposedKey)
diags = diags.Append(err)
if diags.HasErrors() {
return diags
@@ -103,13 +104,13 @@ func (n *NodePlanDeposedResourceInstanceObject) Execute(ctx EvalContext, op walk
// Note any upgrades that readResourceInstanceState might've done in the
// prevRunState, so that it'll conform to current schema.
diags = diags.Append(n.writeResourceInstanceStateDeposed(ctx, n.DeposedKey, state, prevRunState))
diags = diags.Append(n.writeResourceInstanceStateDeposed(evalCtx, n.DeposedKey, state, prevRunState))
if diags.HasErrors() {
return diags
}
// Also the refreshState, because that should still reflect schema upgrades
// even if not refreshing.
diags = diags.Append(n.writeResourceInstanceStateDeposed(ctx, n.DeposedKey, state, refreshState))
diags = diags.Append(n.writeResourceInstanceStateDeposed(evalCtx, n.DeposedKey, state, refreshState))
if diags.HasErrors() {
return diags
}
@@ -127,13 +128,13 @@ func (n *NodePlanDeposedResourceInstanceObject) Execute(ctx EvalContext, op walk
// resource during Delete correctly. If this is a simple refresh,
// OpenTofu is expected to remove the missing resource from the state
// entirely
refreshedState, refreshDiags := n.refresh(ctx, n.DeposedKey, state)
refreshedState, refreshDiags := n.refresh(evalCtx, n.DeposedKey, state)
diags = diags.Append(refreshDiags)
if diags.HasErrors() {
return diags
}
diags = diags.Append(n.writeResourceInstanceStateDeposed(ctx, n.DeposedKey, refreshedState, refreshState))
diags = diags.Append(n.writeResourceInstanceStateDeposed(evalCtx, n.DeposedKey, refreshedState, refreshState))
if diags.HasErrors() {
return diags
}
@@ -159,17 +160,17 @@ func (n *NodePlanDeposedResourceInstanceObject) Execute(ctx EvalContext, op walk
if shouldForget {
if shouldDestroy {
change, planDiags = n.planDestroy(ctx, state, n.DeposedKey)
change, planDiags = n.planDestroy(evalCtx, state, n.DeposedKey)
} else {
diags = diags.Append(&hcl.Diagnostic{
Severity: hcl.DiagWarning,
Summary: "Resource going to be removed from the state",
Detail: fmt.Sprintf("After this plan gets applied, the resource %s will not be managed anymore by OpenTofu.\n\nIn case you want to manage the resource again, you will have to import it.", n.Addr),
})
change = n.planForget(ctx, state, n.DeposedKey)
change = n.planForget(evalCtx, state, n.DeposedKey)
}
} else {
change, planDiags = n.planDestroy(ctx, state, n.DeposedKey)
change, planDiags = n.planDestroy(evalCtx, state, n.DeposedKey)
}
diags = diags.Append(planDiags)
@@ -185,16 +186,16 @@ func (n *NodePlanDeposedResourceInstanceObject) Execute(ctx EvalContext, op walk
// now just need to get the deposed object destroyed, because there
// should be a new object already serving as its replacement.
diags = diags.Append(n.writeChange(ctx, change, n.DeposedKey))
diags = diags.Append(n.writeChange(evalCtx, change, n.DeposedKey))
if diags.HasErrors() {
return diags
}
diags = diags.Append(n.writeResourceInstanceStateDeposed(ctx, n.DeposedKey, nil, workingState))
diags = diags.Append(n.writeResourceInstanceStateDeposed(evalCtx, n.DeposedKey, nil, workingState))
} else {
// The working state should at least be updated with the result
// of upgrading and refreshing from above.
diags = diags.Append(n.writeResourceInstanceStateDeposed(ctx, n.DeposedKey, state, workingState))
diags = diags.Append(n.writeResourceInstanceStateDeposed(evalCtx, n.DeposedKey, state, workingState))
}
return diags
@@ -267,16 +268,16 @@ func (n *NodeDestroyDeposedResourceInstanceObject) ModifyCreateBeforeDestroy(v b
}
// GraphNodeExecutable impl.
func (n *NodeDestroyDeposedResourceInstanceObject) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
func (n *NodeDestroyDeposedResourceInstanceObject) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
var change *plans.ResourceInstanceChange
diags = n.resolveProvider(ctx, false, n.DeposedKey)
diags = n.resolveProvider(evalCtx, false, n.DeposedKey)
if diags.HasErrors() {
return diags
}
// Read the state for the deposed resource instance
state, err := n.readResourceInstanceStateDeposed(ctx, n.Addr, n.DeposedKey)
state, err := n.readResourceInstanceStateDeposed(evalCtx, n.Addr, n.DeposedKey)
if err != nil {
return diags.Append(err)
}
@@ -286,35 +287,35 @@ func (n *NodeDestroyDeposedResourceInstanceObject) Execute(ctx EvalContext, op w
return diags
}
change, destroyPlanDiags := n.planDestroy(ctx, state, n.DeposedKey)
change, destroyPlanDiags := n.planDestroy(evalCtx, state, n.DeposedKey)
diags = diags.Append(destroyPlanDiags)
if diags.HasErrors() {
return diags
}
// Call pre-apply hook
diags = diags.Append(n.preApplyHook(ctx, change))
diags = diags.Append(n.preApplyHook(evalCtx, change))
if diags.HasErrors() {
return diags
}
// we pass a nil configuration to apply because we are destroying
state, applyDiags := n.apply(ctx, state, change, nil, instances.RepetitionData{}, false)
state, applyDiags := n.apply(evalCtx, state, change, nil, instances.RepetitionData{}, false)
diags = diags.Append(applyDiags)
// don't return immediately on errors, we need to handle the state
// Always write the resource back to the state deposed. If it
// was successfully destroyed it will be pruned. If it was not, it will
// be caught on the next run.
writeDiags := n.writeResourceInstanceState(ctx, state)
writeDiags := n.writeResourceInstanceState(evalCtx, state)
diags.Append(writeDiags)
if diags.HasErrors() {
return diags
}
diags = diags.Append(n.postApplyHook(ctx, state, diags.Err()))
diags = diags.Append(n.postApplyHook(evalCtx, state, diags.Err()))
return diags.Append(updateStateHook(ctx))
return diags.Append(updateStateHook(evalCtx))
}
// GraphNodeDeposer is an optional interface implemented by graph nodes that
@@ -421,14 +422,14 @@ func (n *NodeForgetDeposedResourceInstanceObject) References() []*addrs.Referenc
}
// GraphNodeExecutable impl.
func (n *NodeForgetDeposedResourceInstanceObject) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
diags = n.resolveProvider(ctx, false, n.DeposedKey)
func (n *NodeForgetDeposedResourceInstanceObject) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
diags = n.resolveProvider(evalCtx, false, n.DeposedKey)
if diags.HasErrors() {
return diags
}
// Read the state for the deposed resource instance
state, err := n.readResourceInstanceStateDeposed(ctx, n.Addr, n.DeposedKey)
state, err := n.readResourceInstanceStateDeposed(evalCtx, n.Addr, n.DeposedKey)
if err != nil {
return diags.Append(err)
}
@@ -437,8 +438,8 @@ func (n *NodeForgetDeposedResourceInstanceObject) Execute(ctx EvalContext, op wa
log.Printf("[WARN] NodeForgetDeposedResourceInstanceObject for %s (%s) with no state", n.Addr, n.DeposedKey)
}
contextState := ctx.State()
contextState := evalCtx.State()
contextState.ForgetResourceInstanceDeposed(n.Addr, n.DeposedKey)
return diags.Append(updateStateHook(ctx))
return diags.Append(updateStateHook(evalCtx))
}

View File

@@ -195,7 +195,7 @@ func TestNodePlanDeposedResourceInstanceObject_Execute(t *testing.T) {
deposedKey := states.NewDeposedKey()
absResource := mustResourceInstanceAddr(test.nodeAddress)
ctx, p := initMockEvalContext(test.nodeAddress, deposedKey)
evalCtx, p := initMockEvalContext(test.nodeAddress, deposedKey)
node := NodePlanDeposedResourceInstanceObject{
NodeAbstractResourceInstance: &NodeAbstractResourceInstance{
@@ -208,7 +208,7 @@ func TestNodePlanDeposedResourceInstanceObject_Execute(t *testing.T) {
RemoveStatements: test.nodeEndpointsToRemove,
}
gotDiags := node.Execute(ctx, walkPlan)
gotDiags := node.Execute(t.Context(), evalCtx, walkPlan)
assertDiags(t, gotDiags, test.wantDiags)
if !p.UpgradeResourceStateCalled {
@@ -218,7 +218,7 @@ func TestNodePlanDeposedResourceInstanceObject_Execute(t *testing.T) {
t.Errorf("ReadResource wasn't called; should've been called to refresh the deposed object")
}
change := ctx.Changes().GetResourceInstanceChange(absResource, deposedKey)
change := evalCtx.Changes().GetResourceInstanceChange(absResource, deposedKey)
if got, want := change.ChangeSrc.Action, test.wantAction; got != want {
t.Fatalf("wrong planned action\ngot: %s\nwant: %s", got, want)
}
@@ -230,7 +230,7 @@ func TestNodeDestroyDeposedResourceInstanceObject_Execute(t *testing.T) {
deposedKey := states.NewDeposedKey()
state := states.NewState()
absResourceAddr := "test_instance.foo"
ctx, _ := initMockEvalContext(absResourceAddr, deposedKey)
evalCtx, _ := initMockEvalContext(absResourceAddr, deposedKey)
absResource := mustResourceInstanceAddr(absResourceAddr)
node := NodeDestroyDeposedResourceInstanceObject{
@@ -242,7 +242,7 @@ func TestNodeDestroyDeposedResourceInstanceObject_Execute(t *testing.T) {
},
DeposedKey: deposedKey,
}
err := node.Execute(ctx, walkApply)
err := node.Execute(t.Context(), evalCtx, walkApply)
if err != nil {
t.Fatalf("unexpected error: %s", err)
@@ -299,7 +299,7 @@ aws_instance.foo: (1 deposed)
func TestNodeDestroyDeposedResourceInstanceObject_ExecuteMissingState(t *testing.T) {
p := simpleMockProvider()
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
StateState: states.NewState().SyncWrapper(),
ProviderProvider: simpleMockProvider(),
ProviderSchemaSchema: p.GetProviderSchema(),
@@ -315,7 +315,7 @@ func TestNodeDestroyDeposedResourceInstanceObject_ExecuteMissingState(t *testing
},
DeposedKey: states.NewDeposedKey(),
}
err := node.Execute(ctx, walkApply)
err := node.Execute(t.Context(), evalCtx, walkApply)
if err == nil {
t.Fatal("expected error")
@@ -326,7 +326,7 @@ func TestNodeForgetDeposedResourceInstanceObject_Execute(t *testing.T) {
deposedKey := states.NewDeposedKey()
state := states.NewState()
absResourceAddr := "test_instance.foo"
ctx, _ := initMockEvalContext(absResourceAddr, deposedKey)
evalCtx, _ := initMockEvalContext(absResourceAddr, deposedKey)
absResource := mustResourceInstanceAddr(absResourceAddr)
node := NodeForgetDeposedResourceInstanceObject{
@@ -338,7 +338,7 @@ func TestNodeForgetDeposedResourceInstanceObject_Execute(t *testing.T) {
},
DeposedKey: deposedKey,
}
err := node.Execute(ctx, walkApply)
err := node.Execute(t.Context(), evalCtx, walkApply)
if err != nil {
t.Fatalf("unexpected error: %s", err)

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"fmt"
"log"
@@ -137,19 +138,19 @@ func (n *NodeDestroyResourceInstance) References() []*addrs.Reference {
}
// GraphNodeExecutable
func (n *NodeDestroyResourceInstance) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
func (n *NodeDestroyResourceInstance) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
addr := n.ResourceInstanceAddr()
// Eval info is different depending on what kind of resource this is
switch addr.Resource.Resource.Mode {
case addrs.ManagedResourceMode:
diags = n.resolveProvider(ctx, false, states.NotDeposed)
diags = n.resolveProvider(evalCtx, false, states.NotDeposed)
if diags.HasErrors() {
return diags
}
return n.managedResourceExecute(ctx)
return n.managedResourceExecute(evalCtx)
case addrs.DataResourceMode:
return n.dataResourceExecute(ctx)
return n.dataResourceExecute(evalCtx)
default:
panic(fmt.Errorf("unsupported resource mode %s", n.Config.Mode))
}

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"fmt"
"log"
@@ -44,7 +45,7 @@ func (n *NodeForgetResourceInstance) Name() string {
}
// GraphNodeExecutable
func (n *NodeForgetResourceInstance) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
func (n *NodeForgetResourceInstance) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
addr := n.ResourceInstanceAddr()
// Get our state
@@ -53,14 +54,14 @@ func (n *NodeForgetResourceInstance) Execute(ctx EvalContext, op walkOperation)
log.Printf("[WARN] NodeForgetResourceInstance for %s with no state", addr)
}
diags = n.resolveProvider(ctx, false, states.NotDeposed)
diags = n.resolveProvider(evalCtx, false, states.NotDeposed)
if diags.HasErrors() {
return diags
}
var state *states.ResourceInstanceObject
state, readDiags := n.readResourceInstanceState(ctx, addr)
state, readDiags := n.readResourceInstanceState(evalCtx, addr)
diags = diags.Append(readDiags)
if diags.HasErrors() {
return diags
@@ -71,10 +72,10 @@ func (n *NodeForgetResourceInstance) Execute(ctx EvalContext, op walkOperation)
return diags
}
contextState := ctx.State()
contextState := evalCtx.State()
contextState.ForgetResourceInstanceAll(n.Addr)
diags = diags.Append(updateStateHook(ctx))
diags = diags.Append(updateStateHook(evalCtx))
return diags
}

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"fmt"
"log"
@@ -75,7 +76,7 @@ func (n *graphNodeImportState) ModulePath() addrs.Module {
}
// GraphNodeExecutable impl.
func (n *graphNodeImportState) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
func (n *graphNodeImportState) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
// Reset our states
n.states = nil
@@ -92,24 +93,24 @@ func (n *graphNodeImportState) Execute(ctx EvalContext, op walkOperation) (diags
ResolvedProvider: n.ResolvedProvider,
},
}
diags = diags.Append(asAbsNode.resolveProvider(ctx, true, states.NotDeposed))
diags = diags.Append(asAbsNode.resolveProvider(evalCtx, true, states.NotDeposed))
if diags.HasErrors() {
return diags
}
n.ResolvedProviderKey = asAbsNode.ResolvedProviderKey
log.Printf("[TRACE] graphNodeImportState: importing using %s", n.ResolvedProvider.ProviderConfig.InstanceString(n.ResolvedProviderKey))
provider, _, err := getProvider(ctx, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
provider, _, err := getProvider(evalCtx, n.ResolvedProvider.ProviderConfig, n.ResolvedProviderKey)
diags = diags.Append(err)
if diags.HasErrors() {
return diags
}
// import state
absAddr := n.Addr.Resource.Absolute(ctx.Path())
absAddr := n.Addr.Resource.Absolute(evalCtx.Path())
// Call pre-import hook
diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
diags = diags.Append(evalCtx.Hook(func(h Hook) (HookAction, error) {
return h.PreImportState(absAddr, n.ID)
}))
if diags.HasErrors() {
@@ -132,7 +133,7 @@ func (n *graphNodeImportState) Execute(ctx EvalContext, op walkOperation) (diags
n.states = imported
// Call post-import hook
diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
diags = diags.Append(evalCtx.Hook(func(h Hook) (HookAction, error) {
return h.PostImportState(absAddr, imported)
}))
return diags
@@ -243,7 +244,7 @@ func (n *graphNodeImportStateSub) Path() addrs.ModuleInstance {
}
// GraphNodeExecutable impl.
func (n *graphNodeImportStateSub) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
func (n *graphNodeImportStateSub) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
// If the Ephemeral type isn't set, then it is an error
if n.State.TypeName == "" {
diags = diags.Append(fmt.Errorf("import of %s didn't set type", n.TargetAddr.String()))
@@ -260,7 +261,7 @@ func (n *graphNodeImportStateSub) Execute(ctx EvalContext, op walkOperation) (di
},
ResolvedProviderKey: n.ResolvedProviderKey,
}
state, refreshDiags := riNode.refresh(ctx, states.NotDeposed, state)
state, refreshDiags := riNode.refresh(evalCtx, states.NotDeposed, state)
diags = diags.Append(refreshDiags)
if diags.HasErrors() {
return diags
@@ -288,7 +289,7 @@ func (n *graphNodeImportStateSub) Execute(ctx EvalContext, op walkOperation) (di
// Insert marks from configuration
if n.Config != nil {
// Since the import command allow import resource with incomplete configuration, we ignore diagnostics here
valueWithConfigurationSchemaMarks, _, _ := ctx.EvaluateBlock(n.Config.Config, n.Schema, nil, EvalDataForNoInstanceKey)
valueWithConfigurationSchemaMarks, _, _ := evalCtx.EvaluateBlock(n.Config.Config, n.Schema, nil, EvalDataForNoInstanceKey)
_, stateValueMarks := state.Value.UnmarkDeepWithPaths()
_, valueWithConfigurationSchemaMarksPaths := valueWithConfigurationSchemaMarks.UnmarkDeepWithPaths()
@@ -296,6 +297,6 @@ func (n *graphNodeImportStateSub) Execute(ctx EvalContext, op walkOperation) (di
state.Value = state.Value.MarkWithPaths(combined)
}
diags = diags.Append(riNode.writeResourceInstanceState(ctx, state, workingState))
diags = diags.Append(riNode.writeResourceInstanceState(evalCtx, state, workingState))
return diags
}

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"fmt"
"github.com/opentofu/opentofu/internal/addrs"
@@ -44,19 +45,19 @@ func (n *NodePlanDestroyableResourceInstance) DestroyAddr() *addrs.AbsResourceIn
}
// GraphNodeEvalable
func (n *NodePlanDestroyableResourceInstance) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
func (n *NodePlanDestroyableResourceInstance) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
addr := n.ResourceInstanceAddr()
diags = diags.Append(n.resolveProvider(ctx, false, states.NotDeposed))
diags = diags.Append(n.resolveProvider(evalCtx, false, states.NotDeposed))
if diags.HasErrors() {
return diags
}
switch addr.Resource.Resource.Mode {
case addrs.ManagedResourceMode:
return n.managedResourceExecute(ctx, op)
return n.managedResourceExecute(evalCtx, op)
case addrs.DataResourceMode:
return n.dataResourceExecute(ctx, op)
return n.dataResourceExecute(evalCtx, op)
default:
panic(fmt.Errorf("unsupported resource mode %s", n.Config.Mode))
}

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"fmt"
"log"
"path/filepath"
@@ -83,10 +84,10 @@ var (
)
// GraphNodeEvalable
func (n *NodePlannableResourceInstance) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics {
func (n *NodePlannableResourceInstance) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) tfdiags.Diagnostics {
addr := n.ResourceInstanceAddr()
diags := n.resolveProvider(ctx, true, states.NotDeposed)
diags := n.resolveProvider(evalCtx, true, states.NotDeposed)
if diags.HasErrors() {
return diags
}
@@ -94,9 +95,9 @@ func (n *NodePlannableResourceInstance) Execute(ctx EvalContext, op walkOperatio
// Eval info is different depending on what kind of resource this is
switch addr.Resource.Resource.Mode {
case addrs.ManagedResourceMode:
return n.managedResourceExecute(ctx)
return n.managedResourceExecute(evalCtx)
case addrs.DataResourceMode:
return n.dataResourceExecute(ctx)
return n.dataResourceExecute(evalCtx)
default:
panic(fmt.Errorf("unsupported resource mode %s", n.Config.Mode))
}

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"fmt"
"log"
@@ -53,19 +54,19 @@ func (n *NodePlannableResourceInstanceOrphan) Name() string {
}
// GraphNodeExecutable
func (n *NodePlannableResourceInstanceOrphan) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics {
func (n *NodePlannableResourceInstanceOrphan) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) tfdiags.Diagnostics {
addr := n.ResourceInstanceAddr()
// Eval info is different depending on what kind of resource this is
switch addr.Resource.Resource.Mode {
case addrs.ManagedResourceMode:
diags := n.resolveProvider(ctx, true, states.NotDeposed)
diags := n.resolveProvider(evalCtx, true, states.NotDeposed)
if diags.HasErrors() {
return diags
}
return n.managedResourceExecute(ctx)
return n.managedResourceExecute(evalCtx)
case addrs.DataResourceMode:
return n.dataResourceExecute(ctx)
return n.dataResourceExecute(evalCtx)
default:
panic(fmt.Errorf("unsupported resource mode %s", n.Config.Mode))
}

View File

@@ -218,7 +218,7 @@ func TestNodeResourcePlanOrphan_Execute(t *testing.T) {
p.ConfigureProvider(providers.ConfigureProviderRequest{})
p.GetProviderSchemaResponse = &schema
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
StateState: state.SyncWrapper(),
RefreshStateState: state.DeepCopy().SyncWrapper(),
PrevRunStateState: state.DeepCopy().SyncWrapper(),
@@ -241,10 +241,10 @@ func TestNodeResourcePlanOrphan_Execute(t *testing.T) {
RemoveStatements: test.nodeEndpointsToRemove,
}
gotDiags := node.Execute(ctx, walkPlan)
gotDiags := node.Execute(t.Context(), evalCtx, walkPlan)
assertDiags(t, gotDiags, test.wantDiags)
change := ctx.Changes().GetResourceInstanceChange(absResource, states.NotDeposed)
change := evalCtx.Changes().GetResourceInstanceChange(absResource, states.NotDeposed)
if got, want := change.ChangeSrc.Action, test.wantAction; got != want {
t.Fatalf("wrong planned action\ngot: %s\nwant: %s", got, want)
}
@@ -287,7 +287,7 @@ func TestNodeResourcePlanOrphanExecute_alreadyDeleted(t *testing.T) {
p.ReadResourceResponse = &providers.ReadResourceResponse{
NewState: cty.NullVal(p.GetProviderSchemaResponse.ResourceTypes["test_string"].Block.ImpliedType()),
}
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
StateState: state.SyncWrapper(),
RefreshStateState: refreshState.SyncWrapper(),
PrevRunStateState: prevRunState.SyncWrapper(),
@@ -314,7 +314,7 @@ func TestNodeResourcePlanOrphanExecute_alreadyDeleted(t *testing.T) {
Addr: mustResourceInstanceAddr("test_object.foo"),
},
}
diags := node.Execute(ctx, walkPlan)
diags := node.Execute(t.Context(), evalCtx, walkPlan)
if diags.HasErrors() {
t.Fatalf("unexpected error: %s", diags.Err())
}
@@ -370,7 +370,7 @@ func TestNodeResourcePlanOrphanExecute_deposed(t *testing.T) {
p.ReadResourceResponse = &providers.ReadResourceResponse{
NewState: cty.NullVal(p.GetProviderSchemaResponse.ResourceTypes["test_string"].Block.ImpliedType()),
}
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
StateState: state.SyncWrapper(),
RefreshStateState: refreshState.SyncWrapper(),
PrevRunStateState: prevRunState.SyncWrapper(),
@@ -397,7 +397,7 @@ func TestNodeResourcePlanOrphanExecute_deposed(t *testing.T) {
Addr: mustResourceInstanceAddr("test_object.foo"),
},
}
diags := node.Execute(ctx, walkPlan)
diags := node.Execute(t.Context(), evalCtx, walkPlan)
if diags.HasErrors() {
t.Fatalf("unexpected error: %s", diags.Err())
}

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"fmt"
"strings"
@@ -46,14 +47,14 @@ func (n *NodeValidatableResource) Path() addrs.ModuleInstance {
}
// GraphNodeEvalable
func (n *NodeValidatableResource) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
func (n *NodeValidatableResource) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
if n.Config == nil {
return diags
}
diags = diags.Append(n.validateResource(ctx))
diags = diags.Append(n.validateResource(evalCtx))
diags = diags.Append(n.validateCheckRules(ctx, n.Config))
diags = diags.Append(n.validateCheckRules(evalCtx, n.Config))
if managed := n.Config.Managed; managed != nil {
// Validate all the provisioners
@@ -74,7 +75,7 @@ func (n *NodeValidatableResource) Execute(ctx EvalContext, op walkOperation) (di
}
// Validate Provisioner Config
diags = diags.Append(n.validateProvisioner(ctx, &provisioner))
diags = diags.Append(n.validateProvisioner(evalCtx, &provisioner))
if diags.HasErrors() {
return diags
}

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"log"
"github.com/zclconf/go-cty/cty"
@@ -54,7 +55,7 @@ func (n *NodeRootVariable) ReferenceableAddrs() []addrs.Referenceable {
}
// GraphNodeExecutable
func (n *NodeRootVariable) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics {
func (n *NodeRootVariable) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) tfdiags.Diagnostics {
// Root module variables are special in that they are provided directly
// by the caller (usually, the CLI layer) and so we don't really need to
// evaluate them in the usual sense, but we do need to process the raw
@@ -98,7 +99,7 @@ func (n *NodeRootVariable) Execute(ctx EvalContext, op walkOperation) tfdiags.Di
return diags
}
ctx.SetRootModuleArgument(addr.Variable, finalVal)
evalCtx.SetRootModuleArgument(addr.Variable, finalVal)
return diags
}

View File

@@ -20,7 +20,7 @@ import (
func TestNodeRootVariableExecute(t *testing.T) {
t.Run("type conversion", func(t *testing.T) {
ctx := new(MockEvalContext)
evalCtx := new(MockEvalContext)
n := &NodeRootVariable{
Addr: addrs.InputVariable{Name: "foo"},
@@ -35,7 +35,7 @@ func TestNodeRootVariableExecute(t *testing.T) {
},
}
ctx.ChecksState = checks.NewState(&configs.Config{
evalCtx.ChecksState = checks.NewState(&configs.Config{
Module: &configs.Module{
Variables: map[string]*configs.Variable{
"foo": n.Config,
@@ -43,18 +43,18 @@ func TestNodeRootVariableExecute(t *testing.T) {
},
})
diags := n.Execute(ctx, walkApply)
diags := n.Execute(t.Context(), evalCtx, walkApply)
if diags.HasErrors() {
t.Fatalf("unexpected error: %s", diags.Err())
}
if !ctx.SetRootModuleArgumentCalled {
if !evalCtx.SetRootModuleArgumentCalled {
t.Fatalf("ctx.SetRootModuleArgument wasn't called")
}
if got, want := ctx.SetRootModuleArgumentAddr.String(), "var.foo"; got != want {
if got, want := evalCtx.SetRootModuleArgumentAddr.String(), "var.foo"; got != want {
t.Errorf("wrong address for ctx.SetRootModuleArgument\ngot: %s\nwant: %s", got, want)
}
if got, want := ctx.SetRootModuleArgumentValue, cty.StringVal("true"); !want.RawEquals(got) {
if got, want := evalCtx.SetRootModuleArgumentValue, cty.StringVal("true"); !want.RawEquals(got) {
// NOTE: The given value was cty.Bool but the type constraint was
// cty.String, so it was NodeRootVariable's responsibility to convert
// as part of preparing the "final value".
@@ -62,25 +62,25 @@ func TestNodeRootVariableExecute(t *testing.T) {
}
})
t.Run("validation", func(t *testing.T) {
ctx := new(MockEvalContext)
evalCtx := new(MockEvalContext)
// The variable validation function gets called with OpenTofu's
// built-in functions available, so we need a minimal scope just for
// it to get the functions from.
ctx.EvaluationScopeScope = &lang.Scope{}
evalCtx.EvaluationScopeScope = &lang.Scope{}
// We need to reimplement a _little_ bit of EvalContextBuiltin logic
// here to get a similar effect with EvalContextMock just to get the
// value to flow through here in a realistic way that'll make this test
// useful.
var finalVal cty.Value
ctx.SetRootModuleArgumentFunc = func(addr addrs.InputVariable, v cty.Value) {
evalCtx.SetRootModuleArgumentFunc = func(addr addrs.InputVariable, v cty.Value) {
if addr.Name == "foo" {
t.Logf("set %s to %#v", addr.String(), v)
finalVal = v
}
}
ctx.GetVariableValueFunc = func(addr addrs.AbsInputVariableInstance) cty.Value {
evalCtx.GetVariableValueFunc = func(addr addrs.AbsInputVariableInstance) cty.Value {
if addr.String() != "var.foo" {
return cty.NilVal
}
@@ -133,7 +133,7 @@ func TestNodeRootVariableExecute(t *testing.T) {
Config: n.Config,
}
ctx.ChecksState = checks.NewState(&configs.Config{
evalCtx.ChecksState = checks.NewState(&configs.Config{
Module: &configs.Module{
Variables: map[string]*configs.Variable{
"foo": n.Config,
@@ -141,38 +141,38 @@ func TestNodeRootVariableExecute(t *testing.T) {
},
})
diags := n.Execute(ctx, walkApply)
diags := n.Execute(t.Context(), evalCtx, walkApply)
if diags.HasErrors() {
t.Fatalf("unexpected error: %s", diags.Err())
}
g, err := ref.DynamicExpand(ctx)
g, err := ref.DynamicExpand(evalCtx)
if err != nil {
t.Fatalf("unexpected error: %s", err)
}
for _, v := range g.Vertices() {
if ev, ok := v.(GraphNodeExecutable); ok {
diags = ev.Execute(ctx, walkApply)
diags = ev.Execute(t.Context(), evalCtx, walkApply)
if diags.HasErrors() {
t.Fatalf("unexpected error: %s", diags.Err())
}
}
}
if !ctx.SetRootModuleArgumentCalled {
if !evalCtx.SetRootModuleArgumentCalled {
t.Fatalf("ctx.SetRootModuleArgument wasn't called")
}
if got, want := ctx.SetRootModuleArgumentAddr.String(), "var.foo"; got != want {
if got, want := evalCtx.SetRootModuleArgumentAddr.String(), "var.foo"; got != want {
t.Errorf("wrong address for ctx.SetRootModuleArgument\ngot: %s\nwant: %s", got, want)
}
if got, want := ctx.SetRootModuleArgumentValue, cty.NumberIntVal(5); !want.RawEquals(got) {
if got, want := evalCtx.SetRootModuleArgumentValue, cty.NumberIntVal(5); !want.RawEquals(got) {
// NOTE: The given value was cty.Bool but the type constraint was
// cty.String, so it was NodeRootVariable's responsibility to convert
// as part of preparing the "final value".
t.Errorf("wrong value for ctx.SetRootModuleArgument\ngot: %#v\nwant: %#v", got, want)
}
if status := ctx.Checks().ObjectCheckStatus(n.Addr.Absolute(addrs.RootModuleInstance)); status != checks.StatusPass {
if status := evalCtx.Checks().ObjectCheckStatus(n.Addr.Absolute(addrs.RootModuleInstance)); status != checks.StatusPass {
t.Errorf("expected checks to pass but go %s instead", status)
}
})

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"fmt"
"log"
@@ -143,10 +144,10 @@ func (n *nodeVariableReferenceInstance) ModulePath() addrs.Module {
}
// GraphNodeExecutable
func (n *nodeVariableReferenceInstance) Execute(ctx EvalContext, op walkOperation) tfdiags.Diagnostics {
func (n *nodeVariableReferenceInstance) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) tfdiags.Diagnostics {
log.Printf("[TRACE] nodeVariableReferenceInstance: evaluating %s", n.Addr)
diags := evalVariableValidations(n.Addr, n.Config, n.Expr, ctx)
diags = diags.Append(evalVariableDeprecation(n.Addr, n.Config, n.Expr, ctx))
diags := evalVariableValidations(n.Addr, n.Config, n.Expr, evalCtx)
diags = diags.Append(evalVariableDeprecation(n.Addr, n.Config, n.Expr, evalCtx))
if op == walkValidate {
var filtered tfdiags.Diagnostics

View File

@@ -31,7 +31,7 @@ func TestGraphNodeImportStateExecute(t *testing.T) {
}
provider.ConfigureProvider(providers.ConfigureProviderRequest{})
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
StateState: state.SyncWrapper(),
ProviderProvider: provider,
}
@@ -52,7 +52,7 @@ func TestGraphNodeImportStateExecute(t *testing.T) {
}},
}
diags := node.Execute(ctx, walkImport)
diags := node.Execute(t.Context(), evalCtx, walkImport)
if diags.HasErrors() {
t.Fatalf("Unexpected error: %s", diags.Err())
}
@@ -71,7 +71,7 @@ func TestGraphNodeImportStateSubExecute(t *testing.T) {
state := states.NewState()
provider := testProvider("aws")
provider.ConfigureProvider(providers.ConfigureProviderRequest{})
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
StateState: state.SyncWrapper(),
ProviderProvider: provider,
ProviderSchemaSchema: providers.ProviderSchema{
@@ -107,7 +107,7 @@ func TestGraphNodeImportStateSubExecute(t *testing.T) {
Module: addrs.RootModule,
}},
}
diags := node.Execute(ctx, walkImport)
diags := node.Execute(t.Context(), evalCtx, walkImport)
if diags.HasErrors() {
t.Fatalf("Unexpected error: %s", diags.Err())
}
@@ -133,7 +133,7 @@ func TestGraphNodeImportStateSubExecuteNull(t *testing.T) {
return resp
}
ctx := &MockEvalContext{
evalCtx := &MockEvalContext{
StateState: state.SyncWrapper(),
ProviderProvider: provider,
ProviderSchemaSchema: providers.ProviderSchema{
@@ -169,7 +169,7 @@ func TestGraphNodeImportStateSubExecuteNull(t *testing.T) {
Module: addrs.RootModule,
}},
}
diags := node.Execute(ctx, walkImport)
diags := node.Execute(t.Context(), evalCtx, walkImport)
if !diags.HasErrors() {
t.Fatal("expected error for non-existent resource")
}

View File

@@ -6,6 +6,7 @@
package tofu
import (
"context"
"fmt"
"log"
@@ -593,8 +594,8 @@ func (n *graphNodeCloseProvider) ModulePath() addrs.Module {
}
// GraphNodeExecutable impl.
func (n *graphNodeCloseProvider) Execute(ctx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
return diags.Append(ctx.CloseProvider(n.Addr))
func (n *graphNodeCloseProvider) Execute(_ context.Context, evalCtx EvalContext, op walkOperation) (diags tfdiags.Diagnostics) {
return diags.Append(evalCtx.CloseProvider(n.Addr))
}
func (n *graphNodeCloseProvider) CloseProviderAddr() addrs.AbsProviderConfig {