create clistate.Locker interface
Simplify the use of clistate.Lock by creating a clistate.Locker instance, which stores the context of locking a state, to allow unlock to be called without knowledge of how the state was locked. This alows the backend code to bring the needed UI methods to the point where the state is locked, and still unlock the state from an outer scope.
This commit is contained in:
parent
7c6072c2a0
commit
e88bd74bb7
|
@ -59,18 +59,13 @@ func (b *Local) opApply(
|
||||||
lockCtx, cancel := context.WithTimeout(stopCtx, op.StateLockTimeout)
|
lockCtx, cancel := context.WithTimeout(stopCtx, op.StateLockTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
lockInfo := state.NewLockInfo()
|
unlock, err := clistate.Lock(lockCtx, opState, op.Type.String(), "", b.CLI, b.Colorize())
|
||||||
lockInfo.Operation = op.Type.String()
|
|
||||||
lockID, err := clistate.Lock(lockCtx, opState, lockInfo, b.CLI, b.Colorize())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
runningOp.Err = errwrap.Wrapf("Error locking state: {{err}}", err)
|
runningOp.Err = errwrap.Wrapf("Error locking state: {{err}}", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := clistate.Unlock(opState, lockID, b.CLI, b.Colorize()); err != nil {
|
runningOp.Err = unlock(runningOp.Err)
|
||||||
runningOp.Err = multierror.Append(runningOp.Err, err)
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,12 +9,10 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
"github.com/hashicorp/go-multierror"
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/command/clistate"
|
"github.com/hashicorp/terraform/command/clistate"
|
||||||
"github.com/hashicorp/terraform/command/format"
|
"github.com/hashicorp/terraform/command/format"
|
||||||
"github.com/hashicorp/terraform/config/module"
|
"github.com/hashicorp/terraform/config/module"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -66,18 +64,13 @@ func (b *Local) opPlan(
|
||||||
lockCtx, cancel := context.WithTimeout(stopCtx, op.StateLockTimeout)
|
lockCtx, cancel := context.WithTimeout(stopCtx, op.StateLockTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
lockInfo := state.NewLockInfo()
|
unlock, err := clistate.Lock(lockCtx, opState, op.Type.String(), "", b.CLI, b.Colorize())
|
||||||
lockInfo.Operation = op.Type.String()
|
|
||||||
lockID, err := clistate.Lock(lockCtx, opState, lockInfo, b.CLI, b.Colorize())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
runningOp.Err = errwrap.Wrapf("Error locking state: {{err}}", err)
|
runningOp.Err = errwrap.Wrapf("Error locking state: {{err}}", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := clistate.Unlock(opState, lockID, b.CLI, b.Colorize()); err != nil {
|
runningOp.Err = unlock(runningOp.Err)
|
||||||
runningOp.Err = multierror.Append(runningOp.Err, err)
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -8,11 +8,9 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
"github.com/hashicorp/go-multierror"
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/command/clistate"
|
"github.com/hashicorp/terraform/command/clistate"
|
||||||
"github.com/hashicorp/terraform/config/module"
|
"github.com/hashicorp/terraform/config/module"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -57,18 +55,13 @@ func (b *Local) opRefresh(
|
||||||
lockCtx, cancel := context.WithTimeout(stopCtx, op.StateLockTimeout)
|
lockCtx, cancel := context.WithTimeout(stopCtx, op.StateLockTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
lockInfo := state.NewLockInfo()
|
unlock, err := clistate.Lock(lockCtx, opState, op.Type.String(), "", b.CLI, b.Colorize())
|
||||||
lockInfo.Operation = op.Type.String()
|
|
||||||
lockID, err := clistate.Lock(lockCtx, opState, lockInfo, b.CLI, b.Colorize())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
runningOp.Err = errwrap.Wrapf("Error locking state: {{err}}", err)
|
runningOp.Err = errwrap.Wrapf("Error locking state: {{err}}", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
defer func() {
|
defer func() {
|
||||||
if err := clistate.Unlock(opState, lockID, b.CLI, b.Colorize()); err != nil {
|
runningOp.Err = unlock(runningOp.Err)
|
||||||
runningOp.Err = multierror.Append(runningOp.Err, err)
|
|
||||||
}
|
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -9,6 +9,7 @@ import (
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
"runtime/debug"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
@ -81,6 +82,9 @@ func (c *RemoteClient) Get() (*remote.Payload, error) {
|
||||||
|
|
||||||
c.modifyIndex = pair.ModifyIndex
|
c.modifyIndex = pair.ModifyIndex
|
||||||
|
|
||||||
|
log.Println("[XXXX] GOT STATE WITH INDEX:", c.modifyIndex)
|
||||||
|
log.Println(string(debug.Stack()))
|
||||||
|
|
||||||
payload := pair.Value
|
payload := pair.Value
|
||||||
// If the payload starts with 0x1f, it's gzip, not json
|
// If the payload starts with 0x1f, it's gzip, not json
|
||||||
if len(pair.Value) >= 1 && pair.Value[0] == '\x1f' {
|
if len(pair.Value) >= 1 && pair.Value[0] == '\x1f' {
|
||||||
|
@ -280,6 +284,7 @@ func (c *RemoteClient) lock() (string, error) {
|
||||||
return "", lockErr
|
return "", lockErr
|
||||||
}
|
}
|
||||||
|
|
||||||
|
defer log.Println("[XXXX] OBTAINED CONSUL LOCK")
|
||||||
c.lockCh = lockCh
|
c.lockCh = lockCh
|
||||||
|
|
||||||
err = c.putLockInfo(c.info)
|
err = c.putLockInfo(c.info)
|
||||||
|
|
|
@ -8,9 +8,11 @@ import (
|
||||||
"context"
|
"context"
|
||||||
"fmt"
|
"fmt"
|
||||||
"strings"
|
"strings"
|
||||||
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
|
multierror "github.com/hashicorp/go-multierror"
|
||||||
"github.com/hashicorp/terraform/helper/slowmessage"
|
"github.com/hashicorp/terraform/helper/slowmessage"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/state"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
|
@ -48,47 +50,119 @@ that no one else is holding a lock.
|
||||||
`
|
`
|
||||||
)
|
)
|
||||||
|
|
||||||
// Lock locks the given state and outputs to the user if locking
|
// Locker allows for more convenient locking, by creating the timeout context
|
||||||
// is taking longer than the threshold. The lock is retried until the context
|
// and LockInfo for the caller, while storing any related data required for
|
||||||
// is cancelled.
|
// Unlock.
|
||||||
func Lock(ctx context.Context, s state.State, info *state.LockInfo, ui cli.Ui, color *colorstring.Colorize) (string, error) {
|
type Locker interface {
|
||||||
var lockID string
|
// Lock the provided state, storing the reason string in the LockInfo.
|
||||||
|
Lock(s state.State, reason string) error
|
||||||
|
// Unlock the previously locked state.
|
||||||
|
// An optional error can be passed in, and will be combined with any error
|
||||||
|
// from the Unlock operation.
|
||||||
|
Unlock(error) error
|
||||||
|
}
|
||||||
|
|
||||||
|
type locker struct {
|
||||||
|
mu sync.Mutex
|
||||||
|
ctx context.Context
|
||||||
|
timeout time.Duration
|
||||||
|
state state.State
|
||||||
|
ui cli.Ui
|
||||||
|
color *colorstring.Colorize
|
||||||
|
lockID string
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new Locker.
|
||||||
|
// The provided context will be used for lock cancellation, and combined with
|
||||||
|
// the timeout duration. Lock progress will be be reported to the user through
|
||||||
|
// the provided UI.
|
||||||
|
func NewLocker(
|
||||||
|
ctx context.Context,
|
||||||
|
timeout time.Duration,
|
||||||
|
ui cli.Ui,
|
||||||
|
color *colorstring.Colorize) Locker {
|
||||||
|
|
||||||
|
l := &locker{
|
||||||
|
ctx: ctx,
|
||||||
|
timeout: timeout,
|
||||||
|
ui: ui,
|
||||||
|
color: color,
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
|
// Locker locks the given state and outputs to the user if locking is taking
|
||||||
|
// longer than the threshold. The lock is retried until the context is
|
||||||
|
// cancelled.
|
||||||
|
func (l *locker) Lock(s state.State, reason string) error {
|
||||||
|
l.mu.Lock()
|
||||||
|
defer l.mu.Unlock()
|
||||||
|
|
||||||
|
l.state = s
|
||||||
|
|
||||||
|
ctx, cancel := context.WithTimeout(l.ctx, l.timeout)
|
||||||
|
defer cancel()
|
||||||
|
|
||||||
|
lockInfo := state.NewLockInfo()
|
||||||
|
lockInfo.Operation = reason
|
||||||
|
|
||||||
err := slowmessage.Do(LockThreshold, func() error {
|
err := slowmessage.Do(LockThreshold, func() error {
|
||||||
id, err := state.LockWithContext(ctx, s, info)
|
id, err := state.LockWithContext(ctx, s, lockInfo)
|
||||||
lockID = id
|
l.lockID = id
|
||||||
return err
|
return err
|
||||||
}, func() {
|
}, func() {
|
||||||
if ui != nil {
|
if l.ui != nil {
|
||||||
ui.Output(color.Color(LockMessage))
|
l.ui.Output(l.color.Color(LockMessage))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
err = errwrap.Wrapf(strings.TrimSpace(LockErrorMessage), err)
|
return errwrap.Wrapf(strings.TrimSpace(LockErrorMessage), err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return lockID, err
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unlock unlocks the given state and outputs to the user if the
|
func (l *locker) Unlock(parentErr error) error {
|
||||||
// unlock fails what can be done.
|
l.mu.Lock()
|
||||||
func Unlock(s state.State, id string, ui cli.Ui, color *colorstring.Colorize) error {
|
defer l.mu.Unlock()
|
||||||
|
|
||||||
|
if l.lockID == "" {
|
||||||
|
return parentErr
|
||||||
|
}
|
||||||
|
|
||||||
err := slowmessage.Do(LockThreshold, func() error {
|
err := slowmessage.Do(LockThreshold, func() error {
|
||||||
return s.Unlock(id)
|
return l.state.Unlock(l.lockID)
|
||||||
}, func() {
|
}, func() {
|
||||||
if ui != nil {
|
if l.ui != nil {
|
||||||
ui.Output(color.Color(UnlockMessage))
|
l.ui.Output(l.color.Color(UnlockMessage))
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
ui.Output(color.Color(fmt.Sprintf(
|
l.ui.Output(l.color.Color(fmt.Sprintf(
|
||||||
"\n"+strings.TrimSpace(UnlockErrorMessage)+"\n", err)))
|
"\n"+strings.TrimSpace(UnlockErrorMessage)+"\n", err)))
|
||||||
|
|
||||||
err = fmt.Errorf(
|
if parentErr != nil {
|
||||||
"Error releasing the state lock. Please see the longer error message above.")
|
parentErr = multierror.Append(parentErr, err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return parentErr
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
type noopLocker struct{}
|
||||||
|
|
||||||
|
// NewNoopLocker returns a valid Locker that does nothing.
|
||||||
|
func NewNoopLocker() Locker {
|
||||||
|
return noopLocker{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l noopLocker) Lock(state.State, string) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l noopLocker) Unlock(err error) error {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -586,15 +586,11 @@ func (m *Meta) backendFromPlan(opts *BackendOpts) (backend.Backend, error) {
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), m.stateLockTimeout)
|
lockCtx, cancel := context.WithTimeout(context.Background(), m.stateLockTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Lock the state if we can
|
unlock, err := clistate.Lock(lockCtx, realMgr, "backend from plan", "", m.Ui, m.Colorize())
|
||||||
lockInfo := state.NewLockInfo()
|
|
||||||
lockInfo.Operation = "backend from plan"
|
|
||||||
|
|
||||||
lockID, err := clistate.Lock(lockCtx, realMgr, lockInfo, m.Ui, m.Colorize())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error locking state: %s", err)
|
return nil, fmt.Errorf("Error locking state: %s", err)
|
||||||
}
|
}
|
||||||
defer clistate.Unlock(realMgr, lockID, m.Ui, m.Colorize())
|
defer unlock(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := realMgr.RefreshState(); err != nil {
|
if err := realMgr.RefreshState(); err != nil {
|
||||||
|
@ -967,15 +963,11 @@ func (m *Meta) backend_C_r_s(
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), m.stateLockTimeout)
|
lockCtx, cancel := context.WithTimeout(context.Background(), m.stateLockTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Lock the state if we can
|
unlock, err := clistate.Lock(lockCtx, sMgr, "backend from config", "", m.Ui, m.Colorize())
|
||||||
lockInfo := state.NewLockInfo()
|
|
||||||
lockInfo.Operation = "backend from config"
|
|
||||||
|
|
||||||
lockID, err := clistate.Lock(lockCtx, sMgr, lockInfo, m.Ui, m.Colorize())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error locking state: %s", err)
|
return nil, fmt.Errorf("Error locking state: %s", err)
|
||||||
}
|
}
|
||||||
defer clistate.Unlock(sMgr, lockID, m.Ui, m.Colorize())
|
defer unlock(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the metadata in our saved state location
|
// Store the metadata in our saved state location
|
||||||
|
@ -1050,15 +1042,11 @@ func (m *Meta) backend_C_r_S_changed(
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), m.stateLockTimeout)
|
lockCtx, cancel := context.WithTimeout(context.Background(), m.stateLockTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Lock the state if we can
|
unlock, err := clistate.Lock(lockCtx, sMgr, "backend from config", "", m.Ui, m.Colorize())
|
||||||
lockInfo := state.NewLockInfo()
|
|
||||||
lockInfo.Operation = "backend from config"
|
|
||||||
|
|
||||||
lockID, err := clistate.Lock(lockCtx, sMgr, lockInfo, m.Ui, m.Colorize())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error locking state: %s", err)
|
return nil, fmt.Errorf("Error locking state: %s", err)
|
||||||
}
|
}
|
||||||
defer clistate.Unlock(sMgr, lockID, m.Ui, m.Colorize())
|
defer unlock(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update the backend state
|
// Update the backend state
|
||||||
|
@ -1193,15 +1181,11 @@ func (m *Meta) backend_C_R_S_unchanged(
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), m.stateLockTimeout)
|
lockCtx, cancel := context.WithTimeout(context.Background(), m.stateLockTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Lock the state if we can
|
unlock, err := clistate.Lock(lockCtx, sMgr, "backend from config", "", m.Ui, m.Colorize())
|
||||||
lockInfo := state.NewLockInfo()
|
|
||||||
lockInfo.Operation = "backend from config"
|
|
||||||
|
|
||||||
lockID, err := clistate.Lock(lockCtx, sMgr, lockInfo, m.Ui, m.Colorize())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Error locking state: %s", err)
|
return nil, fmt.Errorf("Error locking state: %s", err)
|
||||||
}
|
}
|
||||||
defer clistate.Unlock(sMgr, lockID, m.Ui, m.Colorize())
|
defer unlock(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unset the remote state
|
// Unset the remote state
|
||||||
|
|
|
@ -236,25 +236,17 @@ func (m *Meta) backendMigrateState_s_s(opts *backendMigrateOpts) error {
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), m.stateLockTimeout)
|
lockCtx, cancel := context.WithTimeout(context.Background(), m.stateLockTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
lockInfoOne := state.NewLockInfo()
|
unlockOne, err := clistate.Lock(lockCtx, stateOne, "migration", "source state", m.Ui, m.Colorize())
|
||||||
lockInfoOne.Operation = "migration"
|
|
||||||
lockInfoOne.Info = "source state"
|
|
||||||
|
|
||||||
lockIDOne, err := clistate.Lock(lockCtx, stateOne, lockInfoOne, m.Ui, m.Colorize())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error locking source state: %s", err)
|
return fmt.Errorf("Error locking source state: %s", err)
|
||||||
}
|
}
|
||||||
defer clistate.Unlock(stateOne, lockIDOne, m.Ui, m.Colorize())
|
defer unlockOne(nil)
|
||||||
|
|
||||||
lockInfoTwo := state.NewLockInfo()
|
unlockTwo, err := clistate.Lock(lockCtx, stateTwo, "migration", "destination state", m.Ui, m.Colorize())
|
||||||
lockInfoTwo.Operation = "migration"
|
|
||||||
lockInfoTwo.Info = "destination state"
|
|
||||||
|
|
||||||
lockIDTwo, err := clistate.Lock(lockCtx, stateTwo, lockInfoTwo, m.Ui, m.Colorize())
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("Error locking destination state: %s", err)
|
return fmt.Errorf("Error locking destination state: %s", err)
|
||||||
}
|
}
|
||||||
defer clistate.Unlock(stateTwo, lockIDTwo, m.Ui, m.Colorize())
|
defer unlockTwo(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.
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/command/clistate"
|
"github.com/hashicorp/terraform/command/clistate"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -87,15 +86,13 @@ func (c *TaintCommand) Run(args []string) int {
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), c.stateLockTimeout)
|
lockCtx, cancel := context.WithTimeout(context.Background(), c.stateLockTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
lockInfo := state.NewLockInfo()
|
unlock, err := clistate.Lock(lockCtx, st, "taint", "", c.Ui, c.Colorize())
|
||||||
lockInfo.Operation = "taint"
|
|
||||||
lockID, err := clistate.Lock(lockCtx, st, lockInfo, c.Ui, c.Colorize())
|
|
||||||
if err != nil {
|
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 clistate.Unlock(st, lockID, c.Ui, c.Colorize())
|
defer unlock(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the actual state structure
|
// Get the actual state structure
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/command/clistate"
|
"github.com/hashicorp/terraform/command/clistate"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// UntaintCommand is a cli.Command implementation that manually untaints
|
// UntaintCommand is a cli.Command implementation that manually untaints
|
||||||
|
@ -75,15 +74,12 @@ func (c *UntaintCommand) Run(args []string) int {
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), c.stateLockTimeout)
|
lockCtx, cancel := context.WithTimeout(context.Background(), c.stateLockTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
lockInfo := state.NewLockInfo()
|
unlock, err := clistate.Lock(lockCtx, st, "untaint", "", c.Ui, c.Colorize())
|
||||||
lockInfo.Operation = "untaint"
|
|
||||||
lockID, err := clistate.Lock(lockCtx, st, lockInfo, c.Ui, c.Colorize())
|
|
||||||
if err != nil {
|
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 clistate.Unlock(st, lockID, c.Ui, c.Colorize())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Get the actual state structure
|
// Get the actual state structure
|
||||||
|
|
|
@ -6,7 +6,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/command/clistate"
|
"github.com/hashicorp/terraform/command/clistate"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"github.com/posener/complete"
|
"github.com/posener/complete"
|
||||||
)
|
)
|
||||||
|
@ -114,10 +113,7 @@ func (c *WorkspaceDeleteCommand) Run(args []string) int {
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), c.stateLockTimeout)
|
lockCtx, cancel := context.WithTimeout(context.Background(), c.stateLockTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Lock the state if we can
|
unlock, err := clistate.Lock(lockCtx, sMgr, "workspace delete", "", c.Ui, c.Colorize())
|
||||||
lockInfo := state.NewLockInfo()
|
|
||||||
lockInfo.Operation = "workspace delete"
|
|
||||||
lockID, err := clistate.Lock(lockCtx, sMgr, lockInfo, c.Ui, c.Colorize())
|
|
||||||
if err != nil {
|
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
|
||||||
|
@ -132,7 +128,7 @@ func (c *WorkspaceDeleteCommand) Run(args []string) int {
|
||||||
// state deletion, i.e. in a CI environment. Adding Delete() as a
|
// state deletion, i.e. in a CI environment. Adding Delete() as a
|
||||||
// required method of States would allow the removal of the resource to
|
// required method of States would allow the removal of the resource to
|
||||||
// be delegated from the Backend to the State itself.
|
// be delegated from the Backend to the State itself.
|
||||||
clistate.Unlock(sMgr, lockID, c.Ui, c.Colorize())
|
unlock(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
err = b.DeleteState(delEnv)
|
err = b.DeleteState(delEnv)
|
||||||
|
|
|
@ -7,7 +7,6 @@ import (
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/command/clistate"
|
"github.com/hashicorp/terraform/command/clistate"
|
||||||
"github.com/hashicorp/terraform/state"
|
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
"github.com/mitchellh/cli"
|
"github.com/mitchellh/cli"
|
||||||
"github.com/posener/complete"
|
"github.com/posener/complete"
|
||||||
|
@ -118,15 +117,12 @@ func (c *WorkspaceNewCommand) Run(args []string) int {
|
||||||
lockCtx, cancel := context.WithTimeout(context.Background(), c.stateLockTimeout)
|
lockCtx, cancel := context.WithTimeout(context.Background(), c.stateLockTimeout)
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
// Lock the state if we can
|
unlock, err := clistate.Lock(lockCtx, sMgr, "workspace_new", "", c.Ui, c.Colorize())
|
||||||
lockInfo := state.NewLockInfo()
|
|
||||||
lockInfo.Operation = "workspace new"
|
|
||||||
lockID, err := clistate.Lock(lockCtx, sMgr, lockInfo, c.Ui, c.Colorize())
|
|
||||||
if err != nil {
|
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 clistate.Unlock(sMgr, lockID, c.Ui, c.Colorize())
|
defer unlock(nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
// read the existing state file
|
// read the existing state file
|
||||||
|
|
Loading…
Reference in New Issue