Skip to content

Commit

Permalink
adding exclude flag to plan and apply to exclude specified resource f…
Browse files Browse the repository at this point in the history
…rom map

reverting changes, changing target to exclude when using !

cleanup
  • Loading branch information
nevins-b authored and josephholsten committed Sep 30, 2015
1 parent 0c3f2a9 commit b5718dd
Show file tree
Hide file tree
Showing 4 changed files with 124 additions and 11 deletions.
3 changes: 2 additions & 1 deletion command/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -332,7 +332,8 @@ Options:
-target=resource Resource to target. Operation will be limited to this
resource and its dependencies. This flag can be used
multiple times.
multiple times. Prefixing the resource with ! will
exclude the resource.
-var 'foo=bar' Set a variable in the Terraform configuration. This
flag can be set multiple times.
Expand Down
3 changes: 2 additions & 1 deletion command/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -191,7 +191,8 @@ Options:
-target=resource Resource to target. Operation will be limited to this
resource and its dependencies. This flag can be used
multiple times.
multiple times. Prefixing the resource with ! will
exclude the resource.
-var 'foo=bar' Set a variable in the Terraform configuration. This
flag can be set multiple times.
Expand Down
34 changes: 25 additions & 9 deletions terraform/transform_targets.go
Original file line number Diff line number Diff line change
Expand Up @@ -21,38 +21,54 @@ type TargetsTransformer struct {
func (t *TargetsTransformer) Transform(g *Graph) error {
if len(t.Targets) > 0 {
// TODO: duplicated in OrphanTransformer; pull up parsing earlier
addrs, err := t.parseTargetAddresses()
targeted, excluded, err := t.parseTargetAddresses()
if err != nil {
return err
}

targetedNodes, err := t.selectTargetedNodes(g, addrs)
targetedNodes, err := t.selectTargetedNodes(g, targeted)
if err != nil {
return err
}
excludedNodes, err := t.selectTargetedNodes(g, excluded)
if err != nil {
return err
}

for _, v := range g.Vertices() {
if _, ok := v.(GraphNodeAddressable); ok {
if !targetedNodes.Include(v) {
if targetedNodes.Len() > 0 && !targetedNodes.Include(v) {
log.Printf("[DEBUG] Removing %q, filtered by targeting.", dag.VertexName(v))
g.Remove(v)
} else if excludedNodes.Len() > 0 && excludedNodes.Include(v) {
log.Printf("[DEBUG] Removing %s, filtered by targeting exclude.", dag.VertexName(v))
g.Remove(v)
}
}
}
}
return nil
}

func (t *TargetsTransformer) parseTargetAddresses() ([]ResourceAddress, error) {
addrs := make([]ResourceAddress, len(t.Targets))
for i, target := range t.Targets {
func (t *TargetsTransformer) parseTargetAddresses() ([]ResourceAddress, []ResourceAddress, error) {
var targeted, excluded []ResourceAddress
for _, target := range t.Targets {
exclude := string(target[0]) == "!"
if exclude {
target = target[1:]
log.Printf("[DEBUG] Excluding %s", target)
}
ta, err := ParseResourceAddress(target)
if err != nil {
return nil, err
return nil, nil, err
}
if exclude {
excluded = append(excluded, *ta)
} else {
targeted = append(targeted, *ta)
}
addrs[i] = *ta
}
return addrs, nil
return targeted, excluded, nil
}

// Returns the list of targeted nodes. A targeted node is either addressed
Expand Down
95 changes: 95 additions & 0 deletions terraform/transform_targets_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,3 +69,98 @@ aws_instance.metoo
t.Fatalf("bad:\n\nexpected:\n%s\n\ngot:\n%s\n", expected, actual)
}
}

func TestTargetsTransformer_exclude(t *testing.T) {
mod := testModule(t, "transform-targets-basic")

g := Graph{Path: RootModulePath}
{
tf := &ConfigTransformer{Module: mod}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}

{
transform := &TargetsTransformer{Targets: []string{"!aws_instance.me"}}
if err := transform.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}

actual := strings.TrimSpace(g.String())
expected := strings.TrimSpace(`
aws_instance.notme
aws_instance.notmeeither
aws_subnet.notme
aws_vpc.notme
`)
if actual != expected {
t.Fatalf("bad:\n\nexpected:\n%s\n\ngot:\n%s\n", expected, actual)
}
}

func TestTargetsTransformer_exclude_destroy(t *testing.T) {
mod := testModule(t, "transform-targets-destroy")

g := Graph{Path: RootModulePath}
{
tf := &ConfigTransformer{Module: mod}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}

{
transform := &TargetsTransformer{
Targets: []string{"!aws_instance.me"},
Destroy: true,
}
if err := transform.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}

actual := strings.TrimSpace(g.String())
expected := strings.TrimSpace(`
aws_instance.notme
aws_subnet.notme
aws_vpc.notme
aws_vpc.notme
`)
if actual != expected {
t.Fatalf("bad:\n\nexpected:\n%s\n\ngot:\n%s\n", expected, actual)
}
}

func TestTargetsTransformer_include_exclude(t *testing.T) {
mod := testModule(t, "transform-targets-basic")

g := Graph{Path: RootModulePath}
{
tf := &ConfigTransformer{Module: mod}
if err := tf.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}

{
transform := &TargetsTransformer{
Targets: []string{
"aws_instance.me",
"!aws_subnet.me",
},
}
if err := transform.Transform(&g); err != nil {
t.Fatalf("err: %s", err)
}
}

actual := strings.TrimSpace(g.String())
expected := strings.TrimSpace(`
aws_instance.me
`)
if actual != expected {
t.Fatalf("bad:\n\nexpected:\n%s\n\ngot:\n%s\n", expected, actual)
}
}

0 comments on commit b5718dd

Please sign in to comment.