Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

terraform state commands ignore the -state flag #15388

Merged
merged 3 commits into from
Jun 23, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
79 changes: 48 additions & 31 deletions command/state_meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,46 +18,63 @@ type StateMeta struct{}
// backups to be timestamped rather than just the original state path plus a
// backup path.
func (c *StateMeta) State(m *Meta) (state.State, error) {
// Load the backend
b, err := m.Backend(nil)
if err != nil {
return nil, err
}
var realState state.State
backupPath := m.backupPath
stateOutPath := m.statePath

env := m.Workspace()
// Get the state
s, err := b.State(env)
if err != nil {
return nil, err
}
// use the specified state
if m.statePath != "" {
realState = &state.LocalState{
Path: m.statePath,
}
} else {
// Load the backend
b, err := m.Backend(nil)
if err != nil {
return nil, err
}

// Get a local backend
localRaw, err := m.Backend(&BackendOpts{ForceLocal: true})
if err != nil {
// This should never fail
panic(err)
}
localB := localRaw.(*backendlocal.Local)
_, stateOutPath, _ := localB.StatePaths(env)
if err != nil {
return nil, err
env := m.Workspace()
// Get the state
s, err := b.State(env)
if err != nil {
return nil, err
}

// Get a local backend
localRaw, err := m.Backend(&BackendOpts{ForceLocal: true})
if err != nil {
// This should never fail
panic(err)
}
localB := localRaw.(*backendlocal.Local)
_, stateOutPath, _ = localB.StatePaths(env)
if err != nil {
return nil, err
}

realState = s
}

// Determine the backup path. stateOutPath is set to the resulting
// file where state is written (cached in the case of remote state)
backupPath := fmt.Sprintf(
"%s.%d%s",
stateOutPath,
time.Now().UTC().Unix(),
DefaultBackupExtension)
// We always backup state commands, so set the back if none was specified
// (the default is "-", but some tests bypass the flag parsing).
if backupPath == "-" || backupPath == "" {
// Determine the backup path. stateOutPath is set to the resulting
// file where state is written (cached in the case of remote state)
backupPath = fmt.Sprintf(
"%s.%d%s",
stateOutPath,
time.Now().UTC().Unix(),
DefaultBackupExtension)
}

// Wrap it for backups
s = &state.BackupState{
Real: s,
realState = &state.BackupState{
Real: realState,
Path: backupPath,
}

return s, nil
return realState, nil
}

// filterInstance filters a single instance out of filter results.
Expand Down
3 changes: 1 addition & 2 deletions command/state_mv.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,8 +203,7 @@ Options:
-backup=PATH Path where Terraform should write the backup for the original
state. This can't be disabled. If not set, Terraform
will write it to the same path as the statefile with
a backup extension. This backup will be made in addition
to the timestamped backup.
a backup extension.

-backup-out=PATH Path where Terraform should write the backup for the destination
state. This can't be disabled. If not set, Terraform
Expand Down
88 changes: 82 additions & 6 deletions command/state_mv_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ import (
"path/filepath"
"testing"

"github.com/hashicorp/terraform/helper/copy"
"github.com/hashicorp/terraform/terraform"
"github.com/mitchellh/cli"
)
Expand Down Expand Up @@ -72,6 +73,86 @@ func TestStateMv(t *testing.T) {
testStateOutput(t, backups[0], testStateMvOutputOriginal)
}

// don't modify backend state is we supply a -state flag
func TestStateMv_explicitWithBackend(t *testing.T) {
td := tempDir(t)
copy.CopyDir(testFixturePath("init-backend"), td)
defer os.RemoveAll(td)
defer testChdir(t, td)()

backupPath := filepath.Join(td, "backup")

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.baz": &terraform.ResourceState{
Type: "test_instance",
Primary: &terraform.InstanceState{
ID: "foo",
Attributes: map[string]string{
"foo": "value",
"bar": "value",
},
},
},
},
},
},
}

statePath := testStateFile(t, state)

// init our backend
ui := new(cli.MockUi)
ic := &InitCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(testProvider()),
Ui: ui,
},
}

args := []string{}
if code := ic.Run(args); code != 0 {
t.Fatalf("bad: \n%s", ui.ErrorWriter.String())
}

// only modify statePath
p := testProvider()
ui = new(cli.MockUi)
c := &StateMvCommand{
Meta: Meta{
testingOverrides: metaOverridesForProvider(p),
Ui: ui,
},
}

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

// Test it is correct
testStateOutput(t, statePath, testStateMvOutput)
}

func TestStateMv_backupExplicit(t *testing.T) {
td := tempDir(t)
defer os.RemoveAll(td)
Expand Down Expand Up @@ -132,12 +213,7 @@ func TestStateMv_backupExplicit(t *testing.T) {
// Test it is correct
testStateOutput(t, statePath, testStateMvOutput)

// Test we have backups
backups := testStateBackups(t, filepath.Dir(statePath))
if len(backups) != 1 {
t.Fatalf("bad: %#v", backups)
}
testStateOutput(t, backups[0], testStateMvOutputOriginal)
// Test backup
testStateOutput(t, backupPath, testStateMvOutputOriginal)
}

Expand Down
3 changes: 1 addition & 2 deletions command/state_rm.go
Original file line number Diff line number Diff line change
Expand Up @@ -78,8 +78,7 @@ Options:
-backup=PATH Path where Terraform should write the backup
state. This can't be disabled. If not set, Terraform
will write it to the same path as the statefile with
a backup extension. This backup will be made in addition
to the timestamped backup.
a backup extension.

-state=statefile Path to a Terraform state file to use to look
up Terraform-managed resources. By default it will
Expand Down
7 changes: 1 addition & 6 deletions command/state_rm_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -130,12 +130,7 @@ func TestStateRm_backupExplicit(t *testing.T) {
// Test it is correct
testStateOutput(t, statePath, testStateRmOutput)

// Test we have backups
backups := testStateBackups(t, filepath.Dir(statePath))
if len(backups) != 1 {
t.Fatalf("bad: %#v", backups)
}
testStateOutput(t, backups[0], testStateRmOutputOriginal)
// Test backup
testStateOutput(t, backupPath, testStateRmOutputOriginal)
}

Expand Down