more nil/known checks before val.LengthInt

This commit is contained in:
James Bardin 2018-10-19 16:51:15 -04:00
parent d50a152f8b
commit e93d69f18b
3 changed files with 30 additions and 14 deletions

View File

@ -856,7 +856,7 @@ func ctyGetAttrMaybeNull(val cty.Value, name string) cty.Value {
}
func ctyCollectionValues(val cty.Value) []cty.Value {
if !val.IsKnown() {
if !val.IsKnown() || val.IsNull() {
return 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.IsKnown() && plannedV.LengthInt() == 1 {
if plannedV.IsKnown() && !plannedV.IsNull() && plannedV.LengthInt() == 1 {
elemVs := plannedV.AsValueSlice()
if allLeafValuesUnknown(elemVs[0]) {
return errs
@ -84,7 +84,7 @@ 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() {
if !plannedV.IsKnown() || plannedV.IsNull() || actualV.IsNull() {
continue
}
@ -129,7 +129,7 @@ func assertObjectCompatible(schema *configschema.Block, planned, actual cty.Valu
}
}
} else {
if !plannedV.IsKnown() {
if !plannedV.IsKnown() || plannedV.IsNull() || actualV.IsNull() {
continue
}
plannedL := plannedV.LengthInt()
@ -153,7 +153,7 @@ 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() {
if !plannedV.IsKnown() || plannedV.IsNull() || actualV.IsNull() {
continue
}
plannedL := plannedV.LengthInt()
@ -251,7 +251,7 @@ 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.
if planned.IsKnown() {
if planned.IsKnown() && !planned.IsNull() && !actual.IsNull() {
plannedL := planned.LengthInt()
actualL := actual.LengthInt()
if plannedL < actualL {

View File

@ -92,8 +92,12 @@ func ProposedNewObject(schema *configschema.Block, prior, config cty.Value) cty.
case configschema.NestingList:
// Nested blocks are correlated by index.
if l := configV.LengthInt(); l > 0 {
newVals := make([]cty.Value, 0, l)
configVLen := 0
if configV.IsKnown() && !configV.IsNull() {
configVLen = configV.LengthInt()
}
if configVLen > 0 {
newVals := make([]cty.Value, 0, configVLen)
for it := configV.ElementIterator(); it.Next(); {
idx, configEV := it.Element()
if priorV.IsKnown() && (priorV.IsNull() || !priorV.HasIndex(idx).True()) {
@ -130,8 +134,12 @@ func ProposedNewObject(schema *configschema.Block, prior, config cty.Value) cty.
// dynamically-typed attributes.
if configV.Type().IsObjectType() {
// Nested blocks are correlated by key.
if l := configV.LengthInt(); l > 0 {
newVals := make(map[string]cty.Value, l)
configVLen := 0
if configV.IsKnown() && !configV.IsNull() {
configVLen = configV.LengthInt()
}
if configVLen > 0 {
newVals := make(map[string]cty.Value, configVLen)
atys := configV.Type().AttributeTypes()
for name := range atys {
configEV := configV.GetAttr(name)
@ -154,8 +162,12 @@ func ProposedNewObject(schema *configschema.Block, prior, config cty.Value) cty.
newV = cty.EmptyObjectVal
}
} else {
if l := configV.LengthInt(); l > 0 {
newVals := make(map[string]cty.Value, l)
configVLen := 0
if configV.IsKnown() && !configV.IsNull() {
configVLen = configV.LengthInt()
}
if configVLen > 0 {
newVals := make(map[string]cty.Value, configVLen)
for it := configV.ElementIterator(); it.Next(); {
idx, configEV := it.Element()
k := idx.AsString()
@ -190,9 +202,13 @@ func ProposedNewObject(schema *configschema.Block, prior, config cty.Value) cty.
if priorV.IsKnown() && !priorV.IsNull() {
cmpVals = setElementCompareValues(&blockType.Block, priorV, false)
}
if l := configV.LengthInt(); l > 0 {
configVLen := 0
if configV.IsKnown() && !configV.IsNull() {
configVLen = configV.LengthInt()
}
if configVLen > 0 {
used := make([]bool, len(cmpVals)) // track used elements in case multiple have the same compare value
newVals := make([]cty.Value, 0, l)
newVals := make([]cty.Value, 0, configVLen)
for it := configV.ElementIterator(); it.Next(); {
_, configEV := it.Element()
var priorEV cty.Value