Skip to content

Commit

Permalink
make command tests pass with new state.Locker
Browse files Browse the repository at this point in the history
  • Loading branch information
jbardin committed Feb 15, 2017
1 parent cd233fe commit 4f0c465
Show file tree
Hide file tree
Showing 7 changed files with 63 additions and 34 deletions.
32 changes: 24 additions & 8 deletions command/meta_backend.go
Original file line number Diff line number Diff line change
Expand Up @@ -533,11 +533,16 @@ func (m *Meta) backendFromPlan(opts *BackendOpts) (backend.Backend, error) {
}

// Lock the state if we can
err = clistate.Lock(realMgr, "backend from plan", m.Ui, m.Colorize())
lockInfo := &state.LockInfo{
Operation: "plan",
Info: "backend from plan",
}

lockID, err := clistate.Lock(realMgr, lockInfo, m.Ui, m.Colorize())
if err != nil {
return nil, fmt.Errorf("Error locking state: %s", err)
}
defer clistate.Unlock(realMgr, m.Ui, m.Colorize())
defer clistate.Unlock(realMgr, lockID, m.Ui, m.Colorize())

if err := realMgr.RefreshState(); err != nil {
return nil, fmt.Errorf("Error reading state: %s", err)
Expand Down Expand Up @@ -986,11 +991,15 @@ func (m *Meta) backend_C_r_s(
}

// Lock the state if we can
err = clistate.Lock(sMgr, "backend from config", m.Ui, m.Colorize())
lockInfo := &state.LockInfo{
Info: "backend from config",
}

lockID, err := clistate.Lock(sMgr, lockInfo, m.Ui, m.Colorize())
if err != nil {
return nil, fmt.Errorf("Error locking state: %s", err)
}
defer clistate.Unlock(sMgr, m.Ui, m.Colorize())
defer clistate.Unlock(sMgr, lockID, m.Ui, m.Colorize())

// Store the metadata in our saved state location
s := sMgr.State()
Expand Down Expand Up @@ -1091,11 +1100,14 @@ func (m *Meta) backend_C_r_S_changed(
}

// Lock the state if we can
err = clistate.Lock(sMgr, "backend from config", m.Ui, m.Colorize())
lockInfo := &state.LockInfo{
Info: "backend from config",
}
lockID, err := clistate.Lock(sMgr, lockInfo, m.Ui, m.Colorize())
if err != nil {
return nil, fmt.Errorf("Error locking state: %s", err)
}
defer clistate.Unlock(sMgr, m.Ui, m.Colorize())
defer clistate.Unlock(sMgr, lockID, m.Ui, m.Colorize())

// Update the backend state
s = sMgr.State()
Expand Down Expand Up @@ -1249,11 +1261,15 @@ func (m *Meta) backend_C_R_S_unchanged(
}

// Lock the state if we can
err = clistate.Lock(sMgr, "backend from config", m.Ui, m.Colorize())
lockInfo := &state.LockInfo{
Info: "backend from config",
}

lockID, err := clistate.Lock(sMgr, lockInfo, m.Ui, m.Colorize())
if err != nil {
return nil, fmt.Errorf("Error locking state: %s", err)
}
defer clistate.Unlock(sMgr, m.Ui, m.Colorize())
defer clistate.Unlock(sMgr, lockID, m.Ui, m.Colorize())

// Unset the remote state
s = sMgr.State()
Expand Down
16 changes: 12 additions & 4 deletions command/meta_backend_migrate.go
Original file line number Diff line number Diff line change
Expand Up @@ -24,17 +24,25 @@ import (
//
// This will attempt to lock both states for the migration.
func (m *Meta) backendMigrateState(opts *backendMigrateOpts) error {
err := clistate.Lock(opts.One, "migration source state", m.Ui, m.Colorize())
lockInfoOne := &state.LockInfo{
Info: "migration source state",
}

lockIDOne, err := clistate.Lock(opts.One, lockInfoOne, m.Ui, m.Colorize())
if err != nil {
return fmt.Errorf("Error locking source state: %s", err)
}
defer clistate.Unlock(opts.One, m.Ui, m.Colorize())
defer clistate.Unlock(opts.One, lockIDOne, m.Ui, m.Colorize())

lockInfoTwo := &state.LockInfo{
Info: "migration source state",
}

err = clistate.Lock(opts.Two, "migration destination state", m.Ui, m.Colorize())
lockIDTwo, err := clistate.Lock(opts.Two, lockInfoTwo, m.Ui, m.Colorize())
if err != nil {
return fmt.Errorf("Error locking destination state: %s", err)
}
defer clistate.Unlock(opts.Two, m.Ui, m.Colorize())
defer clistate.Unlock(opts.Two, lockIDTwo, m.Ui, m.Colorize())

one := opts.One.State()
two := opts.Two.State()
Expand Down
8 changes: 6 additions & 2 deletions command/taint.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

clistate "github.com/hashicorp/terraform/command/state"
"github.com/hashicorp/terraform/state"
"github.com/hashicorp/terraform/terraform"
)

Expand Down Expand Up @@ -73,13 +74,16 @@ func (c *TaintCommand) Run(args []string) int {
}

if c.Meta.stateLock {
err := clistate.Lock(st, "taint", c.Ui, c.Colorize())
lockInfo := &state.LockInfo{
Operation: "taint",
}
lockID, err := clistate.Lock(st, lockInfo, c.Ui, c.Colorize())
if err != nil {
c.Ui.Error(fmt.Sprintf("Error locking state: %s", err))
return 1
}

defer clistate.Unlock(st, c.Ui, c.Colorize())
defer clistate.Unlock(st, lockID, c.Ui, c.Colorize())
}

// Get the actual state structure
Expand Down
4 changes: 2 additions & 2 deletions command/testdata/statelocker.go
Original file line number Diff line number Diff line change
Expand Up @@ -23,7 +23,7 @@ func main() {
Path: os.Args[1],
}

err := s.Lock("command test")
lockID, err := s.Lock(&state.LockInfo{Operation: "test", Info: "state locker"})
if err != nil {
io.WriteString(os.Stderr, err.Error())
return
Expand All @@ -33,7 +33,7 @@ func main() {
io.WriteString(os.Stdout, "LOCKED")

defer func() {
if err := s.Unlock(); err != nil {
if err := s.Unlock(lockID); err != nil {
io.WriteString(os.Stderr, err.Error())
}
}()
Expand Down
3 changes: 2 additions & 1 deletion command/unlock.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,8 @@ func (c *UnlockCommand) Run(args []string) int {
}
}

if err := s.Unlock(); err != nil {
// FIXME: unlock should require the lock ID
if err := s.Unlock(""); err != nil {
c.Ui.Error(fmt.Sprintf("Failed to unlock state: %s", err))
return 1
}
Expand Down
8 changes: 6 additions & 2 deletions command/untaint.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ import (
"strings"

clistate "github.com/hashicorp/terraform/command/state"
"github.com/hashicorp/terraform/state"
)

// UntaintCommand is a cli.Command implementation that manually untaints
Expand Down Expand Up @@ -61,13 +62,16 @@ func (c *UntaintCommand) Run(args []string) int {
}

if c.Meta.stateLock {
err := clistate.Lock(st, "untaint", c.Ui, c.Colorize())
lockInfo := &state.LockInfo{
Operation: "untaint",
}
lockID, err := clistate.Lock(st, lockInfo, c.Ui, c.Colorize())
if err != nil {
c.Ui.Error(fmt.Sprintf("Error locking state: %s", err))
return 1
}

defer clistate.Unlock(st, c.Ui, c.Colorize())
defer clistate.Unlock(st, lockID, c.Ui, c.Colorize())
}

// Get the actual state structure
Expand Down
26 changes: 11 additions & 15 deletions state/local.go
Original file line number Diff line number Diff line change
Expand Up @@ -134,25 +134,25 @@ func (s *LocalState) RefreshState() error {
}

// Lock implements a local filesystem state.Locker.
func (s *LocalState) Lock(reason string) error {
func (s *LocalState) Lock(info *LockInfo) (string, error) {
if s.stateFileOut == nil {
if err := s.createStateFiles(); err != nil {
return err
return "", err
}
}

if err := s.lock(); err != nil {
if info, err := s.lockInfo(); err == nil {
return info.Err()
return "", info.Err()
}

return fmt.Errorf("state file %q locked: %s", s.Path, err)
return "", fmt.Errorf("state file %q locked: %s", s.Path, err)
}

return s.writeLockInfo(reason)
return "", s.writeLockInfo(info)
}

func (s *LocalState) Unlock() error {
func (s *LocalState) Unlock(id string) error {
// we can't be locked if we don't have a file
if s.stateFileOut == nil {
return nil
Expand Down Expand Up @@ -232,18 +232,14 @@ func (s *LocalState) lockInfo() (*LockInfo, error) {
}

// write a new lock info file
func (s *LocalState) writeLockInfo(info string) error {
func (s *LocalState) writeLockInfo(info *LockInfo) error {
path := s.lockInfoPath()
info.Path = s.Path
info.Created = time.Now().UTC()

lockInfo := &LockInfo{
Path: s.Path,
Created: time.Now().UTC(),
Info: info,
}

infoData, err := json.Marshal(lockInfo)
infoData, err := json.Marshal(info)
if err != nil {
panic(fmt.Sprintf("could not marshal lock info: %#v", lockInfo))
panic(fmt.Sprintf("could not marshal lock info: %#v", info))
}

err = ioutil.WriteFile(path, infoData, 0600)
Expand Down

0 comments on commit 4f0c465

Please sign in to comment.