From 408ae6230676831f70eefb179da61c52c531bf88 Mon Sep 17 00:00:00 2001 From: Armon Dadgar Date: Wed, 7 Jan 2015 13:08:32 -0800 Subject: [PATCH] command/apply: Handle remote state in a plan file --- command/apply_test.go | 65 +++++++++++++++++++++++++++++++++++++++++++ command/meta.go | 8 ++++++ 2 files changed, 73 insertions(+) diff --git a/command/apply_test.go b/command/apply_test.go index e5c5a6b08..bac67d7ba 100644 --- a/command/apply_test.go +++ b/command/apply_test.go @@ -15,6 +15,7 @@ import ( "testing" "time" + "github.com/hashicorp/terraform/remote" "github.com/hashicorp/terraform/terraform" "github.com/mitchellh/cli" ) @@ -368,6 +369,70 @@ func TestApply_plan(t *testing.T) { } } +func TestApply_plan_remoteState(t *testing.T) { + // Disable test mode so input would be asked + test = false + defer func() { test = true }() + tmp, cwd := testCwd(t) + defer testFixCwd(t, tmp, cwd) + if err := remote.EnsureDirectory(); err != nil { + t.Fatalf("err: %v", err) + } + + // Set some default reader/writers for the inputs + defaultInputReader = new(bytes.Buffer) + defaultInputWriter = new(bytes.Buffer) + + // Create a remote state + state := testState() + conf, srv := testRemoteState(t, state, 200) + defer srv.Close() + state.Remote = conf + + planPath := testPlanFile(t, &terraform.Plan{ + Module: testModule(t, "apply"), + State: state, + }) + + p := testProvider() + ui := new(cli.MockUi) + c := &ApplyCommand{ + Meta: Meta{ + ContextOpts: testCtxConfig(p), + Ui: ui, + }, + } + + args := []string{ + planPath, + } + if code := c.Run(args); code != 0 { + t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) + } + + if p.InputCalled { + t.Fatalf("input should not be called for plans") + } + + // State file should be not be installed + exists, err := remote.ExistsFile(DefaultStateFilename) + if err != nil { + t.Fatalf("err: %v", err) + } + if exists { + t.Fatalf("State path should not exist") + } + + // Check for remote state + output, _, err := remote.ReadLocalState() + if err != nil { + t.Fatalf("err: %v", err) + } + if output == nil { + t.Fatalf("missing remote state") + } +} + func TestApply_planWithVarFile(t *testing.T) { varFileDir := testTempDir(t) varFilePath := filepath.Join(varFileDir, "terraform.tfvars") diff --git a/command/meta.go b/command/meta.go index 34f094758..0b04a9336 100644 --- a/command/meta.go +++ b/command/meta.go @@ -106,6 +106,14 @@ func (m *Meta) Context(copts contextOpts) (*terraform.Context, bool, error) { plan, err := terraform.ReadPlan(f) f.Close() if err == nil { + // Check if remote state is enabled, but do not refresh. + // Since a plan is supposed to lock-in the changes, we do not + // attempt a state refresh. + if plan.State.Remote != nil && plan.State.Remote.Type != "" { + log.Printf("[INFO] Enabling remote state from plan") + m.useRemoteState = true + } + if len(m.variables) > 0 { return nil, false, fmt.Errorf( "You can't set variables with the '-var' or '-var-file' flag\n" +