Merge pull request #26606 from hashicorp/jbardin/proposed-set-comparison
More precise handling of lists and maps within sets for ProposedNewObject
This commit is contained in:
commit
98dc399062
|
@ -333,8 +333,9 @@ func setElementCompareValue(schema *configschema.Block, v cty.Value, isConfig bo
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, blockType := range schema.BlockTypes {
|
for name, blockType := range schema.BlockTypes {
|
||||||
switch blockType.Nesting {
|
elementType := blockType.Block.ImpliedType()
|
||||||
|
|
||||||
|
switch blockType.Nesting {
|
||||||
case configschema.NestingSingle, configschema.NestingGroup:
|
case configschema.NestingSingle, configschema.NestingGroup:
|
||||||
attrs[name] = setElementCompareValue(&blockType.Block, v.GetAttr(name), isConfig)
|
attrs[name] = setElementCompareValue(&blockType.Block, v.GetAttr(name), isConfig)
|
||||||
|
|
||||||
|
@ -344,32 +345,44 @@ func setElementCompareValue(schema *configschema.Block, v cty.Value, isConfig bo
|
||||||
attrs[name] = cv
|
attrs[name] = cv
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
|
||||||
if l := cv.LengthInt(); l > 0 {
|
if l := cv.LengthInt(); l > 0 {
|
||||||
elems := make([]cty.Value, 0, l)
|
elems := make([]cty.Value, 0, l)
|
||||||
for it := cv.ElementIterator(); it.Next(); {
|
for it := cv.ElementIterator(); it.Next(); {
|
||||||
_, ev := it.Element()
|
_, ev := it.Element()
|
||||||
elems = append(elems, setElementCompareValue(&blockType.Block, ev, isConfig))
|
elems = append(elems, setElementCompareValue(&blockType.Block, ev, isConfig))
|
||||||
}
|
}
|
||||||
if blockType.Nesting == configschema.NestingSet {
|
|
||||||
|
switch {
|
||||||
|
case blockType.Nesting == configschema.NestingSet:
|
||||||
// SetValEmpty would panic if given elements that are not
|
// SetValEmpty would panic if given elements that are not
|
||||||
// all of the same type, but that's guaranteed not to
|
// all of the same type, but that's guaranteed not to
|
||||||
// happen here because our input value was _already_ a
|
// happen here because our input value was _already_ a
|
||||||
// set and we've not changed the types of any elements here.
|
// set and we've not changed the types of any elements here.
|
||||||
attrs[name] = cty.SetVal(elems)
|
attrs[name] = cty.SetVal(elems)
|
||||||
} else {
|
|
||||||
|
// NestingList cases
|
||||||
|
case elementType.HasDynamicTypes():
|
||||||
attrs[name] = cty.TupleVal(elems)
|
attrs[name] = cty.TupleVal(elems)
|
||||||
|
default:
|
||||||
|
attrs[name] = cty.ListVal(elems)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if blockType.Nesting == configschema.NestingSet {
|
switch {
|
||||||
attrs[name] = cty.SetValEmpty(blockType.Block.ImpliedType())
|
case blockType.Nesting == configschema.NestingSet:
|
||||||
} else {
|
attrs[name] = cty.SetValEmpty(elementType)
|
||||||
|
|
||||||
|
// NestingList cases
|
||||||
|
case elementType.HasDynamicTypes():
|
||||||
attrs[name] = cty.EmptyTupleVal
|
attrs[name] = cty.EmptyTupleVal
|
||||||
|
default:
|
||||||
|
attrs[name] = cty.ListValEmpty(elementType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
case configschema.NestingMap:
|
case configschema.NestingMap:
|
||||||
cv := v.GetAttr(name)
|
cv := v.GetAttr(name)
|
||||||
if cv.IsNull() || !cv.IsKnown() {
|
if cv.IsNull() || !cv.IsKnown() || cv.LengthInt() == 0 {
|
||||||
attrs[name] = cv
|
attrs[name] = cv
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -378,7 +391,13 @@ func setElementCompareValue(schema *configschema.Block, v cty.Value, isConfig bo
|
||||||
kv, ev := it.Element()
|
kv, ev := it.Element()
|
||||||
elems[kv.AsString()] = setElementCompareValue(&blockType.Block, ev, isConfig)
|
elems[kv.AsString()] = setElementCompareValue(&blockType.Block, ev, isConfig)
|
||||||
}
|
}
|
||||||
attrs[name] = cty.ObjectVal(elems)
|
|
||||||
|
switch {
|
||||||
|
case elementType.HasDynamicTypes():
|
||||||
|
attrs[name] = cty.ObjectVal(elems)
|
||||||
|
default:
|
||||||
|
attrs[name] = cty.MapVal(elems)
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
// Should never happen, since the above cases are comprehensive.
|
// Should never happen, since the above cases are comprehensive.
|
||||||
|
|
|
@ -440,7 +440,7 @@ func TestProposedNewObject(t *testing.T) {
|
||||||
}),
|
}),
|
||||||
"b": cty.ObjectVal(map[string]cty.Value{
|
"b": cty.ObjectVal(map[string]cty.Value{
|
||||||
"bar": cty.StringVal("blep"),
|
"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{
|
"c": cty.ObjectVal(map[string]cty.Value{
|
||||||
"bar": cty.StringVal("bosh"),
|
"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{
|
"c": cty.ObjectVal(map[string]cty.Value{
|
||||||
"bar": cty.StringVal("bosh"),
|
"bar": cty.StringVal("bosh"),
|
||||||
"baz": cty.NullVal(cty.String),
|
"baz": cty.NullVal(cty.List(cty.String)),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
@ -572,6 +572,288 @@ func TestProposedNewObject(t *testing.T) {
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
},
|
},
|
||||||
|
"nested list 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.String,
|
||||||
|
},
|
||||||
|
"qux": {
|
||||||
|
Type: cty.String,
|
||||||
|
Computed: true,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": cty.SetVal([]cty.Value{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"bar": cty.ListVal([]cty.Value{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"baz": cty.StringVal("beep"),
|
||||||
|
"qux": cty.StringVal("boop"),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": cty.SetVal([]cty.Value{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"bar": cty.ListVal([]cty.Value{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"baz": cty.StringVal("beep"),
|
||||||
|
"qux": cty.NullVal(cty.String),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": cty.SetVal([]cty.Value{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"bar": cty.ListVal([]cty.Value{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"baz": cty.StringVal("beep"),
|
||||||
|
"qux": cty.StringVal("boop"),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
"empty nested list 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{},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": cty.SetVal([]cty.Value{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"bar": cty.ListValEmpty((&configschema.Block{}).ImpliedType()),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": cty.SetVal([]cty.Value{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"bar": cty.ListValEmpty((&configschema.Block{}).ImpliedType()),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": cty.SetVal([]cty.Value{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"bar": cty.ListValEmpty((&configschema.Block{}).ImpliedType()),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
"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")}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
"empty nested map 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.String,
|
||||||
|
Optional: true,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": cty.SetVal([]cty.Value{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"bar": cty.MapValEmpty(cty.Object(map[string]cty.Type{
|
||||||
|
"baz": cty.String,
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": cty.SetVal([]cty.Value{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"bar": cty.MapVal(map[string]cty.Value{
|
||||||
|
"bing": cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"baz": cty.StringVal("true"),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"foo": cty.SetVal([]cty.Value{
|
||||||
|
cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"bar": cty.MapVal(map[string]cty.Value{
|
||||||
|
"bing": cty.ObjectVal(map[string]cty.Value{
|
||||||
|
"baz": cty.StringVal("true"),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
for name, test := range tests {
|
for name, test := range tests {
|
||||||
|
|
Loading…
Reference in New Issue