Merge pull request #1544 from hashicorp/b-destroy-target-provisioner

core: fix resource targeting w/ provisioners
This commit is contained in:
Paul Hinze 2015-04-30 16:03:17 -05:00
commit 443c7e053f
3 changed files with 76 additions and 22 deletions

View File

@ -2831,6 +2831,48 @@ func TestContext2Validate_tainted(t *testing.T) {
}
}
func TestContext2Validate_targetedDestroy(t *testing.T) {
m := testModule(t, "validate-targeted")
p := testProvider("aws")
pr := testProvisioner()
p.ApplyFn = testApplyFn
p.DiffFn = testDiffFn
ctx := testContext2(t, &ContextOpts{
Module: m,
Providers: map[string]ResourceProviderFactory{
"aws": testProviderFuncFixed(p),
},
Provisioners: map[string]ResourceProvisionerFactory{
"shell": testProvisionerFuncFixed(pr),
},
State: &State{
Modules: []*ModuleState{
&ModuleState{
Path: rootModulePath,
Resources: map[string]*ResourceState{
"aws_instance.foo": resourceState("aws_instance", "i-bcd345"),
"aws_instance.bar": resourceState("aws_instance", "i-abc123"),
},
},
},
},
Targets: []string{"aws_instance.foo"},
Destroy: true,
})
w, e := ctx.Validate()
if len(w) > 0 {
warnStr := ""
for _, v := range w {
warnStr = warnStr + " " + v
}
t.Fatalf("bad: %s", warnStr)
}
if len(e) > 0 {
t.Fatalf("bad: %s", e)
}
}
func TestContext2Validate_varRef(t *testing.T) {
m := testModule(t, "validate-variable-ref")
p := testProvider("aws")

View File

@ -0,0 +1,13 @@
resource "aws_instance" "foo" {
num = "2"
provisioner "shell" {
command = "echo hi"
}
}
resource "aws_instance" "bar" {
foo = "bar"
provisioner "shell" {
command = "echo hi"
}
}

View File

@ -28,12 +28,13 @@ func (t *TargetsTransformer) Transform(g *Graph) error {
}
for _, v := range g.Vertices() {
if targetedNodes.Include(v) {
} else {
if _, ok := v.(GraphNodeAddressable); ok {
if !targetedNodes.Include(v) {
g.Remove(v)
}
}
}
}
return nil
}
@ -49,35 +50,29 @@ func (t *TargetsTransformer) parseTargetAddresses() ([]ResourceAddress, error) {
return addrs, nil
}
// Returns the list of targeted nodes. A targeted node is either addressed
// directly, or is an Ancestor of a targeted node. Destroy mode keeps
// Descendents instead of Ancestors.
func (t *TargetsTransformer) selectTargetedNodes(
g *Graph, addrs []ResourceAddress) (*dag.Set, error) {
targetedNodes := new(dag.Set)
for _, v := range g.Vertices() {
// Keep all providers; they'll be pruned later if necessary
if r, ok := v.(GraphNodeProvider); ok {
targetedNodes.Add(r)
continue
}
if t.nodeIsTarget(v, addrs) {
targetedNodes.Add(v)
// For the remaining filter, we only care about addressable nodes
r, ok := v.(GraphNodeAddressable)
if !ok {
continue
}
if t.nodeIsTarget(r, addrs) {
targetedNodes.Add(r)
// If the node would like to know about targets, tell it.
if n, ok := r.(GraphNodeTargetable); ok {
n.SetTargets(addrs)
// We inform nodes that ask about the list of targets - helps for nodes
// that need to dynamically expand. Note that this only occurs for nodes
// that are already directly targeted.
if tn, ok := v.(GraphNodeTargetable); ok {
tn.SetTargets(addrs)
}
var deps *dag.Set
var err error
if t.Destroy {
deps, err = g.Descendents(r)
deps, err = g.Descendents(v)
} else {
deps, err = g.Ancestors(r)
deps, err = g.Ancestors(v)
}
if err != nil {
return nil, err
@ -92,7 +87,11 @@ func (t *TargetsTransformer) selectTargetedNodes(
}
func (t *TargetsTransformer) nodeIsTarget(
r GraphNodeAddressable, addrs []ResourceAddress) bool {
v dag.Vertex, addrs []ResourceAddress) bool {
r, ok := v.(GraphNodeAddressable)
if !ok {
return false
}
addr := r.ResourceAddress()
for _, targetAddr := range addrs {
if targetAddr.Equals(addr) {