state: only change serial if changed

This commit is contained in:
Mitchell Hashimoto 2015-02-23 21:26:33 -08:00
parent bfe0edef51
commit c2bf600603
6 changed files with 64 additions and 22 deletions

View File

@ -104,6 +104,8 @@ func (s *CacheState) RefreshState() error {
s.refreshResult = CacheRefreshNoop
return err
}
cached = durable
}
s.state = cached

View File

@ -18,6 +18,7 @@ func (s *InmemState) RefreshState() error {
}
func (s *InmemState) WriteState(state *terraform.State) error {
state.IncrementSerialMaybe(s.state)
s.state = state
return nil
}

View File

@ -15,13 +15,15 @@ type LocalState struct {
Path string
PathOut string
state *terraform.State
written bool
state *terraform.State
readState *terraform.State
written bool
}
// SetState will force a specific state in-memory for this local state.
func (s *LocalState) SetState(state *terraform.State) {
s.state = state
s.readState = state
}
// StateReader impl.
@ -61,6 +63,9 @@ func (s *LocalState) WriteState(state *terraform.State) error {
}
defer f.Close()
s.state.IncrementSerialMaybe(s.readState)
s.readState = s.state
if err := terraform.WriteState(s.state, f); err != nil {
return err
}
@ -105,5 +110,6 @@ func (s *LocalState) RefreshState() error {
}
s.state = state
s.readState = state
return nil
}

View File

@ -28,9 +28,7 @@ func TestState(t *testing.T, s interface{}) {
current := TestStateInitial()
// Check that the initial state is correct
state := reader.State()
current.Serial = state.Serial
if !reflect.DeepEqual(state, current) {
if state := reader.State(); !reflect.DeepEqual(state, current) {
t.Fatalf("not initial: %#v\n\n%#v", state, current)
}
@ -67,11 +65,49 @@ func TestState(t *testing.T, s interface{}) {
// Just set the serials the same... Then compare.
actual := reader.State()
actual.Serial = current.Serial
if !reflect.DeepEqual(actual, current) {
t.Fatalf("bad: %#v\n\n%#v", actual, current)
}
}
// If we can write and persist then verify that the serial
// is only implemented on change.
writer, writeOk := s.(StateWriter)
persister, persistOk := s.(StatePersister)
if writeOk && persistOk {
// Same serial
serial := current.Serial
if err := writer.WriteState(current); err != nil {
t.Fatalf("err: %s", err)
}
if err := persister.PersistState(); err != nil {
t.Fatalf("err: %s", err)
}
if reader.State().Serial != serial {
t.Fatalf("bad: expected %d, got %d", serial, reader.State().Serial)
}
// Change the serial
currentCopy := *current
current = &currentCopy
current.Modules = []*terraform.ModuleState{
&terraform.ModuleState{
Path: []string{"root", "somewhere"},
Outputs: map[string]string{"serialCheck": "true"},
},
}
if err := writer.WriteState(current); err != nil {
t.Fatalf("err: %s", err)
}
if err := persister.PersistState(); err != nil {
t.Fatalf("err: %s", err)
}
if reader.State().Serial <= serial {
t.Fatalf("bad: expected %d, got %d", serial, reader.State().Serial)
}
}
}
// TestStateInitial is the initial state that a State should have

View File

@ -161,6 +161,11 @@ func (s *State) RootModule() *ModuleState {
// Equal tests if one state is equal to another.
func (s *State) Equal(other *State) bool {
// If one is nil, we do a direct check
if s == nil || other == nil {
return s == other
}
// If the versions are different, they're certainly not equal
if s.Version != other.Version {
return false
@ -183,6 +188,14 @@ func (s *State) Equal(other *State) bool {
return true
}
// IncrementSerialMaybe increments the serial number of this state
// if it different from the other state.
func (s *State) IncrementSerialMaybe(other *State) {
if !s.Equal(other) {
s.Serial++
}
}
func (s *State) init() {
if s.Version == 0 {
s.Version = StateVersion
@ -951,9 +964,6 @@ func WriteState(d *State, dst io.Writer) error {
// Ensure the version is set
d.Version = StateVersion
// Always increment the serial number
d.Serial++
// Encode the data in a human-friendly way
data, err := json.MarshalIndent(d, "", " ")
if err != nil {

View File

@ -537,15 +537,6 @@ func TestReadWriteState(t *testing.T) {
t.Fatalf("bad version number: %d", state.Version)
}
// Verify the serial number is incremented
if state.Serial != 10 {
t.Fatalf("bad serial: %d", state.Serial)
}
// Remove the changes or the checksum will fail
state.Version = 0
state.Serial = 9
// Checksum after the write
chksumAfter := checksumStruct(t, state)
if chksumAfter != chksum {
@ -557,10 +548,6 @@ func TestReadWriteState(t *testing.T) {
t.Fatalf("err: %s", err)
}
// Verify the changes came through
state.Version = StateVersion
state.Serial = 10
// ReadState should not restore sensitive information!
mod := state.RootModule()
mod.Resources["foo"].Primary.Ephemeral = EphemeralState{}