add diags to eval_diff

This commit is contained in:
James Bardin 2020-10-28 11:46:07 -04:00
parent fe9c93b9f9
commit b42aad5856
7 changed files with 101 additions and 90 deletions

View File

@ -37,7 +37,9 @@ type EvalCheckPlannedChange struct {
Planned, Actual **plans.ResourceInstanceChange Planned, Actual **plans.ResourceInstanceChange
} }
func (n *EvalCheckPlannedChange) Eval(ctx EvalContext) (interface{}, error) { func (n *EvalCheckPlannedChange) Eval(ctx EvalContext) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
providerSchema := *n.ProviderSchema providerSchema := *n.ProviderSchema
plannedChange := *n.Planned plannedChange := *n.Planned
actualChange := *n.Actual actualChange := *n.Actual
@ -45,10 +47,10 @@ func (n *EvalCheckPlannedChange) Eval(ctx EvalContext) (interface{}, error) {
schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource()) schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource())
if schema == nil { if schema == nil {
// Should be caught during validation, so we don't bother with a pretty error here // Should be caught during validation, so we don't bother with a pretty error here
return nil, fmt.Errorf("provider does not support %q", n.Addr.Resource.Type) diags = diags.Append(fmt.Errorf("provider does not support %q", n.Addr.Resource.Type))
return diags
} }
var diags tfdiags.Diagnostics
absAddr := n.Addr.Absolute(ctx.Path()) absAddr := n.Addr.Absolute(ctx.Path())
log.Printf("[TRACE] EvalCheckPlannedChange: Verifying that actual change (action %s) matches planned change (action %s)", actualChange.Action, plannedChange.Action) log.Printf("[TRACE] EvalCheckPlannedChange: Verifying that actual change (action %s) matches planned change (action %s)", actualChange.Action, plannedChange.Action)
@ -96,7 +98,7 @@ func (n *EvalCheckPlannedChange) Eval(ctx EvalContext) (interface{}, error) {
), ),
)) ))
} }
return nil, diags.Err() return diags
} }
// EvalDiff is an EvalNode implementation that detects changes for a given // EvalDiff is an EvalNode implementation that detects changes for a given
@ -124,7 +126,9 @@ type EvalDiff struct {
} }
// TODO: test // TODO: test
func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) { func (n *EvalDiff) Eval(ctx EvalContext) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
state := *n.State state := *n.State
config := *n.Config config := *n.Config
provider := *n.Provider provider := *n.Provider
@ -137,26 +141,26 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
} }
if providerSchema == nil { if providerSchema == nil {
return nil, fmt.Errorf("provider schema is unavailable for %s", n.Addr) diags = diags.Append(fmt.Errorf("provider schema is unavailable for %s", n.Addr))
return diags
} }
if n.ProviderAddr.Provider.Type == "" { if n.ProviderAddr.Provider.Type == "" {
panic(fmt.Sprintf("EvalDiff for %s does not have ProviderAddr set", n.Addr.Absolute(ctx.Path()))) panic(fmt.Sprintf("EvalDiff for %s does not have ProviderAddr set", n.Addr.Absolute(ctx.Path())))
} }
var diags tfdiags.Diagnostics
// Evaluate the configuration // Evaluate the configuration
schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource()) schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource())
if schema == nil { if schema == nil {
// Should be caught during validation, so we don't bother with a pretty error here // Should be caught during validation, so we don't bother with a pretty error here
return nil, fmt.Errorf("provider does not support resource type %q", n.Addr.Resource.Type) diags = diags.Append(fmt.Errorf("provider does not support resource type %q", n.Addr.Resource.Type))
return diags
} }
forEach, _ := evaluateForEachExpression(n.Config.ForEach, ctx) forEach, _ := evaluateForEachExpression(n.Config.ForEach, ctx)
keyData := EvalDataForInstanceKey(n.Addr.Key, forEach) keyData := EvalDataForInstanceKey(n.Addr.Key, forEach)
origConfigVal, _, configDiags := ctx.EvaluateBlock(config.Config, schema, nil, keyData) origConfigVal, _, configDiags := ctx.EvaluateBlock(config.Config, schema, nil, keyData)
diags = diags.Append(configDiags) diags = diags.Append(configDiags)
if configDiags.HasErrors() { if configDiags.HasErrors() {
return nil, diags.Err() return diags
} }
metaConfigVal := cty.NullVal(cty.DynamicPseudoType) metaConfigVal := cty.NullVal(cty.DynamicPseudoType)
@ -175,7 +179,7 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
metaConfigVal, _, configDiags = ctx.EvaluateBlock(m.Config, (*n.ProviderSchema).ProviderMeta, nil, EvalDataForNoInstanceKey) metaConfigVal, _, configDiags = ctx.EvaluateBlock(m.Config, (*n.ProviderSchema).ProviderMeta, nil, EvalDataForNoInstanceKey)
diags = diags.Append(configDiags) diags = diags.Append(configDiags)
if configDiags.HasErrors() { if configDiags.HasErrors() {
return nil, diags.Err() return diags
} }
} }
} }
@ -216,18 +220,18 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
configValIgnored, ignoreChangeDiags := n.processIgnoreChanges(unmarkedPriorVal, unmarkedConfigVal) configValIgnored, ignoreChangeDiags := n.processIgnoreChanges(unmarkedPriorVal, unmarkedConfigVal)
diags = diags.Append(ignoreChangeDiags) diags = diags.Append(ignoreChangeDiags)
if ignoreChangeDiags.HasErrors() { if ignoreChangeDiags.HasErrors() {
return nil, diags.Err() return diags
} }
proposedNewVal := objchange.ProposedNewObject(schema, unmarkedPriorVal, configValIgnored) proposedNewVal := objchange.ProposedNewObject(schema, unmarkedPriorVal, configValIgnored)
// Call pre-diff hook // Call pre-diff hook
if !n.Stub { if !n.Stub {
err := ctx.Hook(func(h Hook) (HookAction, error) { diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
return h.PreDiff(absAddr, states.CurrentGen, priorVal, proposedNewVal) return h.PreDiff(absAddr, states.CurrentGen, priorVal, proposedNewVal)
}) }))
if err != nil { if diags.HasErrors() {
return nil, err return diags
} }
} }
@ -242,7 +246,8 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
}, },
) )
if validateResp.Diagnostics.HasErrors() { if validateResp.Diagnostics.HasErrors() {
return nil, validateResp.Diagnostics.InConfigBody(config.Config).Err() diags = diags.Append(validateResp.Diagnostics.InConfigBody(config.Config))
return diags
} }
resp := provider.PlanResourceChange(providers.PlanResourceChangeRequest{ resp := provider.PlanResourceChange(providers.PlanResourceChangeRequest{
@ -255,7 +260,7 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
}) })
diags = diags.Append(resp.Diagnostics.InConfigBody(config.Config)) diags = diags.Append(resp.Diagnostics.InConfigBody(config.Config))
if diags.HasErrors() { if diags.HasErrors() {
return nil, diags.Err() return diags
} }
plannedNewVal := resp.PlannedState plannedNewVal := resp.PlannedState
@ -283,7 +288,7 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
)) ))
} }
if diags.HasErrors() { if diags.HasErrors() {
return nil, diags.Err() return diags
} }
if errs := objchange.AssertPlanValid(schema, unmarkedPriorVal, configValIgnored, plannedNewVal); len(errs) > 0 { if errs := objchange.AssertPlanValid(schema, unmarkedPriorVal, configValIgnored, plannedNewVal); len(errs) > 0 {
@ -313,7 +318,7 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
), ),
)) ))
} }
return nil, diags.Err() return diags
} }
} }
@ -380,7 +385,7 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
} }
} }
if diags.HasErrors() { if diags.HasErrors() {
return nil, diags.Err() return diags
} }
} }
@ -447,7 +452,7 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
// append these new diagnostics if there's at least one error inside. // append these new diagnostics if there's at least one error inside.
if resp.Diagnostics.HasErrors() { if resp.Diagnostics.HasErrors() {
diags = diags.Append(resp.Diagnostics.InConfigBody(config.Config)) diags = diags.Append(resp.Diagnostics.InConfigBody(config.Config))
return nil, diags.Err() return diags
} }
plannedNewVal = resp.PlannedState plannedNewVal = resp.PlannedState
plannedPrivate = resp.PlannedPrivate plannedPrivate = resp.PlannedPrivate
@ -467,7 +472,7 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
)) ))
} }
if diags.HasErrors() { if diags.HasErrors() {
return nil, diags.Err() return diags
} }
} }
@ -506,11 +511,11 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
// Call post-refresh hook // Call post-refresh hook
if !n.Stub { if !n.Stub {
err := ctx.Hook(func(h Hook) (HookAction, error) { diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
return h.PostDiff(absAddr, states.CurrentGen, action, priorVal, plannedNewVal) return h.PostDiff(absAddr, states.CurrentGen, action, priorVal, plannedNewVal)
}) }))
if err != nil { if diags.HasErrors() {
return nil, err return diags
} }
} }
@ -547,7 +552,7 @@ func (n *EvalDiff) Eval(ctx EvalContext) (interface{}, error) {
} }
} }
return nil, nil return diags
} }
func (n *EvalDiff) processIgnoreChanges(prior, config cty.Value) (cty.Value, tfdiags.Diagnostics) { func (n *EvalDiff) processIgnoreChanges(prior, config cty.Value) (cty.Value, tfdiags.Diagnostics) {
@ -738,7 +743,9 @@ type EvalDiffDestroy struct {
} }
// TODO: test // TODO: test
func (n *EvalDiffDestroy) Eval(ctx EvalContext) (interface{}, error) { func (n *EvalDiffDestroy) Eval(ctx EvalContext) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
absAddr := n.Addr.Absolute(ctx.Path()) absAddr := n.Addr.Absolute(ctx.Path())
state := *n.State state := *n.State
@ -753,19 +760,19 @@ func (n *EvalDiffDestroy) Eval(ctx EvalContext) (interface{}, error) {
// If there is no state or our attributes object is null then we're already // If there is no state or our attributes object is null then we're already
// destroyed. // destroyed.
if state == nil || state.Value.IsNull() { if state == nil || state.Value.IsNull() {
return nil, nil return nil
} }
// Call pre-diff hook // Call pre-diff hook
err := ctx.Hook(func(h Hook) (HookAction, error) { diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
return h.PreDiff( return h.PreDiff(
absAddr, n.DeposedKey.Generation(), absAddr, n.DeposedKey.Generation(),
state.Value, state.Value,
cty.NullVal(cty.DynamicPseudoType), cty.NullVal(cty.DynamicPseudoType),
) )
}) }))
if err != nil { if diags.HasErrors() {
return nil, err return diags
} }
// Change is always the same for a destroy. We don't need the provider's // Change is always the same for a destroy. We don't need the provider's
@ -784,7 +791,7 @@ func (n *EvalDiffDestroy) Eval(ctx EvalContext) (interface{}, error) {
} }
// Call post-diff hook // Call post-diff hook
err = ctx.Hook(func(h Hook) (HookAction, error) { diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) {
return h.PostDiff( return h.PostDiff(
absAddr, absAddr,
n.DeposedKey.Generation(), n.DeposedKey.Generation(),
@ -792,9 +799,9 @@ func (n *EvalDiffDestroy) Eval(ctx EvalContext) (interface{}, error) {
change.Before, change.Before,
change.After, change.After,
) )
}) }))
if err != nil { if diags.HasErrors() {
return nil, err return diags
} }
// Update our output // Update our output
@ -805,7 +812,7 @@ func (n *EvalDiffDestroy) Eval(ctx EvalContext) (interface{}, error) {
*n.OutputState = nil *n.OutputState = nil
} }
return nil, nil return diags
} }
// EvalReduceDiff is an EvalNode implementation that takes a planned resource // EvalReduceDiff is an EvalNode implementation that takes a planned resource
@ -829,7 +836,7 @@ type EvalReduceDiff struct {
} }
// TODO: test // TODO: test
func (n *EvalReduceDiff) Eval(ctx EvalContext) (interface{}, error) { func (n *EvalReduceDiff) Eval(ctx EvalContext) tfdiags.Diagnostics {
in := *n.InChange in := *n.InChange
out := in.Simplify(n.Destroy) out := in.Simplify(n.Destroy)
if n.OutChange != nil { if n.OutChange != nil {
@ -842,7 +849,7 @@ func (n *EvalReduceDiff) Eval(ctx EvalContext) (interface{}, error) {
log.Printf("[TRACE] EvalReduceDiff: %s change simplified from %s to %s for apply node", n.Addr, in.Action, out.Action) log.Printf("[TRACE] EvalReduceDiff: %s change simplified from %s to %s for apply node", n.Addr, in.Action, out.Action)
} }
} }
return nil, nil return nil
} }
// EvalWriteDiff is an EvalNode implementation that saves a planned change // EvalWriteDiff is an EvalNode implementation that saves a planned change
@ -855,7 +862,9 @@ type EvalWriteDiff struct {
} }
// TODO: test // TODO: test
func (n *EvalWriteDiff) Eval(ctx EvalContext) (interface{}, error) { func (n *EvalWriteDiff) Eval(ctx EvalContext) tfdiags.Diagnostics {
var diags tfdiags.Diagnostics
changes := ctx.Changes() changes := ctx.Changes()
addr := n.Addr.Absolute(ctx.Path()) addr := n.Addr.Absolute(ctx.Path())
if n.Change == nil || *n.Change == nil { if n.Change == nil || *n.Change == nil {
@ -866,7 +875,7 @@ func (n *EvalWriteDiff) Eval(ctx EvalContext) (interface{}, error) {
gen = n.DeposedKey gen = n.DeposedKey
} }
changes.RemoveResourceInstanceChange(addr, gen) changes.RemoveResourceInstanceChange(addr, gen)
return nil, nil return nil
} }
providerSchema := *n.ProviderSchema providerSchema := *n.ProviderSchema
@ -880,12 +889,14 @@ func (n *EvalWriteDiff) Eval(ctx EvalContext) (interface{}, error) {
schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource()) schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource())
if schema == nil { if schema == nil {
// Should be caught during validation, so we don't bother with a pretty error here // Should be caught during validation, so we don't bother with a pretty error here
return nil, fmt.Errorf("provider does not support resource type %q", n.Addr.Resource.Type) diags = diags.Append(fmt.Errorf("provider does not support resource type %q", n.Addr.Resource.Type))
return diags
} }
csrc, err := change.Encode(schema.ImpliedType()) csrc, err := change.Encode(schema.ImpliedType())
if err != nil { if err != nil {
return nil, fmt.Errorf("failed to encode planned changes for %s: %s", addr, err) diags = diags.Append(fmt.Errorf("failed to encode planned changes for %s: %s", addr, err))
return diags
} }
changes.AppendResourceInstanceChange(csrc) changes.AppendResourceInstanceChange(csrc)
@ -895,5 +906,5 @@ func (n *EvalWriteDiff) Eval(ctx EvalContext) (interface{}, error) {
log.Printf("[TRACE] EvalWriteDiff: recorded %s change for %s deposed object %s", change.Action, addr, n.DeposedKey) log.Printf("[TRACE] EvalWriteDiff: recorded %s change for %s deposed object %s", change.Action, addr, n.DeposedKey)
} }
return nil, nil return diags
} }

