terraform: support create-before-destroy
This commit is contained in:
parent
a14ea76c84
commit
aef7718778
|
@ -482,6 +482,7 @@ func graphAddConfigResources(
|
|||
// these nodes for you.
|
||||
func graphAddDiff(g *depgraph.Graph, d *ModuleDiff) error {
|
||||
var nlist []*depgraph.Noun
|
||||
injected := make(map[*depgraph.Dependency]struct{})
|
||||
for _, n := range g.Nouns {
|
||||
rn, ok := n.Meta.(*GraphNodeResource)
|
||||
if !ok {
|
||||
|
@ -530,13 +531,43 @@ func graphAddDiff(g *depgraph.Graph, d *ModuleDiff) error {
|
|||
newDiff.Destroy = false
|
||||
rd = newDiff
|
||||
|
||||
// Add to the new noun to our dependencies so that the destroy
|
||||
// happens before the apply.
|
||||
n.Deps = append(n.Deps, &depgraph.Dependency{
|
||||
Name: newN.Name,
|
||||
Source: n,
|
||||
Target: newN,
|
||||
})
|
||||
// The dependency ordering depends on if the CreateBeforeDestroy
|
||||
// flag is enabled. If so, we must create the replacement first,
|
||||
// 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,
|
||||
Source: n,
|
||||
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
|
||||
|
@ -544,7 +575,6 @@ func graphAddDiff(g *depgraph.Graph, d *ModuleDiff) error {
|
|||
|
||||
// Go through each noun and make sure we calculate all the dependencies
|
||||
// properly.
|
||||
injected := make(map[*depgraph.Dependency]struct{})
|
||||
for _, n := range nlist {
|
||||
deps := n.Deps
|
||||
num := len(deps)
|
||||
|
@ -948,6 +978,7 @@ func graphAddRoot(g *depgraph.Graph) {
|
|||
})
|
||||
}
|
||||
g.Nouns = append(g.Nouns, root)
|
||||
g.Root = root
|
||||
}
|
||||
|
||||
// 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) {
|
||||
m := testModule(t, "graph-diff-module")
|
||||
diff := &Diff{
|
||||
|
@ -1044,8 +1130,19 @@ aws_load_balancer.weblb
|
|||
aws_load_balancer.weblb -> provider.aws
|
||||
provider.aws
|
||||
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 = `
|
||||
root: root
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
provider "aws" {}
|
||||
|
||||
resource "aws_instance" "bar" {
|
||||
ami = "abc"
|
||||
create_before_destroy = true
|
||||
}
|
Loading…
Reference in New Issue