make the diagnostics handling of apply easier

Now that we don't need to track separate error values for the apply
logic, it's easier to reorganize the diagnostic handling to use a single
set of diagnostics.
This commit is contained in:
James Bardin 2021-01-13 15:27:17 -05:00
parent 3f3565d48a
commit 833647bdfd
3 changed files with 36 additions and 44 deletions

View File

@ -265,34 +265,36 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext)
} }
state, applyDiags := n.apply(ctx, state, diffApply, n.Config, n.CreateBeforeDestroy()) state, applyDiags := n.apply(ctx, state, diffApply, n.Config, n.CreateBeforeDestroy())
// keep the applyDiags separate to handle the error case independently diags = diags.Append(applyDiags)
// we must add these into diags before returning
// We clear the change out here so that future nodes don't see a change // We clear the change out here so that future nodes don't see a change
// that is already complete. // that is already complete.
diags = diags.Append(n.writeChange(ctx, nil, "")) err = n.writeChange(ctx, nil, "")
if err != nil {
state = maybeTainted(addr.Absolute(ctx.Path()), state, diffApply, applyDiags.Err()) return diags.Append(err)
diags = diags.Append(n.writeResourceInstanceState(ctx, state, n.Dependencies, workingState))
if diags.HasErrors() {
return diags.Append(applyDiags)
} }
state = maybeTainted(addr.Absolute(ctx.Path()), state, diffApply, diags.Err())
err = n.writeResourceInstanceState(ctx, state, n.Dependencies, workingState)
if err != nil {
return diags.Append(err)
}
// Run Provisioners
createNew := (diffApply.Action == plans.Create || diffApply.Action.IsReplace()) createNew := (diffApply.Action == plans.Create || diffApply.Action.IsReplace())
applyProvisionersDiags := n.evalApplyProvisioners(ctx, state, createNew, configs.ProvisionerWhenCreate) applyProvisionersDiags := n.evalApplyProvisioners(ctx, state, createNew, configs.ProvisionerWhenCreate)
// the provisioner errors count as port of the apply error, so we can bundle the diags // the provisioner errors count as port of the apply error, so we can bundle the diags
applyDiags = applyDiags.Append(applyProvisionersDiags) diags = diags.Append(applyProvisionersDiags)
applyErr := applyDiags.Err() state = maybeTainted(addr.Absolute(ctx.Path()), state, diffApply, diags.Err())
state = maybeTainted(addr.Absolute(ctx.Path()), state, diffApply, applyErr)
diags = diags.Append(n.writeResourceInstanceState(ctx, state, n.Dependencies, workingState)) err = n.writeResourceInstanceState(ctx, state, n.Dependencies, workingState)
if diags.HasErrors() { if err != nil {
return diags.Append(applyDiags) return diags.Append(err)
} }
if createBeforeDestroyEnabled && applyErr != nil { if createBeforeDestroyEnabled && diags.HasErrors() {
if deposedKey == states.NotDeposed { if deposedKey == states.NotDeposed {
// This should never happen, and so it always indicates a bug. // This should never happen, and so it always indicates a bug.
// We should evaluate this node only if we've previously deposed // We should evaluate this node only if we've previously deposed
@ -327,7 +329,6 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext)
} }
diags = diags.Append(n.postApplyHook(ctx, state, diags.Err())) diags = diags.Append(n.postApplyHook(ctx, state, diags.Err()))
diags = diags.Append(applyDiags)
diags = diags.Append(updateStateHook(ctx)) diags = diags.Append(updateStateHook(ctx))
return diags return diags
} }

View File

