use the new clistate.Locker in commands
Use the new StateLocker field to provide a wrapper for locking the state during terraform.Context creation in the commands that directly manipulate the state.
This commit is contained in:
parent
0b804a9686
commit
400f6ca4c5
|
@ -583,14 +583,11 @@ func (m *Meta) backendFromPlan(opts *BackendOpts) (backend.Backend, error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.stateLock {
|
if m.stateLock {
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), m.stateLockTimeout)
|
stateLocker := clistate.NewLocker(context.Background(), m.stateLockTimeout, m.Ui, m.Colorize())
|
||||||
defer cancel()
|
if err := stateLocker.Lock(realMgr, "backend from plan"); err != nil {
|
||||||
|
|
||||||
unlock, err := clistate.Lock(lockCtx, realMgr, "backend from plan", "", m.Ui, m.Colorize())
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Error locking state: %s", err)
|
return nil, fmt.Errorf("Error locking state: %s", err)
|
||||||
}
|
}
|
||||||
defer unlock(nil)
|
defer stateLocker.Unlock(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := realMgr.RefreshState(); err != nil {
|
if err := realMgr.RefreshState(); err != nil {
|
||||||
|
@ -960,14 +957,11 @@ func (m *Meta) backend_C_r_s(
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.stateLock {
|
if m.stateLock {
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), m.stateLockTimeout)
|
stateLocker := clistate.NewLocker(context.Background(), m.stateLockTimeout, m.Ui, m.Colorize())
|
||||||
defer cancel()
|
if err := stateLocker.Lock(sMgr, "backend from plan"); err != nil {
|
||||||
|
|
||||||
unlock, err := clistate.Lock(lockCtx, sMgr, "backend from config", "", m.Ui, m.Colorize())
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Error locking state: %s", err)
|
return nil, fmt.Errorf("Error locking state: %s", err)
|
||||||
}
|
}
|
||||||
defer unlock(nil)
|
defer stateLocker.Unlock(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the metadata in our saved state location
|
// Store the metadata in our saved state location
|
||||||
|
@ -1039,14 +1033,11 @@ func (m *Meta) backend_C_r_S_changed(
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.stateLock {
|
if m.stateLock {
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), m.stateLockTimeout)
|
stateLocker := clistate.NewLocker(context.Background(), m.stateLockTimeout, m.Ui, m.Colorize())
|
||||||
defer cancel()
|
if err := stateLocker.Lock(sMgr, "backend from plan"); err != nil {
|
||||||
|
|
||||||
unlock, err := clistate.Lock(lockCtx, sMgr, "backend from config", "", m.Ui, m.Colorize())
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Error locking state: %s", err)
|
return nil, fmt.Errorf("Error locking state: %s", err)
|
||||||
}
|
}
|
||||||
defer unlock(nil)
|
defer stateLocker.Unlock(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the backend state
|
// Update the backend state
|
||||||
|
@ -1178,14 +1169,11 @@ func (m *Meta) backend_C_R_S_unchanged(
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.stateLock {
|
if m.stateLock {
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), m.stateLockTimeout)
|
stateLocker := clistate.NewLocker(context.Background(), m.stateLockTimeout, m.Ui, m.Colorize())
|
||||||
defer cancel()
|
if err := stateLocker.Lock(sMgr, "backend from plan"); err != nil {
|
||||||
|
|
||||||
unlock, err := clistate.Lock(lockCtx, sMgr, "backend from config", "", m.Ui, m.Colorize())
|
|
||||||
if err != nil {
|
|
||||||
return nil, fmt.Errorf("Error locking state: %s", err)
|
return nil, fmt.Errorf("Error locking state: %s", err)
|
||||||
}
|
}
|
||||||
defer unlock(nil)
|
defer stateLocker.Unlock(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unset the remote state
|
// Unset the remote state
|
||||||
|
|
|
@ -233,20 +233,19 @@ func (m *Meta) backendMigrateState_s_s(opts *backendMigrateOpts) error {
|
||||||
}
|
}
|
||||||
|
|
||||||
if m.stateLock {
|
if m.stateLock {
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), m.stateLockTimeout)
|
lockCtx := context.Background()
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
unlockOne, err := clistate.Lock(lockCtx, stateOne, "migration", "source state", m.Ui, m.Colorize())
|
lockerOne := clistate.NewLocker(lockCtx, m.stateLockTimeout, m.Ui, m.Colorize())
|
||||||
if err != nil {
|
if err := lockerOne.Lock(stateOne, "migration source state"); err != nil {
|
||||||
return fmt.Errorf("Error locking source state: %s", err)
|
return fmt.Errorf("Error locking source state: %s", err)
|
||||||
}
|
}
|
||||||
defer unlockOne(nil)
|
defer lockerOne.Unlock(nil)
|
||||||
|
|
||||||
unlockTwo, err := clistate.Lock(lockCtx, stateTwo, "migration", "destination state", m.Ui, m.Colorize())
|
lockerTwo := clistate.NewLocker(lockCtx, m.stateLockTimeout, m.Ui, m.Colorize())
|
||||||
if err != nil {
|
if err := lockerTwo.Lock(stateTwo, "migration destination state"); err != nil {
|
||||||
return fmt.Errorf("Error locking destination state: %s", err)
|
return fmt.Errorf("Error locking destination state: %s", err)
|
||||||
}
|
}
|
||||||
defer unlockTwo(nil)
|
defer lockerTwo.Unlock(nil)
|
||||||
|
|
||||||
// We now own a lock, so double check that we have the version
|
// We now own a lock, so double check that we have the version
|
||||||
// corresponding to the lock.
|
// corresponding to the lock.
|
||||||
|
|
|
@ -83,16 +83,12 @@ func (c *TaintCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.stateLock {
|
if c.stateLock {
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), c.stateLockTimeout)
|
stateLocker := clistate.NewLocker(context.Background(), c.stateLockTimeout, c.Ui, c.Colorize())
|
||||||
defer cancel()
|
if err := stateLocker.Lock(st, "taint"); err != nil {
|
||||||
|
|
||||||
unlock, err := clistate.Lock(lockCtx, st, "taint", "", c.Ui, c.Colorize())
|
|
||||||
if err != nil {
|
|
||||||
c.Ui.Error(fmt.Sprintf("Error locking state: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error locking state: %s", err))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
defer stateLocker.Unlock(nil)
|
||||||
defer unlock(nil)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the actual state structure
|
// Get the actual state structure
|
||||||
|
|
|
@ -71,15 +71,12 @@ func (c *UntaintCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.stateLock {
|
if c.stateLock {
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), c.stateLockTimeout)
|
stateLocker := clistate.NewLocker(context.Background(), c.stateLockTimeout, c.Ui, c.Colorize())
|
||||||
defer cancel()
|
if err := stateLocker.Lock(st, "untaint"); err != nil {
|
||||||
|
|
||||||
unlock, err := clistate.Lock(lockCtx, st, "untaint", "", c.Ui, c.Colorize())
|
|
||||||
if err != nil {
|
|
||||||
c.Ui.Error(fmt.Sprintf("Error locking state: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error locking state: %s", err))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
defer unlock(nil)
|
defer stateLocker.Unlock(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the actual state structure
|
// Get the actual state structure
|
||||||
|
|
|
@ -96,6 +96,17 @@ func (c *WorkspaceDeleteCommand) Run(args []string) int {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var stateLocker clistate.Locker
|
||||||
|
if c.stateLock {
|
||||||
|
stateLocker = clistate.NewLocker(context.Background(), c.stateLockTimeout, c.Ui, c.Colorize())
|
||||||
|
if err := stateLocker.Lock(sMgr, "workspace_delete"); err != nil {
|
||||||
|
c.Ui.Error(fmt.Sprintf("Error locking state: %s", err))
|
||||||
|
return 1
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
stateLocker = clistate.NewNoopLocker()
|
||||||
|
}
|
||||||
|
|
||||||
if err := sMgr.RefreshState(); err != nil {
|
if err := sMgr.RefreshState(); err != nil {
|
||||||
c.Ui.Error(err.Error())
|
c.Ui.Error(err.Error())
|
||||||
return 1
|
return 1
|
||||||
|
@ -108,28 +119,16 @@ func (c *WorkspaceDeleteCommand) Run(args []string) int {
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
|
|
||||||
// Honor the lock request, for consistency and one final safety check.
|
// We need to release the lock just before deleting the state, in case
|
||||||
if c.stateLock {
|
// the backend can't remove the resource while holding the lock. This
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), c.stateLockTimeout)
|
// is currently true for Windows local files.
|
||||||
defer cancel()
|
//
|
||||||
|
// TODO: While there is little safety in locking while deleting the
|
||||||
unlock, err := clistate.Lock(lockCtx, sMgr, "workspace delete", "", c.Ui, c.Colorize())
|
// state, it might be nice to be able to coordinate processes around
|
||||||
if err != nil {
|
// state deletion, i.e. in a CI environment. Adding Delete() as a
|
||||||
c.Ui.Error(fmt.Sprintf("Error locking state: %s", err))
|
// required method of States would allow the removal of the resource to
|
||||||
return 1
|
// be delegated from the Backend to the State itself.
|
||||||
}
|
stateLocker.Unlock(nil)
|
||||||
|
|
||||||
// We need to release the lock just before deleting the state, in case
|
|
||||||
// the backend can't remove the resource while holding the lock. This
|
|
||||||
// is currently true for Windows local files.
|
|
||||||
//
|
|
||||||
// TODO: While there is little safety in locking while deleting the
|
|
||||||
// state, it might be nice to be able to coordinate processes around
|
|
||||||
// state deletion, i.e. in a CI environment. Adding Delete() as a
|
|
||||||
// required method of States would allow the removal of the resource to
|
|
||||||
// be delegated from the Backend to the State itself.
|
|
||||||
unlock(nil)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = b.DeleteState(delEnv)
|
err = b.DeleteState(delEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
|
@ -114,15 +114,12 @@ func (c *WorkspaceNewCommand) Run(args []string) int {
|
||||||
}
|
}
|
||||||
|
|
||||||
if c.stateLock {
|
if c.stateLock {
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), c.stateLockTimeout)
|
stateLocker := clistate.NewLocker(context.Background(), c.stateLockTimeout, c.Ui, c.Colorize())
|
||||||
defer cancel()
|
if err := stateLocker.Lock(sMgr, "workspace_delete"); err != nil {
|
||||||
|
|
||||||
unlock, err := clistate.Lock(lockCtx, sMgr, "workspace_new", "", c.Ui, c.Colorize())
|
|
||||||
if err != nil {
|
|
||||||
c.Ui.Error(fmt.Sprintf("Error locking state: %s", err))
|
c.Ui.Error(fmt.Sprintf("Error locking state: %s", err))
|
||||||
return 1
|
return 1
|
||||||
}
|
}
|
||||||
defer unlock(nil)
|
defer stateLocker.Unlock(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// read the existing state file
|
// read the existing state file
|
||||||
|
|
Loading…
Reference in New Issue