From 58e001c22aeb79ed183e7e8fe446a100f1bbbec9 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 17 Dec 2021 11:27:46 -0500 Subject: [PATCH] return graph errors from Context.Apply errors from building during apply were lost --- internal/terraform/context_apply.go | 5 +- internal/terraform/context_apply2_test.go | 58 +++++++++++++++++++++++ 2 files changed, 60 insertions(+), 3 deletions(-) diff --git a/internal/terraform/context_apply.go b/internal/terraform/context_apply.go index e94449b72..e5d2702bc 100644 --- a/internal/terraform/context_apply.go +++ b/internal/terraform/context_apply.go @@ -22,12 +22,11 @@ import ( // resulting state which is likely to have been partially-updated. func (c *Context) Apply(plan *plans.Plan, config *configs.Config) (*states.State, tfdiags.Diagnostics) { defer c.acquireRun("apply")() - var diags tfdiags.Diagnostics log.Printf("[DEBUG] Building and walking apply graph for %s plan", plan.UIMode) - graph, operation, moreDiags := c.applyGraph(plan, config, true) - if moreDiags.HasErrors() { + graph, operation, diags := c.applyGraph(plan, config, true) + if diags.HasErrors() { return nil, diags } diff --git a/internal/terraform/context_apply2_test.go b/internal/terraform/context_apply2_test.go index e02c73df1..6b87d409d 100644 --- a/internal/terraform/context_apply2_test.go +++ b/internal/terraform/context_apply2_test.go @@ -678,3 +678,61 @@ resource "test_object" "s" { }) assertNoErrors(t, diags) } + +func TestContext2Apply_graphError(t *testing.T) { + m := testModuleInline(t, map[string]string{ + "main.tf": ` +resource "test_object" "a" { + test_string = "ok" +} + +resource "test_object" "b" { + test_string = test_object.a.test_string +} +`, + }) + + p := simpleMockProvider() + + state := states.NewState() + root := state.EnsureModule(addrs.RootModuleInstance) + root.SetResourceInstanceCurrent( + mustResourceInstanceAddr("test_object.a").Resource, + &states.ResourceInstanceObjectSrc{ + Status: states.ObjectTainted, + AttrsJSON: []byte(`{"test_string":"ok"}`), + }, + mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), + ) + root.SetResourceInstanceCurrent( + mustResourceInstanceAddr("test_object.b").Resource, + &states.ResourceInstanceObjectSrc{ + Status: states.ObjectTainted, + AttrsJSON: []byte(`{"test_string":"ok"}`), + }, + mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), + ) + + ctx := testContext2(t, &ContextOpts{ + Providers: map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), + }, + }) + + plan, diags := ctx.Plan(m, state, &PlanOpts{ + Mode: plans.DestroyMode, + }) + if diags.HasErrors() { + t.Fatalf("plan: %s", diags.Err()) + } + + // We're going to corrupt the stored state so that the dependencies will + // cause a cycle when building the apply graph. + testObjA := plan.PriorState.Modules[""].Resources["test_object.a"].Instances[addrs.NoKey].Current + testObjA.Dependencies = append(testObjA.Dependencies, mustResourceInstanceAddr("test_object.b").ContainingResource().Config()) + + _, diags = ctx.Apply(plan, m) + if !diags.HasErrors() { + t.Fatal("expected cycle error from apply") + } +}