diff --git a/states/statemgr/filesystem.go b/states/statemgr/filesystem.go index e44f85db5..bbb03dad7 100644 --- a/states/statemgr/filesystem.go +++ b/states/statemgr/filesystem.go @@ -123,6 +123,13 @@ func (s *Filesystem) WriteState(state *states.State) error { // writing to a temp file on the same filesystem, and renaming the file over // the original. + if s.readFile == nil { + err := s.RefreshState() + if err != nil { + return err + } + } + defer s.mutex()() // We'll try to write our backup first, so we can be sure we've created @@ -150,6 +157,9 @@ func (s *Filesystem) WriteState(state *states.State) error { defer s.stateFileOut.Sync() s.file = s.file.DeepCopy() + if s.file == nil { + s.file = NewStateFile() + } s.file.State = state.DeepCopy() if _, err := s.stateFileOut.Seek(0, os.SEEK_SET); err != nil { @@ -164,7 +174,7 @@ func (s *Filesystem) WriteState(state *states.State) error { return nil } - if !statefile.StatesMarshalEqual(s.file.State, s.readFile.State) { + if s.readFile == nil || !statefile.StatesMarshalEqual(s.file.State, s.readFile.State) { s.file.Serial++ } diff --git a/states/statemgr/lineage.go b/states/statemgr/lineage.go new file mode 100644 index 000000000..73010081a --- /dev/null +++ b/states/statemgr/lineage.go @@ -0,0 +1,32 @@ +package statemgr + +import ( + "fmt" + + uuid "github.com/hashicorp/go-uuid" + + "github.com/hashicorp/terraform/states/statefile" + "github.com/hashicorp/terraform/version" +) + +// NewLineage generates a new lineage identifier string. A lineage identifier +// is an opaque string that is intended to be unique in space and time, chosen +// when state is recorded at a location for the first time and then preserved +// afterwards to allow Terraform to recognize when one state snapshot is a +// predecessor or successor of another. +func NewLineage() string { + lineage, err := uuid.GenerateUUID() + if err != nil { + panic(fmt.Errorf("Failed to generate lineage: %v", err)) + } + return lineage +} + +// NewStateFile creates a new statefile.File object, with a newly-minted +// lineage identifier and serial 0, and returns a pointer to it. +func NewStateFile() *statefile.File { + return &statefile.File{ + Lineage: NewLineage(), + TerraformVersion: version.SemVer, + } +}