command/state: helpers for UX with lock/unlock state
This commit is contained in:
parent
2124135287
commit
34f438b635
|
@ -0,0 +1,83 @@
|
||||||
|
// Package state exposes common helpers for working with state from the CLI.
|
||||||
|
//
|
||||||
|
// This is a separate package so that backends can use this for consistent
|
||||||
|
// messaging without creating a circular reference to the command package.
|
||||||
|
package message
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/hashicorp/terraform/helper/slowmessage"
|
||||||
|
"github.com/hashicorp/terraform/state"
|
||||||
|
"github.com/mitchellh/cli"
|
||||||
|
"github.com/mitchellh/colorstring"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
LockThreshold = 250 * time.Millisecond
|
||||||
|
LockMessage = "Acquiring state lock. This may take a few moments..."
|
||||||
|
UnlockMessage = "Releasing state lock. This may take a few moments..."
|
||||||
|
|
||||||
|
UnlockErrorMessage = `
|
||||||
|
[reset][bold][red]Error releasing the state lock![reset][red]
|
||||||
|
|
||||||
|
Error message: %s
|
||||||
|
|
||||||
|
Terraform acquires a lock when accessing your state to prevent others
|
||||||
|
running Terraform to potentially modify the state at the same time. An
|
||||||
|
error occurred while releasing this lock. This could mean that the lock
|
||||||
|
did or did not release properly. If the lock didn't release properly,
|
||||||
|
Terraform may not be able to run future commands since it'll appear as if
|
||||||
|
the lock is held.
|
||||||
|
|
||||||
|
In this scenario, please call the "force-unlock" command to unlock the
|
||||||
|
state manually. This is a very dangerous operation since if it is done
|
||||||
|
erroneously it could result in two people modifying state at the same time.
|
||||||
|
Only call this command if you're certain that the unlock above failed and
|
||||||
|
that no one else is holding a lock.
|
||||||
|
`
|
||||||
|
)
|
||||||
|
|
||||||
|
// Lock locks the given state and outputs to the user if locking
|
||||||
|
// is taking longer than the threshold.
|
||||||
|
func Lock(s state.State, info string, ui cli.Ui, color *colorstring.Colorize) error {
|
||||||
|
sl, ok := s.(state.Locker)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return slowmessage.Do(LockThreshold, func() error {
|
||||||
|
return sl.Lock(info)
|
||||||
|
}, func() {
|
||||||
|
if ui != nil {
|
||||||
|
ui.Output(color.Color(LockMessage))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
// Unlock unlocks the given state and outputs to the user if the
|
||||||
|
// unlock fails what can be done.
|
||||||
|
func Unlock(s state.State, ui cli.Ui, color *colorstring.Colorize) error {
|
||||||
|
sl, ok := s.(state.Locker)
|
||||||
|
if !ok {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
err := slowmessage.Do(LockThreshold, sl.Unlock, func() {
|
||||||
|
if ui != nil {
|
||||||
|
ui.Output(color.Color(UnlockMessage))
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
ui.Output(color.Color(fmt.Sprintf(
|
||||||
|
"\n"+strings.TrimSpace(UnlockErrorMessage)+"\n", err)))
|
||||||
|
|
||||||
|
err = fmt.Errorf(
|
||||||
|
"Error releasing the state lock. Please see the longer error message above.")
|
||||||
|
}
|
||||||
|
|
||||||
|
return err
|
||||||
|
}
|
Loading…
Reference in New Issue