diff --git a/command/diff.go b/command/diff.go index 58018be42c..48a1e82eeb 100644 --- a/command/diff.go +++ b/command/diff.go @@ -3,6 +3,7 @@ package command import ( "flag" "fmt" + "os" "strings" "github.com/hashicorp/terraform/config" @@ -18,7 +19,10 @@ type DiffCommand struct { } func (c *DiffCommand) Run(args []string) int { + var statePath string + cmdFlags := flag.NewFlagSet("diff", flag.ContinueOnError) + cmdFlags.StringVar(&statePath, "state", "", "path") cmdFlags.Usage = func() { c.Ui.Error(c.Help()) } if err := cmdFlags.Parse(args); err != nil { return 1 @@ -33,6 +37,23 @@ func (c *DiffCommand) Run(args []string) int { return 1 } + // Load up the state + var state *terraform.State + if statePath != "" { + f, err := os.Open(statePath) + if err != nil { + c.Ui.Error(fmt.Sprintf("Error loading state: %s", err)) + return 1 + } + + state, err = terraform.ReadState(f) + f.Close() + if err != nil { + c.Ui.Error(fmt.Sprintf("Error loading state: %s", err)) + return 1 + } + } + b, err := config.Load(args[0]) if err != nil { c.Ui.Error(fmt.Sprintf("Error loading blueprint: %s", err)) @@ -48,7 +69,7 @@ func (c *DiffCommand) Run(args []string) int { return 1 } - diff, err := tf.Diff(nil) + diff, err := tf.Diff(state) if err != nil { c.Ui.Error(fmt.Sprintf("Error running diff: %s", err)) return 1 diff --git a/command/diff_test.go b/command/diff_test.go new file mode 100644 index 0000000000..54121732d6 --- /dev/null +++ b/command/diff_test.go @@ -0,0 +1,80 @@ +package command + +import ( + "io/ioutil" + "os" + "reflect" + "testing" + + "github.com/hashicorp/terraform/terraform" + "github.com/mitchellh/cli" +) + +func TestDiff_noState(t *testing.T) { + p := testProvider() + ui := new(cli.MockUi) + c := &DiffCommand{ + TFConfig: testTFConfig(p), + Ui: ui, + } + + args := []string{ + testFixturePath("diff"), + } + 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 + expectedState := &terraform.ResourceState{ + Type: "test_instance", + } + if !reflect.DeepEqual(p.DiffState, expectedState) { + t.Fatalf("bad: %#v", p.DiffState) + } +} +func TestDiff_state(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{ + Resources: map[string]*terraform.ResourceState{ + "test_instance.foo": &terraform.ResourceState{ + ID: "bar", + Type: "test_instance", + }, + }, + } + + err = terraform.WriteState(originalState, tf) + tf.Close() + if err != nil { + t.Fatalf("err: %s", err) + } + + p := testProvider() + ui := new(cli.MockUi) + c := &DiffCommand{ + TFConfig: testTFConfig(p), + Ui: ui, + } + + args := []string{ + "-state", statePath, + testFixturePath("diff"), + } + 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 + expectedState := originalState.Resources["test_instance.foo"] + if !reflect.DeepEqual(p.DiffState, expectedState) { + t.Fatalf("bad: %#v", p.DiffState) + } +} diff --git a/command/test-fixtures/diff/main.tf b/command/test-fixtures/diff/main.tf new file mode 100644 index 0000000000..5794f94d9d --- /dev/null +++ b/command/test-fixtures/diff/main.tf @@ -0,0 +1,3 @@ +resource "test_instance" "foo" { + ami = "bar" +}