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 Jun 11, 2017
1 parent e50a57b commit d33174f
Show file tree
Hide file tree
Showing 4 changed files with 135 additions and 16 deletions.
3 changes: 2 additions & 1 deletion command/apply.go
Original file line number Diff line number Diff line change
Expand Up @@ -351,7 +351,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 @@ -171,7 +171,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
50 changes: 36 additions & 14 deletions terraform/transform_targets.go
Original file line number Diff line number Diff line change
Expand Up @@ -41,27 +41,36 @@ type TargetsTransformer struct {
// that already have the targets parsed
ParsedTargets []ResourceAddress

// List of parsed excludes, provided by callers like ResourceCountTransform
// that already have the targets parsed
ParsedExcludes []ResourceAddress

// Set to true when we're in a `terraform destroy` or a
// `terraform plan -destroy`
Destroy bool
}

func (t *TargetsTransformer) Transform(g *Graph) error {
if len(t.Targets) > 0 && len(t.ParsedTargets) == 0 {
addrs, err := t.parseTargetAddresses()
targeted, excluded, err := t.parseTargetAddresses()
if err != nil {
return err
}

t.ParsedTargets = addrs
t.ParsedTargets = targeted
t.ParsedExcludes = excluded
}

if len(t.ParsedTargets) > 0 {
if len(t.ParsedTargets) > 0 || len(t.ParsedExcludes) > 0 {
targetedNodes, err := t.selectTargetedNodes(g, t.ParsedTargets)
if err != nil {
return err
}

excludedNodes, err := t.selectTargetedNodes(g, t.ParsedExcludes)
if err != nil {
return err
}

for _, v := range g.Vertices() {
removable := false
if _, ok := v.(GraphNodeResource); ok {
Expand All @@ -70,27 +79,40 @@ func (t *TargetsTransformer) Transform(g *Graph) error {
if vr, ok := v.(RemovableIfNotTargeted); ok {
removable = vr.RemoveIfNotTargeted()
}
if removable && !targetedNodes.Include(v) {
log.Printf("[DEBUG] Removing %q, filtered by targeting.", dag.VertexName(v))
g.Remove(v)
if removable {
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 excluding.", 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 @@ -160,3 +160,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 d33174f

Please sign in to comment.