View File

@ -187,9 +187,9 @@ func (n *NodeApplyableResourceInstance) dataResourceExecute(ctx EvalContext) err
ProviderSchema: &providerSchema, ProviderSchema: &providerSchema,
Change: nil, Change: nil,
} }
_, err = writeDiff.Eval(ctx) diags := writeDiff.Eval(ctx)
if err != nil { if diags.HasErrors() {
return err return diags.ErrWithWarnings()
} }
UpdateStateHook(ctx) UpdateStateHook(ctx)
@ -276,9 +276,9 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext)
OutputChange: &diffApply, OutputChange: &diffApply,
OutputState: &state, OutputState: &state,
} }
_, err = evalDiff.Eval(ctx) diags = evalDiff.Eval(ctx)
if err != nil { if diags.HasErrors() {
return err return diags.ErrWithWarnings()
} }
// Compare the diffs // Compare the diffs
@ -289,9 +289,9 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext)
Planned: &diff, Planned: &diff,
Actual: &diffApply, Actual: &diffApply,
} }
_, err = checkPlannedChange.Eval(ctx) diags = checkPlannedChange.Eval(ctx)
if err != nil { if diags.HasErrors() {
return err return diags.ErrWithWarnings()
} }
readState = &EvalReadState{ readState = &EvalReadState{
@ -312,9 +312,9 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext)
Destroy: false, Destroy: false,
OutChange: &diffApply, OutChange: &diffApply,
} }
_, err = reduceDiff.Eval(ctx) diags = reduceDiff.Eval(ctx)
if err != nil { if diags.HasErrors() {
return err return diags.ErrWithWarnings()
} }
// EvalReduceDiff may have simplified our planned change // EvalReduceDiff may have simplified our planned change
@ -361,9 +361,9 @@ func (n *NodeApplyableResourceInstance) managedResourceExecute(ctx EvalContext)
ProviderSchema: &providerSchema, ProviderSchema: &providerSchema,
Change: nil, Change: nil,
} }
_, err = writeDiff.Eval(ctx) diags = writeDiff.Eval(ctx)
if err != nil { if diags.HasErrors() {
return err return diags.ErrWithWarnings()
} }
evalMaybeTainted := &EvalMaybeTainted{ evalMaybeTainted := &EvalMaybeTainted{

View File

@ -155,9 +155,9 @@ func (n *NodeDestroyResourceInstance) Execute(ctx EvalContext, op walkOperation)
Destroy: true, Destroy: true,
OutChange: &changeApply, OutChange: &changeApply,
} }
_, err = evalReduceDiff.Eval(ctx) diags = evalReduceDiff.Eval(ctx)
if err != nil { if diags.HasErrors() {
return err return diags.ErrWithWarnings()
} }
// EvalReduceDiff may have simplified our planned change // EvalReduceDiff may have simplified our planned change

