Split out the backend environment interface

Split the interface to change environments out from the minimal Backend
interface, to make it optional for backend implementations. If
backend.MultiState isn't implemented, return a "not implemented" from
environment related methods.

Have the Local backend delegate the MultiState methods to the proper
backend.
This commit is contained in:
James Bardin 2017-02-22 13:40:04 -05:00
parent 1ea9413c07
commit 0933541a8c
2 changed files with 40 additions and 2 deletions

View File

@ -27,13 +27,22 @@ type Backend interface {
// to load the state. If the state.State is a state.Locker, it's up to the
// caller to call Lock and Unlock as needed.
State() (state.State, error)
}
// MultiState is an interface that a backend can implement to allow changing
// between named states depending on the configured environment.
type MultiState interface {
// States returns a list of configured named states and the current state.
States() ([]string, string, error)
// ChangeState changes to the named state. If this doesn't exist it'll be
// created.
// ChangeState changes to the named state. If the named state doesn't exist
// it will be created.
ChangeState(name string) error
// DeleteState removes the named state if it exists. If the current state is
// deleted, the backend should change to the default state. It is an error
// to delete the default state.
DeleteState(name string) error
}
// Enhanced implements additional behavior on top of a normal backend.

View File

@ -27,6 +27,8 @@ const (
DefaultBackupExtension = ".backup"
)
var ErrEnvNotSupported = errors.New("environments not supported")
// Local is an implementation of EnhancedBackend that performs all operations
// locally. This is the "default" backend and implements normal Terraform
// behavior as it is well known.
@ -117,6 +119,15 @@ func (b *Local) Configure(c *terraform.ResourceConfig) error {
}
func (b *Local) States() ([]string, string, error) {
// If we have a backend handling state, defer to that.
if b.Backend != nil {
if b, ok := b.Backend.(backend.MultiState); ok {
return b.States()
} else {
return nil, "", ErrEnvNotSupported
}
}
// the listing always start with "default"
envs := []string{backend.DefaultStateName}
@ -154,6 +165,15 @@ func (b *Local) States() ([]string, string, error) {
// DeleteState removes a named state.
// The "default" state cannot be removed.
func (b *Local) DeleteState(name string) error {
// If we have a backend handling state, defer to that.
if b.Backend != nil {
if b, ok := b.Backend.(backend.MultiState); ok {
return b.DeleteState(name)
} else {
return ErrEnvNotSupported
}
}
if name == "" {
return errors.New("empty state name")
}
@ -174,6 +194,15 @@ func (b *Local) DeleteState(name string) error {
// Change to the named state, creating it if it doesn't exist.
func (b *Local) ChangeState(name string) error {
// If we have a backend handling state, defer to that.
if b.Backend != nil {
if b, ok := b.Backend.(backend.MultiState); ok {
return b.ChangeState(name)
} else {
return ErrEnvNotSupported
}
}
name = strings.TrimSpace(name)
if name == "" {
return errors.New("state name cannot be empty")