Unknown set blocks with dynamic may have 0 elems

The couldHaveUnknownBlockPlaceholder helper was added to detect when a
set block has a placeholder for an unknown number of values. This worked
fine when the number increased from 1, but we were still attempting to
validate the unknown placeholder against the empty set when the final
count turned out to be 0.

Since we can't differentiate the unknown dynamic placeholder value from
an actual set value, we have to skip that object's validation
altogether.
This commit is contained in:
James Bardin 2020-07-23 15:32:23 -04:00
parent 5734a0c014
commit 2b4101fdff
2 changed files with 59 additions and 6 deletions

View File

@ -168,12 +168,6 @@ func assertObjectCompatible(schema *configschema.Block, planned, actual cty.Valu
continue
}
setErrs := assertSetValuesCompatible(plannedV, actualV, path, func(plannedEV, actualEV cty.Value) bool {
errs := assertObjectCompatible(&blockS.Block, plannedEV, actualEV, append(path, cty.IndexStep{Key: actualEV}))
return len(errs) == 0
})
errs = append(errs, setErrs...)
if maybeUnknownBlocks {
// When unknown blocks are present the final number of blocks
// may be different, either because the unknown set values
@ -184,6 +178,12 @@ func assertObjectCompatible(schema *configschema.Block, planned, actual cty.Valu
continue
}
setErrs := assertSetValuesCompatible(plannedV, actualV, path, func(plannedEV, actualEV cty.Value) bool {
errs := assertObjectCompatible(&blockS.Block, plannedEV, actualEV, append(path, cty.IndexStep{Key: actualEV}))
return len(errs) == 0
})
errs = append(errs, setErrs...)
// There can be fewer elements in a set after its elements are all
// known (values that turn out to be equal will coalesce) but the
// number of elements must never get larger.

View File

@ -1163,6 +1163,59 @@ func TestAssertObjectCompatible(t *testing.T) {
}),
nil,
},
// test a set with an unknown dynamic count going to 0 values
{
&configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{
"block2": {
Nesting: configschema.NestingSet,
Block: schemaWithFoo,
},
},
},
cty.ObjectVal(map[string]cty.Value{
"block2": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"foo": cty.UnknownVal(cty.String),
}),
}),
}),
cty.ObjectVal(map[string]cty.Value{
"block2": cty.SetValEmpty(cty.Object(map[string]cty.Type{
"foo": cty.String,
})),
}),
nil,
},
// test a set with a patially known dynamic count reducing it's values
{
&configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{
"block3": {
Nesting: configschema.NestingSet,
Block: schemaWithFoo,
},
},
},
cty.ObjectVal(map[string]cty.Value{
"block3": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"foo": cty.StringVal("a"),
}),
cty.ObjectVal(map[string]cty.Value{
"foo": cty.UnknownVal(cty.String),
}),
}),
}),
cty.ObjectVal(map[string]cty.Value{
"block3": cty.SetVal([]cty.Value{
cty.ObjectVal(map[string]cty.Value{
"foo": cty.StringVal("a"),
}),
}),
}),
nil,
},
{
&configschema.Block{
BlockTypes: map[string]*configschema.NestedBlock{