Merge pull request #1544 from hashicorp/b-destroy-target-provisioner
core: fix resource targeting w/ provisioners
This commit is contained in:
commit
443c7e053f
|
@ -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) {
|
func TestContext2Validate_varRef(t *testing.T) {
|
||||||
m := testModule(t, "validate-variable-ref")
|
m := testModule(t, "validate-variable-ref")
|
||||||
p := testProvider("aws")
|
p := testProvider("aws")
|
||||||
|
|
|
@ -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"
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,9 +28,10 @@ func (t *TargetsTransformer) Transform(g *Graph) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range g.Vertices() {
|
for _, v := range g.Vertices() {
|
||||||
if targetedNodes.Include(v) {
|
if _, ok := v.(GraphNodeAddressable); ok {
|
||||||
} else {
|
if !targetedNodes.Include(v) {
|
||||||
g.Remove(v)
|
g.Remove(v)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -49,35 +50,29 @@ func (t *TargetsTransformer) parseTargetAddresses() ([]ResourceAddress, error) {
|
||||||
return addrs, nil
|
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(
|
func (t *TargetsTransformer) selectTargetedNodes(
|
||||||
g *Graph, addrs []ResourceAddress) (*dag.Set, error) {
|
g *Graph, addrs []ResourceAddress) (*dag.Set, error) {
|
||||||
targetedNodes := new(dag.Set)
|
targetedNodes := new(dag.Set)
|
||||||
for _, v := range g.Vertices() {
|
for _, v := range g.Vertices() {
|
||||||
// Keep all providers; they'll be pruned later if necessary
|
if t.nodeIsTarget(v, addrs) {
|
||||||
if r, ok := v.(GraphNodeProvider); ok {
|
targetedNodes.Add(v)
|
||||||
targetedNodes.Add(r)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
// For the remaining filter, we only care about addressable nodes
|
// We inform nodes that ask about the list of targets - helps for nodes
|
||||||
r, ok := v.(GraphNodeAddressable)
|
// that need to dynamically expand. Note that this only occurs for nodes
|
||||||
if !ok {
|
// that are already directly targeted.
|
||||||
continue
|
if tn, ok := v.(GraphNodeTargetable); ok {
|
||||||
}
|
tn.SetTargets(addrs)
|
||||||
|
|
||||||
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)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var deps *dag.Set
|
var deps *dag.Set
|
||||||
var err error
|
var err error
|
||||||
if t.Destroy {
|
if t.Destroy {
|
||||||
deps, err = g.Descendents(r)
|
deps, err = g.Descendents(v)
|
||||||
} else {
|
} else {
|
||||||
deps, err = g.Ancestors(r)
|
deps, err = g.Ancestors(v)
|
||||||
}
|
}
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
@ -92,7 +87,11 @@ func (t *TargetsTransformer) selectTargetedNodes(
|
||||||
}
|
}
|
||||||
|
|
||||||
func (t *TargetsTransformer) nodeIsTarget(
|
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()
|
addr := r.ResourceAddress()
|
||||||
for _, targetAddr := range addrs {
|
for _, targetAddr := range addrs {
|
||||||
if targetAddr.Equals(addr) {
|
if targetAddr.Equals(addr) {
|
||||||
|
|
Loading…
Reference in New Issue