From e77a0741211aa2e96cb1c5a045085b27900990d9 Mon Sep 17 00:00:00 2001 From: Liam Cervante Date: Wed, 19 Oct 2022 09:40:43 +0200 Subject: [PATCH 1/2] Make sure to remove optional attributes in all cases --- cty/convert/conversion_collection.go | 15 ++++ cty/convert/public.go | 2 +- cty/convert/public_test.go | 125 +++++++++++++++++++++++++++ 3 files changed, 141 insertions(+), 1 deletion(-) diff --git a/cty/convert/conversion_collection.go b/cty/convert/conversion_collection.go index c21f4183..12465a2c 100644 --- a/cty/convert/conversion_collection.go +++ b/cty/convert/conversion_collection.go @@ -39,6 +39,11 @@ func conversionCollectionToList(ety cty.Type, conv conversion) conversion { return cty.NilVal, err } } + + if val.IsNull() { + val = cty.NullVal(val.Type().WithoutOptionalAttributesDeep()) + } + elems = append(elems, val) i++ @@ -88,6 +93,11 @@ func conversionCollectionToSet(ety cty.Type, conv conversion) conversion { return cty.NilVal, err } } + + if val.IsNull() { + val = cty.NullVal(val.Type().WithoutOptionalAttributesDeep()) + } + elems = append(elems, val) i++ @@ -242,6 +252,11 @@ func conversionTupleToSet(tupleType cty.Type, setEty cty.Type, unsafe bool) conv return cty.NilVal, err } } + + if val.IsNull() { + val = cty.NullVal(val.Type().WithoutOptionalAttributesDeep()) + } + elems = append(elems, val) i++ diff --git a/cty/convert/public.go b/cty/convert/public.go index af19bdc5..aab0d0ec 100644 --- a/cty/convert/public.go +++ b/cty/convert/public.go @@ -40,7 +40,7 @@ func GetConversionUnsafe(in cty.Type, out cty.Type) Conversion { // This is a convenience wrapper around calling GetConversionUnsafe and then // immediately passing the given value to the resulting function. func Convert(in cty.Value, want cty.Type) (cty.Value, error) { - if in.Type().Equals(want) { + if in.Type().Equals(want.WithoutOptionalAttributesDeep()) { return in, nil } diff --git a/cty/convert/public_test.go b/cty/convert/public_test.go index d7ed9edb..aab2abaf 100644 --- a/cty/convert/public_test.go +++ b/cty/convert/public_test.go @@ -1099,6 +1099,131 @@ func TestConvert(t *testing.T) { ), WantError: false, }, + // We should strip optional attributes out of null values in sets, maps, + // lists and tuples. + { + Value: cty.ListVal([]cty.Value{ + cty.NullVal(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + }), + Type: cty.Set(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.SetVal([]cty.Value{ + cty.NullVal(cty.Object(map[string]cty.Type{ + "a": cty.String, + })), + }), + }, + { + Value: cty.TupleVal([]cty.Value{ + cty.NullVal(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + }), + Type: cty.Set(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.SetVal([]cty.Value{ + cty.NullVal(cty.Object(map[string]cty.Type{ + "a": cty.String, + })), + }), + }, + { + Value: cty.SetVal([]cty.Value{ + cty.NullVal(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + }), + Type: cty.List(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.ListVal([]cty.Value{ + cty.NullVal(cty.Object(map[string]cty.Type{ + "a": cty.String, + })), + }), + }, + { + Value: cty.TupleVal([]cty.Value{ + cty.NullVal(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + }), + Type: cty.List(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.ListVal([]cty.Value{ + cty.NullVal(cty.Object(map[string]cty.Type{ + "a": cty.String, + })), + }), + }, + { + Value: cty.ObjectVal(map[string]cty.Value{ + "object": cty.NullVal(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + }), + Type: cty.Map(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.MapVal(map[string]cty.Value{ + "object": cty.NullVal(cty.Object(map[string]cty.Type{ + "a": cty.String, + })), + }), + }, + { + Value: cty.MapVal(map[string]cty.Value{ + "object": cty.NullVal(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.Number, + }, []string{"a"})), + }), + Type: cty.Map(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.MapVal(map[string]cty.Value{ + "object": cty.NullVal(cty.Object(map[string]cty.Type{ + "a": cty.String, + })), + }), + }, + { + Value: cty.TupleVal([]cty.Value{ + cty.NullVal(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.Number, + }, []string{"a"})), + }), + Type: cty.Tuple([]cty.Type{ + cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"}), + }), + Want: cty.TupleVal([]cty.Value{ + cty.NullVal(cty.Object(map[string]cty.Type{ + "a": cty.String, + })), + }), + }, + // We should strip optional attributes out of types even if they match. + { + Value: cty.MapVal(map[string]cty.Value{ + "object": cty.NullVal(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + }), + Type: cty.Map(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + Want: cty.MapVal(map[string]cty.Value{ + "object": cty.NullVal(cty.Object(map[string]cty.Type{ + "a": cty.String, + })), + }), + }, } for _, test := range tests { From 4e19ce84a5d6d8511cbd3fec1f34cb895a48dadb Mon Sep 17 00:00:00 2001 From: Liam Cervante Date: Wed, 19 Oct 2022 09:44:42 +0200 Subject: [PATCH 2/2] also check map to object --- cty/convert/conversion_collection.go | 4 ++++ cty/convert/public_test.go | 17 +++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/cty/convert/conversion_collection.go b/cty/convert/conversion_collection.go index 12465a2c..0101712c 100644 --- a/cty/convert/conversion_collection.go +++ b/cty/convert/conversion_collection.go @@ -497,6 +497,10 @@ func conversionMapToObject(mapType cty.Type, objType cty.Type, unsafe bool) conv } } + if val.IsNull() { + val = cty.NullVal(val.Type().WithoutOptionalAttributesDeep()) + } + elems[name.AsString()] = val } diff --git a/cty/convert/public_test.go b/cty/convert/public_test.go index aab2abaf..725d6333 100644 --- a/cty/convert/public_test.go +++ b/cty/convert/public_test.go @@ -1176,6 +1176,23 @@ func TestConvert(t *testing.T) { })), }), }, + { + Value: cty.MapVal(map[string]cty.Value{ + "object": cty.NullVal(cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"})), + }), + Type: cty.Object(map[string]cty.Type{ + "object": cty.ObjectWithOptionalAttrs(map[string]cty.Type{ + "a": cty.String, + }, []string{"a"}), + }), + Want: cty.ObjectVal(map[string]cty.Value{ + "object": cty.NullVal(cty.Object(map[string]cty.Type{ + "a": cty.String, + })), + }), + }, { Value: cty.MapVal(map[string]cty.Value{ "object": cty.NullVal(cty.ObjectWithOptionalAttrs(map[string]cty.Type{