diff --git a/plans/objchange/objchange.go b/plans/objchange/objchange.go index 6d88de97c..27ef709b0 100644 --- a/plans/objchange/objchange.go +++ b/plans/objchange/objchange.go @@ -357,13 +357,21 @@ func setElementCompareValue(schema *configschema.Block, v cty.Value, isConfig bo // set and we've not changed the types of any elements here. attrs[name] = cty.SetVal(elems) } else { - attrs[name] = cty.ListVal(elems) + if blockType.Block.ImpliedType().HasDynamicTypes() { + attrs[name] = cty.TupleVal(elems) + } else { + attrs[name] = cty.ListVal(elems) + } } } else { if blockType.Nesting == configschema.NestingSet { attrs[name] = cty.SetValEmpty(blockType.Block.ImpliedType()) } else { - attrs[name] = cty.ListValEmpty(blockType.Block.ImpliedType()) + if blockType.Block.ImpliedType().HasDynamicTypes() { + attrs[name] = cty.EmptyTupleVal + } else { + attrs[name] = cty.ListValEmpty(blockType.Block.ImpliedType()) + } } } @@ -378,7 +386,11 @@ func setElementCompareValue(schema *configschema.Block, v cty.Value, isConfig bo kv, ev := it.Element() elems[kv.AsString()] = setElementCompareValue(&blockType.Block, ev, isConfig) } - attrs[name] = cty.ObjectVal(elems) + if blockType.Block.ImpliedType().HasDynamicTypes() { + attrs[name] = cty.ObjectVal(elems) + } else { + attrs[name] = cty.MapVal(elems) + } default: // Should never happen, since the above cases are comprehensive. diff --git a/plans/objchange/objchange_test.go b/plans/objchange/objchange_test.go index 5106feb1f..d6352337b 100644 --- a/plans/objchange/objchange_test.go +++ b/plans/objchange/objchange_test.go @@ -440,7 +440,7 @@ func TestProposedNewObject(t *testing.T) { }), "b": cty.ObjectVal(map[string]cty.Value{ "bar": cty.StringVal("blep"), - "baz": cty.StringVal("boot"), + "baz": cty.ListVal([]cty.Value{cty.StringVal("boot")}), }), }), }), @@ -452,7 +452,7 @@ func TestProposedNewObject(t *testing.T) { }), "c": cty.ObjectVal(map[string]cty.Value{ "bar": cty.StringVal("bosh"), - "baz": cty.NullVal(cty.String), + "baz": cty.NullVal(cty.List(cty.String)), }), }), }), @@ -464,7 +464,7 @@ func TestProposedNewObject(t *testing.T) { }), "c": cty.ObjectVal(map[string]cty.Value{ "bar": cty.StringVal("bosh"), - "baz": cty.NullVal(cty.String), + "baz": cty.NullVal(cty.List(cty.String)), }), }), }), @@ -674,6 +674,131 @@ func TestProposedNewObject(t *testing.T) { }), }), }, + "nested list with dynamic in set": { + &configschema.Block{ + BlockTypes: map[string]*configschema.NestedBlock{ + "foo": { + Nesting: configschema.NestingSet, + Block: configschema.Block{ + BlockTypes: map[string]*configschema.NestedBlock{ + "bar": { + Nesting: configschema.NestingList, + Block: configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "baz": { + Type: cty.DynamicPseudoType, + }, + }, + }, + }, + }, + }, + }, + }, + }, + cty.ObjectVal(map[string]cty.Value{ + "foo": cty.SetVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "bar": cty.TupleVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "baz": cty.StringVal("true"), + }), + cty.ObjectVal(map[string]cty.Value{ + "baz": cty.ListVal([]cty.Value{cty.StringVal("true")}), + }), + }), + }), + }), + }), + cty.ObjectVal(map[string]cty.Value{ + "foo": cty.SetVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "bar": cty.TupleVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "baz": cty.StringVal("true"), + }), + cty.ObjectVal(map[string]cty.Value{ + "baz": cty.ListVal([]cty.Value{cty.StringVal("true")}), + }), + }), + }), + }), + }), + cty.ObjectVal(map[string]cty.Value{ + "foo": cty.SetVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "bar": cty.TupleVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "baz": cty.StringVal("true"), + }), + cty.ObjectVal(map[string]cty.Value{ + "baz": cty.ListVal([]cty.Value{cty.StringVal("true")}), + }), + }), + }), + }), + }), + }, + "nested map with dynamic in set": { + &configschema.Block{ + BlockTypes: map[string]*configschema.NestedBlock{ + "foo": { + Nesting: configschema.NestingSet, + Block: configschema.Block{ + BlockTypes: map[string]*configschema.NestedBlock{ + "bar": { + Nesting: configschema.NestingMap, + Block: configschema.Block{ + Attributes: map[string]*configschema.Attribute{ + "baz": { + Type: cty.DynamicPseudoType, + Optional: true, + }, + }, + }, + }, + }, + }, + }, + }, + }, + cty.ObjectVal(map[string]cty.Value{ + "foo": cty.SetVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "bar": cty.ObjectVal(map[string]cty.Value{ + "bing": cty.ObjectVal(map[string]cty.Value{ + "baz": cty.StringVal("true"), + }), + "bang": cty.ObjectVal(map[string]cty.Value{ + "baz": cty.ListVal([]cty.Value{cty.StringVal("true")}), + }), + }), + }), + }), + }), + cty.ObjectVal(map[string]cty.Value{ + "foo": cty.SetVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "bar": cty.ObjectVal(map[string]cty.Value{ + "bing": cty.ObjectVal(map[string]cty.Value{ + "baz": cty.ListVal([]cty.Value{cty.StringVal("true")}), + }), + }), + }), + }), + }), + cty.ObjectVal(map[string]cty.Value{ + "foo": cty.SetVal([]cty.Value{ + cty.ObjectVal(map[string]cty.Value{ + "bar": cty.ObjectVal(map[string]cty.Value{ + "bing": cty.ObjectVal(map[string]cty.Value{ + "baz": cty.ListVal([]cty.Value{cty.StringVal("true")}), + }), + }), + }), + }), + }), + }, } for name, test := range tests {