diff --git a/terraform/eval_read_data_apply.go b/terraform/eval_read_data_apply.go index 179fe368d..c9e235250 100644 --- a/terraform/eval_read_data_apply.go +++ b/terraform/eval_read_data_apply.go @@ -15,7 +15,7 @@ type evalReadDataApply struct { evalReadData } -func (n *evalReadDataApply) Eval(ctx EvalContext) (interface{}, error) { +func (n *evalReadDataApply) Eval(ctx EvalContext) tfdiags.Diagnostics { absAddr := n.Addr.Absolute(ctx.Path()) var diags tfdiags.Diagnostics @@ -26,22 +26,25 @@ func (n *evalReadDataApply) Eval(ctx EvalContext) (interface{}, error) { } if n.ProviderSchema == nil || *n.ProviderSchema == nil { - return nil, fmt.Errorf("provider schema not available for %s", n.Addr) + diags = diags.Append(fmt.Errorf("provider schema not available for %s", n.Addr)) + return diags } if planned != nil && planned.Action != plans.Read { // If any other action gets in here then that's always a bug; this // EvalNode only deals with reading. - return nil, fmt.Errorf( + diags = diags.Append(fmt.Errorf( "invalid action %s for %s: only Read is supported (this is a bug in Terraform; please report it!)", planned.Action, absAddr, - ) + )) + return diags } - if err := ctx.Hook(func(h Hook) (HookAction, error) { + diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) { return h.PreApply(absAddr, states.CurrentGen, planned.Action, planned.Before, planned.After) - }); err != nil { - return nil, err + })) + if diags.HasErrors() { + return diags } config := *n.Config @@ -49,7 +52,8 @@ func (n *evalReadDataApply) Eval(ctx EvalContext) (interface{}, error) { schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource()) if schema == nil { // Should be caught during validation, so we don't bother with a pretty error here - return nil, fmt.Errorf("provider %q does not support data source %q", n.ProviderAddr.Provider.String(), n.Addr.Resource.Type) + diags = diags.Append(fmt.Errorf("provider %q does not support data source %q", n.ProviderAddr.Provider.String(), n.Addr.Resource.Type)) + return diags } forEach, _ := evaluateForEachExpression(config.ForEach, ctx) @@ -58,13 +62,13 @@ func (n *evalReadDataApply) Eval(ctx EvalContext) (interface{}, error) { configVal, _, configDiags := ctx.EvaluateBlock(config.Config, schema, nil, keyData) diags = diags.Append(configDiags) if configDiags.HasErrors() { - return nil, diags.ErrWithWarnings() + return diags } newVal, readDiags := n.readDataSource(ctx, configVal) diags = diags.Append(readDiags) if diags.HasErrors() { - return nil, diags.ErrWithWarnings() + return diags } *n.State = &states.ResourceInstanceObject{ @@ -72,11 +76,9 @@ func (n *evalReadDataApply) Eval(ctx EvalContext) (interface{}, error) { Status: states.ObjectReady, } - if err := ctx.Hook(func(h Hook) (HookAction, error) { + diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) { return h.PostApply(absAddr, states.CurrentGen, newVal, diags.Err()) - }); err != nil { - diags = diags.Append(err) - } + })) - return nil, diags.ErrWithWarnings() + return diags } diff --git a/terraform/eval_read_data_plan.go b/terraform/eval_read_data_plan.go index 226594299..a1d7ccce6 100644 --- a/terraform/eval_read_data_plan.go +++ b/terraform/eval_read_data_plan.go @@ -21,14 +21,15 @@ type evalReadDataPlan struct { evalReadData } -func (n *evalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) { +func (n *evalReadDataPlan) Eval(ctx EvalContext) tfdiags.Diagnostics { absAddr := n.Addr.Absolute(ctx.Path()) var diags tfdiags.Diagnostics var configVal cty.Value if n.ProviderSchema == nil || *n.ProviderSchema == nil { - return nil, fmt.Errorf("provider schema not available for %s", n.Addr) + diags = diags.Append(fmt.Errorf("provider schema not available for %s", n.Addr)) + return diags } config := *n.Config @@ -36,7 +37,8 @@ func (n *evalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) { schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource()) if schema == nil { // Should be caught during validation, so we don't bother with a pretty error here - return nil, fmt.Errorf("provider %q does not support data source %q", n.ProviderAddr.Provider.String(), n.Addr.Resource.Type) + diags = diags.Append(fmt.Errorf("provider %q does not support data source %q", n.ProviderAddr.Provider.String(), n.Addr.Resource.Type)) + return diags } objTy := schema.ImpliedType() @@ -52,7 +54,7 @@ func (n *evalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) { configVal, _, configDiags = ctx.EvaluateBlock(config.Config, schema, nil, keyData) diags = diags.Append(configDiags) if configDiags.HasErrors() { - return nil, diags.ErrWithWarnings() + return diags } configKnown := configVal.IsWhollyKnown() @@ -69,11 +71,11 @@ func (n *evalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) { proposedNewVal := objchange.PlannedDataResourceObject(schema, configVal) - if 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) - }); err != nil { - diags = diags.Append(err) - return nil, diags.ErrWithWarnings() + })) + if diags.HasErrors() { + return diags } // Apply detects that the data source will need to be read by the After @@ -93,13 +95,11 @@ func (n *evalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) { Status: states.ObjectPlanned, } - if err := ctx.Hook(func(h Hook) (HookAction, error) { + diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) { return h.PostDiff(absAddr, states.CurrentGen, plans.Read, priorVal, proposedNewVal) - }); err != nil { - diags = diags.Append(err) - } + })) - return nil, diags.ErrWithWarnings() + return diags } // We have a complete configuration with no dependencies to wait on, so we @@ -107,7 +107,7 @@ func (n *evalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) { newVal, readDiags := n.readDataSource(ctx, configVal) diags = diags.Append(readDiags) if diags.HasErrors() { - return nil, diags.ErrWithWarnings() + return diags } // if we have a prior value, we can check for any irregularities in the response @@ -137,13 +137,10 @@ func (n *evalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) { Status: states.ObjectReady, } - if err := ctx.Hook(func(h Hook) (HookAction, error) { + diags = diags.Append(ctx.Hook(func(h Hook) (HookAction, error) { return h.PostDiff(absAddr, states.CurrentGen, plans.Update, priorVal, newVal) - }); err != nil { - return nil, err - } - - return nil, diags.ErrWithWarnings() + })) + return diags } // forcePlanRead determines if we need to override the usual behavior of diff --git a/terraform/node_resource_apply_instance.go b/terraform/node_resource_apply_instance.go index 7a109855f..82f5b2f46 100644 --- a/terraform/node_resource_apply_instance.go +++ b/terraform/node_resource_apply_instance.go @@ -134,6 +134,7 @@ func (n *NodeApplyableResourceInstance) Execute(ctx EvalContext, op walkOperatio } func (n *NodeApplyableResourceInstance) dataResourceExecute(ctx EvalContext) error { + var diags tfdiags.Diagnostics addr := n.ResourceInstanceAddr().Resource provider, providerSchema, err := GetProvider(ctx, n.ResolvedProvider) @@ -166,9 +167,9 @@ func (n *NodeApplyableResourceInstance) dataResourceExecute(ctx EvalContext) err State: &state, }, } - _, err = readDataApply.Eval(ctx) - if err != nil { - return err + diags = readDataApply.Eval(ctx) + if diags.HasErrors() { + return diags.ErrWithWarnings() } writeState := &EvalWriteState{ @@ -187,7 +188,7 @@ func (n *NodeApplyableResourceInstance) dataResourceExecute(ctx EvalContext) err ProviderSchema: &providerSchema, Change: nil, } - diags := writeDiff.Eval(ctx) + diags = writeDiff.Eval(ctx) if diags.HasErrors() { return diags.ErrWithWarnings() } diff --git a/terraform/node_resource_plan_instance.go b/terraform/node_resource_plan_instance.go index 836f1328e..64ab930ec 100644 --- a/terraform/node_resource_plan_instance.go +++ b/terraform/node_resource_plan_instance.go @@ -5,6 +5,7 @@ import ( "github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/states" + "github.com/hashicorp/terraform/tfdiags" "github.com/hashicorp/terraform/addrs" ) @@ -45,6 +46,7 @@ func (n *NodePlannableResourceInstance) Execute(ctx EvalContext, op walkOperatio } func (n *NodePlannableResourceInstance) dataResourceExecute(ctx EvalContext) error { + var diags tfdiags.Diagnostics config := n.Config addr := n.ResourceInstanceAddr() @@ -84,9 +86,9 @@ func (n *NodePlannableResourceInstance) dataResourceExecute(ctx EvalContext) err dependsOn: n.dependsOn, }, } - _, err = readDataPlan.Eval(ctx) - if err != nil { - return err + diags = readDataPlan.Eval(ctx) + if diags.HasErrors() { + return diags.ErrWithWarnings() } // write the data source into both the refresh state and the @@ -119,7 +121,7 @@ func (n *NodePlannableResourceInstance) dataResourceExecute(ctx EvalContext) err ProviderSchema: &providerSchema, Change: &change, } - diags := writeDiff.Eval(ctx) + diags = writeDiff.Eval(ctx) return diags.ErrWithWarnings() }