Merge pull request #26186 from hashicorp/jbardin/cbd-module-dep

don't connect module closers to destroy nodes
This commit is contained in:
James Bardin 2020-09-09 14:15:57 -04:00 committed by GitHub
commit b8b6cae8ef
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 98 additions and 12 deletions

View File

@ -11766,3 +11766,84 @@ output "outputs" {
// Destroying again from the empty state should not cause any errors either // Destroying again from the empty state should not cause any errors either
destroy() destroy()
} }
func TestContext2Apply_createBeforeDestroyWithModule(t *testing.T) {
m := testModuleInline(t, map[string]string{
"main.tf": `
variable "v" {}
module "mod" {
source = "./mod"
in = var.v
}
resource "test_resource" "a" {
value = var.v
depends_on = [module.mod]
lifecycle {
create_before_destroy = true
}
}
`,
"mod/main.tf": `
variable "in" {}
resource "test_resource" "a" {
value = var.in
}
`})
p := testProvider("test")
p.ApplyFn = testApplyFn
p.PlanResourceChangeFn = func(req providers.PlanResourceChangeRequest) providers.PlanResourceChangeResponse {
proposed := req.ProposedNewState.AsValueMap()
proposed["id"] = cty.UnknownVal(cty.String)
return providers.PlanResourceChangeResponse{
PlannedState: cty.ObjectVal(proposed),
RequiresReplace: []cty.Path{cty.Path{cty.GetAttrStep{Name: "value"}}},
}
}
ctx := testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
},
Variables: InputValues{
"v": &InputValue{
Value: cty.StringVal("A"),
},
},
})
if _, diags := ctx.Plan(); diags.HasErrors() {
t.Fatalf("plan errors: %s", diags.Err())
}
state, diags := ctx.Apply()
if diags.HasErrors() {
t.Fatalf("apply errors: %s", diags.Err())
}
ctx = testContext2(t, &ContextOpts{
Config: m,
Providers: map[addrs.Provider]providers.Factory{
addrs.NewDefaultProvider("test"): testProviderFuncFixed(p),
},
Variables: InputValues{
"v": &InputValue{
Value: cty.StringVal("B"),
},
},
State: state,
})
if _, diags := ctx.Plan(); diags.HasErrors() {
t.Fatalf("plan errors: %s", diags.Err())
}
_, diags = ctx.Apply()
if diags.HasErrors() {
t.Fatalf("apply errors: %s", diags.Err())
}
}

View File

@ -43,8 +43,13 @@ func (t *ModuleExpansionTransformer) Transform(g *Graph) error {
// handled by the RemovedModuleTransformer, and those module closers are in // handled by the RemovedModuleTransformer, and those module closers are in
// the graph already, and need to be connected to their parent closers. // the graph already, and need to be connected to their parent closers.
for _, v := range g.Vertices() { for _, v := range g.Vertices() {
// skip closers so they don't attach to themselves switch v.(type) {
if _, ok := v.(*nodeCloseModule); ok { case GraphNodeDestroyer:
// Destroy nodes can only be ordered relative to other resource
// instances.
continue
case *nodeCloseModule:
// a module closer cannot connect to itself
continue continue
} }
@ -84,17 +89,17 @@ func (t *ModuleExpansionTransformer) transform(g *Graph, c *configs.Config, pare
Config: c.Module, Config: c.Module,
ModuleCall: modCall, ModuleCall: modCall,
} }
var v dag.Vertex = n var expander dag.Vertex = n
if t.Concrete != nil { if t.Concrete != nil {
v = t.Concrete(n) expander = t.Concrete(n)
} }
g.Add(v) g.Add(expander)
log.Printf("[TRACE] ModuleExpansionTransformer: Added %s as %T", c.Path, v) log.Printf("[TRACE] ModuleExpansionTransformer: Added %s as %T", c.Path, expander)
if parentNode != nil { if parentNode != nil {
log.Printf("[TRACE] ModuleExpansionTransformer: %s must wait for expansion of %s", dag.VertexName(v), dag.VertexName(parentNode)) log.Printf("[TRACE] ModuleExpansionTransformer: %s must wait for expansion of %s", dag.VertexName(expander), dag.VertexName(parentNode))
g.Connect(dag.BasicEdge(v, parentNode)) g.Connect(dag.BasicEdge(expander, parentNode))
} }
// Add the closer (which acts as the root module node) to provide a // 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
Addr: c.Path, Addr: c.Path,
} }
g.Add(closer) g.Add(closer)
g.Connect(dag.BasicEdge(closer, v)) g.Connect(dag.BasicEdge(closer, expander))
t.closers[c.Path.String()] = closer t.closers[c.Path.String()] = closer
for _, childV := range g.Vertices() { for _, childV := range g.Vertices() {
// don't connect a node to itself // don't connect a node to itself
if childV == v { if childV == expander {
continue continue
} }
@ -126,13 +131,13 @@ func (t *ModuleExpansionTransformer) transform(g *Graph, c *configs.Config, pare
if path.Equal(c.Path) { if path.Equal(c.Path) {
log.Printf("[TRACE] ModuleExpansionTransformer: %s must wait for expansion of %s", dag.VertexName(childV), c.Path) log.Printf("[TRACE] ModuleExpansionTransformer: %s must wait for expansion of %s", dag.VertexName(childV), c.Path)
g.Connect(dag.BasicEdge(childV, v)) g.Connect(dag.BasicEdge(childV, expander))
} }
} }
// Also visit child modules, recursively. // Also visit child modules, recursively.
for _, cc := range c.Children { for _, cc := range c.Children {
if err := t.transform(g, cc, v); err != nil { if err := t.transform(g, cc, expander); err != nil {
return err return err
} }
} }