Skip to content

Commit

Permalink
core: Do not persist state after plans
Browse files Browse the repository at this point in the history
This makes the behavior of plans much more predictable, as they no
longer potentially have side effects on shared remote state.
  • Loading branch information
phinze committed May 23, 2016
1 parent 6830993 commit ae73aa2
Show file tree
Hide file tree
Showing 2 changed files with 1 addition and 183 deletions.
11 changes: 1 addition & 10 deletions command/plan.go
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,6 @@ func (c *PlanCommand) Run(args []string) int {
cmdFlags.IntVar(
&c.Meta.parallelism, "parallelism", DefaultParallelism, "parallelism")
cmdFlags.StringVar(&c.Meta.statePath, "state", DefaultStateFilename, "path")
cmdFlags.StringVar(&c.Meta.backupPath, "backup", "", "path")
cmdFlags.BoolVar(&detailed, "detailed-exitcode", false, "detailed-exitcode")
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
if err := cmdFlags.Parse(args); err != nil {
Expand Down Expand Up @@ -80,20 +79,12 @@ func (c *PlanCommand) Run(args []string) int {

if refresh {
c.Ui.Output("Refreshing Terraform state prior to plan...\n")
state, err := ctx.Refresh()
_, err := ctx.Refresh()
if err != nil {
c.Ui.Error(fmt.Sprintf("Error refreshing state: %s", err))
return 1
}
c.Ui.Output("")

if state != nil {
log.Printf("[INFO] Writing state output to: %s", c.Meta.StateOutPath())
if err := c.Meta.PersistState(state); err != nil {
c.Ui.Error(fmt.Sprintf("Error writing state file: %s", err))
return 1
}
}
}

plan, err := ctx.Plan()
Expand Down
173 changes: 0 additions & 173 deletions command/plan_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -88,23 +88,6 @@ func TestPlan_destroy(t *testing.T) {
}
}
}

f, err := os.Open(statePath + DefaultBackupExtension)
if err != nil {
t.Fatalf("err: %s", err)
}

backupState, err := terraform.ReadState(f)
f.Close()
if err != nil {
t.Fatalf("err: %s", err)
}

actualStr := strings.TrimSpace(backupState.String())
expectedStr := strings.TrimSpace(originalState.String())
if actualStr != expectedStr {
t.Fatalf("bad:\n\n%s\n\n%s", actualStr, expectedStr)
}
}

func TestPlan_noState(t *testing.T) {
Expand Down Expand Up @@ -560,154 +543,6 @@ func TestPlan_varFileDefault(t *testing.T) {
}
}

func TestPlan_backup(t *testing.T) {
// Write out some prior state
tf, err := ioutil.TempFile("", "tf")
if err != nil {
t.Fatalf("err: %s", err)
}
statePath := tf.Name()
defer os.Remove(tf.Name())

// Write out some prior state
backupf, err := ioutil.TempFile("", "tf")
if err != nil {
t.Fatalf("err: %s", err)
}
backupPath := backupf.Name()
backupf.Close()
os.Remove(backupPath)
defer os.Remove(backupPath)

originalState := &terraform.State{
Modules: []*terraform.ModuleState{
&terraform.ModuleState{
Path: []string{"root"},
Resources: map[string]*terraform.ResourceState{
"test_instance.foo": &terraform.ResourceState{
Type: "test_instance",
Primary: &terraform.InstanceState{
ID: "bar",
},
},
},
},
},
}

err = terraform.WriteState(originalState, tf)
tf.Close()
if err != nil {
t.Fatalf("err: %s", err)
}

p := testProvider()
ui := new(cli.MockUi)
c := &PlanCommand{
Meta: Meta{
ContextOpts: testCtxConfig(p),
Ui: ui,
},
}

args := []string{
"-state", statePath,
"-backup", backupPath,
testFixturePath("plan"),
}
if code := c.Run(args); code != 0 {
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
}

// Verify that the provider was called with the existing state
actual := strings.TrimSpace(p.DiffState.String())
expected := strings.TrimSpace(testPlanBackupStr)
if actual != expected {
t.Fatalf("bad:\n\n%s", actual)
}

// Verify the backup exist
f, err := os.Open(backupPath)
if err != nil {
t.Fatalf("err: %s", err)
}

backupState, err := terraform.ReadState(f)
f.Close()
if err != nil {
t.Fatalf("err: %s", err)
}

actualStr := strings.TrimSpace(backupState.String())
expectedStr := strings.TrimSpace(originalState.String())
if actualStr != expectedStr {
t.Fatalf("bad:\n\n%s\n\n%s", actualStr, expectedStr)
}
}

func TestPlan_disableBackup(t *testing.T) {
// Write out some prior state
tf, err := ioutil.TempFile("", "tf")
if err != nil {
t.Fatalf("err: %s", err)
}
statePath := tf.Name()
defer os.Remove(tf.Name())

originalState := &terraform.State{
Modules: []*terraform.ModuleState{
&terraform.ModuleState{
Path: []string{"root"},
Resources: map[string]*terraform.ResourceState{
"test_instance.foo": &terraform.ResourceState{
Type: "test_instance",
Primary: &terraform.InstanceState{
ID: "bar",
},
},
},
},
},
}

err = terraform.WriteState(originalState, tf)
tf.Close()
if err != nil {
t.Fatalf("err: %s", err)
}

p := testProvider()
ui := new(cli.MockUi)
c := &PlanCommand{
Meta: Meta{
ContextOpts: testCtxConfig(p),
Ui: ui,
},
}

args := []string{
"-state", statePath,
"-backup", "-",
testFixturePath("plan"),
}
if code := c.Run(args); code != 0 {
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
}

// Verify that the provider was called with the existing state
actual := strings.TrimSpace(p.DiffState.String())
expected := strings.TrimSpace(testPlanDisableBackupStr)
if actual != expected {
t.Fatalf("bad:\n\n%s", actual)
}

// Ensure there is no backup
_, err = os.Stat(statePath + DefaultBackupExtension)
if err == nil || !os.IsNotExist(err) {
t.Fatalf("backup should not exist")
}
}

func TestPlan_detailedExitcode(t *testing.T) {
cwd, err := os.Getwd()
if err != nil {
Expand Down Expand Up @@ -762,14 +597,6 @@ const planVarFile = `
foo = "bar"
`

const testPlanBackupStr = `
ID = bar
`

const testPlanDisableBackupStr = `
ID = bar
`

const testPlanNoStateStr = `
<not created>
`
Expand Down

0 comments on commit ae73aa2

Please sign in to comment.