From 0e507e7e5e39f024a88831c1dcf18a3b884c4de2 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Mon, 20 Jun 2016 18:18:25 -0400 Subject: [PATCH] Remove computed maps from the diff Same check Just like computed sets, computed maps may have both different values and different cardinality after they're computed. Remove the computed maps and the values from the compared diffs. --- terraform/diff.go | 26 ++++++++++++++++---------- terraform/diff_test.go | 28 ++++++++++++++++++++++++++++ 2 files changed, 44 insertions(+), 10 deletions(-) diff --git a/terraform/diff.go b/terraform/diff.go index 5a99e0fac..d5008c6c8 100644 --- a/terraform/diff.go +++ b/terraform/diff.go @@ -471,12 +471,12 @@ func (d *InstanceDiff) Same(d2 *InstanceDiff) (bool, string) { } } - // This is a little tricky, but when a diff contains a computed list - // or set that can only be interpolated after the apply command has - // created the dependent resources, it could turn out that the result - // is actually the same as the existing state which would remove the - // key from the diff. - if diffOld.NewComputed && strings.HasSuffix(k, ".#") { + // This is a little tricky, but when a diff contains a computed + // list, set, or map that can only be interpolated after the apply + // command has created the dependent resources, it could turn out + // that the result is actually the same as the existing state which + // would remove the key from the diff. + if diffOld.NewComputed && (strings.HasSuffix(k, ".#") || strings.HasSuffix(k, ".%")) { ok = true } @@ -492,10 +492,16 @@ func (d *InstanceDiff) Same(d2 *InstanceDiff) (bool, string) { } } - if diffOld.NewComputed && strings.HasSuffix(k, ".#") { - // This is a computed list or set, so remove any keys with this - // prefix from the check list. - kprefix := k[:len(k)-1] + // search for the suffix of the base of a [computed] map, list or set. + multiVal := regexp.MustCompile(`\.(#|~#|%)$`) + match := multiVal.FindStringSubmatch(k) + + if diffOld.NewComputed && len(match) == 2 { + matchLen := len(match[1]) + + // This is a computed list, set, or map, so remove any keys with + // this prefix from the check list. + kprefix := k[:len(k)-matchLen] for k2, _ := range checkOld { if strings.HasPrefix(k2, kprefix) { delete(checkOld, k2) diff --git a/terraform/diff_test.go b/terraform/diff_test.go index f769737c5..bf1c1c9f2 100644 --- a/terraform/diff_test.go +++ b/terraform/diff_test.go @@ -566,6 +566,34 @@ func TestInstanceDiffSame(t *testing.T) { "", }, + // Computed values in maps will fail the "Same" check as well + { + &InstanceDiff{ + Attributes: map[string]*ResourceAttrDiff{ + "foo.%": &ResourceAttrDiff{ + Old: "", + New: "", + NewComputed: true, + }, + }, + }, + &InstanceDiff{ + Attributes: map[string]*ResourceAttrDiff{ + "foo.%": &ResourceAttrDiff{ + Old: "0", + New: "1", + NewComputed: false, + }, + "foo.val": &ResourceAttrDiff{ + Old: "", + New: "something", + }, + }, + }, + true, + "", + }, + // In a DESTROY/CREATE scenario, the plan diff will be run against the // state of the old instance, while the apply diff will be run against an // empty state (because the state is cleared when the destroy runs.)