Skip to content

Commit b8b6cae

Browse files
authored
Merge pull request #26186 from hashicorp/jbardin/cbd-module-dep
don't connect module closers to destroy nodes
2 parents 069f379 + c9e581e commit b8b6cae

File tree

2 files changed

+98
-12
lines changed

2 files changed

+98
-12
lines changed

terraform/context_apply_test.go

Lines changed: 81 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11766,3 +11766,84 @@ output "outputs" {
1176611766
// Destroying again from the empty state should not cause any errors either
1176711767
destroy()
1176811768
}
11769+
11770+
func TestContext2Apply_createBeforeDestroyWithModule(t *testing.T) {
11771+
m := testModuleInline(t, map[string]string{
11772+
"main.tf": `
11773+
variable "v" {}
11774+
11775+
module "mod" {
11776+
source = "./mod"
11777+
in = var.v
11778+
}
11779+
11780+
resource "test_resource" "a" {
11781+
value = var.v
11782+
depends_on = [module.mod]
11783+
lifecycle {
11784+
create_before_destroy = true
11785+
}
11786+
}
11787+
`,
11788+
"mod/main.tf": `
11789+
variable "in" {}
11790+
11791+
resource "test_resource" "a" {
11792+
value = var.in
11793+
}
11794+
`})
11795+
11796+
p := testProvider("test")
11797+
p.ApplyFn = testApplyFn
11798+
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
11799+
proposed := req.ProposedNewState.AsValueMap()
11800+
proposed["id"] = cty.UnknownVal(cty.String)
11801+
return providers.PlanResourceChangeResponse{
11802+
PlannedState: cty.ObjectVal(proposed),
11803+
RequiresReplace: []cty.Path{cty.Path{cty.GetAttrStep{Name: "value"}}},
11804+
}
11805+
}
11806+
11807+
ctx := testContext2(t, &ContextOpts{
11808+
Config: m,
11809+
Providers: map[addrs.Provider]providers.Factory{
11810+
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
11811+
},
11812+
Variables: InputValues{
11813+
"v": &InputValue{
11814+
Value: cty.StringVal("A"),
11815+
},
11816+
},
11817+
})
11818+
11819+
if _, diags := ctx.Plan(); diags.HasErrors() {
11820+
t.Fatalf("plan errors: %s", diags.Err())
11821+
}
11822+
11823+
state, diags := ctx.Apply()
11824+
if diags.HasErrors() {
11825+
t.Fatalf("apply errors: %s", diags.Err())
11826+
}
11827+
11828+
ctx = testContext2(t, &ContextOpts{
11829+
Config: m,
11830+
Providers: map[addrs.Provider]providers.Factory{
11831+
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
11832+
},
11833+
Variables: InputValues{
11834+
"v": &InputValue{
11835+
Value: cty.StringVal("B"),
11836+
},
11837+
},
11838+
State: state,
11839+
})
11840+
11841+
if _, diags := ctx.Plan(); diags.HasErrors() {
11842+
t.Fatalf("plan errors: %s", diags.Err())
11843+
}
11844+
11845+
_, diags = ctx.Apply()
11846+
if diags.HasErrors() {
11847+
t.Fatalf("apply errors: %s", diags.Err())
11848+
}
11849+
}

terraform/transform_module_expansion.go

Lines changed: 17 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -43,8 +43,13 @@ func (t *ModuleExpansionTransformer) Transform(g *Graph) error {
4343
// handled by the RemovedModuleTransformer, and those module closers are in
4444
// the graph already, and need to be connected to their parent closers.
4545
for _, v := range g.Vertices() {
46-
// skip closers so they don't attach to themselves
47-
if _, ok := v.(*nodeCloseModule); ok {
46+
switch v.(type) {
47+
case GraphNodeDestroyer:
48+
// Destroy nodes can only be ordered relative to other resource
49+
// instances.
50+
continue
51+
case *nodeCloseModule:
52+
// a module closer cannot connect to itself
4853
continue
4954
}
5055

@@ -84,17 +89,17 @@ func (t *ModuleExpansionTransformer) transform(g *Graph, c *configs.Config, pare
8489
Config: c.Module,
8590
ModuleCall: modCall,
8691
}
87-
var v dag.Vertex = n
92+
var expander dag.Vertex = n
8893
if t.Concrete != nil {
89-
v = t.Concrete(n)
94+
expander = t.Concrete(n)
9095
}
9196

92-
g.Add(v)
93-
log.Printf("[TRACE] ModuleExpansionTransformer: Added %s as %T", c.Path, v)
97+
g.Add(expander)
98+
log.Printf("[TRACE] ModuleExpansionTransformer: Added %s as %T", c.Path, expander)
9499

95100
if parentNode != nil {
96-
log.Printf("[TRACE] ModuleExpansionTransformer: %s must wait for expansion of %s", dag.VertexName(v), dag.VertexName(parentNode))
97-
g.Connect(dag.BasicEdge(v, parentNode))
101+
log.Printf("[TRACE] ModuleExpansionTransformer: %s must wait for expansion of %s", dag.VertexName(expander), dag.VertexName(parentNode))
102+
g.Connect(dag.BasicEdge(expander, parentNode))
98103
}
99104

100105
// Add the closer (which acts as the root module node) to provide a
@@ -103,12 +108,12 @@ func (t *ModuleExpansionTransformer) transform(g *Graph, c *configs.Config, pare
103108
Addr: c.Path,
104109
}
105110
g.Add(closer)
106-
g.Connect(dag.BasicEdge(closer, v))
111+
g.Connect(dag.BasicEdge(closer, expander))
107112
t.closers[c.Path.String()] = closer
108113

109114
for _, childV := range g.Vertices() {
110115
// don't connect a node to itself
111-
if childV == v {
116+
if childV == expander {
112117
continue
113118
}
114119

@@ -126,13 +131,13 @@ func (t *ModuleExpansionTransformer) transform(g *Graph, c *configs.Config, pare
126131

127132
if path.Equal(c.Path) {
128133
log.Printf("[TRACE] ModuleExpansionTransformer: %s must wait for expansion of %s", dag.VertexName(childV), c.Path)
129-
g.Connect(dag.BasicEdge(childV, v))
134+
g.Connect(dag.BasicEdge(childV, expander))
130135
}
131136
}
132137

133138
// Also visit child modules, recursively.
134139
for _, cc := range c.Children {
135-
if err := t.transform(g, cc, v); err != nil {
140+
if err := t.transform(g, cc, expander); err != nil {
136141
return err
137142
}
138143
}

0 commit comments

Comments
 (0)