command: Enable reading remote-enabled state
This commit is contained in:
parent
bf10111745
commit
53704db4ee
|
@ -42,6 +42,8 @@ type Meta struct {
|
||||||
oldUi cli.Ui
|
oldUi cli.Ui
|
||||||
|
|
||||||
// useRemoteState is enabled if we are using remote state storage
|
// useRemoteState is enabled if we are using remote state storage
|
||||||
|
// This is set when the context is loaded if we read from a remote
|
||||||
|
// enabled state file.
|
||||||
useRemoteState bool
|
useRemoteState bool
|
||||||
|
|
||||||
// statePath is the path to the state file. If this is empty, then
|
// statePath is the path to the state file. If this is empty, then
|
||||||
|
@ -106,25 +108,16 @@ func (m *Meta) Context(copts contextOpts) (*terraform.Context, bool, error) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Load up the state
|
// Load the statePath if not given
|
||||||
var state *terraform.State
|
|
||||||
if copts.StatePath != "" {
|
if copts.StatePath != "" {
|
||||||
f, err := os.Open(copts.StatePath)
|
m.statePath = copts.StatePath
|
||||||
if err != nil && os.IsNotExist(err) {
|
|
||||||
// If the state file doesn't exist, it is okay, since it
|
|
||||||
// is probably a new infrastructure.
|
|
||||||
err = nil
|
|
||||||
} else if err == nil {
|
|
||||||
state, err = terraform.ReadState(f)
|
|
||||||
f.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
return nil, false, fmt.Errorf("Error loading state: %s", err)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Store the loaded state
|
// Store the loaded state
|
||||||
|
state, err := m.loadState()
|
||||||
|
if err != nil {
|
||||||
|
return nil, false, err
|
||||||
|
}
|
||||||
m.state = state
|
m.state = state
|
||||||
|
|
||||||
// Load the root module
|
// Load the root module
|
||||||
|
@ -171,6 +164,43 @@ func (m *Meta) UIInput() terraform.UIInput {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// laodState is used to load the Terraform state. We give precedence
|
||||||
|
// 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 {
|
||||||
|
return nil, fmt.Errorf("Error loading state: %s", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set the state if enabled
|
||||||
|
var state *terraform.State
|
||||||
|
if localCache != nil {
|
||||||
|
state = localCache
|
||||||
|
m.useRemoteState = true
|
||||||
|
}
|
||||||
|
|
||||||
|
// Load up the state
|
||||||
|
if m.statePath != "" {
|
||||||
|
f, err := os.Open(m.statePath)
|
||||||
|
if err != nil && os.IsNotExist(err) {
|
||||||
|
// 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 {
|
||||||
|
|
|
@ -255,3 +255,78 @@ func TestMeta_persistRemote(t *testing.T) {
|
||||||
t.Fatalf("backup should exist")
|
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
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
Loading…
Reference in New Issue