use the new clistate.Locker in the local backend
Use the new StateLocker field to provide a wrapper for locking the state during terraform.Context creation. We can then remove all the state locking code from individual operations, and unlock them in one place inside the main Operation method.
This commit is contained in:
parent
d3f7edeb27
commit
0b804a9686
|
@ -13,6 +13,7 @@ import (
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
|
"github.com/hashicorp/terraform/command/clistate"
|
||||||
"github.com/hashicorp/terraform/helper/schema"
|
"github.com/hashicorp/terraform/helper/schema"
|
||||||
"github.com/hashicorp/terraform/state"
|
"github.com/hashicorp/terraform/state"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
@ -260,12 +261,21 @@ func (b *Local) Operation(ctx context.Context, op *backend.Operation) (*backend.
|
||||||
cancelCtx, cancel := context.WithCancel(context.Background())
|
cancelCtx, cancel := context.WithCancel(context.Background())
|
||||||
runningOp.Cancel = cancel
|
runningOp.Cancel = cancel
|
||||||
|
|
||||||
|
if op.LockState {
|
||||||
|
op.StateLocker = clistate.NewLocker(stopCtx, op.StateLockTimeout, b.CLI, b.Colorize())
|
||||||
|
} else {
|
||||||
|
op.StateLocker = clistate.NewNoopLocker()
|
||||||
|
}
|
||||||
|
|
||||||
// Do it
|
// Do it
|
||||||
go func() {
|
go func() {
|
||||||
defer done()
|
defer done()
|
||||||
defer stop()
|
defer stop()
|
||||||
defer cancel()
|
defer cancel()
|
||||||
|
|
||||||
|
// the state was locked during context creation, unlock the state when
|
||||||
|
// the operation completes
|
||||||
|
defer op.StateLocker.Unlock(runningOp.Err)
|
||||||
defer b.opLock.Unlock()
|
defer b.opLock.Unlock()
|
||||||
f(stopCtx, cancelCtx, op, runningOp)
|
f(stopCtx, cancelCtx, op, runningOp)
|
||||||
}()
|
}()
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
"github.com/hashicorp/go-multierror"
|
"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/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/state"
|
||||||
|
@ -55,20 +54,6 @@ func (b *Local) opApply(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if op.LockState {
|
|
||||||
lockCtx, cancel := context.WithTimeout(stopCtx, op.StateLockTimeout)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
unlock, err := clistate.Lock(lockCtx, opState, op.Type.String(), "", b.CLI, b.Colorize())
|
|
||||||
if err != nil {
|
|
||||||
runningOp.Err = errwrap.Wrapf("Error locking state: {{err}}", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
runningOp.Err = unlock(runningOp.Err)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup the state
|
// Setup the state
|
||||||
runningOp.State = tfCtx.State()
|
runningOp.State = tfCtx.State()
|
||||||
|
|
||||||
|
|
|
@ -1,9 +1,11 @@
|
||||||
package local
|
package local
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"context"
|
||||||
"errors"
|
"errors"
|
||||||
"log"
|
"log"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/command/clistate"
|
||||||
"github.com/hashicorp/terraform/command/format"
|
"github.com/hashicorp/terraform/command/format"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/tfdiags"
|
"github.com/hashicorp/terraform/tfdiags"
|
||||||
|
@ -20,6 +22,12 @@ func (b *Local) Context(op *backend.Operation) (*terraform.Context, state.State,
|
||||||
// to ask for input/validate.
|
// to ask for input/validate.
|
||||||
op.Type = backend.OperationTypeInvalid
|
op.Type = backend.OperationTypeInvalid
|
||||||
|
|
||||||
|
if op.LockState {
|
||||||
|
op.StateLocker = clistate.NewLocker(context.Background(), op.StateLockTimeout, b.CLI, b.Colorize())
|
||||||
|
} else {
|
||||||
|
op.StateLocker = clistate.NewNoopLocker()
|
||||||
|
}
|
||||||
|
|
||||||
return b.context(op)
|
return b.context(op)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -30,6 +38,10 @@ func (b *Local) context(op *backend.Operation) (*terraform.Context, state.State,
|
||||||
return nil, nil, errwrap.Wrapf("Error loading state: {{err}}", err)
|
return nil, nil, errwrap.Wrapf("Error loading state: {{err}}", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := op.StateLocker.Lock(s, op.Type.String()); err != nil {
|
||||||
|
return nil, nil, errwrap.Wrapf("Error locking state: {{err}}", err)
|
||||||
|
}
|
||||||
|
|
||||||
if err := s.RefreshState(); err != nil {
|
if err := s.RefreshState(); err != nil {
|
||||||
return nil, nil, errwrap.Wrapf("Error loading state: {{err}}", err)
|
return nil, nil, errwrap.Wrapf("Error loading state: {{err}}", err)
|
||||||
}
|
}
|
||||||
|
|
|
@ -10,7 +10,6 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"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/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
|
@ -60,20 +59,6 @@ func (b *Local) opPlan(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if op.LockState {
|
|
||||||
lockCtx, cancel := context.WithTimeout(stopCtx, op.StateLockTimeout)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
unlock, err := clistate.Lock(lockCtx, opState, op.Type.String(), "", b.CLI, b.Colorize())
|
|
||||||
if err != nil {
|
|
||||||
runningOp.Err = errwrap.Wrapf("Error locking state: {{err}}", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
runningOp.Err = unlock(runningOp.Err)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Setup the state
|
// Setup the state
|
||||||
runningOp.State = tfCtx.State()
|
runningOp.State = tfCtx.State()
|
||||||
|
|
||||||
|
|
|
@ -9,7 +9,6 @@ import (
|
||||||
|
|
||||||
"github.com/hashicorp/errwrap"
|
"github.com/hashicorp/errwrap"
|
||||||
"github.com/hashicorp/terraform/backend"
|
"github.com/hashicorp/terraform/backend"
|
||||||
"github.com/hashicorp/terraform/command/clistate"
|
|
||||||
"github.com/hashicorp/terraform/config/module"
|
"github.com/hashicorp/terraform/config/module"
|
||||||
"github.com/hashicorp/terraform/terraform"
|
"github.com/hashicorp/terraform/terraform"
|
||||||
)
|
)
|
||||||
|
@ -51,20 +50,6 @@ func (b *Local) opRefresh(
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if op.LockState {
|
|
||||||
lockCtx, cancel := context.WithTimeout(stopCtx, op.StateLockTimeout)
|
|
||||||
defer cancel()
|
|
||||||
|
|
||||||
unlock, err := clistate.Lock(lockCtx, opState, op.Type.String(), "", b.CLI, b.Colorize())
|
|
||||||
if err != nil {
|
|
||||||
runningOp.Err = errwrap.Wrapf("Error locking state: {{err}}", err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
runningOp.Err = unlock(runningOp.Err)
|
|
||||||
}()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set our state
|
// Set our state
|
||||||
runningOp.State = opState.State()
|
runningOp.State = opState.State()
|
||||||
if runningOp.State.Empty() || !runningOp.State.HasResources() {
|
if runningOp.State.Empty() || !runningOp.State.HasResources() {
|
||||||
|
|
Loading…
Reference in New Issue