Skip to content

Commit 4f5b9d0

Browse files
core: Document that TransformRoot must produce coalescable node
We use a non-pointer value for this particular node, which means that there can never be two root nodes in the same graph: the graph implementation will just coalesce them together when a second one is added. Our resource expansion code is relying on that coalescing so that it can subsume together multiple graphs for different modules instances into a single mega-graph with all instances across all module instances, with any root nodes coalescing together to produce a single root. This also updates one of the context tests that exercises resource expansion so that it will generate multiple resource instance nodes per module and thus potentially have multiple roots to coalesce together. However, we aren't currently explicitly validating the return values from DynamicExpand and so this test doesn't actually fail if the coalescing doesn't happen. We may choose to validate the DynamicExpand result in a later commit in order to make it more obvious if future modifications fail to uphold this invariant.
1 parent b9b39e9 commit 4f5b9d0

File tree

2 files changed

+33
-5
lines changed

2 files changed

+33
-5
lines changed

internal/terraform/context_plan2_test.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -453,7 +453,21 @@ func TestContext2Plan_resourceChecksInExpandedModule(t *testing.T) {
453453
a = "a"
454454
}
455455
456-
resource "test" "test" {
456+
resource "test" "test1" {
457+
lifecycle {
458+
postcondition {
459+
# It doesn't matter what this checks as long as it
460+
# passes, because if we don't handle expansion properly
461+
# then we'll crash before we even get to evaluating this.
462+
condition = local.a == local.a
463+
error_message = "Postcondition failed."
464+
}
465+
}
466+
}
467+
468+
resource "test" "test2" {
469+
count = 2
470+
457471
lifecycle {
458472
postcondition {
459473
# It doesn't matter what this checks as long as it
@@ -478,8 +492,12 @@ func TestContext2Plan_resourceChecksInExpandedModule(t *testing.T) {
478492
assertNoErrors(t, diags)
479493

480494
resourceInsts := []addrs.AbsResourceInstance{
481-
mustResourceInstanceAddr("module.child[0].test.test"),
482-
mustResourceInstanceAddr("module.child[1].test.test"),
495+
mustResourceInstanceAddr("module.child[0].test.test1"),
496+
mustResourceInstanceAddr("module.child[0].test.test2[0]"),
497+
mustResourceInstanceAddr("module.child[0].test.test2[1]"),
498+
mustResourceInstanceAddr("module.child[1].test.test1"),
499+
mustResourceInstanceAddr("module.child[1].test.test2[0]"),
500+
mustResourceInstanceAddr("module.child[1].test.test2[1]"),
483501
}
484502

485503
for _, instAddr := range resourceInsts {

internal/terraform/transform_root.go

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,21 @@ func (t *RootTransformer) Transform(g *Graph) error {
1515
return nil
1616
}
1717

18-
// Add a root
18+
// We intentionally add a graphNodeRoot value -- rather than a pointer to
19+
// one -- so that all root nodes will coalesce together if two graphs
20+
// are merged. Each distinct node value can only be in a graph once,
21+
// so adding another graphNodeRoot value to the same graph later will
22+
// be a no-op and all of the edges from root nodes will coalesce together
23+
// under Graph.Subsume.
24+
//
25+
// It's important to retain this coalescing guarantee under future
26+
// maintenence.
1927
var root graphNodeRoot
2028
g.Add(root)
2129

22-
// Connect the root to all the edges that need it
30+
// We initially make the root node depend on every node except itself.
31+
// If the caller subsequently runs transitive reduction on the graph then
32+
// it's typical for some of these edges to then be removed.
2333
for _, v := range g.Vertices() {
2434
if v == root {
2535
continue

0 commit comments

Comments
 (0)