Merge pull request #19120 from hashicorp/jbardin/is-known
Check IsKnown where values may panic
This commit is contained in:
commit
9fe391cee7
|
@ -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()
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -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))
|
||||
|
|
Loading…
Reference in New Issue