From a44cf03eaa665270d6da0e1aedb75752c9b855aa Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 12 Dec 2019 15:02:26 -0500 Subject: [PATCH] test for CBD instance being removed entirely Even though this is only the destroy half of CreateBeforeDestroy, the resource may still require the same destroy order. --- terraform/graph_builder_apply_test.go | 105 ++++++++++++++++++++++++++ 1 file changed, 105 insertions(+) diff --git a/terraform/graph_builder_apply_test.go b/terraform/graph_builder_apply_test.go index c0827d05b..8e04587c1 100644 --- a/terraform/graph_builder_apply_test.go +++ b/terraform/graph_builder_apply_test.go @@ -610,6 +610,111 @@ test_object.b } } +// Ensure that an update resulting from the removal of a resource happens before +// a CBD resource is destroyed. +func TestApplyGraphBuilder_updateFromCBDOrphan(t *testing.T) { + schemas := simpleTestSchemas() + instanceSchema := schemas.Providers[addrs.NewLegacyProvider("test")].ResourceTypes["test_object"] + + bBefore, _ := plans.NewDynamicValue( + cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("b_id"), + "test_string": cty.StringVal("a_id"), + }), instanceSchema.ImpliedType()) + bAfter, _ := plans.NewDynamicValue( + cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("b_id"), + "test_string": cty.StringVal("changed"), + }), instanceSchema.ImpliedType()) + + changes := &plans.Changes{ + Resources: []*plans.ResourceInstanceChangeSrc{ + { + Addr: mustResourceInstanceAddr("test_object.a"), + ChangeSrc: plans.ChangeSrc{ + Action: plans.Delete, + }, + }, + { + Addr: mustResourceInstanceAddr("test_object.b"), + ChangeSrc: plans.ChangeSrc{ + Action: plans.Update, + Before: bBefore, + After: bAfter, + }, + }, + }, + } + + state := states.NewState() + root := state.EnsureModule(addrs.RootModuleInstance) + root.SetResourceInstanceCurrent( + addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "test_object", + Name: "a", + }.Instance(addrs.NoKey), + &states.ResourceInstanceObjectSrc{ + Status: states.ObjectReady, + AttrsJSON: []byte(`{"id":"a_id"}`), + CreateBeforeDestroy: true, + }, + addrs.LocalProviderConfig{ + LocalName: "test", + }.Absolute(addrs.RootModuleInstance), + ) + root.SetResourceInstanceCurrent( + addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "test_object", + Name: "b", + }.Instance(addrs.NoKey), + &states.ResourceInstanceObjectSrc{ + Status: states.ObjectReady, + AttrsJSON: []byte(`{"id":"b_id","test_string":"a_id"}`), + Dependencies: []addrs.AbsResource{ + addrs.AbsResource{ + Resource: addrs.Resource{ + Mode: addrs.ManagedResourceMode, + Type: "test_object", + Name: "a", + }, + Module: root.Addr, + }, + }, + }, + addrs.LocalProviderConfig{ + LocalName: "test", + }.Absolute(addrs.RootModuleInstance), + ) + + b := &ApplyGraphBuilder{ + Config: testModule(t, "graph-builder-apply-orphan-update"), + Changes: changes, + Components: simpleMockComponentFactory(), + Schemas: schemas, + State: state, + } + + g, err := b.Build(addrs.RootModuleInstance) + if err != nil { + t.Fatalf("err: %s", err) + } + + expected := strings.TrimSpace(` +test_object.a (destroy) + test_object.b +test_object.b +`) + + instanceGraph := filterInstances(g) + got := strings.TrimSpace(instanceGraph.String()) + + if got != expected { + t.Fatalf("expected:\n%s\ngot:\n%s", expected, got) + } +} + // The orphan clean up node should not be connected to a provider func TestApplyGraphBuilder_orphanedWithProvider(t *testing.T) { changes := &plans.Changes{