Skip to content

Commit b5718dd

Browse files
nevins-bjosephholsten
authored andcommitted
adding exclude flag to plan and apply to exclude specified resource from map
reverting changes, changing target to exclude when using ! cleanup
1 parent 0c3f2a9 commit b5718dd

File tree

4 files changed

+124
-11
lines changed

4 files changed

+124
-11
lines changed

Diff for: command/apply.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -332,7 +332,8 @@ Options:
332332
333333
-target=resource Resource to target. Operation will be limited to this
334334
resource and its dependencies. This flag can be used
335-
multiple times.
335+
multiple times. Prefixing the resource with ! will
336+
exclude the resource.
336337
337338
-var 'foo=bar' Set a variable in the Terraform configuration. This
338339
flag can be set multiple times.

Diff for: command/plan.go

+2-1
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,8 @@ Options:
191191
192192
-target=resource Resource to target. Operation will be limited to this
193193
resource and its dependencies. This flag can be used
194-
multiple times.
194+
multiple times. Prefixing the resource with ! will
195+
exclude the resource.
195196
196197
-var 'foo=bar' Set a variable in the Terraform configuration. This
197198
flag can be set multiple times.

Diff for: terraform/transform_targets.go

+25-9
Original file line numberDiff line numberDiff line change
@@ -21,38 +21,54 @@ type TargetsTransformer struct {
2121
func (t *TargetsTransformer) Transform(g *Graph) error {
2222
if len(t.Targets) > 0 {
2323
// TODO: duplicated in OrphanTransformer; pull up parsing earlier
24-
addrs, err := t.parseTargetAddresses()
24+
targeted, excluded, err := t.parseTargetAddresses()
2525
if err != nil {
2626
return err
2727
}
2828

29-
targetedNodes, err := t.selectTargetedNodes(g, addrs)
29+
targetedNodes, err := t.selectTargetedNodes(g, targeted)
30+
if err != nil {
31+
return err
32+
}
33+
excludedNodes, err := t.selectTargetedNodes(g, excluded)
3034
if err != nil {
3135
return err
3236
}
3337

3438
for _, v := range g.Vertices() {
3539
if _, ok := v.(GraphNodeAddressable); ok {
36-
if !targetedNodes.Include(v) {
40+
if targetedNodes.Len() > 0 && !targetedNodes.Include(v) {
3741
log.Printf("[DEBUG] Removing %q, filtered by targeting.", dag.VertexName(v))
3842
g.Remove(v)
43+
} else if excludedNodes.Len() > 0 && excludedNodes.Include(v) {
44+
log.Printf("[DEBUG] Removing %s, filtered by targeting exclude.", dag.VertexName(v))
45+
g.Remove(v)
3946
}
4047
}
4148
}
4249
}
4350
return nil
4451
}
4552

46-
func (t *TargetsTransformer) parseTargetAddresses() ([]ResourceAddress, error) {
47-
addrs := make([]ResourceAddress, len(t.Targets))
48-
for i, target := range t.Targets {
53+
func (t *TargetsTransformer) parseTargetAddresses() ([]ResourceAddress, []ResourceAddress, error) {
54+
var targeted, excluded []ResourceAddress
55+
for _, target := range t.Targets {
56+
exclude := string(target[0]) == "!"
57+
if exclude {
58+
target = target[1:]
59+
log.Printf("[DEBUG] Excluding %s", target)
60+
}
4961
ta, err := ParseResourceAddress(target)
5062
if err != nil {
51-
return nil, err
63+
return nil, nil, err
64+
}
65+
if exclude {
66+
excluded = append(excluded, *ta)
67+
} else {
68+
targeted = append(targeted, *ta)
5269
}
53-
addrs[i] = *ta
5470
}
55-
return addrs, nil
71+
return targeted, excluded, nil
5672
}
5773

5874
// Returns the list of targeted nodes. A targeted node is either addressed

Diff for: terraform/transform_targets_test.go

+95
Original file line numberDiff line numberDiff line change
@@ -69,3 +69,98 @@ aws_instance.metoo
6969
t.Fatalf("bad:\n\nexpected:\n%s\n\ngot:\n%s\n", expected, actual)
7070
}
7171
}
72+
73+
func TestTargetsTransformer_exclude(t *testing.T) {
74+
mod := testModule(t, "transform-targets-basic")
75+
76+
g := Graph{Path: RootModulePath}
77+
{
78+
tf := &ConfigTransformer{Module: mod}
79+
if err := tf.Transform(&g); err != nil {
80+
t.Fatalf("err: %s", err)
81+
}
82+
}
83+
84+
{
85+
transform := &TargetsTransformer{Targets: []string{"!aws_instance.me"}}
86+
if err := transform.Transform(&g); err != nil {
87+
t.Fatalf("err: %s", err)
88+
}
89+
}
90+
91+
actual := strings.TrimSpace(g.String())
92+
expected := strings.TrimSpace(`
93+
aws_instance.notme
94+
aws_instance.notmeeither
95+
aws_subnet.notme
96+
aws_vpc.notme
97+
`)
98+
if actual != expected {
99+
t.Fatalf("bad:\n\nexpected:\n%s\n\ngot:\n%s\n", expected, actual)
100+
}
101+
}
102+
103+
func TestTargetsTransformer_exclude_destroy(t *testing.T) {
104+
mod := testModule(t, "transform-targets-destroy")
105+
106+
g := Graph{Path: RootModulePath}
107+
{
108+
tf := &ConfigTransformer{Module: mod}
109+
if err := tf.Transform(&g); err != nil {
110+
t.Fatalf("err: %s", err)
111+
}
112+
}
113+
114+
{
115+
transform := &TargetsTransformer{
116+
Targets: []string{"!aws_instance.me"},
117+
Destroy: true,
118+
}
119+
if err := transform.Transform(&g); err != nil {
120+
t.Fatalf("err: %s", err)
121+
}
122+
}
123+
124+
actual := strings.TrimSpace(g.String())
125+
expected := strings.TrimSpace(`
126+
aws_instance.notme
127+
aws_subnet.notme
128+
aws_vpc.notme
129+
aws_vpc.notme
130+
`)
131+
if actual != expected {
132+
t.Fatalf("bad:\n\nexpected:\n%s\n\ngot:\n%s\n", expected, actual)
133+
}
134+
}
135+
136+
func TestTargetsTransformer_include_exclude(t *testing.T) {
137+
mod := testModule(t, "transform-targets-basic")
138+
139+
g := Graph{Path: RootModulePath}
140+
{
141+
tf := &ConfigTransformer{Module: mod}
142+
if err := tf.Transform(&g); err != nil {
143+
t.Fatalf("err: %s", err)
144+
}
145+
}
146+
147+
{
148+
transform := &TargetsTransformer{
149+
Targets: []string{
150+
"aws_instance.me",
151+
"!aws_subnet.me",
152+
},
153+
}
154+
if err := transform.Transform(&g); err != nil {
155+
t.Fatalf("err: %s", err)
156+
}
157+
}
158+
159+
actual := strings.TrimSpace(g.String())
160+
expected := strings.TrimSpace(`
161+
aws_instance.me
162+
`)
163+
if actual != expected {
164+
t.Fatalf("bad:\n\nexpected:\n%s\n\ngot:\n%s\n", expected, actual)
165+
}
166+
}

0 commit comments

Comments
 (0)