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.
This commit is contained in:
Mitchell Hashimoto 2017-03-16 15:42:32 -07:00
parent f7da5d323c
commit e1f4eca93c
No known key found for this signature in database
GPG Key ID: 744E147AA52F5B0A
2 changed files with 27 additions and 16 deletions

View File

@ -481,6 +481,7 @@ func (m *Meta) backendFromPlan(opts *BackendOpts) (backend.Backend, error) {
"and specify the state path when creating the plan.") "and specify the state path when creating the plan.")
} }
planBackend := opts.Plan.Backend
planState := opts.Plan.State planState := opts.Plan.State
if planState == nil { if planState == nil {
// The state can be nil, we just have to make it empty for the logic // 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 // Validation only for non-local plans
local := planState.Remote.Empty() && planState.Backend.Empty() local := planState.Remote.Empty() && planBackend.Empty()
if !local { if !local {
// We currently don't allow "-state-out" to be specified. // We currently don't allow "-state-out" to be specified.
if m.stateOutPath != "" { 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 // Determine the path where we'd be writing state
path := DefaultStateFilename path := DefaultStateFilename
if !planState.Remote.Empty() || !planState.Backend.Empty() { if !planState.Remote.Empty() || !planBackend.Empty() {
path = filepath.Join(m.DataDir(), DefaultStateFilename) path = filepath.Join(m.DataDir(), DefaultStateFilename)
} }
@ -529,16 +530,26 @@ func (m *Meta) backendFromPlan(opts *BackendOpts) (backend.Backend, error) {
var err error var err error
switch { switch {
// No remote state at all, all local // 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 // Get the local backend
b, err = m.Backend(&BackendOpts{ForceLocal: true}) b, err = m.Backend(&BackendOpts{ForceLocal: true})
// New backend configuration set // New backend configuration set
case planState.Remote.Empty() && !planState.Backend.Empty(): case planState.Remote.Empty() && !planBackend.Empty():
b, err = m.backendInitFromSaved(planState.Backend) log.Printf(
"[INFO] command: initializing backend from plan: %s",
planBackend.Type)
b, err = m.backendInitFromSaved(planBackend)
// Legacy remote state set // 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 // Write our current state to an inmemory state just so that we
// have it in the format of state.State // have it in the format of state.State
inmem := &state.InmemState{} 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) b, err = m.backend_c_R_s(nil, inmem)
// Both set, this can't happen in a plan. // 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)) return nil, fmt.Errorf(strings.TrimSpace(errBackendPlanBoth))
} }

View File

@ -2863,12 +2863,12 @@ func TestMetaBackend_planBackendEmptyDir(t *testing.T) {
testFixturePath("backend-plan-backend-empty-config"), testFixturePath("backend-plan-backend-empty-config"),
DefaultDataDir, DefaultStateFilename)) DefaultDataDir, DefaultStateFilename))
planState := original.DeepCopy() planState := original.DeepCopy()
planState.Backend = backendState.Backend
// Create the plan // Create the plan
plan := &terraform.Plan{ plan := &terraform.Plan{
Module: testModule(t, "backend-plan-backend-empty-config"), Module: testModule(t, "backend-plan-backend-empty-config"),
State: planState, State: planState,
Backend: backendState.Backend,
} }
// Setup the meta // Setup the meta
@ -2965,12 +2965,12 @@ func TestMetaBackend_planBackendMatch(t *testing.T) {
testFixturePath("backend-plan-backend-empty-config"), testFixturePath("backend-plan-backend-empty-config"),
DefaultDataDir, DefaultStateFilename)) DefaultDataDir, DefaultStateFilename))
planState := original.DeepCopy() planState := original.DeepCopy()
planState.Backend = backendState.Backend
// Create the plan // Create the plan
plan := &terraform.Plan{ plan := &terraform.Plan{
Module: testModule(t, "backend-plan-backend-empty-config"), Module: testModule(t, "backend-plan-backend-empty-config"),
State: planState, State: planState,
Backend: backendState.Backend,
} }
// Setup the meta // Setup the meta
@ -3067,7 +3067,6 @@ func TestMetaBackend_planBackendMismatchLineage(t *testing.T) {
testFixturePath("backend-plan-backend-empty-config"), testFixturePath("backend-plan-backend-empty-config"),
DefaultDataDir, DefaultStateFilename)) DefaultDataDir, DefaultStateFilename))
planState := original.DeepCopy() planState := original.DeepCopy()
planState.Backend = backendState.Backend
// Get the real original // Get the real original
original = testStateRead(t, "local-state.tfstate") original = testStateRead(t, "local-state.tfstate")
@ -3076,6 +3075,7 @@ func TestMetaBackend_planBackendMismatchLineage(t *testing.T) {
plan := &terraform.Plan{ plan := &terraform.Plan{
Module: testModule(t, "backend-plan-backend-empty-config"), Module: testModule(t, "backend-plan-backend-empty-config"),
State: planState, State: planState,
Backend: backendState.Backend,
} }
// Setup the meta // Setup the meta