Merge pull request #22530 from hashicorp/jbardin/validations

MinItems and MaxItems validations
This commit is contained in:
James Bardin 2019-08-20 11:20:31 -04:00 committed by GitHub
commit 9f5fa2acf6
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 10 additions and 20 deletions

View File

@ -8,9 +8,7 @@ import (
) )
// CoerceValue attempts to force the given value to conform to the type // CoerceValue attempts to force the given value to conform to the type
// implied by the receiever, while also applying the same validation and // implied by the receiever.
// transformation rules that would be applied by the decoder specification
// returned by method DecoderSpec.
// //
// This is useful in situations where a configuration must be derived from // This is useful in situations where a configuration must be derived from
// an already-decoded value. It is always better to decode directly from // an already-decoded value. It is always better to decode directly from
@ -83,16 +81,8 @@ func (b *Block) coerceValue(in cty.Value, path cty.Path) (cty.Value, error) {
if err != nil { if err != nil {
return cty.UnknownVal(b.ImpliedType()), err return cty.UnknownVal(b.ImpliedType()), err
} }
case blockS.MinItems != 1 && blockS.MaxItems != 1:
if blockS.Nesting == NestingGroup {
attrs[typeName] = blockS.EmptyValue()
} else {
attrs[typeName] = cty.NullVal(blockS.ImpliedType())
}
default: default:
// We use the word "attribute" here because we're talking about attrs[typeName] = blockS.EmptyValue()
// the cty sense of that word rather than the HCL sense.
return cty.UnknownVal(b.ImpliedType()), path.NewErrorf("attribute %q is required", typeName)
} }
case NestingList: case NestingList:

View File

@ -288,8 +288,10 @@ func TestCoerceValue(t *testing.T) {
}, },
}, },
cty.EmptyObjectVal, cty.EmptyObjectVal,
cty.DynamicVal, cty.ObjectVal(map[string]cty.Value{
`attribute "foo" is required`, "foo": cty.NullVal(cty.EmptyObject),
}),
``,
}, },
"unknown nested list": { "unknown nested list": {
&Block{ &Block{

View File

@ -35,7 +35,8 @@ func (b *Block) DecoderSpec() hcldec.Spec {
// We can only validate 0 or 1 for MinItems, because a dynamic block // We can only validate 0 or 1 for MinItems, because a dynamic block
// may satisfy any number of min items while only having a single // may satisfy any number of min items while only having a single
// block in the config. // block in the config. We cannot validate MaxItems because a
// configuration may have any number of dynamic blocks
minItems := 0 minItems := 0
if blockS.MinItems > 1 { if blockS.MinItems > 1 {
minItems = 1 minItems = 1
@ -46,7 +47,7 @@ func (b *Block) DecoderSpec() hcldec.Spec {
ret[name] = &hcldec.BlockSpec{ ret[name] = &hcldec.BlockSpec{
TypeName: name, TypeName: name,
Nested: childSpec, Nested: childSpec,
Required: blockS.MinItems == 1 && blockS.MaxItems >= 1, Required: blockS.MinItems == 1,
} }
if blockS.Nesting == NestingGroup { if blockS.Nesting == NestingGroup {
ret[name] = &hcldec.DefaultSpec{ ret[name] = &hcldec.DefaultSpec{
@ -66,14 +67,12 @@ func (b *Block) DecoderSpec() hcldec.Spec {
TypeName: name, TypeName: name,
Nested: childSpec, Nested: childSpec,
MinItems: minItems, MinItems: minItems,
MaxItems: blockS.MaxItems,
} }
} else { } else {
ret[name] = &hcldec.BlockListSpec{ ret[name] = &hcldec.BlockListSpec{
TypeName: name, TypeName: name,
Nested: childSpec, Nested: childSpec,
MinItems: minItems, MinItems: minItems,
MaxItems: blockS.MaxItems,
} }
} }
case NestingSet: case NestingSet:
@ -86,7 +85,6 @@ func (b *Block) DecoderSpec() hcldec.Spec {
TypeName: name, TypeName: name,
Nested: childSpec, Nested: childSpec,
MinItems: minItems, MinItems: minItems,
MaxItems: blockS.MaxItems,
} }
case NestingMap: case NestingMap:
// We prefer to use a list where possible, since it makes our // We prefer to use a list where possible, since it makes our

View File

@ -354,7 +354,7 @@ func TestBlockDecoderSpec(t *testing.T) {
cty.EmptyObjectVal, cty.EmptyObjectVal,
}), }),
}), }),
1, // too many "foo" blocks 0, // max items cannot be validated during decode
}, },
// dynamic blocks may fulfill MinItems, but there is only one block to // dynamic blocks may fulfill MinItems, but there is only one block to
// decode. // decode.