Merge pull request #13665 from hashicorp/jbardin/context-return-state

context Refresh and Apply sometimes return nil
This commit is contained in:
James Bardin 2017-04-14 14:56:47 -04:00 committed by GitHub
commit 1771ba1374
3 changed files with 28 additions and 12 deletions

View File

@ -102,7 +102,9 @@ func (b *Local) opApply(
doneCh := make(chan struct{}) doneCh := make(chan struct{})
go func() { go func() {
defer close(doneCh) defer close(doneCh)
applyState, applyErr = tfCtx.Apply() _, applyErr = tfCtx.Apply()
// we always want the state, even if apply failed
applyState = tfCtx.State()
/* /*
// Record any shadow errors for later // Record any shadow errors for later

View File

@ -453,8 +453,17 @@ func (c *Context) Input(mode InputMode) error {
// Apply applies the changes represented by this context and returns // Apply applies the changes represented by this context and returns
// the resulting state. // the resulting state.
// //
// In addition to returning the resulting state, this context is updated // Even in the case an error is returned, the state may be returned and will
// with the latest state. // potentially be partially updated. In addition to returning the resulting
// state, this context is updated with the latest state.
//
// If the state is required after an error, the caller should call
// Context.State, rather than rely on the return value.
//
// TODO: Apply and Refresh should either always return a state, or rely on the
// State() method. Currently the helper/resource testing framework relies
// on the absence of a returned state to determine if Destroy can be
// called, so that will need to be refactored before this can be changed.
func (c *Context) Apply() (*State, error) { func (c *Context) Apply() (*State, error) {
defer c.acquireRun("apply")() defer c.acquireRun("apply")()
@ -580,7 +589,7 @@ func (c *Context) Plan() (*Plan, error) {
// to their latest state. This will update the state that this context // to their latest state. This will update the state that this context
// works with, along with returning it. // works with, along with returning it.
// //
// Even in the case an error is returned, the state will be returned and // Even in the case an error is returned, the state may be returned and
// will potentially be partially updated. // will potentially be partially updated.
func (c *Context) Refresh() (*State, error) { func (c *Context) Refresh() (*State, error) {
defer c.acquireRun("refresh")() defer c.acquireRun("refresh")()

View File

@ -1960,12 +1960,12 @@ func ReadStateV2(jsonBytes []byte) (*State, error) {
} }
} }
// Sort it
state.sort()
// catch any unitialized fields in the state // catch any unitialized fields in the state
state.init() state.init()
// Sort it
state.sort()
return state, nil return state, nil
} }
@ -1995,12 +1995,12 @@ func ReadStateV3(jsonBytes []byte) (*State, error) {
} }
} }
// Sort it
state.sort()
// catch any unitialized fields in the state // catch any unitialized fields in the state
state.init() state.init()
// Sort it
state.sort()
// Now we write the state back out to detect any changes in normaliztion. // Now we write the state back out to detect any changes in normaliztion.
// If our state is now written out differently, bump the serial number to // If our state is now written out differently, bump the serial number to
// prevent conflicts. // prevent conflicts.
@ -2020,12 +2020,17 @@ func ReadStateV3(jsonBytes []byte) (*State, error) {
// WriteState writes a state somewhere in a binary format. // WriteState writes a state somewhere in a binary format.
func WriteState(d *State, dst io.Writer) error { func WriteState(d *State, dst io.Writer) error {
// Make sure it is sorted // writing a nil state is a noop.
d.sort() if d == nil {
return nil
}
// make sure we have no uninitialized fields // make sure we have no uninitialized fields
d.init() d.init()
// Make sure it is sorted
d.sort()
// Ensure the version is set // Ensure the version is set
d.Version = StateVersion d.Version = StateVersion