Skip to content

Commit

Permalink
command: terraform state rm to require at least one argument
Browse files Browse the repository at this point in the history
Due to how the state filter machinery works, passing no arguments is valid
and matches _all_ resources.

It is very unlikely that someone wants to remove everything from state, so
this ends up being a very dangerous default for the "terraform state rm"
command, and surprising for someone who perhaps runs it looking for the
usage information.

So we'll be pragmatic here and reject the no-arguments case for this
command, accepting that it makes the unlikely case of intentionally
deleting all resources harder in order to make it less likely that it
will happen _unintentionally_.

If someone does really want to remove all resources from the state, they
can provide an explicit empty string argument, but this isn't documented
because it's a weird case that doesn't seem worth mentioning.

This fixes #15283.
  • Loading branch information
apparentlymart committed Jul 5, 2017
1 parent d5ebad3 commit 9373bac
Show file tree
Hide file tree
Showing 2 changed files with 62 additions and 0 deletions.
5 changes: 5 additions & 0 deletions command/state_rm.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,11 @@ func (c *StateRmCommand) Run(args []string) int {
}
args = cmdFlags.Args()

if len(args) < 1 {
c.Ui.Error("At least one resource address is required.")
return 1
}

state, err := c.StateMeta.State(&c.Meta)
if err != nil {
c.Ui.Error(fmt.Sprintf(errStateLoadingState, err))
Expand Down
57 changes: 57 additions & 0 deletions command/state_rm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@ package command
import (
"os"
"path/filepath"
"strings"
"testing"

"github.com/hashicorp/terraform/terraform"
Expand Down Expand Up @@ -71,6 +72,62 @@ func TestStateRm(t *testing.T) {
testStateOutput(t, backups[0], testStateRmOutputOriginal)
}

func TestStateRmNoArgs(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",
Attributes: map[string]string{
"foo": "value",
"bar": "value",
},
},
},

"test_instance.bar": &terraform.ResourceState{
Type: "test_instance",
Primary: &terraform.InstanceState{
ID: "foo",
Attributes: map[string]string{
"foo": "value",
"bar": "value",
},
},
},
},
},
},
}

statePath := testStateFile(t, state)

p := testProvider()
ui := new(cli.MockUi)
c := &StateRmCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(p),
Ui: ui,
},
}

args := []string{
"-state", statePath,
}
if code := c.Run(args); code != 1 {
t.Errorf("wrong exit status %d; want %d", code, 1)
}

if msg := ui.ErrorWriter.String(); !strings.Contains(msg, "At least one resource address") {
t.Errorf("not the error we were looking for:\n%s", msg)
}

}

func TestStateRm_backupExplicit(t *testing.T) {
td := tempDir(t)
defer os.RemoveAll(td)
Expand Down

0 comments on commit 9373bac

Please sign in to comment.