core: Generate "provider bug" warnings only if no errors from provider

We can be more relaxed about our rules that a create musn't return null
or a destroy must return null if the provider also itself indicated an
error. In that case, it's expected that the return value is describing a
partial result, and so we'll just store it and move on.
This commit is contained in:
Martin Atkins 2018-09-14 15:51:17 -07:00
parent f63bba78c9
commit 31c412b44d
1 changed files with 25 additions and 23 deletions

View File

@ -158,25 +158,27 @@ func (n *EvalApply) Eval(ctx EvalContext) (interface{}, error) {
// we still want to save that but it often causes some confusing behaviors
// where it seems like Terraform is failing to take any action at all,
// so we'll generate some errors to draw attention to it.
if change.Action == plans.Delete && !newVal.IsNull() {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Provider returned invalid result object after apply",
fmt.Sprintf(
"After applying a %s plan, the provider returned a non-null object for %s. Destroying should always produce a null value, so this is always a bug in the provider and should be reported in the provider's own repository. Terraform will still save this errant object in the state for debugging and recovery.",
change.Action, n.Addr.Absolute(ctx.Path()),
),
))
}
if change.Action != plans.Delete && newVal.IsNull() {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Provider returned invalid result object after apply",
fmt.Sprintf(
"After applying a %s plan, the provider returned a null object for %s. Only destroying should always produce a null value, so this is always a bug in the provider and should be reported in the provider's own repository.",
change.Action, n.Addr.Absolute(ctx.Path()),
),
))
if !applyDiags.HasErrors() {
if change.Action == plans.Delete && !newVal.IsNull() {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Provider returned invalid result object after apply",
fmt.Sprintf(
"After applying a %s plan, the provider returned a non-null object for %s. Destroying should always produce a null value, so this is always a bug in the provider and should be reported in the provider's own repository. Terraform will still save this errant object in the state for debugging and recovery.",
change.Action, n.Addr.Absolute(ctx.Path()),
),
))
}
if change.Action != plans.Delete && newVal.IsNull() {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
"Provider returned invalid result object after apply",
fmt.Sprintf(
"After applying a %s plan, the provider returned a null object for %s. Only destroying should always produce a null value, so this is always a bug in the provider and should be reported in the provider's own repository.",
change.Action, n.Addr.Absolute(ctx.Path()),
),
))
}
}
var newState *states.ResourceInstanceObject
@ -239,10 +241,10 @@ func (n *EvalApplyPre) Eval(ctx EvalContext) (interface{}, error) {
// EvalApplyPost is an EvalNode implementation that does the post-Apply work
type EvalApplyPost struct {
Addr addrs.ResourceInstance
Gen states.Generation
State **states.ResourceInstanceObject
Error *error
Addr addrs.ResourceInstance
Gen states.Generation
State **states.ResourceInstanceObject
Error *error
}
// TODO: test