Use -state-out option when applying from a plan
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.
This commit is contained in:
parent
a84aa5e914
commit
6b5ee73e86
|
@ -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 {
|
||||
|
|
|
@ -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
|
||||
|
||||
// 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(
|
||||
|
|
|
@ -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 &&
|
||||
|
@ -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
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue