Merge pull request #19120 from hashicorp/jbardin/is-known

Check IsKnown where values may panic
This commit is contained in:
James Bardin 2018-10-18 20:06:44 -04:00 committed by GitHub
commit 9fe391cee7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 43 additions and 11 deletions

View File

@ -856,6 +856,10 @@ func ctyGetAttrMaybeNull(val cty.Value, name string) cty.Value {
}
func ctyCollectionValues(val cty.Value) []cty.Value {
if !val.IsKnown() {
return nil
}
ret := make([]cty.Value, 0, val.LengthInt())
for it := val.ElementIterator(); it.Next(); {
_, value := it.Element()

View File

@ -58,6 +58,11 @@ var ElementFunc = function.New(&function.Spec{
// can't happen because we checked this in the Type function above
return cty.DynamicVal, fmt.Errorf("invalid index: %s", err)
}
if !args[0].IsKnown() {
return cty.UnknownVal(retType), nil
}
l := args[0].LengthInt()
if l == 0 {
return cty.DynamicVal, fmt.Errorf("cannot use element function with an empty list")
@ -251,6 +256,10 @@ var IndexFunc = function.New(&function.Spec{
return cty.NilVal, fmt.Errorf("argument must be a list or tuple")
}
if !args[0].IsKnown() {
return cty.UnknownVal(cty.Number), nil
}
if args[0].LengthInt() == 0 { // Easy path
return cty.NilVal, fmt.Errorf("cannot search an empty list")
}
@ -666,6 +675,9 @@ var MatchkeysFunc = function.New(&function.Spec{
return args[0].Type(), nil
},
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
if !args[0].IsKnown() {
return cty.UnknownVal(cty.List(retType.ElementType())), nil
}
if args[0].LengthInt() != args[1].LengthInt() {
return cty.ListValEmpty(retType.ElementType()), fmt.Errorf("length of keys and values should be equal")
@ -885,14 +897,14 @@ var ValuesFunc = function.New(&function.Spec{
Impl: func(args []cty.Value, retType cty.Type) (ret cty.Value, err error) {
mapVar := args[0]
if mapVar.LengthInt() == 0 {
return cty.ListValEmpty(retType.ElementType()), nil
}
if !mapVar.IsWhollyKnown() {
return cty.UnknownVal(retType), nil
}
if mapVar.LengthInt() == 0 {
return cty.ListValEmpty(retType.ElementType()), nil
}
keys, err := Keys(mapVar)
if err != nil {
return cty.NilVal, err
@ -941,7 +953,7 @@ var ZipmapFunc = function.New(&function.Spec{
keys := args[0]
values := args[1]
if keys.LengthInt() == 0 {
if !keys.IsKnown() || !values.IsKnown() || keys.LengthInt() == 0 {
return cty.Map(cty.DynamicPseudoType), nil
}
@ -955,7 +967,7 @@ var ZipmapFunc = function.New(&function.Spec{
keys := args[0]
values := args[1]
if keys.LengthInt() == 0 {
if !keys.IsKnown() || !values.IsKnown() || keys.LengthInt() == 0 {
return cty.MapValEmpty(cty.DynamicPseudoType), nil
}

View File

@ -64,7 +64,7 @@ func assertObjectCompatible(schema *configschema.Block, planned, actual cty.Valu
return errs
}
case configschema.NestingList, configschema.NestingMap, configschema.NestingSet:
if plannedV.LengthInt() == 1 {
if plannedV.IsKnown() && plannedV.LengthInt() == 1 {
elemVs := plannedV.AsValueSlice()
if allLeafValuesUnknown(elemVs[0]) {
return errs
@ -84,6 +84,10 @@ func assertObjectCompatible(schema *configschema.Block, planned, actual cty.Valu
// whether there are dynamically-typed attributes inside. However,
// both support a similar-enough API that we can treat them the
// same for our purposes here.
if !plannedV.IsKnown() {
continue
}
plannedL := plannedV.LengthInt()
actualL := actualV.LengthInt()
if plannedL != actualL {
@ -125,6 +129,9 @@ func assertObjectCompatible(schema *configschema.Block, planned, actual cty.Valu
}
}
} else {
if !plannedV.IsKnown() {
continue
}
plannedL := plannedV.LengthInt()
actualL := actualV.LengthInt()
if plannedL != actualL {
@ -146,6 +153,9 @@ func assertObjectCompatible(schema *configschema.Block, planned, actual cty.Valu
// content is also their key, and so we have no way to correlate
// them. Because of this, we simply verify that we still have the
// same number of elements.
if !plannedV.IsKnown() {
continue
}
plannedL := plannedV.LengthInt()
actualL := actualV.LengthInt()
if plannedL < actualL {
@ -241,10 +251,12 @@ func assertValueCompatible(planned, actual cty.Value, path cty.Path) []error {
// so we can't correlate them properly. However, we will at least check
// to ensure that the number of elements is consistent, along with
// the general type-match checks we ran earlier in this function.
plannedL := planned.LengthInt()
actualL := actual.LengthInt()
if plannedL < actualL {
errs = append(errs, path.NewErrorf("length changed from %d to %d", plannedL, actualL))
if planned.IsKnown() {
plannedL := planned.LengthInt()
actualL := actual.LengthInt()
if plannedL < actualL {
errs = append(errs, path.NewErrorf("length changed from %d to %d", plannedL, actualL))
}
}
}

View File

@ -276,6 +276,10 @@ func newResourceConfigShimmedComputedKeys(obj cty.Value, schema *configschema.Bl
}
blockVal := obj.GetAttr(typeName)
if !blockVal.IsKnown() {
continue
}
switch blockS.Nesting {
case configschema.NestingSingle:
keys := newResourceConfigShimmedComputedKeys(blockVal, &blockS.Block, fmt.Sprintf("%s%s.", prefix, typeName))