diff --git a/terraform/eval.go b/terraform/eval.go deleted file mode 100644 index 2a8909aee..000000000 --- a/terraform/eval.go +++ /dev/null @@ -1,62 +0,0 @@ -package terraform - -import ( - "log" - - "github.com/hashicorp/terraform/tfdiags" -) - -// EvalNode is the interface that must be implemented by graph nodes to -// evaluate/execute. -type EvalNode interface { - // Eval evaluates this node with the given context. The second parameter - // are the argument values. These will match in order and 1-1 with the - // results of the Args() return value. - Eval(EvalContext) (interface{}, error) -} - -// GraphNodeEvalable is the interface that graph nodes must implement -// to enable valuation. -type GraphNodeEvalable interface { - EvalTree() EvalNode -} - -// EvalEarlyExitError is a special error return value that can be returned -// by eval nodes that does an early exit. -type EvalEarlyExitError struct{} - -func (EvalEarlyExitError) Error() string { return "early exit" } - -// Eval evaluates the given EvalNode with the given context, properly -// evaluating all args in the correct order. -func Eval(n EvalNode, ctx EvalContext) (interface{}, error) { - // Call the lower level eval which doesn't understand early exit, - // and if we early exit, it isn't an error. - result, err := EvalRaw(n, ctx) - if err != nil { - if _, ok := err.(EvalEarlyExitError); ok { - return nil, nil - } - } - - return result, err -} - -// EvalRaw is like Eval except that it returns all errors, even if they -// signal something normal such as EvalEarlyExitError. -func EvalRaw(n EvalNode, ctx EvalContext) (interface{}, error) { - log.Printf("[TRACE] eval: %T", n) - output, err := n.Eval(ctx) - if err != nil { - switch err.(type) { - case EvalEarlyExitError: - log.Printf("[TRACE] eval: %T, early exit err: %s", n, err) - case tfdiags.NonFatalError: - log.Printf("[WARN] eval: %T, non-fatal err: %s", n, err) - default: - log.Printf("[ERROR] eval: %T, err: %s", n, err) - } - } - - return output, err -} diff --git a/terraform/eval_check_prevent_destroy.go b/terraform/eval_check_prevent_destroy.go deleted file mode 100644 index e3400fe4c..000000000 --- a/terraform/eval_check_prevent_destroy.go +++ /dev/null @@ -1,47 +0,0 @@ -package terraform - -import ( - "fmt" - - "github.com/hashicorp/terraform/plans" - - "github.com/hashicorp/hcl/v2" - - "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/configs" - "github.com/hashicorp/terraform/tfdiags" -) - -// EvalPreventDestroy is an EvalNode implementation that returns an -// error if a resource has PreventDestroy configured and the diff -// would destroy the resource. -type EvalCheckPreventDestroy struct { - Addr addrs.ResourceInstance - Config *configs.Resource - Change **plans.ResourceInstanceChange -} - -func (n *EvalCheckPreventDestroy) Eval(ctx EvalContext) (interface{}, error) { - if n.Change == nil || *n.Change == nil || n.Config == nil || n.Config.Managed == nil { - return nil, nil - } - - change := *n.Change - preventDestroy := n.Config.Managed.PreventDestroy - - if (change.Action == plans.Delete || change.Action.IsReplace()) && preventDestroy { - var diags tfdiags.Diagnostics - diags = diags.Append(&hcl.Diagnostic{ - Severity: hcl.DiagError, - Summary: "Instance cannot be destroyed", - Detail: fmt.Sprintf( - "Resource %s has lifecycle.prevent_destroy set, but the plan calls for this resource to be destroyed. To avoid this error and continue with the plan, either disable lifecycle.prevent_destroy or reduce the scope of the plan using the -target flag.", - n.Addr.Absolute(ctx.Path()).String(), - ), - Subject: &n.Config.DeclRange, - }) - return nil, diags.Err() - } - - return nil, nil -} diff --git a/terraform/eval_diff.go b/terraform/eval_diff.go index 7cda14ce1..4ca4215b5 100644 --- a/terraform/eval_diff.go +++ b/terraform/eval_diff.go @@ -789,45 +789,6 @@ func (n *EvalReduceDiff) Eval(ctx EvalContext) (interface{}, error) { return nil, nil } -// EvalReadDiff is an EvalNode implementation that retrieves the planned -// change for a particular resource instance object. -type EvalReadDiff struct { - Addr addrs.ResourceInstance - ProviderSchema **ProviderSchema - Change **plans.ResourceInstanceChange -} - -func (n *EvalReadDiff) Eval(ctx EvalContext) (interface{}, error) { - providerSchema := *n.ProviderSchema - changes := ctx.Changes() - addr := n.Addr.Absolute(ctx.Path()) - - schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource()) - if schema == nil { - // Should be caught during validation, so we don't bother with a pretty error here - return nil, fmt.Errorf("provider does not support resource type %q", n.Addr.Resource.Type) - } - - gen := states.CurrentGen - csrc := changes.GetResourceInstanceChange(addr, gen) - if csrc == nil { - log.Printf("[TRACE] EvalReadDiff: No planned change recorded for %s", addr) - return nil, nil - } - - change, err := csrc.Decode(schema.ImpliedType()) - if err != nil { - return nil, fmt.Errorf("failed to decode planned changes for %s: %s", addr, err) - } - if n.Change != nil { - *n.Change = change - } - - log.Printf("[TRACE] EvalReadDiff: Read %s change from plan for %s", change.Action, addr) - - return nil, nil -} - // EvalWriteDiff is an EvalNode implementation that saves a planned change // for an instance object into the set of global planned changes. type EvalWriteDiff struct { diff --git a/terraform/eval_error.go b/terraform/eval_error.go index 470f798b7..853ea2cc8 100644 --- a/terraform/eval_error.go +++ b/terraform/eval_error.go @@ -1,20 +1,7 @@ package terraform -// EvalReturnError is an EvalNode implementation that returns an -// error if it is present. -// -// This is useful for scenarios where an error has been captured by -// another EvalNode (like EvalApply) for special EvalTree-based error -// handling, and that handling has completed, so the error should be -// returned normally. -type EvalReturnError struct { - Error *error -} +// EvalEarlyExitError is a special error return value that can be returned +// by eval nodes that does an early exit. +type EvalEarlyExitError struct{} -func (n *EvalReturnError) Eval(ctx EvalContext) (interface{}, error) { - if n.Error == nil { - return nil, nil - } - - return nil, *n.Error -} +func (EvalEarlyExitError) Error() string { return "early exit" } diff --git a/terraform/eval_filter.go b/terraform/eval_filter.go deleted file mode 100644 index 711c625c8..000000000 --- a/terraform/eval_filter.go +++ /dev/null @@ -1,25 +0,0 @@ -package terraform - -// EvalNodeFilterFunc is the callback used to replace a node with -// another to node. To not do the replacement, just return the input node. -type EvalNodeFilterFunc func(EvalNode) EvalNode - -// EvalNodeFilterable is an interface that can be implemented by -// EvalNodes to allow filtering of sub-elements. Note that this isn't -// a common thing to implement and you probably don't need it. -type EvalNodeFilterable interface { - EvalNode - Filter(EvalNodeFilterFunc) -} - -// EvalFilter runs the filter on the given node and returns the -// final filtered value. This should be called rather than checking -// the EvalNode directly since this will properly handle EvalNodeFilterables. -func EvalFilter(node EvalNode, fn EvalNodeFilterFunc) EvalNode { - if f, ok := node.(EvalNodeFilterable); ok { - f.Filter(fn) - return node - } - - return fn(node) -} diff --git a/terraform/eval_filter_operation.go b/terraform/eval_filter_operation.go deleted file mode 100644 index 1a55f024a..000000000 --- a/terraform/eval_filter_operation.go +++ /dev/null @@ -1,49 +0,0 @@ -package terraform - -// EvalNodeOpFilterable is an interface that EvalNodes can implement -// to be filterable by the operation that is being run on Terraform. -type EvalNodeOpFilterable interface { - IncludeInOp(walkOperation) bool -} - -// EvalNodeFilterOp returns a filter function that filters nodes that -// include themselves in specific operations. -func EvalNodeFilterOp(op walkOperation) EvalNodeFilterFunc { - return func(n EvalNode) EvalNode { - include := true - if of, ok := n.(EvalNodeOpFilterable); ok { - include = of.IncludeInOp(op) - } - if include { - return n - } - - return EvalNoop{} - } -} - -// EvalOpFilter is an EvalNode implementation that is a proxy to -// another node but filters based on the operation. -type EvalOpFilter struct { - // Ops is the list of operations to include this node in. - Ops []walkOperation - - // Node is the node to execute - Node EvalNode -} - -// TODO: test -func (n *EvalOpFilter) Eval(ctx EvalContext) (interface{}, error) { - return EvalRaw(n.Node, ctx) -} - -// EvalNodeOpFilterable impl. -func (n *EvalOpFilter) IncludeInOp(op walkOperation) bool { - for _, v := range n.Ops { - if v == op { - return true - } - } - - return false -} diff --git a/terraform/eval_if.go b/terraform/eval_if.go deleted file mode 100644 index d6b46a1f2..000000000 --- a/terraform/eval_if.go +++ /dev/null @@ -1,26 +0,0 @@ -package terraform - -// EvalIf is an EvalNode that is a conditional. -type EvalIf struct { - If func(EvalContext) (bool, error) - Then EvalNode - Else EvalNode -} - -// TODO: test -func (n *EvalIf) Eval(ctx EvalContext) (interface{}, error) { - yes, err := n.If(ctx) - if err != nil { - return nil, err - } - - if yes { - return EvalRaw(n.Then, ctx) - } else { - if n.Else != nil { - return EvalRaw(n.Else, ctx) - } - } - - return nil, nil -} diff --git a/terraform/eval_noop.go b/terraform/eval_noop.go deleted file mode 100644 index f4bc8225c..000000000 --- a/terraform/eval_noop.go +++ /dev/null @@ -1,8 +0,0 @@ -package terraform - -// EvalNoop is an EvalNode that does nothing. -type EvalNoop struct{} - -func (EvalNoop) Eval(EvalContext) (interface{}, error) { - return nil, nil -} diff --git a/terraform/eval_provider.go b/terraform/eval_provider.go index 3e425e910..0af5964ea 100644 --- a/terraform/eval_provider.go +++ b/terraform/eval_provider.go @@ -60,42 +60,3 @@ func GetProvider(ctx EvalContext, addr addrs.AbsProviderConfig) (providers.Inter schema := ctx.ProviderSchema(addr) return provider, schema, nil } - -// EvalGetProvider is an EvalNode implementation that retrieves an already -// initialized provider instance for the given name. -// -// Unlike most eval nodes, this takes an _absolute_ provider configuration, -// because providers can be passed into and inherited between modules. -// Resource nodes must therefore know the absolute path of the provider they -// will use, which is usually accomplished by implementing -// interface GraphNodeProviderConsumer. -type EvalGetProvider struct { - Addr addrs.AbsProviderConfig - Output *providers.Interface - - // If non-nil, Schema will be updated after eval to refer to the - // schema of the provider. - Schema **ProviderSchema -} - -func (n *EvalGetProvider) Eval(ctx EvalContext) (interface{}, error) { - if n.Addr.Provider.Type == "" { - // Should never happen - panic("EvalGetProvider used with uninitialized provider configuration address") - } - - result := ctx.Provider(n.Addr) - if result == nil { - return nil, fmt.Errorf("provider %s not initialized", n.Addr) - } - - if n.Output != nil { - *n.Output = result - } - - if n.Schema != nil { - *n.Schema = ctx.ProviderSchema(n.Addr) - } - - return nil, nil -} diff --git a/terraform/eval_provider_test.go b/terraform/eval_provider_test.go index a029f3677..ff1eb8ab3 100644 --- a/terraform/eval_provider_test.go +++ b/terraform/eval_provider_test.go @@ -9,7 +9,6 @@ import ( "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/configs/configschema" - "github.com/hashicorp/terraform/providers" ) func TestBuildProviderConfig(t *testing.T) { @@ -54,30 +53,3 @@ func TestBuildProviderConfig(t *testing.T) { t.Fatalf("incorrect merged config\ngot: %#v\nwant: %#v", got, want) } } - -func TestEvalGetProvider_impl(t *testing.T) { - var _ EvalNode = new(EvalGetProvider) -} - -func TestEvalGetProvider(t *testing.T) { - var actual providers.Interface - n := &EvalGetProvider{ - Addr: addrs.RootModuleInstance.ProviderConfigDefault(addrs.NewDefaultProvider("foo")), - Output: &actual, - } - provider := &MockProvider{} - ctx := &MockEvalContext{ProviderProvider: provider} - if _, err := n.Eval(ctx); err != nil { - t.Fatalf("err: %s", err) - } - if actual != provider { - t.Fatalf("bad: %#v", actual) - } - - if !ctx.ProviderCalled { - t.Fatal("should be called") - } - if ctx.ProviderAddr.String() != `provider["registry.terraform.io/hashicorp/foo"]` { - t.Fatalf("wrong provider address %s", ctx.ProviderAddr) - } -} diff --git a/terraform/eval_sequence.go b/terraform/eval_sequence.go deleted file mode 100644 index 3485e4f14..000000000 --- a/terraform/eval_sequence.go +++ /dev/null @@ -1,42 +0,0 @@ -package terraform - -import ( - "github.com/hashicorp/terraform/tfdiags" -) - -// EvalSequence is an EvalNode that evaluates in sequence. -type EvalSequence struct { - Nodes []EvalNode -} - -func (n *EvalSequence) Eval(ctx EvalContext) (interface{}, error) { - var diags tfdiags.Diagnostics - - for _, n := range n.Nodes { - if n == nil { - continue - } - - if _, err := EvalRaw(n, ctx); err != nil { - if _, isEarlyExit := err.(EvalEarlyExitError); isEarlyExit { - // In this path we abort early, losing any non-error - // diagnostics we saw earlier. - return nil, err - } - diags = diags.Append(err) - if diags.HasErrors() { - // Halt if we get some errors, but warnings are okay. - break - } - } - } - - return nil, diags.ErrWithWarnings() -} - -// EvalNodeFilterable impl. -func (n *EvalSequence) Filter(fn EvalNodeFilterFunc) { - for i, node := range n.Nodes { - n.Nodes[i] = fn(node) - } -} diff --git a/terraform/eval_sequence_test.go b/terraform/eval_sequence_test.go deleted file mode 100644 index 972f0cd6f..000000000 --- a/terraform/eval_sequence_test.go +++ /dev/null @@ -1,9 +0,0 @@ -package terraform - -import ( - "testing" -) - -func TestEvalSequence_impl(t *testing.T) { - var _ EvalNodeFilterable = new(EvalSequence) -} diff --git a/terraform/eval_state.go b/terraform/eval_state.go index aaf6fecfe..1edab4516 100644 --- a/terraform/eval_state.go +++ b/terraform/eval_state.go @@ -149,35 +149,7 @@ func (n *EvalReadStateDeposed) Eval(ctx EvalContext) (interface{}, error) { return obj, nil } -// EvalUpdateStateHook is an EvalNode implementation that calls the -// PostStateUpdate hook with the current state. -type EvalUpdateStateHook struct{} - -func (n *EvalUpdateStateHook) Eval(ctx EvalContext) (interface{}, error) { - // In principle we could grab the lock here just long enough to take a - // deep copy and then pass that to our hooks below, but we'll instead - // hold the hook for the duration to avoid the potential confusing - // situation of us racing to call PostStateUpdate concurrently with - // different state snapshots. - stateSync := ctx.State() - state := stateSync.Lock().DeepCopy() - defer stateSync.Unlock() - - // Call the hook - err := ctx.Hook(func(h Hook) (HookAction, error) { - return h.PostStateUpdate(state) - }) - if err != nil { - return nil, err - } - - return nil, nil -} - // UpdateStateHook calls the PostStateUpdate hook with the current state. -// -// TODO: UpdateStateHook will eventually replace EvalUpdateStateHook, at which -// point EvalUpdateStateHook can be removed and this comment updated. func UpdateStateHook(ctx EvalContext) error { // In principle we could grab the lock here just long enough to take a // deep copy and then pass that to our hooks below, but we'll instead diff --git a/terraform/eval_state_test.go b/terraform/eval_state_test.go index 6d6425a54..a9c73cded 100644 --- a/terraform/eval_state_test.go +++ b/terraform/eval_state_test.go @@ -12,29 +12,6 @@ import ( "github.com/hashicorp/terraform/states" ) -func TestEvalUpdateStateHook(t *testing.T) { - mockHook := new(MockHook) - - state := states.NewState() - state.Module(addrs.RootModuleInstance).SetLocalValue("foo", cty.StringVal("hello")) - - ctx := new(MockEvalContext) - ctx.HookHook = mockHook - ctx.StateState = state.SyncWrapper() - - node := &EvalUpdateStateHook{} - if _, err := node.Eval(ctx); err != nil { - t.Fatalf("err: %s", err) - } - - if !mockHook.PostStateUpdateCalled { - t.Fatal("should call PostStateUpdate") - } - if mockHook.PostStateUpdateState.LocalValue(addrs.LocalValue{Name: "foo"}.Absolute(addrs.RootModuleInstance)) != cty.StringVal("hello") { - t.Fatalf("wrong state passed to hook: %s", spew.Sdump(mockHook.PostStateUpdateState)) - } -} - func TestEvalReadState(t *testing.T) { var output *states.ResourceInstanceObject mockProvider := mockProviderWithResourceTypeSchema("aws_instance", &configschema.Block{ @@ -50,7 +27,7 @@ func TestEvalReadState(t *testing.T) { cases := map[string]struct { Resources map[string]*ResourceState - Node EvalNode + Node *EvalReadState ExpectedInstanceId string }{ "ReadState gets primary instance state": { @@ -74,6 +51,59 @@ func TestEvalReadState(t *testing.T) { }, ExpectedInstanceId: "i-abc123", }, + } + + for k, c := range cases { + t.Run(k, func(t *testing.T) { + ctx := new(MockEvalContext) + state := MustShimLegacyState(&State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: rootModulePath, + Resources: c.Resources, + }, + }, + }) + ctx.StateState = state.SyncWrapper() + ctx.PathPath = addrs.RootModuleInstance + + result, err := c.Node.Eval(ctx) + if err != nil { + t.Fatalf("[%s] Got err: %#v", k, err) + } + + expected := c.ExpectedInstanceId + if !(result != nil && instanceObjectIdForTests(result.(*states.ResourceInstanceObject)) == expected) { + t.Fatalf("[%s] Expected return with ID %#v, got: %#v", k, expected, result) + } + + if !(output != nil && output.Value.GetAttr("id") == cty.StringVal(expected)) { + t.Fatalf("[%s] Expected output with ID %#v, got: %#v", k, expected, output) + } + + output = nil + }) + } +} + +func TestEvalReadStateDeposed(t *testing.T) { + var output *states.ResourceInstanceObject + mockProvider := mockProviderWithResourceTypeSchema("aws_instance", &configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "id": { + Type: cty.String, + Optional: true, + }, + }, + }) + providerSchema := mockProvider.GetSchemaReturn + provider := providers.Interface(mockProvider) + + cases := map[string]struct { + Resources map[string]*ResourceState + Node *EvalReadStateDeposed + ExpectedInstanceId string + }{ "ReadStateDeposed gets deposed instance": { Resources: map[string]*ResourceState{ "aws_instance.bar": &ResourceState{ @@ -97,7 +127,6 @@ func TestEvalReadState(t *testing.T) { ExpectedInstanceId: "i-abc123", }, } - for k, c := range cases { t.Run(k, func(t *testing.T) { ctx := new(MockEvalContext) @@ -225,9 +254,6 @@ aws_instance.foo: (1 deposed) `) } -// Same test as TestEvalUpdateStateHook, similar function, slightly different -// signature. The EvalUpdateStateHook test and function will be removed when the -// EvalNode Removal is complete. func TestUpdateStateHook(t *testing.T) { mockHook := new(MockHook) diff --git a/terraform/eval_test.go b/terraform/eval_test.go deleted file mode 100644 index 29ae25843..000000000 --- a/terraform/eval_test.go +++ /dev/null @@ -1,40 +0,0 @@ -package terraform - -import ( - "testing" -) - -func TestMockEvalContext_impl(t *testing.T) { - var _ EvalContext = new(MockEvalContext) -} - -func TestEval(t *testing.T) { - var result int - n := &testEvalAdd{ - Items: []int{10, 32}, - Result: &result, - } - - if _, err := Eval(n, nil); err != nil { - t.Fatalf("err: %s", err) - } - - if result != 42 { - t.Fatalf("bad: %#v", result) - } -} - -type testEvalAdd struct { - Items []int - Result *int -} - -func (n *testEvalAdd) Eval(ctx EvalContext) (interface{}, error) { - result := 0 - for _, item := range n.Items { - result += item - } - - *n.Result = result - return nil, nil -} diff --git a/terraform/graph.go b/terraform/graph.go index df1ecf134..73996c1f7 100644 --- a/terraform/graph.go +++ b/terraform/graph.go @@ -1,7 +1,6 @@ package terraform import ( - "fmt" "log" "github.com/hashicorp/terraform/tfdiags" @@ -57,38 +56,12 @@ func (g *Graph) walk(walker GraphWalker) tfdiags.Diagnostics { // If the node is exec-able, then execute it. if ev, ok := v.(GraphNodeExecutable); ok { - // A node must not be both Evalable and Executable. This will be - // removed when GraphNodeEvalable is fully removed. - if _, ok := v.(GraphNodeEvalable); ok { - panic(fmt.Sprintf( - "%T implements both GraphNodeEvalable and GraphNodeExecutable", v, - )) - } diags = diags.Append(walker.Execute(vertexCtx, ev)) if diags.HasErrors() { return } } - // If the node is eval-able, then evaluate it. - if ev, ok := v.(GraphNodeEvalable); ok { - tree := ev.EvalTree() - if tree == nil { - panic(fmt.Sprintf("%q (%T): nil eval tree", dag.VertexName(v), v)) - } - - // Allow the walker to change our tree if needed. Eval, - // then callback with the output. - log.Printf("[TRACE] vertex %q: evaluating", dag.VertexName(v)) - - tree = walker.EnterEvalTree(v, tree) - output, err := Eval(tree, vertexCtx) - diags = diags.Append(walker.ExitEvalTree(v, output, err)) - if diags.HasErrors() { - return - } - } - // If the node is dynamically expanded, then expand it if ev, ok := v.(GraphNodeDynamicExpandable); ok { log.Printf("[TRACE] vertex %q: expanding dynamic subgraph", dag.VertexName(v)) diff --git a/terraform/graph_walk.go b/terraform/graph_walk.go index 1ec099b3c..4ede23513 100644 --- a/terraform/graph_walk.go +++ b/terraform/graph_walk.go @@ -2,7 +2,6 @@ package terraform import ( "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/dag" "github.com/hashicorp/terraform/tfdiags" ) @@ -12,8 +11,6 @@ type GraphWalker interface { EvalContext() EvalContext EnterPath(addrs.ModuleInstance) EvalContext ExitPath(addrs.ModuleInstance) - EnterEvalTree(dag.Vertex, EvalNode) EvalNode - ExitEvalTree(dag.Vertex, interface{}, error) tfdiags.Diagnostics Execute(EvalContext, GraphNodeExecutable) tfdiags.Diagnostics } @@ -22,11 +19,7 @@ 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) EnterEvalTree(v dag.Vertex, n EvalNode) EvalNode { return n } -func (NullGraphWalker) ExitEvalTree(dag.Vertex, interface{}, error) 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(EvalContext, GraphNodeExecutable) tfdiags.Diagnostics { return nil } diff --git a/terraform/graph_walk_context.go b/terraform/graph_walk_context.go index d3ca73b3f..c7492ed06 100644 --- a/terraform/graph_walk_context.go +++ b/terraform/graph_walk_context.go @@ -2,14 +2,12 @@ package terraform import ( "context" - "log" "sync" "github.com/zclconf/go-cty/cty" "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/configs/configschema" - "github.com/hashicorp/terraform/dag" "github.com/hashicorp/terraform/instances" "github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/providers" @@ -106,49 +104,6 @@ func (w *ContextGraphWalker) EvalContext() EvalContext { return ctx } -func (w *ContextGraphWalker) EnterEvalTree(v dag.Vertex, n EvalNode) EvalNode { - log.Printf("[TRACE] [%s] Entering eval tree: %s", w.Operation, dag.VertexName(v)) - - // Acquire a lock on the semaphore - w.Context.parallelSem.Acquire() - - // We want to filter the evaluation tree to only include operations - // that belong in this operation. - return EvalFilter(n, EvalNodeFilterOp(w.Operation)) -} - -func (w *ContextGraphWalker) ExitEvalTree(v dag.Vertex, output interface{}, err error) tfdiags.Diagnostics { - log.Printf("[TRACE] [%s] Exiting eval tree: %s", w.Operation, dag.VertexName(v)) - - // Release the semaphore - w.Context.parallelSem.Release() - - if err == nil { - return nil - } - - // Acquire the lock because anything is going to require a lock. - w.errorLock.Lock() - defer w.errorLock.Unlock() - - // If the error is non-fatal then we'll accumulate its diagnostics in our - // non-fatal list, rather than returning it directly, so that the graph - // walk can continue. - if nferr, ok := err.(tfdiags.NonFatalError); ok { - log.Printf("[WARN] %s: %s", dag.VertexName(v), nferr) - w.NonFatalDiagnostics = w.NonFatalDiagnostics.Append(nferr.Diagnostics) - return nil - } - - // Otherwise, we'll let our usual diagnostics machinery figure out how to - // unpack this as one or more diagnostic messages and return that. If we - // get down here then the returned diagnostics will contain at least one - // error, causing the graph walk to halt. - var diags tfdiags.Diagnostics - diags = diags.Append(err) - return diags -} - func (w *ContextGraphWalker) init() { w.contexts = make(map[string]*BuiltinEvalContext) w.providerCache = make(map[string]providers.Interface) diff --git a/terraform/node_resource_destroy.go b/terraform/node_resource_destroy.go index 7b1a2f580..d07b2c2e9 100644 --- a/terraform/node_resource_destroy.go +++ b/terraform/node_resource_destroy.go @@ -143,12 +143,7 @@ func (n *NodeDestroyResourceInstance) Execute(ctx EvalContext, op walkOperation) return err } - evalReadDiff := &EvalReadDiff{ - Addr: addr.Resource, - ProviderSchema: &providerSchema, - Change: &changeApply, - } - _, err = evalReadDiff.Eval(ctx) + changeApply, err = n.ReadDiff(ctx, providerSchema) if err != nil { return err }