Merge pull request #13258 from hashicorp/jbardin/local-init

don't delete local state on a local backend
This commit is contained in:
James Bardin 2017-04-03 14:23:36 -04:00 committed by GitHub
commit f7776e7e1c
2 changed files with 67 additions and 6 deletions

View File

@ -1002,7 +1002,8 @@ func (m *Meta) backend_C_r_s(
}
// If the local state is not empty, we need to potentially do a
// state migration to the new backend (with user permission).
// state migration to the new backend (with user permission), unless the
// destination is also "local"
if localS := localState.State(); !localS.Empty() {
// Perform the migration
err = m.backendMigrateState(&backendMigrateOpts{
@ -1015,12 +1016,27 @@ func (m *Meta) backend_C_r_s(
return nil, err
}
// We always delete the local state
if err := localState.WriteState(nil); err != nil {
return nil, fmt.Errorf(errBackendMigrateLocalDelete, err)
// we usually remove the local state after migration to prevent
// confusion, but adding a default local backend block to the config
// can get us here too. Don't delete our state if the old and new paths
// are the same.
erase := true
if newLocalB, ok := b.(*backendlocal.Local); ok {
if localB, ok := localB.(*backendlocal.Local); ok {
if newLocalB.StatePath == localB.StatePath {
erase = false
}
}
}
if err := localState.PersistState(); err != nil {
return nil, fmt.Errorf(errBackendMigrateLocalDelete, err)
if erase {
// We always delete the local state, unless that was our new state too.
if err := localState.WriteState(nil); err != nil {
return nil, fmt.Errorf(errBackendMigrateLocalDelete, err)
}
if err := localState.PersistState(); err != nil {
return nil, fmt.Errorf(errBackendMigrateLocalDelete, err)
}
}
}

View File

@ -3275,6 +3275,51 @@ func TestMetaBackend_configureWithExtra(t *testing.T) {
}
}
// when confniguring a default local state, don't delete local state
func TestMetaBackend_localDoesNotDeleteLocal(t *testing.T) {
// Create a temporary working directory that is empty
td := tempDir(t)
copy.CopyDir(testFixturePath("init-backend-empty"), td)
defer os.RemoveAll(td)
defer testChdir(t, td)()
// create our local state
orig := &terraform.State{
Modules: []*terraform.ModuleState{
{
Path: []string{"root"},
Outputs: map[string]*terraform.OutputState{
"foo": {
Value: "bar",
Type: "string",
},
},
},
},
}
err := (&state.LocalState{Path: DefaultStateFilename}).WriteState(orig)
if err != nil {
t.Fatal(err)
}
m := testMetaBackend(t, nil)
m.forceInitCopy = true
// init the backend
_, err = m.Backend(&BackendOpts{
Init: true,
})
if err != nil {
t.Fatalf("bad: %s", err)
}
// check that we can read the state
s := testStateRead(t, DefaultStateFilename)
if s.Empty() {
t.Fatal("our state was deleted")
}
}
// move options from config to -backend-config
func TestMetaBackend_configToExtra(t *testing.T) {
// Create a temporary working directory that is empty