Skip to content

Commit

Permalink
command/taint: -allow-missing
Browse files Browse the repository at this point in the history
  • Loading branch information
mitchellh committed Feb 26, 2015
1 parent d43c88f commit d411e29
Show file tree
Hide file tree
Showing 3 changed files with 108 additions and 5 deletions.
40 changes: 35 additions & 5 deletions command/taint.go
Original file line number Diff line number Diff line change
Expand Up @@ -15,8 +15,10 @@ type TaintCommand struct {
func (c *TaintCommand) Run(args []string) int {
args = c.Meta.process(args, false)

var allowMissing bool
var module string
cmdFlags := c.Meta.flagSet("taint")
cmdFlags.BoolVar(&allowMissing, "allow-missing", false, "module")
cmdFlags.StringVar(&module, "module", "", "module")
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
cmdFlags.StringVar(&c.Meta.stateOutPath, "state-out", "", "path")
Expand All @@ -33,7 +35,13 @@ func (c *TaintCommand) Run(args []string) int {
cmdFlags.Usage()
return 1
}

name := args[0]
if module == "" {
module = "root"
} else {
module = "root." + module
}

// Get the state that we'll be modifying
state, err := c.State()
Expand All @@ -45,6 +53,10 @@ func (c *TaintCommand) Run(args []string) int {
// Get the actual state structure
s := state.State()
if s.Empty() {
if allowMissing {
return c.allowMissingExit(name, module)
}

c.Ui.Error(fmt.Sprintf(
"The state is empty. The most common reason for this is that\n" +
"an invalid state file path was given or Terraform has never\n " +
Expand All @@ -54,14 +66,13 @@ func (c *TaintCommand) Run(args []string) int {
}

// Get the proper module we want to taint
if module == "" {
module = "root"
} else {
module = "root." + module
}
modPath := strings.Split(module, ".")
mod := s.ModuleByPath(modPath)
if mod == nil {
if allowMissing {
return c.allowMissingExit(name, module)
}

c.Ui.Error(fmt.Sprintf(
"The module %s could not be found. There is nothing to taint.",
module))
Expand All @@ -70,6 +81,10 @@ func (c *TaintCommand) Run(args []string) int {

// If there are no resources in this module, it is an error
if len(mod.Resources) == 0 {
if allowMissing {
return c.allowMissingExit(name, module)
}

c.Ui.Error(fmt.Sprintf(
"The module %s has no resources. There is nothing to taint.",
module))
Expand All @@ -79,6 +94,10 @@ func (c *TaintCommand) Run(args []string) int {
// Get the resource we're looking for
rs, ok := mod.Resources[name]
if !ok {
if allowMissing {
return c.allowMissingExit(name, module)
}

c.Ui.Error(fmt.Sprintf(
"The resource %s couldn't be found in the module %s.",
name,
Expand Down Expand Up @@ -116,6 +135,9 @@ Usage: terraform taint [options] name
Options:
-allow-missing If specified, the command will succeed (exit code 0)
even if the resource is missing.
-backup=path Path to backup the existing state file before
modifying. Defaults to the "-state-out" path with
".backup" extension. Set to "-" to disable backup.
Expand All @@ -139,3 +161,11 @@ Options:
func (c *TaintCommand) Synopsis() string {
return "Manually mark a resource for recreation"
}

func (c *TaintCommand) allowMissingExit(name, module string) int {
c.Ui.Output(fmt.Sprintf(
"The resource %s in the module %s was not found, but\n"+
"-allow-missing is set, so we're exiting successfully.",
name, module))
return 0
}
69 changes: 69 additions & 0 deletions command/taint_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,75 @@ func TestTaint_defaultState(t *testing.T) {
testStateOutput(t, path, testTaintStr)
}

func TestTaint_missing(t *testing.T) {
state := &terraform.State{
Modules: []*terraform.ModuleState{
&terraform.ModuleState{
Path: []string{"root"},
Resources: map[string]*terraform.ResourceState{
"test_instance.foo": &terraform.ResourceState{
Type: "test_instance",
Primary: &terraform.InstanceState{
ID: "bar",
},
},
},
},
},
}
statePath := testStateFile(t, state)

ui := new(cli.MockUi)
c := &TaintCommand{
Meta: Meta{
Ui: ui,
},
}

args := []string{
"-state", statePath,
"test_instance.bar",
}
if code := c.Run(args); code == 0 {
t.Fatalf("bad: %d\n\n%s", code, ui.OutputWriter.String())
}
}

func TestTaint_missingAllow(t *testing.T) {
state := &terraform.State{
Modules: []*terraform.ModuleState{
&terraform.ModuleState{
Path: []string{"root"},
Resources: map[string]*terraform.ResourceState{
"test_instance.foo": &terraform.ResourceState{
Type: "test_instance",
Primary: &terraform.InstanceState{
ID: "bar",
},
},
},
},
},
}
statePath := testStateFile(t, state)

ui := new(cli.MockUi)
c := &TaintCommand{
Meta: Meta{
Ui: ui,
},
}

args := []string{
"-allow-missing",
"-state", statePath,
"test_instance.bar",
}
if code := c.Run(args); code != 0 {
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
}
}

func TestTaint_stateOut(t *testing.T) {
// Get a temp cwd
tmp, cwd := testCwd(t)
Expand Down
4 changes: 4 additions & 0 deletions website/source/docs/commands/taint.html.markdown
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ The format of this argument is `TYPE.NAME`, such as `aws_instance.foo`.

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

* `-allow-missing` - If specified, the command will succeed (exit code 0)
even if the resource is missing. The command can still error, but only
in critically erroneous cases.

* `-backup=path` - Path to the backup file. Defaults to `-state-out` with
the ".backup" extension. Disabled by setting to "-".

Expand Down

0 comments on commit d411e29

Please sign in to comment.