From 64363da9dddefb10cd0a94fd1c700114de20e8b3 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 1 Jul 2014 09:12:05 -0700 Subject: [PATCH 1/3] command/plan: add -destroy flag to plan a destroy --- command/command_test.go | 15 +++++++++++++++ command/plan.go | 8 +++++--- command/plan_test.go | 37 +++++++++++++++++++++++++++++++++++++ terraform/terraform.go | 2 ++ 4 files changed, 59 insertions(+), 3 deletions(-) diff --git a/command/command_test.go b/command/command_test.go index efcefd55b3..074db94b8f 100644 --- a/command/command_test.go +++ b/command/command_test.go @@ -42,6 +42,21 @@ func testPlanFile(t *testing.T, plan *terraform.Plan) string { return path } +func testReadPlan(t *testing.T, path string) *terraform.Plan { + f, err := os.Open(path) + if err != nil { + t.Fatalf("err: %s", err) + } + defer f.Close() + + p, err := terraform.ReadPlan(f) + if err != nil { + t.Fatalf("err: %s", err) + } + + return p +} + func testStateFile(t *testing.T, s *terraform.State) string { path := testTempFile(t) diff --git a/command/plan.go b/command/plan.go index 3085e1ae9e..7967e330f9 100644 --- a/command/plan.go +++ b/command/plan.go @@ -20,10 +20,11 @@ type PlanCommand struct { } func (c *PlanCommand) Run(args []string) int { - var refresh bool + var destroy, refresh bool var outPath, statePath string cmdFlags := flag.NewFlagSet("plan", flag.ContinueOnError) + cmdFlags.BoolVar(&destroy, "destroy", false, "destroy") cmdFlags.BoolVar(&refresh, "refresh", true, "refresh") cmdFlags.StringVar(&outPath, "out", "", "path") cmdFlags.StringVar(&statePath, "state", "", "path") @@ -80,8 +81,9 @@ func (c *PlanCommand) Run(args []string) int { } plan, err := tf.Plan(&terraform.PlanOpts{ - Config: b, - State: state, + Config: b, + Destroy: destroy, + State: state, }) if err != nil { c.Ui.Error(fmt.Sprintf("Error running plan: %s", err)) diff --git a/command/plan_test.go b/command/plan_test.go index ff2f77dd0b..4ef71cb2e0 100644 --- a/command/plan_test.go +++ b/command/plan_test.go @@ -10,6 +10,43 @@ import ( "github.com/mitchellh/cli" ) +func TestPlan_destroy(t *testing.T) { + originalState := &terraform.State{ + Resources: map[string]*terraform.ResourceState{ + "test_instance.foo": &terraform.ResourceState{ + ID: "bar", + Type: "test_instance", + }, + }, + } + + outPath := testTempFile(t) + statePath := testStateFile(t, originalState) + + p := testProvider() + ui := new(cli.MockUi) + c := &PlanCommand{ + TFConfig: testTFConfig(p), + Ui: ui, + } + + args := []string{ + "-destroy", + "-out", outPath, + "-state", statePath, + testFixturePath("plan"), + } + if code := c.Run(args); code != 0 { + t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) + } + + plan := testReadPlan(t, outPath) + for _, r := range plan.Diff.Resources { + if !r.Destroy { + t.Fatalf("bad: %#v", r) + } + } +} func TestPlan_noState(t *testing.T) { p := testProvider() ui := new(cli.MockUi) diff --git a/terraform/terraform.go b/terraform/terraform.go index 92e3a1f70b..f060bf0b5f 100644 --- a/terraform/terraform.go +++ b/terraform/terraform.go @@ -253,6 +253,8 @@ func (t *Terraform) planWalkFn(result *Plan, opts *PlanOpts) depgraph.WalkFunc { if r.State.ID != "" { log.Printf("[DEBUG] %s: Making for destroy", r.Id) diff = &ResourceDiff{Destroy: true} + } else { + log.Printf("[DEBUG] %s: Not marking for destroy, no ID", r.Id) } } else if r.Config == nil { log.Printf("[DEBUG] %s: Orphan, marking for destroy", r.Id) From a7d3cb843f45b4982810f57941e8290f1e0351cd Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 1 Jul 2014 09:12:35 -0700 Subject: [PATCH 2/3] command/plan: help text --- command/plan.go | 3 +++ 1 file changed, 3 insertions(+) diff --git a/command/plan.go b/command/plan.go index 7967e330f9..5781f01562 100644 --- a/command/plan.go +++ b/command/plan.go @@ -122,6 +122,9 @@ Usage: terraform plan [options] [terraform.tf] Options: + -destroy If set, a plan will be generated to destroy all resources + managed by the given configuration and state. + -out=path Write a plan file to the given path. This can be used as input to the "apply" command. From 367fb3bbbbb244dd55261d5e012b0da68ac26f26 Mon Sep 17 00:00:00 2001 From: Mitchell Hashimoto Date: Tue, 1 Jul 2014 09:25:17 -0700 Subject: [PATCH 3/3] Update TODO --- TODO.md | 1 - 1 file changed, 1 deletion(-) diff --git a/TODO.md b/TODO.md index 60a1c04063..6969120eda 100644 --- a/TODO.md +++ b/TODO.md @@ -1,6 +1,5 @@ This is just to keep track of what we need to do before 0.1: - * `terraform destroy` * `terraform apply/plan/refresh/destroy` need to be able to take variables as input * Provisioners on top of static resource creation: Shell, Chef, Puppet, etc. * `ValidateResource` ResourceProvider API for checking the structure of a resource config