View File

@ -96,9 +96,9 @@ func (n *NodePlanDeposedResourceInstanceObject) Execute(ctx EvalContext, op walk
State: &state, State: &state,
Output: &change, Output: &change,
} }
_, err = diffDestroy.Eval(ctx) diags := diffDestroy.Eval(ctx)
if err != nil { if diags.HasErrors() {
return err return diags.ErrWithWarnings()
} }
writeDiff := &EvalWriteDiff{ writeDiff := &EvalWriteDiff{
@ -107,9 +107,9 @@ func (n *NodePlanDeposedResourceInstanceObject) Execute(ctx EvalContext, op walk
ProviderSchema: &providerSchema, ProviderSchema: &providerSchema,
Change: &change, Change: &change,
} }
_, err = writeDiff.Eval(ctx) diags = writeDiff.Eval(ctx)
if err != nil { if diags.HasErrors() {
return err return diags.ErrWithWarnings()
} }
return nil return nil
@ -214,9 +214,9 @@ func (n *NodeDestroyDeposedResourceInstanceObject) Execute(ctx EvalContext, op w
State: &state, State: &state,
Output: &change, Output: &change,
} }
_, err = diffDestroy.Eval(ctx) diags = diffDestroy.Eval(ctx)
if err != nil { if diags.HasErrors() {
return err return diags.ErrWithWarnings()
} }
// Call pre-apply hook // Call pre-apply hook

