terraform: support create-before-destroy
This commit is contained in:
parent
a14ea76c84
commit
aef7718778
|
@ -482,6 +482,7 @@ func graphAddConfigResources(
|
||||||
// these nodes for you.
|
// these nodes for you.
|
||||||
func graphAddDiff(g *depgraph.Graph, d *ModuleDiff) error {
|
func graphAddDiff(g *depgraph.Graph, d *ModuleDiff) error {
|
||||||
var nlist []*depgraph.Noun
|
var nlist []*depgraph.Noun
|
||||||
|
injected := make(map[*depgraph.Dependency]struct{})
|
||||||
for _, n := range g.Nouns {
|
for _, n := range g.Nouns {
|
||||||
rn, ok := n.Meta.(*GraphNodeResource)
|
rn, ok := n.Meta.(*GraphNodeResource)
|
||||||
if !ok {
|
if !ok {
|
||||||
|
@ -530,13 +531,43 @@ func graphAddDiff(g *depgraph.Graph, d *ModuleDiff) error {
|
||||||
newDiff.Destroy = false
|
newDiff.Destroy = false
|
||||||
rd = newDiff
|
rd = newDiff
|
||||||
|
|
||||||
// Add to the new noun to our dependencies so that the destroy
|
// The dependency ordering depends on if the CreateBeforeDestroy
|
||||||
// happens before the apply.
|
// flag is enabled. If so, we must create the replacement first,
|
||||||
n.Deps = append(n.Deps, &depgraph.Dependency{
|
// and then destroy the old instance.
|
||||||
|
if rn.Config != nil && rn.Config.CreateBeforeDestroy && !rd.Empty() {
|
||||||
|
dep := &depgraph.Dependency{
|
||||||
|
Name: n.Name,
|
||||||
|
Source: newN,
|
||||||
|
Target: n,
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the old noun to the new noun dependencies so that
|
||||||
|
// the create happens before the destroy.
|
||||||
|
newN.Deps = append(newN.Deps, dep)
|
||||||
|
|
||||||
|
// Mark that this dependency has been injected so that
|
||||||
|
// we do not invert the direction below.
|
||||||
|
injected[dep] = struct{}{}
|
||||||
|
|
||||||
|
// Add a depedency from the root, since the create node
|
||||||
|
// does not depend on us
|
||||||
|
g.Root.Deps = append(g.Root.Deps, &depgraph.Dependency{
|
||||||
|
Name: newN.Name,
|
||||||
|
Source: g.Root,
|
||||||
|
Target: newN,
|
||||||
|
})
|
||||||
|
|
||||||
|
} else {
|
||||||
|
dep := &depgraph.Dependency{
|
||||||
Name: newN.Name,
|
Name: newN.Name,
|
||||||
Source: n,
|
Source: n,
|
||||||
Target: newN,
|
Target: newN,
|
||||||
})
|
}
|
||||||
|
|
||||||
|
// Add the new noun to our dependencies so that
|
||||||
|
// the destroy happens before the apply.
|
||||||
|
n.Deps = append(n.Deps, dep)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
rn.Resource.Diff = rd
|
rn.Resource.Diff = rd
|
||||||
|
@ -544,7 +575,6 @@ func graphAddDiff(g *depgraph.Graph, d *ModuleDiff) error {
|
||||||
|
|
||||||
// Go through each noun and make sure we calculate all the dependencies
|
// Go through each noun and make sure we calculate all the dependencies
|
||||||
// properly.
|
// properly.
|
||||||
injected := make(map[*depgraph.Dependency]struct{})
|
|
||||||
for _, n := range nlist {
|
for _, n := range nlist {
|
||||||
deps := n.Deps
|
deps := n.Deps
|
||||||
num := len(deps)
|
num := len(deps)
|
||||||
|
@ -948,6 +978,7 @@ func graphAddRoot(g *depgraph.Graph) {
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
g.Nouns = append(g.Nouns, root)
|
g.Nouns = append(g.Nouns, root)
|
||||||
|
g.Root = root
|
||||||
}
|
}
|
||||||
|
|
||||||
// graphAddVariableDeps inspects all the nouns and adds any dependencies
|
// graphAddVariableDeps inspects all the nouns and adds any dependencies
|
||||||
|
|
|
@ -652,6 +652,92 @@ func TestGraphAddDiff_module(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestGraphAddDiff_createBeforeDestroy(t *testing.T) {
|
||||||
|
config := testConfig(t, "graph-diff-create-before")
|
||||||
|
diff := &Diff{
|
||||||
|
Resources: map[string]*InstanceDiff{
|
||||||
|
"aws_instance.bar": &InstanceDiff{
|
||||||
|
Destroy: true,
|
||||||
|
Attributes: map[string]*ResourceAttrDiff{
|
||||||
|
"ami": &ResourceAttrDiff{
|
||||||
|
Old: "abc",
|
||||||
|
New: "xyz",
|
||||||
|
RequiresNew: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
state := &State{
|
||||||
|
Modules: []*ModuleState{
|
||||||
|
&ModuleState{
|
||||||
|
Path: rootModulePath,
|
||||||
|
Resources: map[string]*ResourceState{
|
||||||
|
"aws_instance.bar": &ResourceState{
|
||||||
|
Type: "aws_instance",
|
||||||
|
Primary: &InstanceState{
|
||||||
|
ID: "bar",
|
||||||
|
Attributes: map[string]string{
|
||||||
|
"ami": "abc",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
diffHash := checksumStruct(t, diff)
|
||||||
|
|
||||||
|
g, err := Graph(&GraphOpts{
|
||||||
|
Config: config,
|
||||||
|
Diff: diff,
|
||||||
|
State: state,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := strings.TrimSpace(g.String())
|
||||||
|
expected := strings.TrimSpace(testTerraformGraphDiffCreateBeforeDestroyStr)
|
||||||
|
if actual != expected {
|
||||||
|
t.Fatalf("bad:\n\n%s\n\nexpected:\n\n%s", actual, expected)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Verify that our original structure has not been modified
|
||||||
|
diffHash2 := checksumStruct(t, diff)
|
||||||
|
if diffHash != diffHash2 {
|
||||||
|
t.Fatal("diff has been modified")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestGraphInitState(t *testing.T) {
|
||||||
|
config := testConfig(t, "graph-basic")
|
||||||
|
state := &State{
|
||||||
|
Modules: []*ModuleState{
|
||||||
|
&ModuleState{
|
||||||
|
Path: rootModulePath,
|
||||||
|
Resources: map[string]*InstanceDiff{
|
||||||
|
"aws_instance.foo": &InstanceDiff{
|
||||||
|
Destroy: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
g, err := Graph(&GraphOpts{Module: m, Diff: diff})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("err: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
actual := strings.TrimSpace(g.String())
|
||||||
|
expected := strings.TrimSpace(testTerraformGraphDiffModuleStr)
|
||||||
|
if actual != expected {
|
||||||
|
t.Fatalf("bad:\n\n%s", actual)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestGraphAddDiff_moduleDestroy(t *testing.T) {
|
func TestGraphAddDiff_moduleDestroy(t *testing.T) {
|
||||||
m := testModule(t, "graph-diff-module")
|
m := testModule(t, "graph-diff-module")
|
||||||
diff := &Diff{
|
diff := &Diff{
|
||||||
|
@ -1044,8 +1130,19 @@ aws_load_balancer.weblb
|
||||||
aws_load_balancer.weblb -> provider.aws
|
aws_load_balancer.weblb -> provider.aws
|
||||||
provider.aws
|
provider.aws
|
||||||
root
|
root
|
||||||
root -> aws_load_balancer.weblb
|
root -> aws_load_balancer.weblb`
|
||||||
`
|
|
||||||
|
const testTerraformGraphDiffCreateBeforeDestroyStr = `
|
||||||
|
root: root
|
||||||
|
aws_instance.bar
|
||||||
|
aws_instance.bar -> provider.aws
|
||||||
|
aws_instance.bar (destroy)
|
||||||
|
aws_instance.bar (destroy) -> aws_instance.bar
|
||||||
|
aws_instance.bar (destroy) -> provider.aws
|
||||||
|
provider.aws
|
||||||
|
root
|
||||||
|
root -> aws_instance.bar
|
||||||
|
root -> aws_instance.bar (destroy)`
|
||||||
|
|
||||||
const testTerraformGraphStateStr = `
|
const testTerraformGraphStateStr = `
|
||||||
root: root
|
root: root
|
||||||
|
|
|
@ -0,0 +1,6 @@
|
||||||
|
provider "aws" {}
|
||||||
|
|
||||||
|
resource "aws_instance" "bar" {
|
||||||
|
ami = "abc"
|
||||||
|
create_before_destroy = true
|
||||||
|
}
|
Loading…
Reference in New Issue