diff --git a/state/local.go b/state/local.go index a18a5b5c6..22c7a7bd0 100644 --- a/state/local.go +++ b/state/local.go @@ -8,9 +8,14 @@ import ( // LocalState manages a state storage that is local to the filesystem. type LocalState struct { - Path string + // Path is the path to read the state from. PathOut is the path to + // write the state to. If PathOut is not specified, Path will be used. + // If PathOut already exists, it will be overwritten. + Path string + PathOut string - state *terraform.State + state *terraform.State + written bool } // StateReader impl. @@ -24,13 +29,23 @@ func (s *LocalState) State() *terraform.State { func (s *LocalState) WriteState(state *terraform.State) error { s.state = state - f, err := os.Create(s.Path) + path := s.PathOut + if path == "" { + path = s.Path + } + + f, err := os.Create(path) if err != nil { return err } defer f.Close() - return terraform.WriteState(s.state, f) + if err := terraform.WriteState(s.state, f); err != nil { + return err + } + + s.written = true + return nil } // PersistState for LocalState is a no-op since WriteState always persists. @@ -42,21 +57,30 @@ func (s *LocalState) PersistState() error { // StateRefresher impl. func (s *LocalState) RefreshState() error { - f, err := os.Open(s.Path) + // If we've never loaded before, read from Path, otherwise we + // read from PathOut. + path := s.Path + if s.written && s.PathOut != "" { + path = s.PathOut + } + + f, err := os.Open(path) if err != nil { // It is okay if the file doesn't exist, we treat that as a nil state - if os.IsNotExist(err) { - s.state = nil - return nil + if !os.IsNotExist(err) { + return err } - return err + f = nil } - defer f.Close() - state, err := terraform.ReadState(f) - if err != nil { - return err + var state *terraform.State + if f != nil { + defer f.Close() + state, err = terraform.ReadState(f) + if err != nil { + return err + } } s.state = state diff --git a/state/local_test.go b/state/local_test.go index edf8595a1..7930d3ccd 100644 --- a/state/local_test.go +++ b/state/local_test.go @@ -14,6 +14,21 @@ func TestLocalState(t *testing.T) { TestState(t, ls) } +func TestLocalState_pathOut(t *testing.T) { + f, err := ioutil.TempFile("", "tf") + if err != nil { + t.Fatalf("err: %s", err) + } + f.Close() + defer os.Remove(f.Name()) + + ls := testLocalState(t) + ls.PathOut = f.Name() + defer os.Remove(ls.Path) + + TestState(t, ls) +} + func TestLocalState_nonExist(t *testing.T) { ls := &LocalState{Path: "ishouldntexist"} if err := ls.RefreshState(); err != nil {