From 0b804a9686b1d56446bd1cab2f201022d0f4ad5d Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 23 Feb 2018 11:28:13 -0500 Subject: [PATCH] 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. --- backend/local/backend.go | 10 ++++++++++ backend/local/backend_apply.go | 15 --------------- backend/local/backend_local.go | 12 ++++++++++++ backend/local/backend_plan.go | 15 --------------- backend/local/backend_refresh.go | 15 --------------- 5 files changed, 22 insertions(+), 45 deletions(-) diff --git a/backend/local/backend.go b/backend/local/backend.go index b42aedb17..b0aae720e 100644 --- a/backend/local/backend.go +++ b/backend/local/backend.go @@ -13,6 +13,7 @@ import ( "sync" "github.com/hashicorp/terraform/backend" + "github.com/hashicorp/terraform/command/clistate" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/state" "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()) runningOp.Cancel = cancel + if op.LockState { + op.StateLocker = clistate.NewLocker(stopCtx, op.StateLockTimeout, b.CLI, b.Colorize()) + } else { + op.StateLocker = clistate.NewNoopLocker() + } + // Do it go func() { defer done() defer stop() 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() f(stopCtx, cancelCtx, op, runningOp) }() diff --git a/backend/local/backend_apply.go b/backend/local/backend_apply.go index 8a97fc829..102d40c39 100644 --- a/backend/local/backend_apply.go +++ b/backend/local/backend_apply.go @@ -11,7 +11,6 @@ import ( "github.com/hashicorp/errwrap" "github.com/hashicorp/go-multierror" "github.com/hashicorp/terraform/backend" - "github.com/hashicorp/terraform/command/clistate" "github.com/hashicorp/terraform/command/format" "github.com/hashicorp/terraform/config/module" "github.com/hashicorp/terraform/state" @@ -55,20 +54,6 @@ func (b *Local) opApply( 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 runningOp.State = tfCtx.State() diff --git a/backend/local/backend_local.go b/backend/local/backend_local.go index aa056a1a1..d26fefa57 100644 --- a/backend/local/backend_local.go +++ b/backend/local/backend_local.go @@ -1,9 +1,11 @@ package local import ( + "context" "errors" "log" + "github.com/hashicorp/terraform/command/clistate" "github.com/hashicorp/terraform/command/format" "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. 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) } @@ -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) } + 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 { return nil, nil, errwrap.Wrapf("Error loading state: {{err}}", err) } diff --git a/backend/local/backend_plan.go b/backend/local/backend_plan.go index d2956e341..00c0a859d 100644 --- a/backend/local/backend_plan.go +++ b/backend/local/backend_plan.go @@ -10,7 +10,6 @@ import ( "github.com/hashicorp/errwrap" "github.com/hashicorp/terraform/backend" - "github.com/hashicorp/terraform/command/clistate" "github.com/hashicorp/terraform/command/format" "github.com/hashicorp/terraform/config/module" "github.com/hashicorp/terraform/terraform" @@ -60,20 +59,6 @@ func (b *Local) opPlan( 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 runningOp.State = tfCtx.State() diff --git a/backend/local/backend_refresh.go b/backend/local/backend_refresh.go index a19aa9e5e..b5ec9aa6d 100644 --- a/backend/local/backend_refresh.go +++ b/backend/local/backend_refresh.go @@ -9,7 +9,6 @@ import ( "github.com/hashicorp/errwrap" "github.com/hashicorp/terraform/backend" - "github.com/hashicorp/terraform/command/clistate" "github.com/hashicorp/terraform/config/module" "github.com/hashicorp/terraform/terraform" ) @@ -51,20 +50,6 @@ func (b *Local) opRefresh( 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 runningOp.State = opState.State() if runningOp.State.Empty() || !runningOp.State.HasResources() {