@ -171,37 +171,32 @@ func (n *NodeDestroyResourceInstance) Execute(ctx EvalContext, op walkOperation)
return diags return diags
} }
var applyDiags tfdiags.Diagnostics
var applyProvisionersDiags tfdiags.Diagnostics
// Run destroy provisioners if not tainted // Run destroy provisioners if not tainted
if state != nil && state.Status != states.ObjectTainted { if state != nil && state.Status != states.ObjectTainted {
applyProvisionersDiags = n.evalApplyProvisioners(ctx, state, false, configs.ProvisionerWhenDestroy) applyProvisionersDiags := n.evalApplyProvisioners(ctx, state, false, configs.ProvisionerWhenDestroy)
diags = diags.Append(applyProvisionersDiags)
// keep the diags separate from the main set until we handle the cleanup // keep the diags separate from the main set until we handle the cleanup
provisionerErr := applyProvisionersDiags.Err() if diags.HasErrors() {
if provisionerErr != nil {
// If we have a provisioning error, then we just call // If we have a provisioning error, then we just call
// the post-apply hook now. // the post-apply hook now.
diags = diags.Append(n.postApplyHook(ctx, state, provisionerErr)) diags = diags.Append(n.postApplyHook(ctx, state, diags.Err()))
return diags.Append(applyProvisionersDiags) return diags
} }
} }
// provisioner and apply diags are handled together from here down
applyDiags = applyDiags.Append(applyProvisionersDiags)
// Managed resources need to be destroyed, while data sources // Managed resources need to be destroyed, while data sources
// are only removed from state. // are only removed from state.
if addr.Resource.Resource.Mode == addrs.ManagedResourceMode { if addr.Resource.Resource.Mode == addrs.ManagedResourceMode {
// we pass a nil configuration to apply because we are destroying // we pass a nil configuration to apply because we are destroying
s, d := n.apply(ctx, state, changeApply, nil, false) s, d := n.apply(ctx, state, changeApply, nil, false)
state, applyDiags = s, applyDiags.Append(d) state, diags = s, diags.Append(d)
// we must keep applyDiags separate until returning in order to process // we must keep applyDiags separate until returning in order to process
// the error independently // the error independently
diags = diags.Append(n.writeResourceInstanceState(ctx, state, n.Dependencies, workingState)) err := n.writeResourceInstanceState(ctx, state, n.Dependencies, workingState)
if diags.HasErrors() { if err != nil {
return diags.Append(applyDiags) return diags.Append(err)
} }
} else { } else {
log.Printf("[TRACE] NodeDestroyResourceInstance: removing state object for %s", n.Addr) log.Printf("[TRACE] NodeDestroyResourceInstance: removing state object for %s", n.Addr)
@ -210,9 +205,7 @@ func (n *NodeDestroyResourceInstance) Execute(ctx EvalContext, op walkOperation)
} }
// create the err value for postApplyHook // create the err value for postApplyHook
diags = diags.Append(n.postApplyHook(ctx, state, applyDiags.Err())) diags = diags.Append(n.postApplyHook(ctx, state, diags.Err()))
diags = diags.Append(applyDiags)
diags = diags.Append(updateStateHook(ctx)) diags = diags.Append(updateStateHook(ctx))
return diags return diags
} }

View File

@ -155,9 +155,8 @@ func (n *NodeDestroyDeposedResourceInstanceObject) Execute(ctx EvalContext, op w
// Read the state for the deposed resource instance // Read the state for the deposed resource instance
state, err := n.readResourceInstanceStateDeposed(ctx, n.Addr, n.DeposedKey) state, err := n.readResourceInstanceStateDeposed(ctx, n.Addr, n.DeposedKey)
diags = diags.Append(err) if err != nil {
if diags.HasErrors() { return diags.Append(err)
return diags
} }
change, destroyPlanDiags := n.planDestroy(ctx, state, n.DeposedKey) change, destroyPlanDiags := n.planDestroy(ctx, state, n.DeposedKey)
@ -174,19 +173,18 @@ func (n *NodeDestroyDeposedResourceInstanceObject) Execute(ctx EvalContext, op w
// we pass a nil configuration to apply because we are destroying // we pass a nil configuration to apply because we are destroying
state, applyDiags := n.apply(ctx, state, change, nil, false) state, applyDiags := n.apply(ctx, state, change, nil, false)
// we need to keep the apply diagnostics separate until we return, so that diags = diags.Append(applyDiags)
// we can handle the apply error case independently // don't return immediately on errors, we need to handle the state
// Always write the resource back to the state deposed. If it // Always write the resource back to the state deposed. If it
// was successfully destroyed it will be pruned. If it was not, it will // was successfully destroyed it will be pruned. If it was not, it will
// be caught on the next run. // be caught on the next run.
diags = diags.Append(n.writeResourceInstanceState(ctx, state)) err = n.writeResourceInstanceState(ctx, state)
if diags.HasErrors() { if err != nil {
return diags.Append(applyDiags) return diags.Append(err)
} }
diags = diags.Append(n.postApplyHook(ctx, state, applyDiags.Err())) diags = diags.Append(n.postApplyHook(ctx, state, diags.Err()))
diags = diags.Append(applyDiags)
return diags.Append(updateStateHook(ctx)) return diags.Append(updateStateHook(ctx))
} }