diff --git a/backend/local/backend.go b/backend/local/backend.go index e45eaec25..62cd71e06 100644 --- a/backend/local/backend.go +++ b/backend/local/backend.go @@ -5,7 +5,6 @@ import ( "fmt" "sync" - "github.com/hashicorp/errwrap" "github.com/hashicorp/terraform/backend" "github.com/hashicorp/terraform/helper/schema" "github.com/hashicorp/terraform/state" @@ -113,11 +112,6 @@ func (b *Local) State() (state.State, error) { PathOut: b.StateOutPath, } - // Load the state as a sanity check - if err := s.RefreshState(); err != nil { - return nil, errwrap.Wrapf("Error reading local state: {{err}}", err) - } - // If we are backing up the state, wrap it if path := b.StateBackupPath; path != "" { s = &state.BackupState{ diff --git a/command/meta_backend_test.go b/command/meta_backend_test.go index de0078164..fc9cfb5b9 100644 --- a/command/meta_backend_test.go +++ b/command/meta_backend_test.go @@ -103,6 +103,9 @@ func TestMetaBackend_emptyWithDefaultState(t *testing.T) { if err != nil { t.Fatalf("bad: %s", err) } + if err := s.RefreshState(); err != nil { + t.Fatalf("err: %s", err) + } if actual := s.State().String(); actual != testState().String() { t.Fatalf("bad: %s", actual) } @@ -173,6 +176,9 @@ func TestMetaBackend_emptyWithExplicitState(t *testing.T) { if err != nil { t.Fatalf("bad: %s", err) } + if err := s.RefreshState(); err != nil { + t.Fatalf("err: %s", err) + } if actual := s.State().String(); actual != testState().String() { t.Fatalf("bad: %s", actual) } diff --git a/command/state_list.go b/command/state_list.go index d66531b1e..afc5c9889 100644 --- a/command/state_list.go +++ b/command/state_list.go @@ -38,6 +38,11 @@ func (c *StateListCommand) Run(args []string) int { return 1 } + if err := state.RefreshState(); err != nil { + c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err)) + return 1 + } + stateReal := state.State() if stateReal == nil { c.Ui.Error(fmt.Sprintf(errStateNotFound)) diff --git a/command/state_list_test.go b/command/state_list_test.go index 0edb97d69..86c4f7194 100644 --- a/command/state_list_test.go +++ b/command/state_list_test.go @@ -1,9 +1,11 @@ package command import ( + "os" "strings" "testing" + "github.com/hashicorp/terraform/helper/copy" "github.com/mitchellh/cli" ) @@ -35,6 +37,35 @@ func TestStateList(t *testing.T) { } } +func TestStateList_backendState(t *testing.T) { + // Create a temporary working directory that is empty + td := tempDir(t) + copy.CopyDir(testFixturePath("state-list-backend"), td) + defer os.RemoveAll(td) + defer testChdir(t, td)() + + p := testProvider() + ui := new(cli.MockUi) + c := &StateListCommand{ + Meta: Meta{ + ContextOpts: testCtxConfig(p), + Ui: ui, + }, + } + + args := []string{} + if code := c.Run(args); code != 0 { + t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) + } + + // Test that outputs were displayed + expected := "null_resource.a\n" + actual := ui.OutputWriter.String() + if actual != expected { + t.Fatalf("Expected:\n%q\n\nTo equal: %q", actual, expected) + } +} + func TestStateList_noState(t *testing.T) { tmp, cwd := testCwd(t) defer testFixCwd(t, tmp, cwd) diff --git a/command/state_mv.go b/command/state_mv.go index ddcc33517..7982d7b92 100644 --- a/command/state_mv.go +++ b/command/state_mv.go @@ -45,6 +45,11 @@ func (c *StateMvCommand) Run(args []string) int { return cli.RunResultHelp } + if err := stateFrom.RefreshState(); err != nil { + c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err)) + return 1 + } + stateFromReal := stateFrom.State() if stateFromReal == nil { c.Ui.Error(fmt.Sprintf(errStateNotFound)) @@ -61,6 +66,11 @@ func (c *StateMvCommand) Run(args []string) int { return cli.RunResultHelp } + if err := stateTo.RefreshState(); err != nil { + c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err)) + return 1 + } + stateToReal = stateTo.State() if stateToReal == nil { stateToReal = terraform.NewState() diff --git a/command/state_rm.go b/command/state_rm.go index d2173622d..b2491c4e8 100644 --- a/command/state_rm.go +++ b/command/state_rm.go @@ -29,6 +29,10 @@ func (c *StateRmCommand) Run(args []string) int { c.Ui.Error(fmt.Sprintf(errStateLoadingState, err)) return cli.RunResultHelp } + if err := state.RefreshState(); err != nil { + c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err)) + return 1 + } stateReal := state.State() if stateReal == nil { diff --git a/command/state_show.go b/command/state_show.go index 6be125d7f..be6df8bf9 100644 --- a/command/state_show.go +++ b/command/state_show.go @@ -39,6 +39,10 @@ func (c *StateShowCommand) Run(args []string) int { c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err)) return 1 } + if err := state.RefreshState(); err != nil { + c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err)) + return 1 + } stateReal := state.State() if stateReal == nil { diff --git a/command/taint.go b/command/taint.go index 9b184e27a..0fd2b4de9 100644 --- a/command/taint.go +++ b/command/taint.go @@ -72,6 +72,10 @@ func (c *TaintCommand) Run(args []string) int { c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err)) return 1 } + if err := st.RefreshState(); err != nil { + c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err)) + return 1 + } if c.Meta.stateLock { lockInfo := state.NewLockInfo() diff --git a/command/test-fixtures/state-list-backend/.terraform/terraform.tfstate b/command/test-fixtures/state-list-backend/.terraform/terraform.tfstate new file mode 100644 index 000000000..073bd7a82 --- /dev/null +++ b/command/test-fixtures/state-list-backend/.terraform/terraform.tfstate @@ -0,0 +1,22 @@ +{ + "version": 3, + "serial": 0, + "lineage": "666f9301-7e65-4b19-ae23-71184bb19b03", + "backend": { + "type": "local", + "config": { + "path": "local-state.tfstate" + }, + "hash": 9073424445967744180 + }, + "modules": [ + { + "path": [ + "root" + ], + "outputs": {}, + "resources": {}, + "depends_on": [] + } + ] +} diff --git a/command/test-fixtures/state-list-backend/local-state.tfstate b/command/test-fixtures/state-list-backend/local-state.tfstate new file mode 100644 index 000000000..fc10b3cc7 --- /dev/null +++ b/command/test-fixtures/state-list-backend/local-state.tfstate @@ -0,0 +1,31 @@ +{ + "version": 3, + "terraform_version": "0.8.2", + "serial": 7, + "lineage": "configuredUnchanged", + "modules": [ + { + "path": [ + "root" + ], + "outputs": {}, + "resources": { + "null_resource.a": { + "type": "null_resource", + "depends_on": [], + "primary": { + "id": "5416263284413907707", + "attributes": { + "id": "5416263284413907707" + }, + "meta": {}, + "tainted": false + }, + "deposed": [], + "provider": "" + } + }, + "depends_on": [] + } + ] +} diff --git a/command/test-fixtures/state-list-backend/main.tf b/command/test-fixtures/state-list-backend/main.tf new file mode 100644 index 000000000..ca1bd3921 --- /dev/null +++ b/command/test-fixtures/state-list-backend/main.tf @@ -0,0 +1,5 @@ +terraform { + backend "local" { + path = "local-state.tfstate" + } +} diff --git a/command/untaint.go b/command/untaint.go index dca2cd9be..c3b413252 100644 --- a/command/untaint.go +++ b/command/untaint.go @@ -60,6 +60,10 @@ func (c *UntaintCommand) Run(args []string) int { c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err)) return 1 } + if err := st.RefreshState(); err != nil { + c.Ui.Error(fmt.Sprintf("Failed to load state: %s", err)) + return 1 + } if c.Meta.stateLock { lockInfo := state.NewLockInfo() diff --git a/terraform/context.go b/terraform/context.go index b9214f84c..06eef4300 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -207,6 +207,7 @@ func (c *Context) Graph(typ GraphType, opts *ContextGraphOpts) (*Graph, error) { opts = &ContextGraphOpts{Validate: true} } + log.Printf("[INFO] terraform: building graph: %s", typ) switch typ { case GraphTypeApply: return (&ApplyGraphBuilder{