states/statemgr: don't panic if no state file is present on first write
This commit is contained in:
parent
5731703de5
commit
03e6771536
|
@ -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
|
// writing to a temp file on the same filesystem, and renaming the file over
|
||||||
// the original.
|
// the original.
|
||||||
|
|
||||||
|
if s.readFile == nil {
|
||||||
|
err := s.RefreshState()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
defer s.mutex()()
|
defer s.mutex()()
|
||||||
|
|
||||||
// We'll try to write our backup first, so we can be sure we've created
|
// 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()
|
defer s.stateFileOut.Sync()
|
||||||
|
|
||||||
s.file = s.file.DeepCopy()
|
s.file = s.file.DeepCopy()
|
||||||
|
if s.file == nil {
|
||||||
|
s.file = NewStateFile()
|
||||||
|
}
|
||||||
s.file.State = state.DeepCopy()
|
s.file.State = state.DeepCopy()
|
||||||
|
|
||||||
if _, err := s.stateFileOut.Seek(0, os.SEEK_SET); err != nil {
|
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
|
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++
|
s.file.Serial++
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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,
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue