command: use new state lock/unlock helpers for better UX

This commit is contained in:
Mitchell Hashimoto 2017-02-14 11:33:55 -08:00
parent 65982bd412
commit 90f3d40c1f
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
5 changed files with 37 additions and 44 deletions

View File

@ -16,6 +16,7 @@ import (
"github.com/hashicorp/go-multierror"
"github.com/hashicorp/hcl"
"github.com/hashicorp/terraform/backend"
clistate "github.com/hashicorp/terraform/command/state"
"github.com/hashicorp/terraform/config"
"github.com/hashicorp/terraform/state"
"github.com/hashicorp/terraform/terraform"
@ -531,11 +532,12 @@ func (m *Meta) backendFromPlan(opts *BackendOpts) (backend.Backend, error) {
return nil, fmt.Errorf("Error reading state: %s", err)
}
unlock, err := lockState(realMgr, "backend from plan")
// Lock the state if we can
err = clistate.Lock(realMgr, "backend from plan", m.Ui, m.Colorize())
if err != nil {
return nil, err
return nil, fmt.Errorf("Error locking state: %s", err)
}
defer unlock()
defer clistate.Unlock(realMgr, m.Ui, m.Colorize())
if err := realMgr.RefreshState(); err != nil {
return nil, fmt.Errorf("Error reading state: %s", err)
@ -983,11 +985,12 @@ func (m *Meta) backend_C_r_s(
}
}
unlock, err := lockState(sMgr, "backend_C_r_s")
// Lock the state if we can
err = clistate.Lock(sMgr, "backend from config", m.Ui, m.Colorize())
if err != nil {
return nil, err
return nil, fmt.Errorf("Error locking state: %s", err)
}
defer unlock()
defer clistate.Unlock(sMgr, m.Ui, m.Colorize())
// Store the metadata in our saved state location
s := sMgr.State()
@ -1087,11 +1090,12 @@ func (m *Meta) backend_C_r_S_changed(
}
}
unlock, err := lockState(sMgr, "backend_C_r_S_changed")
// Lock the state if we can
err = clistate.Lock(sMgr, "backend from config", m.Ui, m.Colorize())
if err != nil {
return nil, err
return nil, fmt.Errorf("Error locking state: %s", err)
}
defer unlock()
defer clistate.Unlock(sMgr, m.Ui, m.Colorize())
// Update the backend state
s = sMgr.State()
@ -1244,11 +1248,12 @@ func (m *Meta) backend_C_R_S_unchanged(
}
}
unlock, err := lockState(sMgr, "backend_C_R_S_unchanged")
// Lock the state if we can
err = clistate.Lock(sMgr, "backend from config", m.Ui, m.Colorize())
if err != nil {
return nil, err
return nil, fmt.Errorf("Error locking state: %s", err)
}
defer unlock()
defer clistate.Unlock(sMgr, m.Ui, m.Colorize())
// Unset the remote state
s = sMgr.State()
@ -1399,21 +1404,6 @@ func init() {
backendlegacy.Init(Backends)
}
// simple wrapper to check for a state.Locker and always provide an unlock
// function to defer.
func lockState(s state.State, info string) (func() error, error) {
l, ok := s.(state.Locker)
if !ok {
return func() error { return nil }, nil
}
if err := l.Lock(info); err != nil {
return nil, err
}
return l.Unlock, nil
}
// errBackendInitRequired is the final error message shown when reinit
// is required for some reason. The error message includes the reason.
var errBackendInitRequired = errors.New(

View File

@ -7,6 +7,7 @@ import (
"path/filepath"
"strings"
clistate "github.com/hashicorp/terraform/command/state"
"github.com/hashicorp/terraform/state"
"github.com/hashicorp/terraform/terraform"
)
@ -23,17 +24,17 @@ import (
//
// This will attempt to lock both states for the migration.
func (m *Meta) backendMigrateState(opts *backendMigrateOpts) error {
unlockOne, err := lockState(opts.One, "migrate from")
err := clistate.Lock(opts.One, "migration source state", m.Ui, m.Colorize())
if err != nil {
return err
return fmt.Errorf("Error locking source state: %s", err)
}
defer unlockOne()
defer clistate.Unlock(opts.One, m.Ui, m.Colorize())
unlockTwo, err := lockState(opts.Two, "migrate to")
err = clistate.Lock(opts.Two, "migration destination state", m.Ui, m.Colorize())
if err != nil {
return err
return fmt.Errorf("Error locking destination state: %s", err)
}
defer unlockTwo()
defer clistate.Unlock(opts.Two, m.Ui, m.Colorize())
one := opts.One.State()
two := opts.Two.State()

View File

@ -5,7 +5,7 @@ import (
"log"
"strings"
"github.com/hashicorp/terraform/state"
clistate "github.com/hashicorp/terraform/command/state"
"github.com/hashicorp/terraform/terraform"
)
@ -72,13 +72,14 @@ func (c *TaintCommand) Run(args []string) int {
return 1
}
if s, ok := st.(state.Locker); c.Meta.stateLock && ok {
if err := s.Lock("taint"); err != nil {
c.Ui.Error(fmt.Sprintf("Failed to lock state: %s", err))
if c.Meta.stateLock {
err := clistate.Lock(st, "taint", c.Ui, c.Colorize())
if err != nil {
c.Ui.Error(fmt.Sprintf("Error locking state: %s", err))
return 1
}
defer s.Unlock()
defer clistate.Unlock(st, c.Ui, c.Colorize())
}
// Get the actual state structure

View File

@ -124,7 +124,7 @@ func (c *UnlockCommand) Synopsis() string {
}
const outputUnlockSuccess = `
[reset][bold][red]Terraform state has been successfully unlocked![reset][red]
[reset][bold][green]Terraform state has been successfully unlocked![reset][green]
The state has been unlocked, and Terraform commands should now be able to
obtain a new lock on the remote state.

View File

@ -5,7 +5,7 @@ import (
"log"
"strings"
"github.com/hashicorp/terraform/state"
clistate "github.com/hashicorp/terraform/command/state"
)
// UntaintCommand is a cli.Command implementation that manually untaints
@ -60,13 +60,14 @@ func (c *UntaintCommand) Run(args []string) int {
return 1
}
if s, ok := st.(state.Locker); c.Meta.stateLock && ok {
if err := s.Lock("untaint"); err != nil {
c.Ui.Error(fmt.Sprintf("Failed to lock state: %s", err))
if c.Meta.stateLock {
err := clistate.Lock(st, "untaint", c.Ui, c.Colorize())
if err != nil {
c.Ui.Error(fmt.Sprintf("Error locking state: %s", err))
return 1
}
defer s.Unlock()
defer clistate.Unlock(st, c.Ui, c.Colorize())
}
// Get the actual state structure