Skip to content

Commit d411e29

Browse files
committed
command/taint: -allow-missing
1 parent d43c88f commit d411e29

3 files changed

Lines changed: 108 additions & 5 deletions

File tree

‎command/taint.go‎

Lines changed: 35 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -15,8 +15,10 @@ type TaintCommand struct {
1515
func (c *TaintCommand) Run(args []string) int {
1616
args = c.Meta.process(args, false)
1717

18+
var allowMissing bool
1819
var module string
1920
cmdFlags := c.Meta.flagSet("taint")
21+
cmdFlags.BoolVar(&allowMissing, "allow-missing", false, "module")
2022
cmdFlags.StringVar(&module, "module", "", "module")
2123
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
2224
cmdFlags.StringVar(&c.Meta.stateOutPath, "state-out", "", "path")
@@ -33,7 +35,13 @@ func (c *TaintCommand) Run(args []string) int {
3335
cmdFlags.Usage()
3436
return 1
3537
}
38+
3639
name := args[0]
40+
if module == "" {
41+
module = "root"
42+
} else {
43+
module = "root." + module
44+
}
3745

3846
// Get the state that we'll be modifying
3947
state, err := c.State()
@@ -45,6 +53,10 @@ func (c *TaintCommand) Run(args []string) int {
4553
// Get the actual state structure
4654
s := state.State()
4755
if s.Empty() {
56+
if allowMissing {
57+
return c.allowMissingExit(name, module)
58+
}
59+
4860
c.Ui.Error(fmt.Sprintf(
4961
"The state is empty. The most common reason for this is that\n" +
5062
"an invalid state file path was given or Terraform has never\n " +
@@ -54,14 +66,13 @@ func (c *TaintCommand) Run(args []string) int {
5466
}
5567

5668
// Get the proper module we want to taint
57-
if module == "" {
58-
module = "root"
59-
} else {
60-
module = "root." + module
61-
}
6269
modPath := strings.Split(module, ".")
6370
mod := s.ModuleByPath(modPath)
6471
if mod == nil {
72+
if allowMissing {
73+
return c.allowMissingExit(name, module)
74+
}
75+
6576
c.Ui.Error(fmt.Sprintf(
6677
"The module %s could not be found. There is nothing to taint.",
6778
module))
@@ -70,6 +81,10 @@ func (c *TaintCommand) Run(args []string) int {
7081

7182
// If there are no resources in this module, it is an error
7283
if len(mod.Resources) == 0 {
84+
if allowMissing {
85+
return c.allowMissingExit(name, module)
86+
}
87+
7388
c.Ui.Error(fmt.Sprintf(
7489
"The module %s has no resources. There is nothing to taint.",
7590
module))
@@ -79,6 +94,10 @@ func (c *TaintCommand) Run(args []string) int {
7994
// Get the resource we're looking for
8095
rs, ok := mod.Resources[name]
8196
if !ok {
97+
if allowMissing {
98+
return c.allowMissingExit(name, module)
99+
}
100+
82101
c.Ui.Error(fmt.Sprintf(
83102
"The resource %s couldn't be found in the module %s.",
84103
name,
@@ -116,6 +135,9 @@ Usage: terraform taint [options] name
116135
117136
Options:
118137
138+
-allow-missing If specified, the command will succeed (exit code 0)
139+
even if the resource is missing.
140+
119141
-backup=path Path to backup the existing state file before
120142
modifying. Defaults to the "-state-out" path with
121143
".backup" extension. Set to "-" to disable backup.
@@ -139,3 +161,11 @@ Options:
139161
func (c *TaintCommand) Synopsis() string {
140162
return "Manually mark a resource for recreation"
141163
}
164+
165+
func (c *TaintCommand) allowMissingExit(name, module string) int {
166+
c.Ui.Output(fmt.Sprintf(
167+
"The resource %s in the module %s was not found, but\n"+
168+
"-allow-missing is set, so we're exiting successfully.",
169+
name, module))
170+
return 0
171+
}

‎command/taint_test.go‎

Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -187,6 +187,75 @@ func TestTaint_defaultState(t *testing.T) {
187187
testStateOutput(t, path, testTaintStr)
188188
}
189189

190+
func TestTaint_missing(t *testing.T) {
191+
state := &terraform.State{
192+
Modules: []*terraform.ModuleState{
193+
&terraform.ModuleState{
194+
Path: []string{"root"},
195+
Resources: map[string]*terraform.ResourceState{
196+
"test_instance.foo": &terraform.ResourceState{
197+
Type: "test_instance",
198+
Primary: &terraform.InstanceState{
199+
ID: "bar",
200+
},
201+
},
202+
},
203+
},
204+
},
205+
}
206+
statePath := testStateFile(t, state)
207+
208+
ui := new(cli.MockUi)
209+
c := &TaintCommand{
210+
Meta: Meta{
211+
Ui: ui,
212+
},
213+
}
214+
215+
args := []string{
216+
"-state", statePath,
217+
"test_instance.bar",
218+
}
219+
if code := c.Run(args); code == 0 {
220+
t.Fatalf("bad: %d\n\n%s", code, ui.OutputWriter.String())
221+
}
222+
}
223+
224+
func TestTaint_missingAllow(t *testing.T) {
225+
state := &terraform.State{
226+
Modules: []*terraform.ModuleState{
227+
&terraform.ModuleState{
228+
Path: []string{"root"},
229+
Resources: map[string]*terraform.ResourceState{
230+
"test_instance.foo": &terraform.ResourceState{
231+
Type: "test_instance",
232+
Primary: &terraform.InstanceState{
233+
ID: "bar",
234+
},
235+
},
236+
},
237+
},
238+
},
239+
}
240+
statePath := testStateFile(t, state)
241+
242+
ui := new(cli.MockUi)
243+
c := &TaintCommand{
244+
Meta: Meta{
245+
Ui: ui,
246+
},
247+
}
248+
249+
args := []string{
250+
"-allow-missing",
251+
"-state", statePath,
252+
"test_instance.bar",
253+
}
254+
if code := c.Run(args); code != 0 {
255+
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
256+
}
257+
}
258+
190259
func TestTaint_stateOut(t *testing.T) {
191260
// Get a temp cwd
192261
tmp, cwd := testCwd(t)

‎website/source/docs/commands/taint.html.markdown‎

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,10 @@ The format of this argument is `TYPE.NAME`, such as `aws_instance.foo`.
4040

4141
The command-line flags are all optional. The list of available flags are:
4242

43+
* `-allow-missing` - If specified, the command will succeed (exit code 0)
44+
even if the resource is missing. The command can still error, but only
45+
in critically erroneous cases.
46+
4347
* `-backup=path` - Path to the backup file. Defaults to `-state-out` with
4448
the ".backup" extension. Disabled by setting to "-".
4549

0 commit comments

Comments
 (0)