From 6fee1f24abc87ff2f386676429a2fe3cecea75d7 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 8 Nov 2018 18:01:39 -0500 Subject: [PATCH] don't add duplicate unknowns to a set The flatmap shim was lazily adding duplicate items and letting cty.Set clear them out, but if those duplicates contains unknown values they can't be checked for equality and will end up remaining in the set. --- config/hcl2shim/flatmap.go | 12 +++++++++ config/hcl2shim/flatmap_test.go | 44 +++++++++++++++++++++++++++++++++ 2 files changed, 56 insertions(+) diff --git a/config/hcl2shim/flatmap.go b/config/hcl2shim/flatmap.go index 2f7954d76..bcecb30df 100644 --- a/config/hcl2shim/flatmap.go +++ b/config/hcl2shim/flatmap.go @@ -356,6 +356,11 @@ func hcl2ValueFromFlatmapSet(m map[string]string, prefix string, ty cty.Type) (c return cty.UnknownVal(ty), nil } + // Keep track of keys we've seen, se we don't add the same set value + // multiple times. The cty.Set will normally de-duplicate values, but we may + // have unknown values that would not show as equivalent. + seen := map[string]bool{} + for fullKey := range m { if !strings.HasPrefix(fullKey, prefix) { continue @@ -370,6 +375,12 @@ func hcl2ValueFromFlatmapSet(m map[string]string, prefix string, ty cty.Type) (c key = fullKey[:dot+len(prefix)] } + if seen[key] { + continue + } + + seen[key] = true + // The flatmap format doesn't allow us to distinguish between keys // that contain periods and nested objects, so by convention a // map is only ever of primitive type in flatmap, and we just assume @@ -386,5 +397,6 @@ func hcl2ValueFromFlatmapSet(m map[string]string, prefix string, ty cty.Type) (c if len(vals) == 0 { return cty.SetValEmpty(ety), nil } + return cty.SetVal(vals), nil } diff --git a/config/hcl2shim/flatmap_test.go b/config/hcl2shim/flatmap_test.go index 56c06c3dc..07f93ac26 100644 --- a/config/hcl2shim/flatmap_test.go +++ b/config/hcl2shim/flatmap_test.go @@ -635,6 +635,50 @@ func TestHCL2ValueFromFlatmap(t *testing.T) { }), }), }, + { + Flatmap: map[string]string{ + "single.#": "1", + "single.~1.value": "a", + "single.~1.optional": UnknownVariableValue, + "two.#": "2", + "two.~2381914684.value": "a", + "two.~2381914684.optional": UnknownVariableValue, + "two.~2798940671.value": "b", + "two.~2798940671.optional": UnknownVariableValue, + }, + Type: cty.Object(map[string]cty.Type{ + "single": cty.Set( + cty.Object(map[string]cty.Type{ + "value": cty.String, + "optional": cty.String, + }), + ), + "two": cty.Set( + cty.Object(map[string]cty.Type{ + "optional": cty.String, + "value": cty.String, + }), + ), + }), + Want: cty.ObjectVal(map[string]cty.Value{ + "single": cty.SetVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "value": cty.StringVal("a"), + "optional": cty.UnknownVal(cty.String), + }), + }), + "two": cty.SetVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "value": cty.StringVal("a"), + "optional": cty.UnknownVal(cty.String), + }), + cty.ObjectVal(map[string]cty.Value{ + "value": cty.StringVal("b"), + "optional": cty.UnknownVal(cty.String), + }), + }), + }), + }, } for _, test := range tests {