Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
小 白蛋
Terraform
Commits
495d1ea3
Commit
495d1ea3
authored
6 years ago
by
Sander van Harmelen
Browse files
Options
Download
Email Patches
Plain Diff
Use New() instead of `once.Do(b.init)`
parent
97d1c466
Changes
13
Hide whitespace changes
Inline
Side-by-side
Showing
13 changed files
backend/atlas/backend.go
+48
-50
backend/atlas/backend.go
backend/atlas/backend_test.go
+2
-2
backend/atlas/backend_test.go
backend/atlas/state_client_test.go
+1
-1
backend/atlas/state_client_test.go
backend/init/init.go
+2
-2
backend/init/init.go
backend/local/backend.go
+118
-117
backend/local/backend.go
backend/local/backend_local.go
+3
-5
backend/local/backend_local.go
backend/local/backend_test.go
+11
-13
backend/local/backend_test.go
backend/local/testing.go
+10
-9
backend/local/testing.go
backend/remote-state/gcs/backend.go
+7
-7
backend/remote-state/gcs/backend.go
backend/remote-state/gcs/backend_state.go
+6
-6
backend/remote-state/gcs/backend_state.go
backend/remote-state/gcs/backend_test.go
+3
-3
backend/remote-state/gcs/backend_test.go
command/init.go
+4
-2
command/init.go
command/meta_backend.go
+1
-1
command/meta_backend.go
with
216 additions
and
218 deletions
+216
-218
backend/atlas/backend.go
+
48
-
50
View file @
495d1ea3
...
@@ -39,59 +39,14 @@ type Backend struct {
...
@@ -39,59 +39,14 @@ type Backend struct {
// schema is the schema for configuration, set by init
// schema is the schema for configuration, set by init
schema
*
schema
.
Backend
schema
*
schema
.
Backend
once
sync
.
Once
// opLock locks operations
// opLock locks operations
opLock
sync
.
Mutex
opLock
sync
.
Mutex
}
}
func
(
b
*
Backend
)
Input
(
// New returns a new initialized Atlas backend.
ui
terraform
.
UIInput
,
c
*
terraform
.
ResourceConfig
)
(
*
terraform
.
ResourceConfig
,
error
)
{
func
New
()
*
Backend
{
b
.
once
.
Do
(
b
.
init
)
b
:=
&
Backend
{}
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
()
{
b
.
schema
=
&
schema
.
Backend
{
b
.
schema
=
&
schema
.
Backend
{
Schema
:
map
[
string
]
*
schema
.
Schema
{
Schema
:
map
[
string
]
*
schema
.
Schema
{
"name"
:
&
schema
.
Schema
{
"name"
:
&
schema
.
Schema
{
...
@@ -115,11 +70,13 @@ func (b *Backend) init() {
...
@@ -115,11 +70,13 @@ func (b *Backend) init() {
},
},
},
},
ConfigureFunc
:
b
.
schemaC
onfigure
,
ConfigureFunc
:
b
.
c
onfigure
,
}
}
return
b
}
}
func
(
b
*
Backend
)
schemaC
onfigure
(
ctx
context
.
Context
)
error
{
func
(
b
*
Backend
)
c
onfigure
(
ctx
context
.
Context
)
error
{
d
:=
schema
.
FromContextBackendConfig
(
ctx
)
d
:=
schema
.
FromContextBackendConfig
(
ctx
)
// Parse the address
// Parse the address
...
@@ -153,6 +110,47 @@ func (b *Backend) schemaConfigure(ctx context.Context) error {
...
@@ -153,6 +110,47 @@ func (b *Backend) schemaConfigure(ctx context.Context) error {
return
nil
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
{
var
schemaDescriptions
=
map
[
string
]
string
{
"name"
:
"Full name of the environment in Atlas, such as 'hashicorp/myenv'"
,
"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
"
+
"access_token"
:
"Access token to use to access Atlas. If ATLAS_TOKEN is set then
\n
"
+
...
...
This diff is collapsed.
Click to expand it.
backend/atlas/backend_test.go
+
2
-
2
View file @
495d1ea3
...
@@ -18,7 +18,7 @@ func TestConfigure_envAddr(t *testing.T) {
...
@@ -18,7 +18,7 @@ func TestConfigure_envAddr(t *testing.T) {
defer
os
.
Setenv
(
"ATLAS_ADDRESS"
,
os
.
Getenv
(
"ATLAS_ADDRESS"
))
defer
os
.
Setenv
(
"ATLAS_ADDRESS"
,
os
.
Getenv
(
"ATLAS_ADDRESS"
))
os
.
Setenv
(
"ATLAS_ADDRESS"
,
"http://foo.com"
)
os
.
Setenv
(
"ATLAS_ADDRESS"
,
"http://foo.com"
)
b
:=
&
Backend
{}
b
:=
New
()
err
:=
b
.
Configure
(
terraform
.
NewResourceConfig
(
config
.
TestRawConfig
(
t
,
map
[
string
]
interface
{}{
err
:=
b
.
Configure
(
terraform
.
NewResourceConfig
(
config
.
TestRawConfig
(
t
,
map
[
string
]
interface
{}{
"name"
:
"foo/bar"
,
"name"
:
"foo/bar"
,
})))
})))
...
@@ -35,7 +35,7 @@ func TestConfigure_envToken(t *testing.T) {
...
@@ -35,7 +35,7 @@ func TestConfigure_envToken(t *testing.T) {
defer
os
.
Setenv
(
"ATLAS_TOKEN"
,
os
.
Getenv
(
"ATLAS_TOKEN"
))
defer
os
.
Setenv
(
"ATLAS_TOKEN"
,
os
.
Getenv
(
"ATLAS_TOKEN"
))
os
.
Setenv
(
"ATLAS_TOKEN"
,
"foo"
)
os
.
Setenv
(
"ATLAS_TOKEN"
,
"foo"
)
b
:=
&
Backend
{}
b
:=
New
()
err
:=
b
.
Configure
(
terraform
.
NewResourceConfig
(
config
.
TestRawConfig
(
t
,
map
[
string
]
interface
{}{
err
:=
b
.
Configure
(
terraform
.
NewResourceConfig
(
config
.
TestRawConfig
(
t
,
map
[
string
]
interface
{}{
"name"
:
"foo/bar"
,
"name"
:
"foo/bar"
,
})))
})))
...
...
This diff is collapsed.
Click to expand it.
backend/atlas/state_client_test.go
+
1
-
1
View file @
495d1ea3
...
@@ -20,7 +20,7 @@ import (
...
@@ -20,7 +20,7 @@ import (
)
)
func
testStateClient
(
t
*
testing
.
T
,
c
map
[
string
]
interface
{})
remote
.
Client
{
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
)
raw
,
err
:=
b
.
State
(
backend
.
DefaultStateName
)
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatalf
(
"err: %s"
,
err
)
t
.
Fatalf
(
"err: %s"
,
err
)
...
...
This diff is collapsed.
Click to expand it.
backend/init/init.go
+
2
-
2
View file @
495d1ea3
...
@@ -39,8 +39,8 @@ func init() {
...
@@ -39,8 +39,8 @@ func init() {
// Our hardcoded backends. We don't need to acquire a lock here
// Our hardcoded backends. We don't need to acquire a lock here
// since init() code is serial and can't spawn goroutines.
// since init() code is serial and can't spawn goroutines.
backends
=
map
[
string
]
func
()
backend
.
Backend
{
backends
=
map
[
string
]
func
()
backend
.
Backend
{
"local"
:
func
()
backend
.
Backend
{
return
&
backendLocal
.
Local
{}
},
"local"
:
func
()
backend
.
Backend
{
return
backendLocal
.
New
()
},
"atlas"
:
func
()
backend
.
Backend
{
return
&
backendAtlas
.
Backend
{}
},
"atlas"
:
func
()
backend
.
Backend
{
return
backendAtlas
.
New
()
},
"azure"
:
deprecateBackend
(
backendAzure
.
New
(),
"azure"
:
deprecateBackend
(
backendAzure
.
New
(),
`Warning: "azure" name is deprecated, please use "azurerm"`
),
`Warning: "azure" name is deprecated, please use "azurerm"`
),
"azurerm"
:
func
()
backend
.
Backend
{
return
backendAzure
.
New
()
},
"azurerm"
:
func
()
backend
.
Backend
{
return
backendAzure
.
New
()
},
...
...
This diff is collapsed.
Click to expand it.
backend/local/backend.go
+
118
-
117
View file @
495d1ea3
...
@@ -91,72 +91,141 @@ type Local struct {
...
@@ -91,72 +91,141 @@ type Local struct {
schema
*
schema
.
Backend
schema
*
schema
.
Backend
opLock
sync
.
Mutex
opLock
sync
.
Mutex
once
sync
.
Once
}
}
func
(
b
*
Local
)
Input
(
// New returns a new initialized local backend.
ui
terraform
.
UIInput
,
c
*
terraform
.
ResourceConfig
)
(
*
terraform
.
ResourceConfig
,
error
)
{
func
New
()
*
Local
{
b
.
once
.
Do
(
b
.
init
)
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
f
:=
b
.
schema
.
Input
if
b
.
Backend
!=
nil
{
if
b
.
Backend
!=
nil
{
f
=
b
.
Backend
.
Input
f
=
b
.
Backend
.
Input
}
}
return
f
(
ui
,
c
)
return
f
(
ui
,
c
)
}
}
func
(
b
*
Local
)
Validate
(
c
*
terraform
.
ResourceConfig
)
([]
string
,
[]
error
)
{
func
(
b
*
Local
)
Validate
(
c
*
terraform
.
ResourceConfig
)
([]
string
,
[]
error
)
{
b
.
once
.
Do
(
b
.
init
)
f
:=
b
.
schema
.
Validate
f
:=
b
.
schema
.
Validate
if
b
.
Backend
!=
nil
{
if
b
.
Backend
!=
nil
{
f
=
b
.
Backend
.
Validate
f
=
b
.
Backend
.
Validate
}
}
return
f
(
c
)
return
f
(
c
)
}
}
func
(
b
*
Local
)
Configure
(
c
*
terraform
.
ResourceConfig
)
error
{
func
(
b
*
Local
)
Configure
(
c
*
terraform
.
ResourceConfig
)
error
{
b
.
once
.
Do
(
b
.
init
)
f
:=
b
.
schema
.
Configure
f
:=
b
.
schema
.
Configure
if
b
.
Backend
!=
nil
{
if
b
.
Backend
!=
nil
{
f
=
b
.
Backend
.
Configure
f
=
b
.
Backend
.
Configure
}
}
return
f
(
c
)
return
f
(
c
)
}
}
func
(
b
*
Local
)
States
()
([]
string
,
error
)
{
func
(
b
*
Local
)
State
(
name
string
)
(
state
.
State
,
error
)
{
// If we have a backend handling state, defer to that.
statePath
,
stateOutPath
,
backupPath
:=
b
.
StatePaths
(
name
)
// If we have a backend handling state, delegate to that.
if
b
.
Backend
!=
nil
{
if
b
.
Backend
!=
nil
{
return
b
.
Backend
.
State
s
()
return
b
.
Backend
.
State
(
name
)
}
}
// the listing always start with "default"
if
s
,
ok
:=
b
.
states
[
name
];
ok
{
envs
:=
[]
string
{
backend
.
DefaultStateName
}
return
s
,
nil
entries
,
err
:=
ioutil
.
ReadDir
(
b
.
stateWorkspaceDir
())
// no error if there's no envs configured
if
os
.
IsNotExist
(
err
)
{
return
envs
,
nil
}
}
if
err
!=
nil
{
if
err
:=
b
.
createState
(
name
);
err
!=
nil
{
return
nil
,
err
return
nil
,
err
}
}
var
listed
[]
string
// Otherwise, we need to load the state.
for
_
,
entry
:=
range
entries
{
var
s
state
.
State
=
&
state
.
LocalState
{
if
entry
.
IsDir
()
{
Path
:
statePath
,
listed
=
append
(
listed
,
filepath
.
Base
(
entry
.
Name
()))
PathOut
:
stateOutPath
,
}
}
}
sort
.
Strings
(
listed
)
// If we are backing up the state, wrap it
envs
=
append
(
envs
,
listed
...
)
if
backupPath
!=
""
{
s
=
&
state
.
BackupState
{
Real
:
s
,
Path
:
backupPath
,
}
}
return
envs
,
nil
if
b
.
states
==
nil
{
b
.
states
=
map
[
string
]
state
.
State
{}
}
b
.
states
[
name
]
=
s
return
s
,
nil
}
}
// DeleteState removes a named state.
// DeleteState removes a named state.
...
@@ -179,41 +248,35 @@ func (b *Local) DeleteState(name string) error {
...
@@ -179,41 +248,35 @@ func (b *Local) DeleteState(name string) error {
return
os
.
RemoveAll
(
filepath
.
Join
(
b
.
stateWorkspaceDir
(),
name
))
return
os
.
RemoveAll
(
filepath
.
Join
(
b
.
stateWorkspaceDir
(),
name
))
}
}
func
(
b
*
Local
)
State
(
name
string
)
(
state
.
State
,
error
)
{
func
(
b
*
Local
)
States
()
([]
string
,
error
)
{
statePath
,
stateOutPath
,
backupPath
:=
b
.
StatePaths
(
name
)
// If we have a backend handling state, defer to that.
// If we have a backend handling state, delegate to that.
if
b
.
Backend
!=
nil
{
if
b
.
Backend
!=
nil
{
return
b
.
Backend
.
State
(
name
)
return
b
.
Backend
.
State
s
()
}
}
if
s
,
ok
:=
b
.
states
[
name
];
ok
{
// the listing always start with "default"
return
s
,
nil
envs
:=
[]
string
{
backend
.
DefaultStateName
}
}
if
err
:=
b
.
createState
(
name
);
err
!=
nil
{
entries
,
err
:=
ioutil
.
ReadDir
(
b
.
stateWorkspaceDir
())
return
nil
,
err
// no error if there's no envs configured
if
os
.
IsNotExist
(
err
)
{
return
envs
,
nil
}
}
if
err
!=
nil
{
// Otherwise, we need to load the state.
return
nil
,
err
var
s
state
.
State
=
&
state
.
LocalState
{
Path
:
statePath
,
PathOut
:
stateOutPath
,
}
}
// If we are backing up the state, wrap it
var
listed
[]
string
if
backupPath
!=
""
{
for
_
,
entry
:=
range
entries
{
s
=
&
state
.
BackupState
{
if
entry
.
IsDir
()
{
Real
:
s
,
listed
=
append
(
listed
,
filepath
.
Base
(
entry
.
Name
()))
Path
:
backupPath
,
}
}
}
}
if
b
.
states
==
nil
{
sort
.
Strings
(
listed
)
b
.
states
=
map
[
string
]
state
.
State
{}
envs
=
append
(
envs
,
listed
...
)
}
b
.
states
[
name
]
=
s
return
envs
,
nil
return
s
,
nil
}
}
// Operation implements backend.Enhanced
// Operation implements backend.Enhanced
...
@@ -348,68 +411,6 @@ func (b *Local) Colorize() *colorstring.Colorize {
...
@@ -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
// StatePaths returns the StatePath, StateOutPath, and StateBackupPath as
// configured from the CLI.
// configured from the CLI.
func
(
b
*
Local
)
StatePaths
(
name
string
)
(
string
,
string
,
string
)
{
func
(
b
*
Local
)
StatePaths
(
name
string
)
(
string
,
string
,
string
)
{
...
...
This diff is collapsed.
Click to expand it.
backend/local/backend_local.go
+
3
-
5
View file @
495d1ea3
...
@@ -5,15 +5,13 @@ import (
...
@@ -5,15 +5,13 @@ import (
"errors"
"errors"
"log"
"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/errwrap"
"github.com/hashicorp/terraform/backend"
"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/state"
"github.com/hashicorp/terraform/terraform"
"github.com/hashicorp/terraform/terraform"
"github.com/hashicorp/terraform/tfdiags"
)
)
// backend.Local implementation.
// backend.Local implementation.
...
...
This diff is collapsed.
Click to expand it.
backend/local/backend_test.go
+
11
-
13
View file @
495d1ea3
...
@@ -15,14 +15,14 @@ import (
...
@@ -15,14 +15,14 @@ import (
)
)
func
TestLocal_impl
(
t
*
testing
.
T
)
{
func
TestLocal_impl
(
t
*
testing
.
T
)
{
var
_
backend
.
Enhanced
=
n
ew
(
Local
)
var
_
backend
.
Enhanced
=
N
ew
()
var
_
backend
.
Local
=
n
ew
(
Local
)
var
_
backend
.
Local
=
N
ew
()
var
_
backend
.
CLI
=
n
ew
(
Local
)
var
_
backend
.
CLI
=
N
ew
()
}
}
func
TestLocal_backend
(
t
*
testing
.
T
)
{
func
TestLocal_backend
(
t
*
testing
.
T
)
{
defer
testTmpDir
(
t
)()
defer
testTmpDir
(
t
)()
b
:=
&
Local
{}
b
:=
New
()
backend
.
TestBackendStates
(
t
,
b
)
backend
.
TestBackendStates
(
t
,
b
)
backend
.
TestBackendStateLocks
(
t
,
b
,
b
)
backend
.
TestBackendStateLocks
(
t
,
b
,
b
)
}
}
...
@@ -49,7 +49,7 @@ func checkState(t *testing.T, path, expected string) {
...
@@ -49,7 +49,7 @@ func checkState(t *testing.T, path, expected string) {
}
}
func
TestLocal_StatePaths
(
t
*
testing
.
T
)
{
func
TestLocal_StatePaths
(
t
*
testing
.
T
)
{
b
:=
&
Local
{}
b
:=
New
()
// Test the defaults
// Test the defaults
path
,
out
,
back
:=
b
.
StatePaths
(
""
)
path
,
out
,
back
:=
b
.
StatePaths
(
""
)
...
@@ -94,7 +94,7 @@ func TestLocal_addAndRemoveStates(t *testing.T) {
...
@@ -94,7 +94,7 @@ func TestLocal_addAndRemoveStates(t *testing.T) {
dflt
:=
backend
.
DefaultStateName
dflt
:=
backend
.
DefaultStateName
expectedStates
:=
[]
string
{
dflt
}
expectedStates
:=
[]
string
{
dflt
}
b
:=
&
Local
{}
b
:=
New
()
states
,
err
:=
b
.
States
()
states
,
err
:=
b
.
States
()
if
err
!=
nil
{
if
err
!=
nil
{
t
.
Fatal
(
err
)
t
.
Fatal
(
err
)
...
@@ -210,13 +210,11 @@ func (b *testDelegateBackend) DeleteState(name string) error {
...
@@ -210,13 +210,11 @@ func (b *testDelegateBackend) DeleteState(name string) error {
// verify that the MultiState methods are dispatched to the correct Backend.
// verify that the MultiState methods are dispatched to the correct Backend.
func
TestLocal_multiStateBackend
(
t
*
testing
.
T
)
{
func
TestLocal_multiStateBackend
(
t
*
testing
.
T
)
{
// assign a separate backend where we can read the state
// assign a separate backend where we can read the state
b
:=
&
Local
{
b
:=
NewWithBackend
(
&
testDelegateBackend
{
Backend
:
&
testDelegateBackend
{
stateErr
:
true
,
stateErr
:
true
,
statesErr
:
true
,
statesErr
:
true
,
deleteErr
:
true
,
deleteErr
:
true
,
})
},
}
if
_
,
err
:=
b
.
State
(
"test"
);
err
!=
errTestDelegateState
{
if
_
,
err
:=
b
.
State
(
"test"
);
err
!=
errTestDelegateState
{
t
.
Fatal
(
"expected errTestDelegateState, got:"
,
err
)
t
.
Fatal
(
"expected errTestDelegateState, got:"
,
err
)
...
...
This diff is collapsed.
Click to expand it.
backend/local/testing.go
+
10
-
9
View file @
495d1ea3
...
@@ -18,13 +18,14 @@ import (
...
@@ -18,13 +18,14 @@ import (
// public fields without any locks.
// public fields without any locks.
func
TestLocal
(
t
*
testing
.
T
)
(
*
Local
,
func
())
{
func
TestLocal
(
t
*
testing
.
T
)
(
*
Local
,
func
())
{
tempDir
:=
testTempDir
(
t
)
tempDir
:=
testTempDir
(
t
)
local
:=
&
Local
{
StatePath
:
filepath
.
Join
(
tempDir
,
"state.tfstate"
),
local
:=
New
()
StateOutPath
:
filepath
.
Join
(
tempDir
,
"state.tfstate"
),
local
.
StatePath
=
filepath
.
Join
(
tempDir
,
"state.tfstate"
)
StateBackupPath
:
filepath
.
Join
(
tempDir
,
"state.tfstate.bak"
),
local
.
StateOutPath
=
filepath
.
Join
(
tempDir
,
"state.tfstate"
)
StateWorkspaceDir
:
filepath
.
Join
(
tempDir
,
"state.tfstate.d"
),
local
.
StateBackupPath
=
filepath
.
Join
(
tempDir
,
"state.tfstate.bak"
)
ContextOpts
:
&
terraform
.
ContextOpts
{},
local
.
StateWorkspaceDir
=
filepath
.
Join
(
tempDir
,
"state.tfstate.d"
)
}
local
.
ContextOpts
=
&
terraform
.
ContextOpts
{}
cleanup
:=
func
()
{
cleanup
:=
func
()
{
if
err
:=
os
.
RemoveAll
(
tempDir
);
err
!=
nil
{
if
err
:=
os
.
RemoveAll
(
tempDir
);
err
!=
nil
{
t
.
Fatal
(
"error clecanup up test:"
,
err
)
t
.
Fatal
(
"error clecanup up test:"
,
err
)
...
@@ -69,7 +70,7 @@ func TestLocalProvider(t *testing.T, b *Local, name string) *terraform.MockResou
...
@@ -69,7 +70,7 @@ func TestLocalProvider(t *testing.T, b *Local, name string) *terraform.MockResou
// TestNewLocalSingle is a factory for creating a TestLocalSingleState.
// TestNewLocalSingle is a factory for creating a TestLocalSingleState.
// This function matches the signature required for backend/init.
// This function matches the signature required for backend/init.
func
TestNewLocalSingle
()
backend
.
Backend
{
func
TestNewLocalSingle
()
backend
.
Backend
{
return
&
TestLocalSingleState
{}
return
&
TestLocalSingleState
{
Local
:
New
()
}
}
}
// TestLocalSingleState is a backend implementation that wraps Local
// TestLocalSingleState is a backend implementation that wraps Local
...
@@ -79,7 +80,7 @@ func TestNewLocalSingle() backend.Backend {
...
@@ -79,7 +80,7 @@ func TestNewLocalSingle() backend.Backend {
// This isn't an actual use case, this is exported just to provide a
// This isn't an actual use case, this is exported just to provide a
// easy way to test that behavior.
// easy way to test that behavior.
type
TestLocalSingleState
struct
{
type
TestLocalSingleState
struct
{
Local
*
Local
}
}
func
(
b
*
TestLocalSingleState
)
State
(
name
string
)
(
state
.
State
,
error
)
{
func
(
b
*
TestLocalSingleState
)
State
(
name
string
)
(
state
.
State
,
error
)
{
...
...
This diff is collapsed.
Click to expand it.
backend/remote-state/gcs/backend.go
+
7
-
7
View file @
495d1ea3
...
@@ -18,10 +18,10 @@ import (
...
@@ -18,10 +18,10 @@ import (
"google.golang.org/api/option"
"google.golang.org/api/option"
)
)
//
gcs
Backend implements "backend".Backend for GCS.
// Backend implements "backend".Backend for GCS.
// Input(), Validate() and Configure() are implemented by embedding *schema.Backend.
// Input(), Validate() and Configure() are implemented by embedding *schema.Backend.
// State(), DeleteState() and States() are implemented explicitly.
// State(), DeleteState() and States() are implemented explicitly.
type
gcs
Backend
struct
{
type
Backend
struct
{
*
schema
.
Backend
*
schema
.
Backend
storageClient
*
storage
.
Client
storageClient
*
storage
.
Client
...
@@ -38,9 +38,9 @@ type gcsBackend struct {
...
@@ -38,9 +38,9 @@ type gcsBackend struct {
}
}
func
New
()
backend
.
Backend
{
func
New
()
backend
.
Backend
{
b
e
:=
&
gcs
Backend
{}
b
:=
&
Backend
{}
b
e
.
Backend
=
&
schema
.
Backend
{
b
.
Backend
=
&
schema
.
Backend
{
ConfigureFunc
:
b
e
.
configure
,
ConfigureFunc
:
b
.
configure
,
Schema
:
map
[
string
]
*
schema
.
Schema
{
Schema
:
map
[
string
]
*
schema
.
Schema
{
"bucket"
:
{
"bucket"
:
{
Type
:
schema
.
TypeString
,
Type
:
schema
.
TypeString
,
...
@@ -91,10 +91,10 @@ func New() backend.Backend {
...
@@ -91,10 +91,10 @@ func New() backend.Backend {
},
},
}
}
return
b
e
return
b
}
}
func
(
b
*
gcs
Backend
)
configure
(
ctx
context
.
Context
)
error
{
func
(
b
*
Backend
)
configure
(
ctx
context
.
Context
)
error
{
if
b
.
storageClient
!=
nil
{
if
b
.
storageClient
!=
nil
{
return
nil
return
nil
}
}
...
...
This diff is collapsed.
Click to expand it.
backend/remote-state/gcs/backend_state.go
+
6
-
6
View file @
495d1ea3
...
@@ -21,7 +21,7 @@ const (
...
@@ -21,7 +21,7 @@ const (
// States returns a list of names for the states found on GCS. The default
// 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.
// state is always returned as the first element in the slice.
func
(
b
*
gcs
Backend
)
States
()
([]
string
,
error
)
{
func
(
b
*
Backend
)
States
()
([]
string
,
error
)
{
states
:=
[]
string
{
backend
.
DefaultStateName
}
states
:=
[]
string
{
backend
.
DefaultStateName
}
bucket
:=
b
.
storageClient
.
Bucket
(
b
.
bucketName
)
bucket
:=
b
.
storageClient
.
Bucket
(
b
.
bucketName
)
...
@@ -54,7 +54,7 @@ func (b *gcsBackend) States() ([]string, error) {
...
@@ -54,7 +54,7 @@ func (b *gcsBackend) States() ([]string, error) {
}
}
// DeleteState deletes the named state. The "default" state cannot be deleted.
// DeleteState deletes the named state. The "default" state cannot be deleted.
func
(
b
*
gcs
Backend
)
DeleteState
(
name
string
)
error
{
func
(
b
*
Backend
)
DeleteState
(
name
string
)
error
{
if
name
==
backend
.
DefaultStateName
{
if
name
==
backend
.
DefaultStateName
{
return
fmt
.
Errorf
(
"cowardly refusing to delete the %q state"
,
name
)
return
fmt
.
Errorf
(
"cowardly refusing to delete the %q state"
,
name
)
}
}
...
@@ -68,7 +68,7 @@ func (b *gcsBackend) DeleteState(name string) error {
...
@@ -68,7 +68,7 @@ func (b *gcsBackend) DeleteState(name string) error {
}
}
// client returns a remoteClient for the named state.
// client returns a remoteClient for the named state.
func
(
b
*
gcs
Backend
)
client
(
name
string
)
(
*
remoteClient
,
error
)
{
func
(
b
*
Backend
)
client
(
name
string
)
(
*
remoteClient
,
error
)
{
if
name
==
""
{
if
name
==
""
{
return
nil
,
fmt
.
Errorf
(
"%q is not a valid state name"
,
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) {
...
@@ -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
// State reads and returns the named state from GCS. If the named state does
// not yet exist, a new state file is created.
// not yet exist, a new state file is created.
func
(
b
*
gcs
Backend
)
State
(
name
string
)
(
state
.
State
,
error
)
{
func
(
b
*
Backend
)
State
(
name
string
)
(
state
.
State
,
error
)
{
c
,
err
:=
b
.
client
(
name
)
c
,
err
:=
b
.
client
(
name
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
err
return
nil
,
err
...
@@ -144,14 +144,14 @@ func (b *gcsBackend) State(name string) (state.State, error) {
...
@@ -144,14 +144,14 @@ func (b *gcsBackend) State(name string) (state.State, error) {
return
st
,
nil
return
st
,
nil
}
}
func
(
b
*
gcs
Backend
)
stateFile
(
name
string
)
string
{
func
(
b
*
Backend
)
stateFile
(
name
string
)
string
{
if
name
==
backend
.
DefaultStateName
&&
b
.
defaultStateFile
!=
""
{
if
name
==
backend
.
DefaultStateName
&&
b
.
defaultStateFile
!=
""
{
return
b
.
defaultStateFile
return
b
.
defaultStateFile
}
}
return
path
.
Join
(
b
.
prefix
,
name
+
stateFileSuffix
)
return
path
.
Join
(
b
.
prefix
,
name
+
stateFileSuffix
)
}
}
func
(
b
*
gcs
Backend
)
lockFile
(
name
string
)
string
{
func
(
b
*
Backend
)
lockFile
(
name
string
)
string
{
if
name
==
backend
.
DefaultStateName
&&
b
.
defaultStateFile
!=
""
{
if
name
==
backend
.
DefaultStateName
&&
b
.
defaultStateFile
!=
""
{
return
strings
.
TrimSuffix
(
b
.
defaultStateFile
,
stateFileSuffix
)
+
lockFileSuffix
return
strings
.
TrimSuffix
(
b
.
defaultStateFile
,
stateFileSuffix
)
+
lockFileSuffix
}
}
...
...
This diff is collapsed.
Click to expand it.
backend/remote-state/gcs/backend_test.go
+
3
-
3
View file @
495d1ea3
...
@@ -39,7 +39,7 @@ func TestStateFile(t *testing.T) {
...
@@ -39,7 +39,7 @@ func TestStateFile(t *testing.T) {
{
"state"
,
"legacy.state"
,
"test"
,
"state/test.tfstate"
,
"state/test.tflock"
},
{
"state"
,
"legacy.state"
,
"test"
,
"state/test.tfstate"
,
"state/test.tflock"
},
}
}
for
_
,
c
:=
range
cases
{
for
_
,
c
:=
range
cases
{
b
:=
&
gcs
Backend
{
b
:=
&
Backend
{
prefix
:
c
.
prefix
,
prefix
:
c
.
prefix
,
defaultStateFile
:
c
.
defaultStateFile
,
defaultStateFile
:
c
.
defaultStateFile
,
}
}
...
@@ -188,7 +188,7 @@ func setupBackend(t *testing.T, bucket, prefix, key string) backend.Backend {
...
@@ -188,7 +188,7 @@ func setupBackend(t *testing.T, bucket, prefix, key string) backend.Backend {
}
}
b
:=
backend
.
TestBackendConfig
(
t
,
New
(),
config
)
b
:=
backend
.
TestBackendConfig
(
t
,
New
(),
config
)
be
:=
b
.
(
*
gcs
Backend
)
be
:=
b
.
(
*
Backend
)
// create the bucket if it doesn't exist
// create the bucket if it doesn't exist
bkt
:=
be
.
storageClient
.
Bucket
(
bucket
)
bkt
:=
be
.
storageClient
.
Bucket
(
bucket
)
...
@@ -213,7 +213,7 @@ func setupBackend(t *testing.T, bucket, prefix, key string) backend.Backend {
...
@@ -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.
// teardownBackend deletes all states from be except the default state.
func
teardownBackend
(
t
*
testing
.
T
,
be
backend
.
Backend
,
prefix
string
)
{
func
teardownBackend
(
t
*
testing
.
T
,
be
backend
.
Backend
,
prefix
string
)
{
t
.
Helper
()
t
.
Helper
()
gcsBE
,
ok
:=
be
.
(
*
gcs
Backend
)
gcsBE
,
ok
:=
be
.
(
*
Backend
)
if
!
ok
{
if
!
ok
{
t
.
Fatalf
(
"be is a %T, want a *gcsBackend"
,
be
)
t
.
Fatalf
(
"be is a %T, want a *gcsBackend"
,
be
)
}
}
...
...
This diff is collapsed.
Click to expand it.
command/init.go
+
4
-
2
View file @
495d1ea3
...
@@ -138,11 +138,13 @@ func (c *InitCommand) Run(args []string) int {
...
@@ -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
// If our directory is empty, then we're done. We can't get or setup
// the backend with an empty directory.
// 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
(
c
.
Ui
.
Error
(
fmt
.
Sprintf
(
"Error checking configuration: %s"
,
err
))
"Error checking configuration: %s"
,
err
))
return
1
return
1
}
else
if
empty
{
}
if
empty
{
c
.
Ui
.
Output
(
c
.
Colorize
()
.
Color
(
strings
.
TrimSpace
(
outputInitEmpty
)))
c
.
Ui
.
Output
(
c
.
Colorize
()
.
Color
(
strings
.
TrimSpace
(
outputInitEmpty
)))
return
0
return
0
}
}
...
...
This diff is collapsed.
Click to expand it.
command/meta_backend.go
+
1
-
1
View file @
495d1ea3
...
@@ -136,7 +136,7 @@ func (m *Meta) Backend(opts *BackendOpts) (backend.Enhanced, error) {
...
@@ -136,7 +136,7 @@ func (m *Meta) Backend(opts *BackendOpts) (backend.Enhanced, error) {
}
}
// Build the local backend
// Build the local backend
local
:=
&
backendLocal
.
Local
{
Backend
:
b
}
local
:=
backendLocal
.
NewWith
Backend
(
b
)
if
err
:=
local
.
CLIInit
(
cliOpts
);
err
!=
nil
{
if
err
:=
local
.
CLIInit
(
cliOpts
);
err
!=
nil
{
// Local backend isn't allowed to fail. It would be a bug.
// Local backend isn't allowed to fail. It would be a bug.
panic
(
err
)
panic
(
err
)
...
...
This diff is collapsed.
Click to expand it.
Write
Preview
Supports
Markdown
0%
Try again
or
attach a new file
.
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment
Menu
Projects
Groups
Snippets
Help