| package terraform |
| |
| import ( |
| "fmt" |
| "strings" |
| "testing" |
| |
| "github.com/google/go-cmp/cmp" |
| "github.com/zclconf/go-cty/cty" |
| |
| "github.com/hashicorp/terraform/internal/addrs" |
| "github.com/hashicorp/terraform/internal/plans" |
| "github.com/hashicorp/terraform/internal/states" |
| ) |
| |
| func TestApplyGraphBuilder_impl(t *testing.T) { |
| var _ GraphBuilder = new(ApplyGraphBuilder) |
| } |
| |
| func TestApplyGraphBuilder(t *testing.T) { |
| changes := &plans.Changes{ |
| Resources: []*plans.ResourceInstanceChangeSrc{ |
| { |
| Addr: mustResourceInstanceAddr("test_object.create"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.Create, |
| }, |
| }, |
| { |
| Addr: mustResourceInstanceAddr("test_object.other"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.Update, |
| }, |
| }, |
| { |
| Addr: mustResourceInstanceAddr("module.child.test_object.create"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.Create, |
| }, |
| }, |
| { |
| Addr: mustResourceInstanceAddr("module.child.test_object.other"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.Create, |
| }, |
| }, |
| }, |
| } |
| |
| b := &ApplyGraphBuilder{ |
| Config: testModule(t, "graph-builder-apply-basic"), |
| Changes: changes, |
| Plugins: simpleMockPluginLibrary(), |
| } |
| |
| g, err := b.Build(addrs.RootModuleInstance) |
| if err != nil { |
| t.Fatalf("err: %s", err) |
| } |
| |
| if g.Path.String() != addrs.RootModuleInstance.String() { |
| t.Fatalf("wrong path %q", g.Path.String()) |
| } |
| |
| got := strings.TrimSpace(g.String()) |
| want := strings.TrimSpace(testApplyGraphBuilderStr) |
| if diff := cmp.Diff(want, got); diff != "" { |
| t.Fatalf("wrong result\n%s", diff) |
| } |
| } |
| |
| // This tests the ordering of two resources where a non-CBD depends |
| // on a CBD. GH-11349. |
| func TestApplyGraphBuilder_depCbd(t *testing.T) { |
| changes := &plans.Changes{ |
| Resources: []*plans.ResourceInstanceChangeSrc{ |
| { |
| Addr: mustResourceInstanceAddr("test_object.A"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.CreateThenDelete, |
| }, |
| }, |
| { |
| Addr: mustResourceInstanceAddr("test_object.B"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.Update, |
| }, |
| }, |
| }, |
| } |
| |
| state := states.NewState() |
| root := state.EnsureModule(addrs.RootModuleInstance) |
| root.SetResourceInstanceCurrent( |
| mustResourceInstanceAddr("test_object.A").Resource, |
| &states.ResourceInstanceObjectSrc{ |
| Status: states.ObjectReady, |
| AttrsJSON: []byte(`{"id":"A"}`), |
| }, |
| mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), |
| ) |
| root.SetResourceInstanceCurrent( |
| mustResourceInstanceAddr("test_object.B").Resource, |
| &states.ResourceInstanceObjectSrc{ |
| Status: states.ObjectReady, |
| AttrsJSON: []byte(`{"id":"B","test_list":["x"]}`), |
| Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("test_object.A")}, |
| }, |
| mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), |
| ) |
| |
| b := &ApplyGraphBuilder{ |
| Config: testModule(t, "graph-builder-apply-dep-cbd"), |
| Changes: changes, |
| Plugins: simpleMockPluginLibrary(), |
| State: state, |
| } |
| |
| g, err := b.Build(addrs.RootModuleInstance) |
| if err != nil { |
| t.Fatalf("err: %s", err) |
| } |
| |
| if g.Path.String() != addrs.RootModuleInstance.String() { |
| t.Fatalf("wrong path %q", g.Path.String()) |
| } |
| |
| // We're going to go hunting for our deposed instance node here, so we |
| // can find out its key to use in the assertions below. |
| var dk states.DeposedKey |
| for _, v := range g.Vertices() { |
| tv, ok := v.(*NodeDestroyDeposedResourceInstanceObject) |
| if !ok { |
| continue |
| } |
| if dk != states.NotDeposed { |
| t.Fatalf("more than one deposed instance node in the graph; want only one") |
| } |
| dk = tv.DeposedKey |
| } |
| if dk == states.NotDeposed { |
| t.Fatalf("no deposed instance node in the graph; want one") |
| } |
| |
| destroyName := fmt.Sprintf("test_object.A (destroy deposed %s)", dk) |
| |
| // Create A, Modify B, Destroy A |
| testGraphHappensBefore( |
| t, g, |
| "test_object.A", |
| destroyName, |
| ) |
| testGraphHappensBefore( |
| t, g, |
| "test_object.A", |
| "test_object.B", |
| ) |
| testGraphHappensBefore( |
| t, g, |
| "test_object.B", |
| destroyName, |
| ) |
| } |
| |
| // This tests the ordering of two resources that are both CBD that |
| // require destroy/create. |
| func TestApplyGraphBuilder_doubleCBD(t *testing.T) { |
| changes := &plans.Changes{ |
| Resources: []*plans.ResourceInstanceChangeSrc{ |
| { |
| Addr: mustResourceInstanceAddr("test_object.A"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.CreateThenDelete, |
| }, |
| }, |
| { |
| Addr: mustResourceInstanceAddr("test_object.B"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.CreateThenDelete, |
| }, |
| }, |
| }, |
| } |
| |
| b := &ApplyGraphBuilder{ |
| Config: testModule(t, "graph-builder-apply-double-cbd"), |
| Changes: changes, |
| Plugins: simpleMockPluginLibrary(), |
| } |
| |
| g, err := b.Build(addrs.RootModuleInstance) |
| if err != nil { |
| t.Fatalf("err: %s", err) |
| } |
| |
| if g.Path.String() != addrs.RootModuleInstance.String() { |
| t.Fatalf("wrong path %q", g.Path.String()) |
| } |
| |
| // We're going to go hunting for our deposed instance node here, so we |
| // can find out its key to use in the assertions below. |
| var destroyA, destroyB string |
| for _, v := range g.Vertices() { |
| tv, ok := v.(*NodeDestroyDeposedResourceInstanceObject) |
| if !ok { |
| continue |
| } |
| |
| switch tv.Addr.Resource.Resource.Name { |
| case "A": |
| destroyA = fmt.Sprintf("test_object.A (destroy deposed %s)", tv.DeposedKey) |
| case "B": |
| destroyB = fmt.Sprintf("test_object.B (destroy deposed %s)", tv.DeposedKey) |
| default: |
| t.Fatalf("unknown instance: %s", tv.Addr) |
| } |
| } |
| |
| // Create A, Modify B, Destroy A |
| testGraphHappensBefore( |
| t, g, |
| "test_object.A", |
| destroyA, |
| ) |
| testGraphHappensBefore( |
| t, g, |
| "test_object.A", |
| "test_object.B", |
| ) |
| testGraphHappensBefore( |
| t, g, |
| "test_object.B", |
| destroyB, |
| ) |
| } |
| |
| // This tests the ordering of two resources being destroyed that depend |
| // on each other from only state. GH-11749 |
| func TestApplyGraphBuilder_destroyStateOnly(t *testing.T) { |
| changes := &plans.Changes{ |
| Resources: []*plans.ResourceInstanceChangeSrc{ |
| { |
| Addr: mustResourceInstanceAddr("module.child.test_object.A"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.Delete, |
| }, |
| }, |
| { |
| Addr: mustResourceInstanceAddr("module.child.test_object.B"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.Delete, |
| }, |
| }, |
| }, |
| } |
| |
| state := states.NewState() |
| root := state.EnsureModule(addrs.RootModuleInstance) |
| child := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey)) |
| root.SetResourceInstanceCurrent( |
| mustResourceInstanceAddr("test_object.A").Resource, |
| &states.ResourceInstanceObjectSrc{ |
| Status: states.ObjectReady, |
| AttrsJSON: []byte(`{"id":"foo"}`), |
| }, |
| mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), |
| ) |
| child.SetResourceInstanceCurrent( |
| mustResourceInstanceAddr("test_object.B").Resource, |
| &states.ResourceInstanceObjectSrc{ |
| Status: states.ObjectReady, |
| AttrsJSON: []byte(`{"id":"bar"}`), |
| Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("module.child.test_object.A")}, |
| }, |
| mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), |
| ) |
| |
| b := &ApplyGraphBuilder{ |
| Config: testModule(t, "empty"), |
| Changes: changes, |
| State: state, |
| Plugins: simpleMockPluginLibrary(), |
| } |
| |
| g, diags := b.Build(addrs.RootModuleInstance) |
| if diags.HasErrors() { |
| t.Fatalf("err: %s", diags.Err()) |
| } |
| |
| if g.Path.String() != addrs.RootModuleInstance.String() { |
| t.Fatalf("wrong path %q", g.Path.String()) |
| } |
| |
| testGraphHappensBefore( |
| t, g, |
| "module.child.test_object.B (destroy)", |
| "module.child.test_object.A (destroy)") |
| } |
| |
| // This tests the ordering of destroying a single count of a resource. |
| func TestApplyGraphBuilder_destroyCount(t *testing.T) { |
| changes := &plans.Changes{ |
| Resources: []*plans.ResourceInstanceChangeSrc{ |
| { |
| Addr: mustResourceInstanceAddr("test_object.A[1]"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.Delete, |
| }, |
| }, |
| { |
| Addr: mustResourceInstanceAddr("test_object.B"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.Update, |
| }, |
| }, |
| }, |
| } |
| |
| state := states.NewState() |
| root := state.RootModule() |
| addrA := mustResourceInstanceAddr("test_object.A[1]") |
| root.SetResourceInstanceCurrent( |
| addrA.Resource, |
| &states.ResourceInstanceObjectSrc{ |
| Status: states.ObjectReady, |
| AttrsJSON: []byte(`{"id":"B"}`), |
| }, |
| mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), |
| ) |
| root.SetResourceInstanceCurrent( |
| mustResourceInstanceAddr("test_object.B").Resource, |
| &states.ResourceInstanceObjectSrc{ |
| Status: states.ObjectReady, |
| AttrsJSON: []byte(`{"id":"B"}`), |
| Dependencies: []addrs.ConfigResource{addrA.ContainingResource().Config()}, |
| }, |
| mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), |
| ) |
| |
| b := &ApplyGraphBuilder{ |
| Config: testModule(t, "graph-builder-apply-count"), |
| Changes: changes, |
| Plugins: simpleMockPluginLibrary(), |
| State: state, |
| } |
| |
| g, err := b.Build(addrs.RootModuleInstance) |
| if err != nil { |
| t.Fatalf("err: %s", err) |
| } |
| |
| if g.Path.String() != addrs.RootModuleInstance.String() { |
| t.Fatalf("wrong module path %q", g.Path) |
| } |
| |
| got := strings.TrimSpace(g.String()) |
| want := strings.TrimSpace(testApplyGraphBuilderDestroyCountStr) |
| if diff := cmp.Diff(want, got); diff != "" { |
| t.Fatalf("wrong result\n%s", diff) |
| } |
| } |
| |
| func TestApplyGraphBuilder_moduleDestroy(t *testing.T) { |
| changes := &plans.Changes{ |
| Resources: []*plans.ResourceInstanceChangeSrc{ |
| { |
| Addr: mustResourceInstanceAddr("module.A.test_object.foo"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.Delete, |
| }, |
| }, |
| { |
| Addr: mustResourceInstanceAddr("module.B.test_object.foo"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.Delete, |
| }, |
| }, |
| }, |
| } |
| |
| state := states.NewState() |
| modA := state.EnsureModule(addrs.RootModuleInstance.Child("A", addrs.NoKey)) |
| modA.SetResourceInstanceCurrent( |
| mustResourceInstanceAddr("test_object.foo").Resource, |
| &states.ResourceInstanceObjectSrc{ |
| Status: states.ObjectReady, |
| AttrsJSON: []byte(`{"id":"foo"}`), |
| }, |
| mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), |
| ) |
| modB := state.EnsureModule(addrs.RootModuleInstance.Child("B", addrs.NoKey)) |
| modB.SetResourceInstanceCurrent( |
| mustResourceInstanceAddr("test_object.foo").Resource, |
| &states.ResourceInstanceObjectSrc{ |
| Status: states.ObjectReady, |
| AttrsJSON: []byte(`{"id":"foo","value":"foo"}`), |
| Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("module.A.test_object.foo")}, |
| }, |
| mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), |
| ) |
| |
| b := &ApplyGraphBuilder{ |
| Config: testModule(t, "graph-builder-apply-module-destroy"), |
| Changes: changes, |
| Plugins: simpleMockPluginLibrary(), |
| State: state, |
| } |
| |
| g, err := b.Build(addrs.RootModuleInstance) |
| if err != nil { |
| t.Fatalf("err: %s", err) |
| } |
| |
| testGraphHappensBefore( |
| t, g, |
| "module.B.test_object.foo (destroy)", |
| "module.A.test_object.foo (destroy)", |
| ) |
| } |
| |
| func TestApplyGraphBuilder_targetModule(t *testing.T) { |
| changes := &plans.Changes{ |
| Resources: []*plans.ResourceInstanceChangeSrc{ |
| { |
| Addr: mustResourceInstanceAddr("test_object.foo"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.Update, |
| }, |
| }, |
| { |
| Addr: mustResourceInstanceAddr("module.child2.test_object.foo"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.Update, |
| }, |
| }, |
| }, |
| } |
| |
| b := &ApplyGraphBuilder{ |
| Config: testModule(t, "graph-builder-apply-target-module"), |
| Changes: changes, |
| Plugins: simpleMockPluginLibrary(), |
| Targets: []addrs.Targetable{ |
| addrs.RootModuleInstance.Child("child2", addrs.NoKey), |
| }, |
| } |
| |
| g, err := b.Build(addrs.RootModuleInstance) |
| if err != nil { |
| t.Fatalf("err: %s", err) |
| } |
| |
| testGraphNotContains(t, g, "module.child1.output.instance_id") |
| } |
| |
| // Ensure that an update resulting from the removal of a resource happens after |
| // that resource is destroyed. |
| func TestApplyGraphBuilder_updateFromOrphan(t *testing.T) { |
| schemas := simpleTestSchemas() |
| instanceSchema := schemas.Providers[addrs.NewDefaultProvider("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"}`), |
| }, |
| addrs.AbsProviderConfig{ |
| Provider: addrs.NewDefaultProvider("test"), |
| Module: addrs.RootModule, |
| }, |
| ) |
| 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.ConfigResource{ |
| { |
| Resource: addrs.Resource{ |
| Mode: addrs.ManagedResourceMode, |
| Type: "test_object", |
| Name: "a", |
| }, |
| Module: root.Addr.Module(), |
| }, |
| }, |
| }, |
| addrs.AbsProviderConfig{ |
| Provider: addrs.NewDefaultProvider("test"), |
| Module: addrs.RootModule, |
| }, |
| ) |
| |
| b := &ApplyGraphBuilder{ |
| Config: testModule(t, "graph-builder-apply-orphan-update"), |
| Changes: changes, |
| Plugins: simpleMockPluginLibrary(), |
| 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.a (destroy) |
| `) |
| |
| instanceGraph := filterInstances(g) |
| got := strings.TrimSpace(instanceGraph.String()) |
| |
| if got != expected { |
| t.Fatalf("expected:\n%s\ngot:\n%s", expected, got) |
| } |
| } |
| |
| // 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.NewDefaultProvider("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, |
| }, |
| mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), |
| ) |
| 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.ConfigResource{ |
| { |
| Resource: addrs.Resource{ |
| Mode: addrs.ManagedResourceMode, |
| Type: "test_object", |
| Name: "a", |
| }, |
| Module: root.Addr.Module(), |
| }, |
| }, |
| }, |
| mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"]`), |
| ) |
| |
| b := &ApplyGraphBuilder{ |
| Config: testModule(t, "graph-builder-apply-orphan-update"), |
| Changes: changes, |
| Plugins: simpleMockPluginLibrary(), |
| 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{ |
| Resources: []*plans.ResourceInstanceChangeSrc{ |
| { |
| Addr: mustResourceInstanceAddr("test_object.A"), |
| ChangeSrc: plans.ChangeSrc{ |
| Action: plans.Delete, |
| }, |
| }, |
| }, |
| } |
| |
| state := states.NewState() |
| root := state.EnsureModule(addrs.RootModuleInstance) |
| root.SetResourceInstanceCurrent( |
| mustResourceInstanceAddr("test_object.A").Resource, |
| &states.ResourceInstanceObjectSrc{ |
| Status: states.ObjectReady, |
| AttrsJSON: []byte(`{"id":"A"}`), |
| }, |
| mustProviderConfig(`provider["registry.terraform.io/hashicorp/test"].foo`), |
| ) |
| |
| b := &ApplyGraphBuilder{ |
| Config: testModule(t, "graph-builder-orphan-alias"), |
| Changes: changes, |
| Plugins: simpleMockPluginLibrary(), |
| State: state, |
| } |
| |
| g, err := b.Build(addrs.RootModuleInstance) |
| if err != nil { |
| t.Fatal(err) |
| } |
| |
| // The cleanup node has no state or config of its own, so would create a |
| // default provider which we don't want. |
| testGraphNotContains(t, g, "provider.test") |
| } |
| |
| const testApplyGraphBuilderStr = ` |
| module.child (close) |
| module.child.test_object.other |
| module.child (expand) |
| module.child.test_object.create |
| module.child.test_object.create (expand) |
| module.child.test_object.create (expand) |
| module.child (expand) |
| provider["registry.terraform.io/hashicorp/test"] |
| module.child.test_object.other |
| module.child.test_object.create |
| module.child.test_object.other (expand) |
| module.child.test_object.other (expand) |
| module.child (expand) |
| provider["registry.terraform.io/hashicorp/test"] |
| provider["registry.terraform.io/hashicorp/test"] |
| provider["registry.terraform.io/hashicorp/test"] (close) |
| module.child.test_object.other |
| test_object.other |
| root |
| module.child (close) |
| provider["registry.terraform.io/hashicorp/test"] (close) |
| test_object.create |
| test_object.create (expand) |
| test_object.create (expand) |
| provider["registry.terraform.io/hashicorp/test"] |
| test_object.other |
| test_object.create |
| test_object.other (expand) |
| test_object.other (expand) |
| provider["registry.terraform.io/hashicorp/test"] |
| ` |
| |
| const testApplyGraphBuilderDestroyCountStr = ` |
| provider["registry.terraform.io/hashicorp/test"] |
| provider["registry.terraform.io/hashicorp/test"] (close) |
| test_object.B |
| root |
| provider["registry.terraform.io/hashicorp/test"] (close) |
| test_object.A (expand) |
| provider["registry.terraform.io/hashicorp/test"] |
| test_object.A[1] (destroy) |
| provider["registry.terraform.io/hashicorp/test"] |
| test_object.B |
| test_object.A (expand) |
| test_object.A[1] (destroy) |
| test_object.B (expand) |
| test_object.B (expand) |
| provider["registry.terraform.io/hashicorp/test"] |
| ` |