Use New() instead of `once.Do(b.init)`
This commit is contained in:
parent
97d1c46602
commit
495d1ea350
|
@ -39,59 +39,14 @@ type Backend struct {
|
|||
|
||||
// schema is the schema for configuration, set by init
|
||||
schema *schema.Backend
|
||||
once sync.Once
|
||||
|
||||
// opLock locks operations
|
||||
opLock sync.Mutex
|
||||
}
|
||||
|
||||
func (b *Backend) Input(
|
||||
ui terraform.UIInput, c *terraform.ResourceConfig) (*terraform.ResourceConfig, error) {
|
||||
b.once.Do(b.init)
|
||||
return b.schema.Input(ui, c)
|
||||
}
|
||||
|
||||
func (b *Backend) Validate(c *terraform.ResourceConfig) ([]string, []error) {
|
||||
b.once.Do(b.init)
|
||||
return b.schema.Validate(c)
|
||||
}
|
||||
|
||||
func (b *Backend) Configure(c *terraform.ResourceConfig) error {
|
||||
b.once.Do(b.init)
|
||||
return b.schema.Configure(c)
|
||||
}
|
||||
|
||||
func (b *Backend) States() ([]string, error) {
|
||||
return nil, backend.ErrNamedStatesNotSupported
|
||||
}
|
||||
|
||||
func (b *Backend) DeleteState(name string) error {
|
||||
return backend.ErrNamedStatesNotSupported
|
||||
}
|
||||
|
||||
func (b *Backend) State(name string) (state.State, error) {
|
||||
if name != backend.DefaultStateName {
|
||||
return nil, backend.ErrNamedStatesNotSupported
|
||||
}
|
||||
|
||||
return &remote.State{Client: b.stateClient}, nil
|
||||
}
|
||||
|
||||
// Colorize returns the Colorize structure that can be used for colorizing
|
||||
// output. This is gauranteed to always return a non-nil value and so is useful
|
||||
// as a helper to wrap any potentially colored strings.
|
||||
func (b *Backend) Colorize() *colorstring.Colorize {
|
||||
if b.CLIColor != nil {
|
||||
return b.CLIColor
|
||||
}
|
||||
|
||||
return &colorstring.Colorize{
|
||||
Colors: colorstring.DefaultColors,
|
||||
Disable: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Backend) init() {
|
||||
// New returns a new initialized Atlas backend.
|
||||
func New() *Backend {
|
||||
b := &Backend{}
|
||||
b.schema = &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"name": &schema.Schema{
|
||||
|
@ -115,11 +70,13 @@ func (b *Backend) init() {
|
|||
},
|
||||
},
|
||||
|
||||
ConfigureFunc: b.schemaConfigure,
|
||||
ConfigureFunc: b.configure,
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *Backend) schemaConfigure(ctx context.Context) error {
|
||||
func (b *Backend) configure(ctx context.Context) error {
|
||||
d := schema.FromContextBackendConfig(ctx)
|
||||
|
||||
// Parse the address
|
||||
|
@ -153,6 +110,47 @@ func (b *Backend) schemaConfigure(ctx context.Context) error {
|
|||
return nil
|
||||
}
|
||||
|
||||
func (b *Backend) Input(ui terraform.UIInput, c *terraform.ResourceConfig) (*terraform.ResourceConfig, error) {
|
||||
return b.schema.Input(ui, c)
|
||||
}
|
||||
|
||||
func (b *Backend) Validate(c *terraform.ResourceConfig) ([]string, []error) {
|
||||
return b.schema.Validate(c)
|
||||
}
|
||||
|
||||
func (b *Backend) Configure(c *terraform.ResourceConfig) error {
|
||||
return b.schema.Configure(c)
|
||||
}
|
||||
|
||||
func (b *Backend) State(name string) (state.State, error) {
|
||||
if name != backend.DefaultStateName {
|
||||
return nil, backend.ErrNamedStatesNotSupported
|
||||
}
|
||||
return &remote.State{Client: b.stateClient}, nil
|
||||
}
|
||||
|
||||
func (b *Backend) DeleteState(name string) error {
|
||||
return backend.ErrNamedStatesNotSupported
|
||||
}
|
||||
|
||||
func (b *Backend) States() ([]string, error) {
|
||||
return nil, backend.ErrNamedStatesNotSupported
|
||||
}
|
||||
|
||||
// Colorize returns the Colorize structure that can be used for colorizing
|
||||
// output. This is gauranteed to always return a non-nil value and so is useful
|
||||
// as a helper to wrap any potentially colored strings.
|
||||
func (b *Backend) Colorize() *colorstring.Colorize {
|
||||
if b.CLIColor != nil {
|
||||
return b.CLIColor
|
||||
}
|
||||
|
||||
return &colorstring.Colorize{
|
||||
Colors: colorstring.DefaultColors,
|
||||
Disable: true,
|
||||
}
|
||||
}
|
||||
|
||||
var schemaDescriptions = map[string]string{
|
||||
"name": "Full name of the environment in Atlas, such as 'hashicorp/myenv'",
|
||||
"access_token": "Access token to use to access Atlas. If ATLAS_TOKEN is set then\n" +
|
||||
|
|
|
@ -18,7 +18,7 @@ func TestConfigure_envAddr(t *testing.T) {
|
|||
defer os.Setenv("ATLAS_ADDRESS", os.Getenv("ATLAS_ADDRESS"))
|
||||
os.Setenv("ATLAS_ADDRESS", "http://foo.com")
|
||||
|
||||
b := &Backend{}
|
||||
b := New()
|
||||
err := b.Configure(terraform.NewResourceConfig(config.TestRawConfig(t, map[string]interface{}{
|
||||
"name": "foo/bar",
|
||||
})))
|
||||
|
@ -35,7 +35,7 @@ func TestConfigure_envToken(t *testing.T) {
|
|||
defer os.Setenv("ATLAS_TOKEN", os.Getenv("ATLAS_TOKEN"))
|
||||
os.Setenv("ATLAS_TOKEN", "foo")
|
||||
|
||||
b := &Backend{}
|
||||
b := New()
|
||||
err := b.Configure(terraform.NewResourceConfig(config.TestRawConfig(t, map[string]interface{}{
|
||||
"name": "foo/bar",
|
||||
})))
|
||||
|
|
|
@ -20,7 +20,7 @@ import (
|
|||
)
|
||||
|
||||
func testStateClient(t *testing.T, c map[string]interface{}) remote.Client {
|
||||
b := backend.TestBackendConfig(t, &Backend{}, c)
|
||||
b := backend.TestBackendConfig(t, New(), c)
|
||||
raw, err := b.State(backend.DefaultStateName)
|
||||
if err != nil {
|
||||
t.Fatalf("err: %s", err)
|
||||
|
|
|
@ -39,8 +39,8 @@ func init() {
|
|||
// Our hardcoded backends. We don't need to acquire a lock here
|
||||
// since init() code is serial and can't spawn goroutines.
|
||||
backends = map[string]func() backend.Backend{
|
||||
"local": func() backend.Backend { return &backendLocal.Local{} },
|
||||
"atlas": func() backend.Backend { return &backendAtlas.Backend{} },
|
||||
"local": func() backend.Backend { return backendLocal.New() },
|
||||
"atlas": func() backend.Backend { return backendAtlas.New() },
|
||||
"azure": deprecateBackend(backendAzure.New(),
|
||||
`Warning: "azure" name is deprecated, please use "azurerm"`),
|
||||
"azurerm": func() backend.Backend { return backendAzure.New() },
|
||||
|
|
|
@ -91,94 +91,106 @@ type Local struct {
|
|||
|
||||
schema *schema.Backend
|
||||
opLock sync.Mutex
|
||||
once sync.Once
|
||||
}
|
||||
|
||||
func (b *Local) Input(
|
||||
ui terraform.UIInput, c *terraform.ResourceConfig) (*terraform.ResourceConfig, error) {
|
||||
b.once.Do(b.init)
|
||||
// New returns a new initialized local backend.
|
||||
func New() *Local {
|
||||
return NewWithBackend(nil)
|
||||
}
|
||||
|
||||
// NewWithBackend returns a new local backend initialized with a
|
||||
// dedicated backend for non-enhanced behavior.
|
||||
func NewWithBackend(backend backend.Backend) *Local {
|
||||
b := &Local{
|
||||
Backend: backend,
|
||||
}
|
||||
|
||||
b.schema = &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"path": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Default: "",
|
||||
},
|
||||
|
||||
"workspace_dir": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Default: "",
|
||||
},
|
||||
|
||||
"environment_dir": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Default: "",
|
||||
ConflictsWith: []string{"workspace_dir"},
|
||||
Deprecated: "workspace_dir should be used instead, with the same meaning",
|
||||
},
|
||||
},
|
||||
|
||||
ConfigureFunc: b.configure,
|
||||
}
|
||||
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *Local) configure(ctx context.Context) error {
|
||||
d := schema.FromContextBackendConfig(ctx)
|
||||
|
||||
// Set the path if it is set
|
||||
pathRaw, ok := d.GetOk("path")
|
||||
if ok {
|
||||
path := pathRaw.(string)
|
||||
if path == "" {
|
||||
return fmt.Errorf("configured path is empty")
|
||||
}
|
||||
|
||||
b.StatePath = path
|
||||
b.StateOutPath = path
|
||||
}
|
||||
|
||||
if raw, ok := d.GetOk("workspace_dir"); ok {
|
||||
path := raw.(string)
|
||||
if path != "" {
|
||||
b.StateWorkspaceDir = path
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy name, which ConflictsWith workspace_dir
|
||||
if raw, ok := d.GetOk("environment_dir"); ok {
|
||||
path := raw.(string)
|
||||
if path != "" {
|
||||
b.StateWorkspaceDir = path
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
func (b *Local) Input(ui terraform.UIInput, c *terraform.ResourceConfig) (*terraform.ResourceConfig, error) {
|
||||
f := b.schema.Input
|
||||
if b.Backend != nil {
|
||||
f = b.Backend.Input
|
||||
}
|
||||
|
||||
return f(ui, c)
|
||||
}
|
||||
|
||||
func (b *Local) Validate(c *terraform.ResourceConfig) ([]string, []error) {
|
||||
b.once.Do(b.init)
|
||||
|
||||
f := b.schema.Validate
|
||||
if b.Backend != nil {
|
||||
f = b.Backend.Validate
|
||||
}
|
||||
|
||||
return f(c)
|
||||
}
|
||||
|
||||
func (b *Local) Configure(c *terraform.ResourceConfig) error {
|
||||
b.once.Do(b.init)
|
||||
|
||||
f := b.schema.Configure
|
||||
if b.Backend != nil {
|
||||
f = b.Backend.Configure
|
||||
}
|
||||
|
||||
return f(c)
|
||||
}
|
||||
|
||||
func (b *Local) States() ([]string, error) {
|
||||
// If we have a backend handling state, defer to that.
|
||||
if b.Backend != nil {
|
||||
return b.Backend.States()
|
||||
}
|
||||
|
||||
// the listing always start with "default"
|
||||
envs := []string{backend.DefaultStateName}
|
||||
|
||||
entries, err := ioutil.ReadDir(b.stateWorkspaceDir())
|
||||
// no error if there's no envs configured
|
||||
if os.IsNotExist(err) {
|
||||
return envs, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var listed []string
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
listed = append(listed, filepath.Base(entry.Name()))
|
||||
}
|
||||
}
|
||||
|
||||
sort.Strings(listed)
|
||||
envs = append(envs, listed...)
|
||||
|
||||
return envs, nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return b.Backend.DeleteState(name)
|
||||
}
|
||||
|
||||
if name == "" {
|
||||
return errors.New("empty state name")
|
||||
}
|
||||
|
||||
if name == backend.DefaultStateName {
|
||||
return errors.New("cannot delete default state")
|
||||
}
|
||||
|
||||
delete(b.states, name)
|
||||
return os.RemoveAll(filepath.Join(b.stateWorkspaceDir(), name))
|
||||
}
|
||||
|
||||
func (b *Local) State(name string) (state.State, error) {
|
||||
statePath, stateOutPath, backupPath := b.StatePaths(name)
|
||||
|
||||
|
@ -216,6 +228,57 @@ func (b *Local) State(name string) (state.State, error) {
|
|||
return s, nil
|
||||
}
|
||||
|
||||
// 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 {
|
||||
return b.Backend.DeleteState(name)
|
||||
}
|
||||
|
||||
if name == "" {
|
||||
return errors.New("empty state name")
|
||||
}
|
||||
|
||||
if name == backend.DefaultStateName {
|
||||
return errors.New("cannot delete default state")
|
||||
}
|
||||
|
||||
delete(b.states, name)
|
||||
return os.RemoveAll(filepath.Join(b.stateWorkspaceDir(), name))
|
||||
}
|
||||
|
||||
func (b *Local) States() ([]string, error) {
|
||||
// If we have a backend handling state, defer to that.
|
||||
if b.Backend != nil {
|
||||
return b.Backend.States()
|
||||
}
|
||||
|
||||
// the listing always start with "default"
|
||||
envs := []string{backend.DefaultStateName}
|
||||
|
||||
entries, err := ioutil.ReadDir(b.stateWorkspaceDir())
|
||||
// no error if there's no envs configured
|
||||
if os.IsNotExist(err) {
|
||||
return envs, nil
|
||||
}
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
var listed []string
|
||||
for _, entry := range entries {
|
||||
if entry.IsDir() {
|
||||
listed = append(listed, filepath.Base(entry.Name()))
|
||||
}
|
||||
}
|
||||
|
||||
sort.Strings(listed)
|
||||
envs = append(envs, listed...)
|
||||
|
||||
return envs, nil
|
||||
}
|
||||
|
||||
// Operation implements backend.Enhanced
|
||||
//
|
||||
// This will initialize an in-memory terraform.Context to perform the
|
||||
|
@ -348,68 +411,6 @@ func (b *Local) Colorize() *colorstring.Colorize {
|
|||
}
|
||||
}
|
||||
|
||||
func (b *Local) init() {
|
||||
b.schema = &schema.Backend{
|
||||
Schema: map[string]*schema.Schema{
|
||||
"path": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Default: "",
|
||||
},
|
||||
|
||||
"workspace_dir": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Default: "",
|
||||
},
|
||||
|
||||
"environment_dir": &schema.Schema{
|
||||
Type: schema.TypeString,
|
||||
Optional: true,
|
||||
Default: "",
|
||||
ConflictsWith: []string{"workspace_dir"},
|
||||
|
||||
Deprecated: "workspace_dir should be used instead, with the same meaning",
|
||||
},
|
||||
},
|
||||
|
||||
ConfigureFunc: b.schemaConfigure,
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Local) schemaConfigure(ctx context.Context) error {
|
||||
d := schema.FromContextBackendConfig(ctx)
|
||||
|
||||
// Set the path if it is set
|
||||
pathRaw, ok := d.GetOk("path")
|
||||
if ok {
|
||||
path := pathRaw.(string)
|
||||
if path == "" {
|
||||
return fmt.Errorf("configured path is empty")
|
||||
}
|
||||
|
||||
b.StatePath = path
|
||||
b.StateOutPath = path
|
||||
}
|
||||
|
||||
if raw, ok := d.GetOk("workspace_dir"); ok {
|
||||
path := raw.(string)
|
||||
if path != "" {
|
||||
b.StateWorkspaceDir = path
|
||||
}
|
||||
}
|
||||
|
||||
// Legacy name, which ConflictsWith workspace_dir
|
||||
if raw, ok := d.GetOk("environment_dir"); ok {
|
||||
path := raw.(string)
|
||||
if path != "" {
|
||||
b.StateWorkspaceDir = path
|
||||
}
|
||||
}
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
// StatePaths returns the StatePath, StateOutPath, and StateBackupPath as
|
||||
// configured from the CLI.
|
||||
func (b *Local) StatePaths(name string) (string, string, string) {
|
||||
|
|
|
@ -5,15 +5,13 @@ import (
|
|||
"errors"
|
||||
"log"
|
||||
|
||||
"github.com/hashicorp/terraform/command/clistate"
|
||||
"github.com/hashicorp/terraform/command/format"
|
||||
|
||||
"github.com/hashicorp/terraform/tfdiags"
|
||||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/terraform/backend"
|
||||
"github.com/hashicorp/terraform/command/clistate"
|
||||
"github.com/hashicorp/terraform/command/format"
|
||||
"github.com/hashicorp/terraform/state"
|
||||
"github.com/hashicorp/terraform/terraform"
|
||||
"github.com/hashicorp/terraform/tfdiags"
|
||||
)
|
||||
|
||||
// backend.Local implementation.
|
||||
|
|
|
@ -15,14 +15,14 @@ import (
|
|||
)
|
||||
|
||||
func TestLocal_impl(t *testing.T) {
|
||||
var _ backend.Enhanced = new(Local)
|
||||
var _ backend.Local = new(Local)
|
||||
var _ backend.CLI = new(Local)
|
||||
var _ backend.Enhanced = New()
|
||||
var _ backend.Local = New()
|
||||
var _ backend.CLI = New()
|
||||
}
|
||||
|
||||
func TestLocal_backend(t *testing.T) {
|
||||
defer testTmpDir(t)()
|
||||
b := &Local{}
|
||||
b := New()
|
||||
backend.TestBackendStates(t, b)
|
||||
backend.TestBackendStateLocks(t, b, b)
|
||||
}
|
||||
|
@ -49,7 +49,7 @@ func checkState(t *testing.T, path, expected string) {
|
|||
}
|
||||
|
||||
func TestLocal_StatePaths(t *testing.T) {
|
||||
b := &Local{}
|
||||
b := New()
|
||||
|
||||
// Test the defaults
|
||||
path, out, back := b.StatePaths("")
|
||||
|
@ -94,7 +94,7 @@ func TestLocal_addAndRemoveStates(t *testing.T) {
|
|||
dflt := backend.DefaultStateName
|
||||
expectedStates := []string{dflt}
|
||||
|
||||
b := &Local{}
|
||||
b := New()
|
||||
states, err := b.States()
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
|
@ -210,13 +210,11 @@ func (b *testDelegateBackend) DeleteState(name string) error {
|
|||
// verify that the MultiState methods are dispatched to the correct Backend.
|
||||
func TestLocal_multiStateBackend(t *testing.T) {
|
||||
// assign a separate backend where we can read the state
|
||||
b := &Local{
|
||||
Backend: &testDelegateBackend{
|
||||
stateErr: true,
|
||||
statesErr: true,
|
||||
deleteErr: true,
|
||||
},
|
||||
}
|
||||
b := NewWithBackend(&testDelegateBackend{
|
||||
stateErr: true,
|
||||
statesErr: true,
|
||||
deleteErr: true,
|
||||
})
|
||||
|
||||
if _, err := b.State("test"); err != errTestDelegateState {
|
||||
t.Fatal("expected errTestDelegateState, got:", err)
|
||||
|
|
|
@ -18,13 +18,14 @@ import (
|
|||
// public fields without any locks.
|
||||
func TestLocal(t *testing.T) (*Local, func()) {
|
||||
tempDir := testTempDir(t)
|
||||
local := &Local{
|
||||
StatePath: filepath.Join(tempDir, "state.tfstate"),
|
||||
StateOutPath: filepath.Join(tempDir, "state.tfstate"),
|
||||
StateBackupPath: filepath.Join(tempDir, "state.tfstate.bak"),
|
||||
StateWorkspaceDir: filepath.Join(tempDir, "state.tfstate.d"),
|
||||
ContextOpts: &terraform.ContextOpts{},
|
||||
}
|
||||
|
||||
local := New()
|
||||
local.StatePath = filepath.Join(tempDir, "state.tfstate")
|
||||
local.StateOutPath = filepath.Join(tempDir, "state.tfstate")
|
||||
local.StateBackupPath = filepath.Join(tempDir, "state.tfstate.bak")
|
||||
local.StateWorkspaceDir = filepath.Join(tempDir, "state.tfstate.d")
|
||||
local.ContextOpts = &terraform.ContextOpts{}
|
||||
|
||||
cleanup := func() {
|
||||
if err := os.RemoveAll(tempDir); err != nil {
|
||||
t.Fatal("error clecanup up test:", err)
|
||||
|
@ -69,7 +70,7 @@ func TestLocalProvider(t *testing.T, b *Local, name string) *terraform.MockResou
|
|||
// TestNewLocalSingle is a factory for creating a TestLocalSingleState.
|
||||
// This function matches the signature required for backend/init.
|
||||
func TestNewLocalSingle() backend.Backend {
|
||||
return &TestLocalSingleState{}
|
||||
return &TestLocalSingleState{Local: New()}
|
||||
}
|
||||
|
||||
// TestLocalSingleState is a backend implementation that wraps Local
|
||||
|
@ -79,7 +80,7 @@ func TestNewLocalSingle() backend.Backend {
|
|||
// This isn't an actual use case, this is exported just to provide a
|
||||
// easy way to test that behavior.
|
||||
type TestLocalSingleState struct {
|
||||
Local
|
||||
*Local
|
||||
}
|
||||
|
||||
func (b *TestLocalSingleState) State(name string) (state.State, error) {
|
||||
|
|
|
@ -18,10 +18,10 @@ import (
|
|||
"google.golang.org/api/option"
|
||||
)
|
||||
|
||||
// gcsBackend implements "backend".Backend for GCS.
|
||||
// Backend implements "backend".Backend for GCS.
|
||||
// Input(), Validate() and Configure() are implemented by embedding *schema.Backend.
|
||||
// State(), DeleteState() and States() are implemented explicitly.
|
||||
type gcsBackend struct {
|
||||
type Backend struct {
|
||||
*schema.Backend
|
||||
|
||||
storageClient *storage.Client
|
||||
|
@ -38,9 +38,9 @@ type gcsBackend struct {
|
|||
}
|
||||
|
||||
func New() backend.Backend {
|
||||
be := &gcsBackend{}
|
||||
be.Backend = &schema.Backend{
|
||||
ConfigureFunc: be.configure,
|
||||
b := &Backend{}
|
||||
b.Backend = &schema.Backend{
|
||||
ConfigureFunc: b.configure,
|
||||
Schema: map[string]*schema.Schema{
|
||||
"bucket": {
|
||||
Type: schema.TypeString,
|
||||
|
@ -91,10 +91,10 @@ func New() backend.Backend {
|
|||
},
|
||||
}
|
||||
|
||||
return be
|
||||
return b
|
||||
}
|
||||
|
||||
func (b *gcsBackend) configure(ctx context.Context) error {
|
||||
func (b *Backend) configure(ctx context.Context) error {
|
||||
if b.storageClient != nil {
|
||||
return nil
|
||||
}
|
||||
|
|
|
@ -21,7 +21,7 @@ const (
|
|||
|
||||
// States returns a list of names for the states found on GCS. The default
|
||||
// state is always returned as the first element in the slice.
|
||||
func (b *gcsBackend) States() ([]string, error) {
|
||||
func (b *Backend) States() ([]string, error) {
|
||||
states := []string{backend.DefaultStateName}
|
||||
|
||||
bucket := b.storageClient.Bucket(b.bucketName)
|
||||
|
@ -54,7 +54,7 @@ func (b *gcsBackend) States() ([]string, error) {
|
|||
}
|
||||
|
||||
// DeleteState deletes the named state. The "default" state cannot be deleted.
|
||||
func (b *gcsBackend) DeleteState(name string) error {
|
||||
func (b *Backend) DeleteState(name string) error {
|
||||
if name == backend.DefaultStateName {
|
||||
return fmt.Errorf("cowardly refusing to delete the %q state", name)
|
||||
}
|
||||
|
@ -68,7 +68,7 @@ func (b *gcsBackend) DeleteState(name string) error {
|
|||
}
|
||||
|
||||
// client returns a remoteClient for the named state.
|
||||
func (b *gcsBackend) client(name string) (*remoteClient, error) {
|
||||
func (b *Backend) client(name string) (*remoteClient, error) {
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("%q is not a valid state name", name)
|
||||
}
|
||||
|
@ -85,7 +85,7 @@ func (b *gcsBackend) client(name string) (*remoteClient, error) {
|
|||
|
||||
// State reads and returns the named state from GCS. If the named state does
|
||||
// not yet exist, a new state file is created.
|
||||
func (b *gcsBackend) State(name string) (state.State, error) {
|
||||
func (b *Backend) State(name string) (state.State, error) {
|
||||
c, err := b.client(name)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
|
@ -144,14 +144,14 @@ func (b *gcsBackend) State(name string) (state.State, error) {
|
|||
return st, nil
|
||||
}
|
||||
|
||||
func (b *gcsBackend) stateFile(name string) string {
|
||||
func (b *Backend) stateFile(name string) string {
|
||||
if name == backend.DefaultStateName && b.defaultStateFile != "" {
|
||||
return b.defaultStateFile
|
||||
}
|
||||
return path.Join(b.prefix, name+stateFileSuffix)
|
||||
}
|
||||
|
||||
func (b *gcsBackend) lockFile(name string) string {
|
||||
func (b *Backend) lockFile(name string) string {
|
||||
if name == backend.DefaultStateName && b.defaultStateFile != "" {
|
||||
return strings.TrimSuffix(b.defaultStateFile, stateFileSuffix) + lockFileSuffix
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ func TestStateFile(t *testing.T) {
|
|||
{"state", "legacy.state", "test", "state/test.tfstate", "state/test.tflock"},
|
||||
}
|
||||
for _, c := range cases {
|
||||
b := &gcsBackend{
|
||||
b := &Backend{
|
||||
prefix: c.prefix,
|
||||
defaultStateFile: c.defaultStateFile,
|
||||
}
|
||||
|
@ -188,7 +188,7 @@ func setupBackend(t *testing.T, bucket, prefix, key string) backend.Backend {
|
|||
}
|
||||
|
||||
b := backend.TestBackendConfig(t, New(), config)
|
||||
be := b.(*gcsBackend)
|
||||
be := b.(*Backend)
|
||||
|
||||
// create the bucket if it doesn't exist
|
||||
bkt := be.storageClient.Bucket(bucket)
|
||||
|
@ -213,7 +213,7 @@ func setupBackend(t *testing.T, bucket, prefix, key string) backend.Backend {
|
|||
// teardownBackend deletes all states from be except the default state.
|
||||
func teardownBackend(t *testing.T, be backend.Backend, prefix string) {
|
||||
t.Helper()
|
||||
gcsBE, ok := be.(*gcsBackend)
|
||||
gcsBE, ok := be.(*Backend)
|
||||
if !ok {
|
||||
t.Fatalf("be is a %T, want a *gcsBackend", be)
|
||||
}
|
||||
|
|
|
@ -138,11 +138,13 @@ func (c *InitCommand) Run(args []string) int {
|
|||
|
||||
// If our directory is empty, then we're done. We can't get or setup
|
||||
// the backend with an empty directory.
|
||||
if empty, err := config.IsEmptyDir(path); err != nil {
|
||||
empty, err := config.IsEmptyDir(path)
|
||||
if err != nil {
|
||||
c.Ui.Error(fmt.Sprintf(
|
||||
"Error checking configuration: %s", err))
|
||||
return 1
|
||||
} else if empty {
|
||||
}
|
||||
if empty {
|
||||
c.Ui.Output(c.Colorize().Color(strings.TrimSpace(outputInitEmpty)))
|
||||
return 0
|
||||
}
|
||||
|
|
|
@ -136,7 +136,7 @@ func (m *Meta) Backend(opts *BackendOpts) (backend.Enhanced, error) {
|
|||
}
|
||||
|
||||
// Build the local backend
|
||||
local := &backendLocal.Local{Backend: b}
|
||||
local := backendLocal.NewWithBackend(b)
|
||||
if err := local.CLIInit(cliOpts); err != nil {
|
||||
// Local backend isn't allowed to fail. It would be a bug.
|
||||
panic(err)
|
||||
|
|
Loading…
Reference in New Issue