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 // 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. // caller to call Lock and Unlock as needed.
State() (state.State, error) 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 returns a list of configured named states and the current state.
States() ([]string, string, error) States() ([]string, string, error)
// ChangeState changes to the named state. If this doesn't exist it'll be // ChangeState changes to the named state. If the named state doesn't exist
// created. // it will be created.
ChangeState(name string) error 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. // Enhanced implements additional behavior on top of a normal backend.

View File

@ -27,6 +27,8 @@ const (
DefaultBackupExtension = ".backup" DefaultBackupExtension = ".backup"
) )
var ErrEnvNotSupported = errors.New("environments not supported")
// Local is an implementation of EnhancedBackend that performs all operations // Local is an implementation of EnhancedBackend that performs all operations
// locally. This is the "default" backend and implements normal Terraform // locally. This is the "default" backend and implements normal Terraform
// behavior as it is well known. // 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) { 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" // the listing always start with "default"
envs := []string{backend.DefaultStateName} envs := []string{backend.DefaultStateName}
@ -154,6 +165,15 @@ func (b *Local) States() ([]string, string, error) {
// DeleteState removes a named state. // DeleteState removes a named state.
// The "default" state cannot be removed. // The "default" state cannot be removed.
func (b *Local) DeleteState(name string) error { 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 == "" { if name == "" {
return errors.New("empty state 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. // Change to the named state, creating it if it doesn't exist.
func (b *Local) ChangeState(name string) error { 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) name = strings.TrimSpace(name)
if name == "" { if name == "" {
return errors.New("state name cannot be empty") return errors.New("state name cannot be empty")