Skip to content
GitLab
Menu
Projects
Groups
Snippets
Help
Help
Support
Community forum
Keyboard shortcuts
?
Submit feedback
Sign in
Toggle navigation
Menu
Open sidebar
小 白蛋
Terraform
Commits
579f102f
Commit
579f102f
authored
10 years ago
by
Mitchell Hashimoto
Browse files
Options
Download
Email Patches
Plain Diff
command: start migrating to new state package
parent
1eec7737
Changes
8
Hide whitespace changes
Inline
Side-by-side
Showing
8 changed files
command/command.go
+3
-0
command/command.go
command/meta.go
+20
-110
command/meta.go
command/meta_test.go
+0
-154
command/meta_test.go
command/output.go
+2
-1
command/output.go
command/show.go
+6
-4
command/show.go
command/state.go
+121
-0
command/state.go
commands.go
+4
-2
commands.go
state/state.go
+8
-0
state/state.go
with
164 additions
and
271 deletions
+164
-271
command/command.go
+
3
-
0
View file @
579f102f
...
@@ -10,6 +10,9 @@ import (
...
@@ -10,6 +10,9 @@ import (
// Set to true when we're testing
// Set to true when we're testing
var
test
bool
=
false
var
test
bool
=
false
// DefaultDataDir is the default directory for storing local data.
const
DefaultDataDir
=
".terraform"
// DefaultStateFilename is the default filename used for the state file.
// DefaultStateFilename is the default filename used for the state file.
const
DefaultStateFilename
=
"terraform.tfstate"
const
DefaultStateFilename
=
"terraform.tfstate"
...
...
This diff is collapsed.
Click to expand it.
command/meta.go
+
20
-
110
View file @
579f102f
...
@@ -10,7 +10,7 @@ import (
...
@@ -10,7 +10,7 @@ import (
"path/filepath"
"path/filepath"
"github.com/hashicorp/terraform/config/module"
"github.com/hashicorp/terraform/config/module"
"github.com/hashicorp/terraform/
remo
te"
"github.com/hashicorp/terraform/
sta
te"
"github.com/hashicorp/terraform/terraform"
"github.com/hashicorp/terraform/terraform"
"github.com/mitchellh/cli"
"github.com/mitchellh/cli"
"github.com/mitchellh/colorstring"
"github.com/mitchellh/colorstring"
...
@@ -24,7 +24,7 @@ type Meta struct {
...
@@ -24,7 +24,7 @@ type Meta struct {
// State read when calling `Context`. This is available after calling
// State read when calling `Context`. This is available after calling
// `Context`.
// `Context`.
state
*
terraform
.
State
state
state
.
State
// This can be set by the command itself to provide extra hooks.
// This can be set by the command itself to provide extra hooks.
extraHooks
[]
terraform
.
Hook
extraHooks
[]
terraform
.
Hook
...
@@ -78,11 +78,6 @@ func (m *Meta) initStatePaths() {
...
@@ -78,11 +78,6 @@ func (m *Meta) initStatePaths() {
// StateOutPath returns the true output path for the state file
// StateOutPath returns the true output path for the state file
func
(
m
*
Meta
)
StateOutPath
()
string
{
func
(
m
*
Meta
)
StateOutPath
()
string
{
m
.
initStatePaths
()
if
m
.
useRemoteState
{
path
,
_
:=
remote
.
HiddenStatePath
()
return
path
}
return
m
.
stateOutPath
return
m
.
stateOutPath
}
}
...
@@ -132,11 +127,12 @@ func (m *Meta) Context(copts contextOpts) (*terraform.Context, bool, error) {
...
@@ -132,11 +127,12 @@ func (m *Meta) Context(copts contextOpts) (*terraform.Context, bool, error) {
}
}
// Store the loaded state
// Store the loaded state
state
,
err
:=
m
.
loadState
(
)
state
,
statePath
,
err
:=
State
(
m
.
statePath
)
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
false
,
err
return
nil
,
false
,
err
}
}
m
.
state
=
state
m
.
state
=
state
m
.
stateOutPath
=
statePath
// Load the root module
// Load the root module
mod
,
err
:=
module
.
NewTreeModule
(
""
,
copts
.
Path
)
mod
,
err
:=
module
.
NewTreeModule
(
""
,
copts
.
Path
)
...
@@ -154,7 +150,7 @@ func (m *Meta) Context(copts contextOpts) (*terraform.Context, bool, error) {
...
@@ -154,7 +150,7 @@ func (m *Meta) Context(copts contextOpts) (*terraform.Context, bool, error) {
}
}
opts
.
Module
=
mod
opts
.
Module
=
mod
opts
.
State
=
state
opts
.
State
=
state
.
State
()
ctx
:=
terraform
.
NewContext
(
opts
)
ctx
:=
terraform
.
NewContext
(
opts
)
return
ctx
,
false
,
nil
return
ctx
,
false
,
nil
}
}
...
@@ -175,122 +171,36 @@ func (m *Meta) InputMode() terraform.InputMode {
...
@@ -175,122 +171,36 @@ func (m *Meta) InputMode() terraform.InputMode {
return
mode
return
mode
}
}
//
UIInput
returns
a UIInput object to be used for asking for input
.
//
State
returns
the state for this meta
.
func
(
m
*
Meta
)
UIInput
()
terraform
.
UIInput
{
func
(
m
*
Meta
)
State
()
(
state
.
State
,
error
)
{
return
&
UIInput
{
if
m
.
state
!=
nil
{
Colorize
:
m
.
Colorize
(),
return
m
.
state
,
nil
}
}
}
// laodState is used to load the Terraform state. We give precedence
state
,
_
,
err
:=
State
(
m
.
statePath
)
// to a remote state if enabled, and then check the normal state path.
func
(
m
*
Meta
)
loadState
()
(
*
terraform
.
State
,
error
)
{
// Check if we remote state is enabled
localCache
,
_
,
err
:=
remote
.
ReadLocalState
()
if
err
!=
nil
{
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"Error loading state: %s"
,
err
)
return
nil
,
err
}
}
// Set the state if enabled
m
.
state
=
state
var
state
*
terraform
.
State
return
state
,
nil
if
localCache
!=
nil
{
}
// Refresh the state
log
.
Printf
(
"[INFO] Refreshing local state..."
)
changes
,
err
:=
remote
.
RefreshState
(
localCache
.
Remote
)
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"Failed to refresh state: %v"
,
err
)
}
switch
changes
{
case
remote
.
StateChangeNoop
:
case
remote
.
StateChangeInit
:
case
remote
.
StateChangeLocalNewer
:
case
remote
.
StateChangeUpdateLocal
:
// Reload the state since we've udpated
localCache
,
_
,
err
=
remote
.
ReadLocalState
()
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"Error loading state: %s"
,
err
)
}
default
:
return
nil
,
fmt
.
Errorf
(
"%s"
,
changes
)
}
state
=
localCache
m
.
useRemoteState
=
true
}
// Load up the state
// UIInput returns a UIInput object to be used for asking for input.
if
m
.
statePath
!=
""
{
func
(
m
*
Meta
)
UIInput
()
terraform
.
UIInput
{
f
,
err
:=
os
.
Open
(
m
.
statePath
)
return
&
UIInput
{
if
err
!=
nil
&&
os
.
IsNotExist
(
err
)
{
Colorize
:
m
.
Colorize
(),
// If the state file doesn't exist, it is okay, since it
// is probably a new infrastructure.
err
=
nil
}
else
if
m
.
useRemoteState
&&
err
==
nil
{
err
=
fmt
.
Errorf
(
"Remote state enabled, but state file '%s' also present."
,
m
.
statePath
)
f
.
Close
()
}
else
if
err
==
nil
{
state
,
err
=
terraform
.
ReadState
(
f
)
f
.
Close
()
}
if
err
!=
nil
{
return
nil
,
fmt
.
Errorf
(
"Error loading state: %s"
,
err
)
}
}
}
return
state
,
nil
}
}
// PersistState is used to write out the state, handling backup of
// PersistState is used to write out the state, handling backup of
// the existing state file and respecting path configurations.
// the existing state file and respecting path configurations.
func
(
m
*
Meta
)
PersistState
(
s
*
terraform
.
State
)
error
{
func
(
m
*
Meta
)
PersistState
(
s
*
terraform
.
State
)
error
{
if
m
.
useRemoteState
{
if
err
:=
m
.
state
.
WriteState
(
s
);
err
!=
nil
{
return
m
.
persistRemoteState
(
s
)
}
return
m
.
persistLocalState
(
s
)
}
// persistRemoteState is used to handle persisting a state file
// when remote state management is enabled
func
(
m
*
Meta
)
persistRemoteState
(
s
*
terraform
.
State
)
error
{
log
.
Printf
(
"[INFO] Persisting state to local cache"
)
if
err
:=
remote
.
PersistState
(
s
);
err
!=
nil
{
return
err
return
err
}
}
log
.
Printf
(
"[INFO] Uploading state to remote store"
)
change
,
err
:=
remote
.
PushState
(
s
.
Remote
,
false
)
if
err
!=
nil
{
return
err
}
if
!
change
.
SuccessfulPush
()
{
return
fmt
.
Errorf
(
"Failed to upload state: %s"
,
change
)
}
return
nil
}
// persistLocalState is used to handle persisting a state file
// when remote state management is disabled.
func
(
m
*
Meta
)
persistLocalState
(
s
*
terraform
.
State
)
error
{
m
.
initStatePaths
()
// Create a backup of the state before updating
if
m
.
backupPath
!=
"-"
{
log
.
Printf
(
"[INFO] Writing backup state to: %s"
,
m
.
backupPath
)
if
err
:=
remote
.
CopyFile
(
m
.
statePath
,
m
.
backupPath
);
err
!=
nil
{
return
fmt
.
Errorf
(
"Failed to backup state: %v"
,
err
)
}
}
// Open the new state file
return
m
.
state
.
PersistState
()
fh
,
err
:=
os
.
Create
(
m
.
stateOutPath
)
if
err
!=
nil
{
return
fmt
.
Errorf
(
"Failed to open state file: %v"
,
err
)
}
defer
fh
.
Close
()
// Write out the state
if
err
:=
terraform
.
WriteState
(
s
,
fh
);
err
!=
nil
{
return
fmt
.
Errorf
(
"Failed to encode the state: %v"
,
err
)
}
return
nil
}
}
// Input returns true if we should ask for input for context.
// Input returns true if we should ask for input for context.
...
...
This diff is collapsed.
Click to expand it.
command/meta_test.go
+
0
-
154
View file @
579f102f
...
@@ -7,7 +7,6 @@ import (
...
@@ -7,7 +7,6 @@ import (
"reflect"
"reflect"
"testing"
"testing"
"github.com/hashicorp/terraform/remote"
"github.com/hashicorp/terraform/terraform"
"github.com/hashicorp/terraform/terraform"
)
)
...
@@ -182,156 +181,3 @@ func TestMeta_initStatePaths(t *testing.T) {
...
@@ -182,156 +181,3 @@ func TestMeta_initStatePaths(t *testing.T) {
t
.
Fatalf
(
"bad: %#v"
,
m
)
t
.
Fatalf
(
"bad: %#v"
,
m
)
}
}
}
}
func
TestMeta_persistLocal
(
t
*
testing
.
T
)
{
tmp
,
cwd
:=
testCwd
(
t
)
defer
testFixCwd
(
t
,
tmp
,
cwd
)
m
:=
new
(
Meta
)
s
:=
terraform
.
NewState
()
if
err
:=
m
.
persistLocalState
(
s
);
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
exists
,
err
:=
remote
.
ExistsFile
(
m
.
stateOutPath
)
if
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
if
!
exists
{
t
.
Fatalf
(
"state should exist"
)
}
// Write again, shoudl backup
if
err
:=
m
.
persistLocalState
(
s
);
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
exists
,
err
=
remote
.
ExistsFile
(
m
.
backupPath
)
if
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
if
!
exists
{
t
.
Fatalf
(
"backup should exist"
)
}
}
func
TestMeta_persistRemote
(
t
*
testing
.
T
)
{
tmp
,
cwd
:=
testCwd
(
t
)
defer
testFixCwd
(
t
,
tmp
,
cwd
)
err
:=
remote
.
EnsureDirectory
()
if
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
s
:=
terraform
.
NewState
()
conf
,
srv
:=
testRemoteState
(
t
,
s
,
200
)
s
.
Remote
=
conf
defer
srv
.
Close
()
m
:=
new
(
Meta
)
if
err
:=
m
.
persistRemoteState
(
s
);
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
local
,
_
,
err
:=
remote
.
ReadLocalState
()
if
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
if
local
==
nil
{
t
.
Fatalf
(
"state should exist"
)
}
if
err
:=
m
.
persistRemoteState
(
s
);
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
backup
:=
remote
.
LocalDirectory
+
"/"
+
remote
.
BackupHiddenStateFile
exists
,
err
:=
remote
.
ExistsFile
(
backup
)
if
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
if
!
exists
{
t
.
Fatalf
(
"backup should exist"
)
}
}
func
TestMeta_loadState_remote
(
t
*
testing
.
T
)
{
tmp
,
cwd
:=
testCwd
(
t
)
defer
testFixCwd
(
t
,
tmp
,
cwd
)
err
:=
remote
.
EnsureDirectory
()
if
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
s
:=
terraform
.
NewState
()
s
.
Serial
=
1000
conf
,
srv
:=
testRemoteState
(
t
,
s
,
200
)
s
.
Remote
=
conf
defer
srv
.
Close
()
s
.
Serial
=
500
if
err
:=
remote
.
PersistState
(
s
);
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
m
:=
new
(
Meta
)
s1
,
err
:=
m
.
loadState
()
if
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
if
s1
.
Serial
<
1000
{
t
.
Fatalf
(
"Bad: %#v"
,
s1
)
}
if
!
m
.
useRemoteState
{
t
.
Fatalf
(
"should enable remote"
)
}
}
func
TestMeta_loadState_statePath
(
t
*
testing
.
T
)
{
tmp
,
cwd
:=
testCwd
(
t
)
defer
testFixCwd
(
t
,
tmp
,
cwd
)
m
:=
new
(
Meta
)
s
:=
terraform
.
NewState
()
s
.
Serial
=
1000
if
err
:=
m
.
persistLocalState
(
s
);
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
s1
,
err
:=
m
.
loadState
()
if
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
if
s1
.
Serial
<
1000
{
t
.
Fatalf
(
"Bad: %#v"
,
s1
)
}
}
func
TestMeta_loadState_conflict
(
t
*
testing
.
T
)
{
tmp
,
cwd
:=
testCwd
(
t
)
defer
testFixCwd
(
t
,
tmp
,
cwd
)
err
:=
remote
.
EnsureDirectory
()
if
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
m
:=
new
(
Meta
)
s
:=
terraform
.
NewState
()
if
err
:=
remote
.
PersistState
(
s
);
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
if
err
:=
m
.
persistLocalState
(
s
);
err
!=
nil
{
t
.
Fatalf
(
"err: %v"
,
err
)
}
_
,
err
=
m
.
loadState
()
if
err
==
nil
{
t
.
Fatalf
(
"should error with conflict"
)
}
}
This diff is collapsed.
Click to expand it.
command/output.go
+
2
-
1
View file @
579f102f
...
@@ -32,12 +32,13 @@ func (c *OutputCommand) Run(args []string) int {
...
@@ -32,12 +32,13 @@ func (c *OutputCommand) Run(args []string) int {
}
}
name
:=
args
[
0
]
name
:=
args
[
0
]
state
,
err
:=
c
.
Meta
.
load
State
()
state
Store
,
err
:=
c
.
Meta
.
State
()
if
err
!=
nil
{
if
err
!=
nil
{
c
.
Ui
.
Error
(
fmt
.
Sprintf
(
"Error reading state: %s"
,
err
))
c
.
Ui
.
Error
(
fmt
.
Sprintf
(
"Error reading state: %s"
,
err
))
return
1
return
1
}
}
state
:=
stateStore
.
State
()
if
len
(
state
.
RootModule
()
.
Outputs
)
==
0
{
if
len
(
state
.
RootModule
()
.
Outputs
)
==
0
{
c
.
Ui
.
Error
(
fmt
.
Sprintf
(
c
.
Ui
.
Error
(
fmt
.
Sprintf
(
"The state file has no outputs defined. Define an output
\n
"
+
"The state file has no outputs defined. Define an output
\n
"
+
...
...
This diff is collapsed.
Click to expand it.
command/show.go
+
6
-
4
View file @
579f102f
...
@@ -6,6 +6,7 @@ import (
...
@@ -6,6 +6,7 @@ import (
"os"
"os"
"strings"
"strings"
statelib
"github.com/hashicorp/terraform/state"
"github.com/hashicorp/terraform/terraform"
"github.com/hashicorp/terraform/terraform"
)
)
...
@@ -36,7 +37,7 @@ func (c *ShowCommand) Run(args []string) int {
...
@@ -36,7 +37,7 @@ func (c *ShowCommand) Run(args []string) int {
return
1
return
1
}
}
var
err
,
planErr
,
stateErr
error
var
planErr
,
stateErr
error
var
path
string
var
path
string
var
plan
*
terraform
.
Plan
var
plan
*
terraform
.
Plan
var
state
*
terraform
.
State
var
state
*
terraform
.
State
...
@@ -68,12 +69,13 @@ func (c *ShowCommand) Run(args []string) int {
...
@@ -68,12 +69,13 @@ func (c *ShowCommand) Run(args []string) int {
}
else
{
}
else
{
// We should use the default state if it exists.
// We should use the default state if it exists.
c
.
Meta
.
statePath
=
DefaultStateFilename
stateStore
:=
&
statelib
.
LocalState
{
Path
:
DefaultStateFilename
}
state
,
err
=
c
.
Meta
.
loadState
()
if
err
:=
stateStore
.
RefreshState
();
err
!=
nil
{
if
err
!=
nil
{
c
.
Ui
.
Error
(
fmt
.
Sprintf
(
"Error reading state: %s"
,
err
))
c
.
Ui
.
Error
(
fmt
.
Sprintf
(
"Error reading state: %s"
,
err
))
return
1
return
1
}
}
state
=
stateStore
.
State
()
if
state
==
nil
{
if
state
==
nil
{
c
.
Ui
.
Output
(
"No state."
)
c
.
Ui
.
Output
(
"No state."
)
return
0
return
0
...
...
This diff is collapsed.
Click to expand it.
command/state.go
0 → 100644
+
121
-
0
View file @
579f102f
package
command
import
(
"fmt"
"os"
"path/filepath"
"github.com/hashicorp/errwrap"
"github.com/hashicorp/terraform/state"
"github.com/hashicorp/terraform/state/remote"
)
// State returns the proper state.State implementation to represent the
// current environment.
//
// localPath is the path to where state would be if stored locally.
// dataDir is the path to the local data directory where the remote state
// cache would be stored.
func
State
(
localPath
string
)
(
state
.
State
,
string
,
error
)
{
var
result
state
.
State
var
resultPath
string
// Get the remote state cache path
remoteCachePath
:=
filepath
.
Join
(
DefaultDataDir
,
DefaultStateFilename
)
if
_
,
err
:=
os
.
Stat
(
remoteCachePath
);
err
==
nil
{
// We have a remote state, initialize that.
result
,
err
=
remoteState
(
remoteCachePath
)
if
err
!=
nil
{
return
nil
,
""
,
err
}
resultPath
=
remoteCachePath
}
// Do we have a local state?
if
localPath
!=
""
{
local
:=
&
state
.
LocalState
{
Path
:
localPath
}
err
:=
local
.
RefreshState
()
if
err
!=
nil
{
isNotExist
:=
false
errwrap
.
Walk
(
err
,
func
(
e
error
)
{
if
!
isNotExist
&&
os
.
IsNotExist
(
e
)
{
isNotExist
=
true
}
})
if
isNotExist
{
err
=
nil
}
}
else
{
if
result
!=
nil
{
// We already have a remote state... that is an error.
return
nil
,
""
,
fmt
.
Errorf
(
"Remote state found, but state file '%s' also present."
,
localPath
)
}
}
if
err
!=
nil
{
return
nil
,
""
,
errwrap
.
Wrapf
(
"Error reading local state: {{err}}"
,
err
)
}
result
=
local
resultPath
=
localPath
}
// Return whatever state we have
return
result
,
resultPath
,
nil
}
func
remoteState
(
path
string
)
(
state
.
State
,
error
)
{
// First create the local state for the path
local
:=
&
state
.
LocalState
{
Path
:
path
}
if
err
:=
local
.
RefreshState
();
err
!=
nil
{
return
nil
,
err
}
localState
:=
local
.
State
()
// If there is no remote settings, it is an error
if
localState
.
Remote
==
nil
{
return
nil
,
fmt
.
Errorf
(
"Remote state cache has no remote info"
)
}
// Initialize the remote client based on the local state
client
,
err
:=
remote
.
NewClient
(
localState
.
Remote
.
Type
,
localState
.
Remote
.
Config
)
if
err
!=
nil
{
return
nil
,
errwrap
.
Wrapf
(
fmt
.
Sprintf
(
"Error initializing remote driver '%s': {{err}}"
,
localState
.
Remote
.
Type
),
err
)
}
// Create the remote client
durable
:=
&
remote
.
State
{
Client
:
client
}
// Create the cached client
cache
:=
&
state
.
CacheState
{
Cache
:
local
,
Durable
:
durable
,
}
// Refresh the cache
if
err
:=
cache
.
RefreshState
();
err
!=
nil
{
return
nil
,
errwrap
.
Wrapf
(
"Error reloading remote state: {{err}}"
,
err
)
}
switch
cache
.
RefreshResult
()
{
case
state
.
CacheRefreshNoop
:
case
state
.
CacheRefreshInit
:
case
state
.
CacheRefreshLocalNewer
:
case
state
.
CacheRefreshUpdateLocal
:
// Write our local state out to the durable storage to start.
if
err
:=
cache
.
WriteState
(
localState
);
err
!=
nil
{
return
nil
,
errwrap
.
Wrapf
(
"Error preparing remote state: {{err}}"
,
err
)
}
if
err
:=
cache
.
PersistState
();
err
!=
nil
{
return
nil
,
errwrap
.
Wrapf
(
"Error preparing remote state: {{err}}"
,
err
)
}
default
:
return
nil
,
errwrap
.
Wrapf
(
"Error initilizing remote state: {{err}}"
,
err
)
}
return
cache
,
nil
}
This diff is collapsed.
Click to expand it.
commands.go
+
4
-
2
View file @
579f102f
...
@@ -14,8 +14,10 @@ var Commands map[string]cli.CommandFactory
...
@@ -14,8 +14,10 @@ var Commands map[string]cli.CommandFactory
// Ui is the cli.Ui used for communicating to the outside world.
// Ui is the cli.Ui used for communicating to the outside world.
var
Ui
cli
.
Ui
var
Ui
cli
.
Ui
const
ErrorPrefix
=
"e:"
const
(
const
OutputPrefix
=
"o:"
ErrorPrefix
=
"e:"
OutputPrefix
=
"o:"
)
func
init
()
{
func
init
()
{
Ui
=
&
cli
.
PrefixedUi
{
Ui
=
&
cli
.
PrefixedUi
{
...
...
This diff is collapsed.
Click to expand it.
state/state.go
+
8
-
0
View file @
579f102f
...
@@ -4,6 +4,14 @@ import (
...
@@ -4,6 +4,14 @@ import (
"github.com/hashicorp/terraform/terraform"
"github.com/hashicorp/terraform/terraform"
)
)
// State is the collection of all state interfaces.
type
State
interface
{
StateReader
StateWriter
StateRefresher
StatePersister
}
// StateReader is the interface for things that can return a state. Retrieving
// StateReader is the interface for things that can return a state. Retrieving
// the state here must not error. Loading the state fresh (an operation that
// the state here must not error. Loading the state fresh (an operation that
// can likely error) should be implemented by RefreshState. If a state hasn't
// can likely error) should be implemented by RefreshState. If a state hasn't
...
...
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