From e1f4eca93ce09b7ed467869773d41f43ee5903d6 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Thu, 16 Mar 2017 15:42:32 -0700 Subject: [PATCH] command: apply needs to look at the right field for backend state Plans were properly encoding backend configuration but the apply was reading it from the wrong field. :( This meant that every apply from a plan was applying it locally with backends. This needs to get released ASAP. --- command/meta_backend.go | 25 ++++++++++++++++++------- command/meta_backend_test.go | 18 +++++++++--------- 2 files changed, 27 insertions(+), 16 deletions(-) diff --git a/command/meta_backend.go b/command/meta_backend.go index f1ad37190..62029278e 100644 --- a/command/meta_backend.go +++ b/command/meta_backend.go @@ -481,6 +481,7 @@ func (m *Meta) backendFromPlan(opts *BackendOpts) (backend.Backend, error) { "and specify the state path when creating the plan.") } + planBackend := opts.Plan.Backend planState := opts.Plan.State if planState == nil { // The state can be nil, we just have to make it empty for the logic @@ -489,7 +490,7 @@ func (m *Meta) backendFromPlan(opts *BackendOpts) (backend.Backend, error) { } // Validation only for non-local plans - local := planState.Remote.Empty() && planState.Backend.Empty() + local := planState.Remote.Empty() && planBackend.Empty() if !local { // We currently don't allow "-state-out" to be specified. if m.stateOutPath != "" { @@ -500,7 +501,7 @@ func (m *Meta) backendFromPlan(opts *BackendOpts) (backend.Backend, error) { /* // Determine the path where we'd be writing state path := DefaultStateFilename - if !planState.Remote.Empty() || !planState.Backend.Empty() { + if !planState.Remote.Empty() || !planBackend.Empty() { path = filepath.Join(m.DataDir(), DefaultStateFilename) } @@ -529,16 +530,26 @@ func (m *Meta) backendFromPlan(opts *BackendOpts) (backend.Backend, error) { var err error switch { // No remote state at all, all local - case planState.Remote.Empty() && planState.Backend.Empty(): + case planState.Remote.Empty() && planBackend.Empty(): + log.Printf("[INFO] command: initializing local backend from plan (not set)") + // Get the local backend b, err = m.Backend(&BackendOpts{ForceLocal: true}) // New backend configuration set - case planState.Remote.Empty() && !planState.Backend.Empty(): - b, err = m.backendInitFromSaved(planState.Backend) + case planState.Remote.Empty() && !planBackend.Empty(): + log.Printf( + "[INFO] command: initializing backend from plan: %s", + planBackend.Type) + + b, err = m.backendInitFromSaved(planBackend) // Legacy remote state set - case !planState.Remote.Empty() && planState.Backend.Empty(): + case !planState.Remote.Empty() && planBackend.Empty(): + log.Printf( + "[INFO] command: initializing legacy remote backend from plan: %s", + planState.Remote.Type) + // Write our current state to an inmemory state just so that we // have it in the format of state.State inmem := &state.InmemState{} @@ -548,7 +559,7 @@ func (m *Meta) backendFromPlan(opts *BackendOpts) (backend.Backend, error) { b, err = m.backend_c_R_s(nil, inmem) // Both set, this can't happen in a plan. - case !planState.Remote.Empty() && !planState.Backend.Empty(): + case !planState.Remote.Empty() && !planBackend.Empty(): return nil, fmt.Errorf(strings.TrimSpace(errBackendPlanBoth)) } diff --git a/command/meta_backend_test.go b/command/meta_backend_test.go index b9ff80658..54bdc2053 100644 --- a/command/meta_backend_test.go +++ b/command/meta_backend_test.go @@ -2863,12 +2863,12 @@ func TestMetaBackend_planBackendEmptyDir(t *testing.T) { testFixturePath("backend-plan-backend-empty-config"), DefaultDataDir, DefaultStateFilename)) planState := original.DeepCopy() - planState.Backend = backendState.Backend // Create the plan plan := &terraform.Plan{ - Module: testModule(t, "backend-plan-backend-empty-config"), - State: planState, + Module: testModule(t, "backend-plan-backend-empty-config"), + State: planState, + Backend: backendState.Backend, } // Setup the meta @@ -2965,12 +2965,12 @@ func TestMetaBackend_planBackendMatch(t *testing.T) { testFixturePath("backend-plan-backend-empty-config"), DefaultDataDir, DefaultStateFilename)) planState := original.DeepCopy() - planState.Backend = backendState.Backend // Create the plan plan := &terraform.Plan{ - Module: testModule(t, "backend-plan-backend-empty-config"), - State: planState, + Module: testModule(t, "backend-plan-backend-empty-config"), + State: planState, + Backend: backendState.Backend, } // Setup the meta @@ -3067,15 +3067,15 @@ func TestMetaBackend_planBackendMismatchLineage(t *testing.T) { testFixturePath("backend-plan-backend-empty-config"), DefaultDataDir, DefaultStateFilename)) planState := original.DeepCopy() - planState.Backend = backendState.Backend // Get the real original original = testStateRead(t, "local-state.tfstate") // Create the plan plan := &terraform.Plan{ - Module: testModule(t, "backend-plan-backend-empty-config"), - State: planState, + Module: testModule(t, "backend-plan-backend-empty-config"), + State: planState, + Backend: backendState.Backend, } // Setup the meta