catch invalidly planned attributes earlier

Catch attributes which are planed but not computed separately to provide
a clearer error to provider developers.

The error conditions were previously caught, however it was unclear from
the error text as to _why_ the change was an error. The statements about
value inequality would be incorrect when planning no changes for a value
which should not have been set in the first place.
This commit is contained in:
James Bardin 2021-02-24 12:13:12 -05:00
parent 21d881d4d1
commit cd7fb9bd5a
2 changed files with 21 additions and 6 deletions

View File

@ -255,12 +255,25 @@ func assertPlannedValueValid(attrS *configschema.Attribute, priorV, configV, pla
// the configuration value in favor of the prior. // the configuration value in favor of the prior.
return errs return errs
} }
if attrS.Computed && configV.IsNull() {
// The provider is allowed to change the value of any computed // the provider is allowed to insert values when the config is
// attribute that isn't explicitly set in the config. // null, but only if the attribute is computed.
if configV.IsNull() {
if attrS.Computed {
return errs return errs
} }
// if the attribute is not computed, then any planned value is incorrect
if !plannedV.IsNull() {
if attrS.Sensitive {
errs = append(errs, path.NewErrorf("sensitive planned value for a non-computed attribute"))
} else {
errs = append(errs, path.NewErrorf("planned value %#v for a non-computed attribute", plannedV))
}
return errs
}
}
// If this attribute has a NestedType, validate the nested object // If this attribute has a NestedType, validate the nested object
if attrS.NestedType != nil { if attrS.NestedType != nil {
return assertPlannedObjectValid(attrS.NestedType, priorV, configV, plannedV, path) return assertPlannedObjectValid(attrS.NestedType, priorV, configV, plannedV, path)
@ -276,11 +289,13 @@ func assertPlannedValueValid(attrS *configschema.Attribute, priorV, configV, pla
} }
return errs return errs
} }
if attrS.Sensitive { if attrS.Sensitive {
errs = append(errs, path.NewErrorf("sensitive planned value does not match config value nor prior value")) errs = append(errs, path.NewErrorf("sensitive planned value does not match config value nor prior value"))
} else { } else {
errs = append(errs, path.NewErrorf("planned value %#v does not match config value %#v nor prior value %#v", plannedV, configV, priorV)) errs = append(errs, path.NewErrorf("planned value %#v does not match config value %#v nor prior value %#v", plannedV, configV, priorV))
} }
return errs return errs
} }

View File

@ -1077,7 +1077,7 @@ func TestAssertPlanValid(t *testing.T) {
}), }),
}), }),
}), }),
[]string{".bloop: planned for existence but config wants absense"}, []string{`.bloop: planned value cty.ListVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{"blop":cty.StringVal("ok")})}) for a non-computed attribute`},
}, },
"NestedType nested set attribute to null": { "NestedType nested set attribute to null": {
&configschema.Block{ &configschema.Block{
@ -1116,7 +1116,7 @@ func TestAssertPlanValid(t *testing.T) {
}), }),
}), }),
}), }),
[]string{".bloop: planned for existence but config wants absense"}, []string{`.bloop: planned value cty.ListVal([]cty.Value{cty.ObjectVal(map[string]cty.Value{"blop":cty.StringVal("ok")})}) for a non-computed attribute`},
}, },
} }