Skip to content

Commit

Permalink
Use -state-out option when applying from a plan
Browse files Browse the repository at this point in the history
When working from an existing plan, we weren't setting the PathOut field
for a LocalState. This required adding an outPath argument to the
StateFromPlan function to avoid having to introspect the returned
state.State interface to find the appropriate field.

To test we run a plan first and provide the new plan to apply with
`-state-out` set.
  • Loading branch information
jbardin committed Jul 1, 2016
1 parent a84aa5e commit 6b5ee73
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 4 deletions.
53 changes: 53 additions & 0 deletions command/apply_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1326,6 +1326,59 @@ func TestApply_disableBackup(t *testing.T) {
}
}

// -state-out wasn't taking effect when a plan is supplied. GH-7264
func TestApply_stateOutWithPlan(t *testing.T) {
p := testProvider()
ui := new(cli.MockUi)

tmpDir := testTempDir(t)
defer os.RemoveAll(tmpDir)

statePath := filepath.Join(tmpDir, "state.tfstate")
planPath := filepath.Join(tmpDir, "terraform.tfplan")

args := []string{
"-state", statePath,
"-out", planPath,
testFixturePath("plan"),
}

// Run plan first to get a current plan file
pc := &PlanCommand{
Meta: Meta{
ContextOpts: testCtxConfig(p),
Ui: ui,
},
}
if code := pc.Run(args); code != 0 {
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
}

// now run apply with the generated plan
stateOutPath := filepath.Join(tmpDir, "state-new.tfstate")

args = []string{
"-state", statePath,
"-state-out", stateOutPath,
planPath,
}

ac := &ApplyCommand{
Meta: Meta{
ContextOpts: testCtxConfig(p),
Ui: ui,
},
}
if code := ac.Run(args); code != 0 {
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
}

// now make sure we wrote out our new state
if _, err := os.Stat(stateOutPath); err != nil {
t.Fatalf("missing new state file: %s", err)
}
}

func testHttpServer(t *testing.T) net.Listener {
ln, err := net.Listen("tcp", "127.0.0.1:0")
if err != nil {
Expand Down
8 changes: 6 additions & 2 deletions command/meta.go
Original file line number Diff line number Diff line change
Expand Up @@ -109,14 +109,18 @@ func (m *Meta) Context(copts contextOpts) (*terraform.Context, bool, error) {
f.Close()
if err == nil {
// Setup our state
state, statePath, err := StateFromPlan(m.statePath, plan)
state, statePath, err := StateFromPlan(m.statePath, m.stateOutPath, plan)
if err != nil {
return nil, false, fmt.Errorf("Error loading plan: %s", err)
}

// Set our state
m.state = state
m.stateOutPath = statePath

// this is used for printing the saved location later
if m.stateOutPath == "" {
m.stateOutPath = statePath
}

if len(m.variables) > 0 {
return nil, false, fmt.Errorf(
Expand Down
8 changes: 6 additions & 2 deletions command/state.go
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,8 @@ func State(opts *StateOpts) (*StateResult, error) {

// StateFromPlan gets our state from the plan.
func StateFromPlan(
localPath string, plan *terraform.Plan) (state.State, string, error) {
localPath, outPath string,
plan *terraform.Plan) (state.State, string, error) {
var result state.State
resultPath := localPath
if plan != nil && plan.State != nil &&
Expand All @@ -186,7 +187,10 @@ func StateFromPlan(
}

if result == nil {
local := &state.LocalState{Path: resultPath}
local := &state.LocalState{
Path: resultPath,
PathOut: outPath,
}
local.SetState(plan.State)
result = local
}
Expand Down

0 comments on commit 6b5ee73

Please sign in to comment.