diff --git a/terraform/context.go b/terraform/context.go index 3f68c245a..66e553738 100644 --- a/terraform/context.go +++ b/terraform/context.go @@ -630,7 +630,9 @@ func computeAggregateVars( var ivars map[string]config.InterpolatedVariable switch m := n.Meta.(type) { case *GraphNodeResource: - ivars = m.Config.RawConfig.Variables + if m.Config != nil { + ivars = m.Config.RawConfig.Variables + } case *GraphNodeResourceProvider: if m.Config != nil { ivars = m.Config.RawConfig.Variables diff --git a/terraform/context_test.go b/terraform/context_test.go index e2eb5826a..25bb48aaf 100644 --- a/terraform/context_test.go +++ b/terraform/context_test.go @@ -668,6 +668,50 @@ func TestContextPlan_count(t *testing.T) { } } +func TestContextPlan_countDecrease(t *testing.T) { + c := testConfig(t, "plan-count-dec") + p := testProvider("aws") + p.DiffFn = testDiffFn + s := &State{ + Resources: map[string]*ResourceState{ + "aws_instance.foo.0": &ResourceState{ + ID: "bar", + Type: "aws_instance", + Attributes: map[string]string{ + "foo": "foo", + "type": "aws_instance", + }, + }, + "aws_instance.foo.1": &ResourceState{ + ID: "bar", + Type: "aws_instance", + }, + "aws_instance.foo.2": &ResourceState{ + ID: "bar", + Type: "aws_instance", + }, + }, + } + ctx := testContext(t, &ContextOpts{ + Config: c, + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + State: s, + }) + + plan, err := ctx.Plan(nil) + if err != nil { + t.Fatalf("err: %s", err) + } + + actual := strings.TrimSpace(plan.String()) + expected := strings.TrimSpace(testTerraformPlanCountDecreaseStr) + if actual != expected { + t.Fatalf("bad:\n%s", actual) + } +} + func TestContextPlan_destroy(t *testing.T) { c := testConfig(t, "plan-destroy") p := testProvider("aws") @@ -944,10 +988,6 @@ func testDiffFn( c *ResourceConfig) (*ResourceDiff, error) { var diff ResourceDiff diff.Attributes = make(map[string]*ResourceAttrDiff) - diff.Attributes["type"] = &ResourceAttrDiff{ - Old: "", - New: s.Type, - } for k, v := range c.Raw { if _, ok := v.(string); !ok { @@ -1009,6 +1049,27 @@ func testDiffFn( } } + for k, v := range diff.Attributes { + if v.NewComputed { + continue + } + + old, ok := s.Attributes[k] + if !ok { + continue + } + if old == v.New { + delete(diff.Attributes, k) + } + } + + if !diff.Empty() { + diff.Attributes["type"] = &ResourceAttrDiff{ + Old: "", + New: s.Type, + } + } + return &diff, nil } diff --git a/terraform/graph.go b/terraform/graph.go index 2dd3a0616..fd7a40cff 100644 --- a/terraform/graph.go +++ b/terraform/graph.go @@ -156,16 +156,6 @@ func graphAddConfigResources( // This tracks all the resource nouns nouns := make(map[string]*depgraph.Noun) for _, r := range c.Resources { - var state *ResourceState - if s != nil { - state = s.Resources[r.Id()] - } - if state == nil { - state = &ResourceState{ - Type: r.Type, - } - } - resourceNouns := make([]*depgraph.Noun, r.Count) for i := 0; i < r.Count; i++ { name := r.Id() @@ -178,6 +168,22 @@ func graphAddConfigResources( index = i } + var state *ResourceState + if s != nil { + state = s.Resources[name] + + // If the count is one, check the state for ".0" appended, which + // might exist if we go from count > 1 to count == 1. + if state == nil && r.Count == 1 { + state = s.Resources[r.Id()+".0"] + } + } + if state == nil { + state = &ResourceState{ + Type: r.Type, + } + } + resourceNouns[i] = &depgraph.Noun{ Name: name, Meta: &GraphNodeResource{ diff --git a/terraform/state.go b/terraform/state.go index 171870d0b..104459155 100644 --- a/terraform/state.go +++ b/terraform/state.go @@ -38,6 +38,12 @@ func (s *State) Orphans(c *config.Config) []string { for _, r := range c.Resources { delete(keys, r.Id()) + + // If there is only one of this instance, then we alias that + // to the ".0" version as well so that it can count + if r.Count == 1 { + delete(keys, r.Id()+".0") + } } result := make([]string, 0, len(keys)) diff --git a/terraform/terraform_test.go b/terraform/terraform_test.go index 7183b20c7..84c360e16 100644 --- a/terraform/terraform_test.go +++ b/terraform/terraform_test.go @@ -182,6 +182,27 @@ STATE: ` +const testTerraformPlanCountDecreaseStr = ` +DIFF: + +UPDATE: aws_instance.bar + foo: "" => "bar" + type: "" => "aws_instance" +DESTROY: aws_instance.foo.1 +DESTROY: aws_instance.foo.2 + +STATE: + +aws_instance.foo.0: + ID = bar + foo = foo + type = aws_instance +aws_instance.foo.1: + ID = bar +aws_instance.foo.2: + ID = bar +` + const testTerraformPlanDestroyStr = ` DIFF: diff --git a/terraform/test-fixtures/plan-count-dec/main.tf b/terraform/test-fixtures/plan-count-dec/main.tf new file mode 100644 index 000000000..e4cba316c --- /dev/null +++ b/terraform/test-fixtures/plan-count-dec/main.tf @@ -0,0 +1,7 @@ +resource "aws_instance" "foo" { + foo = "foo" +} + +resource "aws_instance" "bar" { + foo = "bar" +}