github.com/eliastor/durgaform@v0.0.0-20220816172711-d0ab2d17673e/internal/durgaform/graph_builder_apply_test.go (about) 1 package durgaform 2 3 import ( 4 "fmt" 5 "strings" 6 "testing" 7 8 "github.com/google/go-cmp/cmp" 9 "github.com/zclconf/go-cty/cty" 10 11 "github.com/eliastor/durgaform/internal/addrs" 12 "github.com/eliastor/durgaform/internal/plans" 13 "github.com/eliastor/durgaform/internal/states" 14 ) 15 16 func TestApplyGraphBuilder_impl(t *testing.T) { 17 var _ GraphBuilder = new(ApplyGraphBuilder) 18 } 19 20 func TestApplyGraphBuilder(t *testing.T) { 21 changes := &plans.Changes{ 22 Resources: []*plans.ResourceInstanceChangeSrc{ 23 { 24 Addr: mustResourceInstanceAddr("test_object.create"), 25 ChangeSrc: plans.ChangeSrc{ 26 Action: plans.Create, 27 }, 28 }, 29 { 30 Addr: mustResourceInstanceAddr("test_object.other"), 31 ChangeSrc: plans.ChangeSrc{ 32 Action: plans.Update, 33 }, 34 }, 35 { 36 Addr: mustResourceInstanceAddr("module.child.test_object.create"), 37 ChangeSrc: plans.ChangeSrc{ 38 Action: plans.Create, 39 }, 40 }, 41 { 42 Addr: mustResourceInstanceAddr("module.child.test_object.other"), 43 ChangeSrc: plans.ChangeSrc{ 44 Action: plans.Create, 45 }, 46 }, 47 }, 48 } 49 50 b := &ApplyGraphBuilder{ 51 Config: testModule(t, "graph-builder-apply-basic"), 52 Changes: changes, 53 Plugins: simpleMockPluginLibrary(), 54 } 55 56 g, err := b.Build(addrs.RootModuleInstance) 57 if err != nil { 58 t.Fatalf("err: %s", err) 59 } 60 61 if g.Path.String() != addrs.RootModuleInstance.String() { 62 t.Fatalf("wrong path %q", g.Path.String()) 63 } 64 65 got := strings.TrimSpace(g.String()) 66 want := strings.TrimSpace(testApplyGraphBuilderStr) 67 if diff := cmp.Diff(want, got); diff != "" { 68 t.Fatalf("wrong result\n%s", diff) 69 } 70 } 71 72 // This tests the ordering of two resources where a non-CBD depends 73 // on a CBD. GH-11349. 74 func TestApplyGraphBuilder_depCbd(t *testing.T) { 75 changes := &plans.Changes{ 76 Resources: []*plans.ResourceInstanceChangeSrc{ 77 { 78 Addr: mustResourceInstanceAddr("test_object.A"), 79 ChangeSrc: plans.ChangeSrc{ 80 Action: plans.CreateThenDelete, 81 }, 82 }, 83 { 84 Addr: mustResourceInstanceAddr("test_object.B"), 85 ChangeSrc: plans.ChangeSrc{ 86 Action: plans.Update, 87 }, 88 }, 89 }, 90 } 91 92 state := states.NewState() 93 root := state.EnsureModule(addrs.RootModuleInstance) 94 root.SetResourceInstanceCurrent( 95 mustResourceInstanceAddr("test_object.A").Resource, 96 &states.ResourceInstanceObjectSrc{ 97 Status: states.ObjectReady, 98 AttrsJSON: []byte(`{"id":"A"}`), 99 }, 100 mustProviderConfig(`provider["registry.durgaform.io/hashicorp/test"]`), 101 ) 102 root.SetResourceInstanceCurrent( 103 mustResourceInstanceAddr("test_object.B").Resource, 104 &states.ResourceInstanceObjectSrc{ 105 Status: states.ObjectReady, 106 AttrsJSON: []byte(`{"id":"B","test_list":["x"]}`), 107 Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("test_object.A")}, 108 }, 109 mustProviderConfig(`provider["registry.durgaform.io/hashicorp/test"]`), 110 ) 111 112 b := &ApplyGraphBuilder{ 113 Config: testModule(t, "graph-builder-apply-dep-cbd"), 114 Changes: changes, 115 Plugins: simpleMockPluginLibrary(), 116 State: state, 117 } 118 119 g, err := b.Build(addrs.RootModuleInstance) 120 if err != nil { 121 t.Fatalf("err: %s", err) 122 } 123 124 if g.Path.String() != addrs.RootModuleInstance.String() { 125 t.Fatalf("wrong path %q", g.Path.String()) 126 } 127 128 // We're going to go hunting for our deposed instance node here, so we 129 // can find out its key to use in the assertions below. 130 var dk states.DeposedKey 131 for _, v := range g.Vertices() { 132 tv, ok := v.(*NodeDestroyDeposedResourceInstanceObject) 133 if !ok { 134 continue 135 } 136 if dk != states.NotDeposed { 137 t.Fatalf("more than one deposed instance node in the graph; want only one") 138 } 139 dk = tv.DeposedKey 140 } 141 if dk == states.NotDeposed { 142 t.Fatalf("no deposed instance node in the graph; want one") 143 } 144 145 destroyName := fmt.Sprintf("test_object.A (destroy deposed %s)", dk) 146 147 // Create A, Modify B, Destroy A 148 testGraphHappensBefore( 149 t, g, 150 "test_object.A", 151 destroyName, 152 ) 153 testGraphHappensBefore( 154 t, g, 155 "test_object.A", 156 "test_object.B", 157 ) 158 testGraphHappensBefore( 159 t, g, 160 "test_object.B", 161 destroyName, 162 ) 163 } 164 165 // This tests the ordering of two resources that are both CBD that 166 // require destroy/create. 167 func TestApplyGraphBuilder_doubleCBD(t *testing.T) { 168 changes := &plans.Changes{ 169 Resources: []*plans.ResourceInstanceChangeSrc{ 170 { 171 Addr: mustResourceInstanceAddr("test_object.A"), 172 ChangeSrc: plans.ChangeSrc{ 173 Action: plans.CreateThenDelete, 174 }, 175 }, 176 { 177 Addr: mustResourceInstanceAddr("test_object.B"), 178 ChangeSrc: plans.ChangeSrc{ 179 Action: plans.CreateThenDelete, 180 }, 181 }, 182 }, 183 } 184 185 b := &ApplyGraphBuilder{ 186 Config: testModule(t, "graph-builder-apply-double-cbd"), 187 Changes: changes, 188 Plugins: simpleMockPluginLibrary(), 189 } 190 191 g, err := b.Build(addrs.RootModuleInstance) 192 if err != nil { 193 t.Fatalf("err: %s", err) 194 } 195 196 if g.Path.String() != addrs.RootModuleInstance.String() { 197 t.Fatalf("wrong path %q", g.Path.String()) 198 } 199 200 // We're going to go hunting for our deposed instance node here, so we 201 // can find out its key to use in the assertions below. 202 var destroyA, destroyB string 203 for _, v := range g.Vertices() { 204 tv, ok := v.(*NodeDestroyDeposedResourceInstanceObject) 205 if !ok { 206 continue 207 } 208 209 switch tv.Addr.Resource.Resource.Name { 210 case "A": 211 destroyA = fmt.Sprintf("test_object.A (destroy deposed %s)", tv.DeposedKey) 212 case "B": 213 destroyB = fmt.Sprintf("test_object.B (destroy deposed %s)", tv.DeposedKey) 214 default: 215 t.Fatalf("unknown instance: %s", tv.Addr) 216 } 217 } 218 219 // Create A, Modify B, Destroy A 220 testGraphHappensBefore( 221 t, g, 222 "test_object.A", 223 destroyA, 224 ) 225 testGraphHappensBefore( 226 t, g, 227 "test_object.A", 228 "test_object.B", 229 ) 230 testGraphHappensBefore( 231 t, g, 232 "test_object.B", 233 destroyB, 234 ) 235 } 236 237 // This tests the ordering of two resources being destroyed that depend 238 // on each other from only state. GH-11749 239 func TestApplyGraphBuilder_destroyStateOnly(t *testing.T) { 240 changes := &plans.Changes{ 241 Resources: []*plans.ResourceInstanceChangeSrc{ 242 { 243 Addr: mustResourceInstanceAddr("module.child.test_object.A"), 244 ChangeSrc: plans.ChangeSrc{ 245 Action: plans.Delete, 246 }, 247 }, 248 { 249 Addr: mustResourceInstanceAddr("module.child.test_object.B"), 250 ChangeSrc: plans.ChangeSrc{ 251 Action: plans.Delete, 252 }, 253 }, 254 }, 255 } 256 257 state := states.NewState() 258 root := state.EnsureModule(addrs.RootModuleInstance) 259 child := state.EnsureModule(addrs.RootModuleInstance.Child("child", addrs.NoKey)) 260 root.SetResourceInstanceCurrent( 261 mustResourceInstanceAddr("test_object.A").Resource, 262 &states.ResourceInstanceObjectSrc{ 263 Status: states.ObjectReady, 264 AttrsJSON: []byte(`{"id":"foo"}`), 265 }, 266 mustProviderConfig(`provider["registry.durgaform.io/hashicorp/test"]`), 267 ) 268 child.SetResourceInstanceCurrent( 269 mustResourceInstanceAddr("test_object.B").Resource, 270 &states.ResourceInstanceObjectSrc{ 271 Status: states.ObjectReady, 272 AttrsJSON: []byte(`{"id":"bar"}`), 273 Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("module.child.test_object.A")}, 274 }, 275 mustProviderConfig(`provider["registry.durgaform.io/hashicorp/test"]`), 276 ) 277 278 b := &ApplyGraphBuilder{ 279 Config: testModule(t, "empty"), 280 Changes: changes, 281 State: state, 282 Plugins: simpleMockPluginLibrary(), 283 } 284 285 g, diags := b.Build(addrs.RootModuleInstance) 286 if diags.HasErrors() { 287 t.Fatalf("err: %s", diags.Err()) 288 } 289 290 if g.Path.String() != addrs.RootModuleInstance.String() { 291 t.Fatalf("wrong path %q", g.Path.String()) 292 } 293 294 testGraphHappensBefore( 295 t, g, 296 "module.child.test_object.B (destroy)", 297 "module.child.test_object.A (destroy)") 298 } 299 300 // This tests the ordering of destroying a single count of a resource. 301 func TestApplyGraphBuilder_destroyCount(t *testing.T) { 302 changes := &plans.Changes{ 303 Resources: []*plans.ResourceInstanceChangeSrc{ 304 { 305 Addr: mustResourceInstanceAddr("test_object.A[1]"), 306 ChangeSrc: plans.ChangeSrc{ 307 Action: plans.Delete, 308 }, 309 }, 310 { 311 Addr: mustResourceInstanceAddr("test_object.B"), 312 ChangeSrc: plans.ChangeSrc{ 313 Action: plans.Update, 314 }, 315 }, 316 }, 317 } 318 319 state := states.NewState() 320 root := state.RootModule() 321 addrA := mustResourceInstanceAddr("test_object.A[1]") 322 root.SetResourceInstanceCurrent( 323 addrA.Resource, 324 &states.ResourceInstanceObjectSrc{ 325 Status: states.ObjectReady, 326 AttrsJSON: []byte(`{"id":"B"}`), 327 }, 328 mustProviderConfig(`provider["registry.durgaform.io/hashicorp/test"]`), 329 ) 330 root.SetResourceInstanceCurrent( 331 mustResourceInstanceAddr("test_object.B").Resource, 332 &states.ResourceInstanceObjectSrc{ 333 Status: states.ObjectReady, 334 AttrsJSON: []byte(`{"id":"B"}`), 335 Dependencies: []addrs.ConfigResource{addrA.ContainingResource().Config()}, 336 }, 337 mustProviderConfig(`provider["registry.durgaform.io/hashicorp/test"]`), 338 ) 339 340 b := &ApplyGraphBuilder{ 341 Config: testModule(t, "graph-builder-apply-count"), 342 Changes: changes, 343 Plugins: simpleMockPluginLibrary(), 344 State: state, 345 } 346 347 g, err := b.Build(addrs.RootModuleInstance) 348 if err != nil { 349 t.Fatalf("err: %s", err) 350 } 351 352 if g.Path.String() != addrs.RootModuleInstance.String() { 353 t.Fatalf("wrong module path %q", g.Path) 354 } 355 356 got := strings.TrimSpace(g.String()) 357 want := strings.TrimSpace(testApplyGraphBuilderDestroyCountStr) 358 if diff := cmp.Diff(want, got); diff != "" { 359 t.Fatalf("wrong result\n%s", diff) 360 } 361 } 362 363 func TestApplyGraphBuilder_moduleDestroy(t *testing.T) { 364 changes := &plans.Changes{ 365 Resources: []*plans.ResourceInstanceChangeSrc{ 366 { 367 Addr: mustResourceInstanceAddr("module.A.test_object.foo"), 368 ChangeSrc: plans.ChangeSrc{ 369 Action: plans.Delete, 370 }, 371 }, 372 { 373 Addr: mustResourceInstanceAddr("module.B.test_object.foo"), 374 ChangeSrc: plans.ChangeSrc{ 375 Action: plans.Delete, 376 }, 377 }, 378 }, 379 } 380 381 state := states.NewState() 382 modA := state.EnsureModule(addrs.RootModuleInstance.Child("A", addrs.NoKey)) 383 modA.SetResourceInstanceCurrent( 384 mustResourceInstanceAddr("test_object.foo").Resource, 385 &states.ResourceInstanceObjectSrc{ 386 Status: states.ObjectReady, 387 AttrsJSON: []byte(`{"id":"foo"}`), 388 }, 389 mustProviderConfig(`provider["registry.durgaform.io/hashicorp/test"]`), 390 ) 391 modB := state.EnsureModule(addrs.RootModuleInstance.Child("B", addrs.NoKey)) 392 modB.SetResourceInstanceCurrent( 393 mustResourceInstanceAddr("test_object.foo").Resource, 394 &states.ResourceInstanceObjectSrc{ 395 Status: states.ObjectReady, 396 AttrsJSON: []byte(`{"id":"foo","value":"foo"}`), 397 Dependencies: []addrs.ConfigResource{mustConfigResourceAddr("module.A.test_object.foo")}, 398 }, 399 mustProviderConfig(`provider["registry.durgaform.io/hashicorp/test"]`), 400 ) 401 402 b := &ApplyGraphBuilder{ 403 Config: testModule(t, "graph-builder-apply-module-destroy"), 404 Changes: changes, 405 Plugins: simpleMockPluginLibrary(), 406 State: state, 407 } 408 409 g, err := b.Build(addrs.RootModuleInstance) 410 if err != nil { 411 t.Fatalf("err: %s", err) 412 } 413 414 testGraphHappensBefore( 415 t, g, 416 "module.B.test_object.foo (destroy)", 417 "module.A.test_object.foo (destroy)", 418 ) 419 } 420 421 func TestApplyGraphBuilder_targetModule(t *testing.T) { 422 changes := &plans.Changes{ 423 Resources: []*plans.ResourceInstanceChangeSrc{ 424 { 425 Addr: mustResourceInstanceAddr("test_object.foo"), 426 ChangeSrc: plans.ChangeSrc{ 427 Action: plans.Update, 428 }, 429 }, 430 { 431 Addr: mustResourceInstanceAddr("module.child2.test_object.foo"), 432 ChangeSrc: plans.ChangeSrc{ 433 Action: plans.Update, 434 }, 435 }, 436 }, 437 } 438 439 b := &ApplyGraphBuilder{ 440 Config: testModule(t, "graph-builder-apply-target-module"), 441 Changes: changes, 442 Plugins: simpleMockPluginLibrary(), 443 Targets: []addrs.Targetable{ 444 addrs.RootModuleInstance.Child("child2", addrs.NoKey), 445 }, 446 } 447 448 g, err := b.Build(addrs.RootModuleInstance) 449 if err != nil { 450 t.Fatalf("err: %s", err) 451 } 452 453 testGraphNotContains(t, g, "module.child1.output.instance_id") 454 } 455 456 // Ensure that an update resulting from the removal of a resource happens after 457 // that resource is destroyed. 458 func TestApplyGraphBuilder_updateFromOrphan(t *testing.T) { 459 schemas := simpleTestSchemas() 460 instanceSchema := schemas.Providers[addrs.NewDefaultProvider("test")].ResourceTypes["test_object"] 461 462 bBefore, _ := plans.NewDynamicValue( 463 cty.ObjectVal(map[string]cty.Value{ 464 "id": cty.StringVal("b_id"), 465 "test_string": cty.StringVal("a_id"), 466 }), instanceSchema.ImpliedType()) 467 bAfter, _ := plans.NewDynamicValue( 468 cty.ObjectVal(map[string]cty.Value{ 469 "id": cty.StringVal("b_id"), 470 "test_string": cty.StringVal("changed"), 471 }), instanceSchema.ImpliedType()) 472 473 changes := &plans.Changes{ 474 Resources: []*plans.ResourceInstanceChangeSrc{ 475 { 476 Addr: mustResourceInstanceAddr("test_object.a"), 477 ChangeSrc: plans.ChangeSrc{ 478 Action: plans.Delete, 479 }, 480 }, 481 { 482 Addr: mustResourceInstanceAddr("test_object.b"), 483 ChangeSrc: plans.ChangeSrc{ 484 Action: plans.Update, 485 Before: bBefore, 486 After: bAfter, 487 }, 488 }, 489 }, 490 } 491 492 state := states.NewState() 493 root := state.EnsureModule(addrs.RootModuleInstance) 494 root.SetResourceInstanceCurrent( 495 addrs.Resource{ 496 Mode: addrs.ManagedResourceMode, 497 Type: "test_object", 498 Name: "a", 499 }.Instance(addrs.NoKey), 500 &states.ResourceInstanceObjectSrc{ 501 Status: states.ObjectReady, 502 AttrsJSON: []byte(`{"id":"a_id"}`), 503 }, 504 addrs.AbsProviderConfig{ 505 Provider: addrs.NewDefaultProvider("test"), 506 Module: addrs.RootModule, 507 }, 508 ) 509 root.SetResourceInstanceCurrent( 510 addrs.Resource{ 511 Mode: addrs.ManagedResourceMode, 512 Type: "test_object", 513 Name: "b", 514 }.Instance(addrs.NoKey), 515 &states.ResourceInstanceObjectSrc{ 516 Status: states.ObjectReady, 517 AttrsJSON: []byte(`{"id":"b_id","test_string":"a_id"}`), 518 Dependencies: []addrs.ConfigResource{ 519 { 520 Resource: addrs.Resource{ 521 Mode: addrs.ManagedResourceMode, 522 Type: "test_object", 523 Name: "a", 524 }, 525 Module: root.Addr.Module(), 526 }, 527 }, 528 }, 529 addrs.AbsProviderConfig{ 530 Provider: addrs.NewDefaultProvider("test"), 531 Module: addrs.RootModule, 532 }, 533 ) 534 535 b := &ApplyGraphBuilder{ 536 Config: testModule(t, "graph-builder-apply-orphan-update"), 537 Changes: changes, 538 Plugins: simpleMockPluginLibrary(), 539 State: state, 540 } 541 542 g, err := b.Build(addrs.RootModuleInstance) 543 if err != nil { 544 t.Fatalf("err: %s", err) 545 } 546 547 expected := strings.TrimSpace(` 548 test_object.a (destroy) 549 test_object.b 550 test_object.a (destroy) 551 `) 552 553 instanceGraph := filterInstances(g) 554 got := strings.TrimSpace(instanceGraph.String()) 555 556 if got != expected { 557 t.Fatalf("expected:\n%s\ngot:\n%s", expected, got) 558 } 559 } 560 561 // Ensure that an update resulting from the removal of a resource happens before 562 // a CBD resource is destroyed. 563 func TestApplyGraphBuilder_updateFromCBDOrphan(t *testing.T) { 564 schemas := simpleTestSchemas() 565 instanceSchema := schemas.Providers[addrs.NewDefaultProvider("test")].ResourceTypes["test_object"] 566 567 bBefore, _ := plans.NewDynamicValue( 568 cty.ObjectVal(map[string]cty.Value{ 569 "id": cty.StringVal("b_id"), 570 "test_string": cty.StringVal("a_id"), 571 }), instanceSchema.ImpliedType()) 572 bAfter, _ := plans.NewDynamicValue( 573 cty.ObjectVal(map[string]cty.Value{ 574 "id": cty.StringVal("b_id"), 575 "test_string": cty.StringVal("changed"), 576 }), instanceSchema.ImpliedType()) 577 578 changes := &plans.Changes{ 579 Resources: []*plans.ResourceInstanceChangeSrc{ 580 { 581 Addr: mustResourceInstanceAddr("test_object.a"), 582 ChangeSrc: plans.ChangeSrc{ 583 Action: plans.Delete, 584 }, 585 }, 586 { 587 Addr: mustResourceInstanceAddr("test_object.b"), 588 ChangeSrc: plans.ChangeSrc{ 589 Action: plans.Update, 590 Before: bBefore, 591 After: bAfter, 592 }, 593 }, 594 }, 595 } 596 597 state := states.NewState() 598 root := state.EnsureModule(addrs.RootModuleInstance) 599 root.SetResourceInstanceCurrent( 600 addrs.Resource{ 601 Mode: addrs.ManagedResourceMode, 602 Type: "test_object", 603 Name: "a", 604 }.Instance(addrs.NoKey), 605 &states.ResourceInstanceObjectSrc{ 606 Status: states.ObjectReady, 607 AttrsJSON: []byte(`{"id":"a_id"}`), 608 CreateBeforeDestroy: true, 609 }, 610 mustProviderConfig(`provider["registry.durgaform.io/hashicorp/test"]`), 611 ) 612 root.SetResourceInstanceCurrent( 613 addrs.Resource{ 614 Mode: addrs.ManagedResourceMode, 615 Type: "test_object", 616 Name: "b", 617 }.Instance(addrs.NoKey), 618 &states.ResourceInstanceObjectSrc{ 619 Status: states.ObjectReady, 620 AttrsJSON: []byte(`{"id":"b_id","test_string":"a_id"}`), 621 Dependencies: []addrs.ConfigResource{ 622 { 623 Resource: addrs.Resource{ 624 Mode: addrs.ManagedResourceMode, 625 Type: "test_object", 626 Name: "a", 627 }, 628 Module: root.Addr.Module(), 629 }, 630 }, 631 }, 632 mustProviderConfig(`provider["registry.durgaform.io/hashicorp/test"]`), 633 ) 634 635 b := &ApplyGraphBuilder{ 636 Config: testModule(t, "graph-builder-apply-orphan-update"), 637 Changes: changes, 638 Plugins: simpleMockPluginLibrary(), 639 State: state, 640 } 641 642 g, err := b.Build(addrs.RootModuleInstance) 643 if err != nil { 644 t.Fatalf("err: %s", err) 645 } 646 647 expected := strings.TrimSpace(` 648 test_object.a (destroy) 649 test_object.b 650 test_object.b 651 `) 652 653 instanceGraph := filterInstances(g) 654 got := strings.TrimSpace(instanceGraph.String()) 655 656 if got != expected { 657 t.Fatalf("expected:\n%s\ngot:\n%s", expected, got) 658 } 659 } 660 661 // The orphan clean up node should not be connected to a provider 662 func TestApplyGraphBuilder_orphanedWithProvider(t *testing.T) { 663 changes := &plans.Changes{ 664 Resources: []*plans.ResourceInstanceChangeSrc{ 665 { 666 Addr: mustResourceInstanceAddr("test_object.A"), 667 ChangeSrc: plans.ChangeSrc{ 668 Action: plans.Delete, 669 }, 670 }, 671 }, 672 } 673 674 state := states.NewState() 675 root := state.EnsureModule(addrs.RootModuleInstance) 676 root.SetResourceInstanceCurrent( 677 mustResourceInstanceAddr("test_object.A").Resource, 678 &states.ResourceInstanceObjectSrc{ 679 Status: states.ObjectReady, 680 AttrsJSON: []byte(`{"id":"A"}`), 681 }, 682 mustProviderConfig(`provider["registry.durgaform.io/hashicorp/test"].foo`), 683 ) 684 685 b := &ApplyGraphBuilder{ 686 Config: testModule(t, "graph-builder-orphan-alias"), 687 Changes: changes, 688 Plugins: simpleMockPluginLibrary(), 689 State: state, 690 } 691 692 g, err := b.Build(addrs.RootModuleInstance) 693 if err != nil { 694 t.Fatal(err) 695 } 696 697 // The cleanup node has no state or config of its own, so would create a 698 // default provider which we don't want. 699 testGraphNotContains(t, g, "provider.test") 700 } 701 702 const testApplyGraphBuilderStr = ` 703 module.child (close) 704 module.child.test_object.other 705 module.child (expand) 706 module.child.test_object.create 707 module.child.test_object.create (expand) 708 module.child.test_object.create (expand) 709 module.child (expand) 710 provider["registry.durgaform.io/hashicorp/test"] 711 module.child.test_object.other 712 module.child.test_object.create 713 module.child.test_object.other (expand) 714 module.child.test_object.other (expand) 715 module.child (expand) 716 provider["registry.durgaform.io/hashicorp/test"] 717 provider["registry.durgaform.io/hashicorp/test"] 718 provider["registry.durgaform.io/hashicorp/test"] (close) 719 module.child.test_object.other 720 test_object.other 721 root 722 module.child (close) 723 provider["registry.durgaform.io/hashicorp/test"] (close) 724 test_object.create 725 test_object.create (expand) 726 test_object.create (expand) 727 provider["registry.durgaform.io/hashicorp/test"] 728 test_object.other 729 test_object.create 730 test_object.other (expand) 731 test_object.other (expand) 732 provider["registry.durgaform.io/hashicorp/test"] 733 ` 734 735 const testApplyGraphBuilderDestroyCountStr = ` 736 provider["registry.durgaform.io/hashicorp/test"] 737 provider["registry.durgaform.io/hashicorp/test"] (close) 738 test_object.B 739 root 740 provider["registry.durgaform.io/hashicorp/test"] (close) 741 test_object.A (expand) 742 provider["registry.durgaform.io/hashicorp/test"] 743 test_object.A[1] (destroy) 744 provider["registry.durgaform.io/hashicorp/test"] 745 test_object.B 746 test_object.A (expand) 747 test_object.A[1] (destroy) 748 test_object.B (expand) 749 test_object.B (expand) 750 provider["registry.durgaform.io/hashicorp/test"] 751 `