View File

@ -57,9 +57,9 @@ func (n *NodePlanDestroyableResourceInstance) Execute(ctx EvalContext, op walkOp
State: &state, State: &state,
Output: &change, Output: &change,
} }
_, err = diffDestroy.Eval(ctx) diags := diffDestroy.Eval(ctx)
if err != nil { if diags.HasErrors() {
return err return diags.ErrWithWarnings()
} }
err = n.checkPreventDestroy(change) err = n.checkPreventDestroy(change)
@ -72,6 +72,6 @@ func (n *NodePlanDestroyableResourceInstance) Execute(ctx EvalContext, op walkOp
ProviderSchema: &providerSchema, ProviderSchema: &providerSchema,
Change: &change, Change: &change,
} }
_, err = writeDiff.Eval(ctx) diags = writeDiff.Eval(ctx)
return err return diags.ErrWithWarnings()
} }

View File

@ -119,8 +119,8 @@ func (n *NodePlannableResourceInstance) dataResourceExecute(ctx EvalContext) err
ProviderSchema: &providerSchema, ProviderSchema: &providerSchema,
Change: &change, Change: &change,
} }
_, err = writeDiff.Eval(ctx) diags := writeDiff.Eval(ctx)
return err return diags.ErrWithWarnings()
} }
func (n *NodePlannableResourceInstance) managedResourceExecute(ctx EvalContext) error { func (n *NodePlannableResourceInstance) managedResourceExecute(ctx EvalContext) error {
@ -204,9 +204,9 @@ func (n *NodePlannableResourceInstance) managedResourceExecute(ctx EvalContext)
OutputChange: &change, OutputChange: &change,
OutputState: &instancePlanState, OutputState: &instancePlanState,
} }
_, err = diff.Eval(ctx) diags := diff.Eval(ctx)
if err != nil { if diags.HasErrors() {
return err return diags.ErrWithWarnings()
} }
err = n.checkPreventDestroy(change) err = n.checkPreventDestroy(change)
@ -230,6 +230,6 @@ func (n *NodePlannableResourceInstance) managedResourceExecute(ctx EvalContext)
ProviderSchema: &providerSchema, ProviderSchema: &providerSchema,
Change: &change, Change: &change,
} }
_, err = writeDiff.Eval(ctx) diags = writeDiff.Eval(ctx)
return err return diags.ErrWithWarnings()
} }

View File

@ -114,9 +114,9 @@ func (n *NodePlannableResourceInstanceOrphan) managedResourceExecute(ctx EvalCon
Output: &change, Output: &change,
OutputState: &state, // Will point to a nil state after this complete, signalling destroyed OutputState: &state, // Will point to a nil state after this complete, signalling destroyed
} }
_, err = diffDestroy.Eval(ctx) diags := diffDestroy.Eval(ctx)
if err != nil { if err != nil {
return err return diags.ErrWithWarnings()
} }
err = n.checkPreventDestroy(change) err = n.checkPreventDestroy(change)
@ -129,9 +129,9 @@ func (n *NodePlannableResourceInstanceOrphan) managedResourceExecute(ctx EvalCon
ProviderSchema: &providerSchema, ProviderSchema: &providerSchema,
Change: &change, Change: &change,
} }
_, err = writeDiff.Eval(ctx) diags = writeDiff.Eval(ctx)
if err != nil { if diags.HasErrors() {
return err return diags.ErrWithWarnings()
} }
writeState := &EvalWriteState{ writeState := &EvalWriteState{