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 { func ctyCollectionValues(val cty.Value) []cty.Value {
if !val.IsKnown() { if !val.IsKnown() || val.IsNull() {
return nil return nil
} }

View File

@ -64,7 +64,7 @@ func assertObjectCompatible(schema *configschema.Block, planned, actual cty.Valu
return errs return errs
} }
case configschema.NestingList, configschema.NestingMap, configschema.NestingSet: case configschema.NestingList, configschema.NestingMap, configschema.NestingSet:
if plannedV.IsKnown() && plannedV.LengthInt() == 1 { if plannedV.IsKnown() && !plannedV.IsNull() && plannedV.LengthInt() == 1 {
elemVs := plannedV.AsValueSlice() elemVs := plannedV.AsValueSlice()
if allLeafValuesUnknown(elemVs[0]) { if allLeafValuesUnknown(elemVs[0]) {
return errs return errs
@ -84,7 +84,7 @@ func assertObjectCompatible(schema *configschema.Block, planned, actual cty.Valu
// whether there are dynamically-typed attributes inside. However, // whether there are dynamically-typed attributes inside. However,
// both support a similar-enough API that we can treat them the // both support a similar-enough API that we can treat them the
// same for our purposes here. // same for our purposes here.
if !plannedV.IsKnown() { if !plannedV.IsKnown() || plannedV.IsNull() || actualV.IsNull() {
continue continue
} }
@ -129,7 +129,7 @@ func assertObjectCompatible(schema *configschema.Block, planned, actual cty.Valu
} }
} }
} else { } else {
if !plannedV.IsKnown() { if !plannedV.IsKnown() || plannedV.IsNull() || actualV.IsNull() {
continue continue
} }
plannedL := plannedV.LengthInt() 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 // 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 // them. Because of this, we simply verify that we still have the
// same number of elements. // same number of elements.
if !plannedV.IsKnown() { if !plannedV.IsKnown() || plannedV.IsNull() || actualV.IsNull() {
continue continue
} }
plannedL := plannedV.LengthInt() 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 // so we can't correlate them properly. However, we will at least check
// to ensure that the number of elements is consistent, along with // to ensure that the number of elements is consistent, along with
// the general type-match checks we ran earlier in this function. // the general type-match checks we ran earlier in this function.
if planned.IsKnown() { if planned.IsKnown() && !planned.IsNull() && !actual.IsNull() {
plannedL := planned.LengthInt() plannedL := planned.LengthInt()
actualL := actual.LengthInt() actualL := actual.LengthInt()
if plannedL < actualL { if plannedL < actualL {

View File

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