diff --git a/terraform/eval_read_data.go b/terraform/eval_read_data.go index c85e60f73..474e82f93 100644 --- a/terraform/eval_read_data.go +++ b/terraform/eval_read_data.go @@ -70,11 +70,8 @@ func (n *evalReadData) readDataSource(ctx EvalContext, configVal cty.Value) (cty } provider := *n.Provider + providerSchema := *n.ProviderSchema - - forEach, _ := evaluateForEachExpression(config.ForEach, ctx) - keyData := EvalDataForInstanceKey(n.Addr.Key, forEach) - schema, _ := providerSchema.SchemaForResourceAddr(n.Addr.ContainingResource()) if schema == nil { // Should be caught during validation, so we don't bother with a pretty error here @@ -82,15 +79,6 @@ func (n *evalReadData) readDataSource(ctx EvalContext, configVal cty.Value) (cty return newVal, diags } - if configVal == cty.NilVal { - val, _, configDiags := ctx.EvaluateBlock(config.Config, schema, nil, keyData) - diags = diags.Append(configDiags) - if configDiags.HasErrors() { - return newVal, diags - } - configVal = val - } - metaConfigVal, metaDiags := n.providerMetas(ctx) diags = diags.Append(metaDiags) if diags.HasErrors() { @@ -232,7 +220,7 @@ func (n *EvalReadDataRefresh) Eval(ctx EvalContext) (interface{}, error) { configVal, _, configDiags := ctx.EvaluateBlock(config.Config, schema, nil, keyData) diags = diags.Append(configDiags) if configDiags.HasErrors() { - return nil, diags.Err() + return nil, diags.ErrWithWarnings() } configKnown := configVal.IsWhollyKnown() @@ -257,7 +245,7 @@ func (n *EvalReadDataRefresh) Eval(ctx EvalContext) (interface{}, error) { // We need to store a change so tat other references to this data // source can resolve correctly, since the state is not going to be up // to date. - change := &plans.ResourceInstanceChange{ + *n.OutputChange = &plans.ResourceInstanceChange{ Addr: absAddr, ProviderAddr: n.ProviderAddr, Change: plans.Change{ @@ -267,15 +255,9 @@ func (n *EvalReadDataRefresh) Eval(ctx EvalContext) (interface{}, error) { }, } - if n.OutputChange != nil { - *n.OutputChange = change - } - - if n.State != nil { - *n.State = &states.ResourceInstanceObject{ - Value: cty.NullVal(objTy), - Status: states.ObjectPlanned, - } + *n.State = &states.ResourceInstanceObject{ + Value: cty.NullVal(objTy), + Status: states.ObjectPlanned, } return nil, diags.ErrWithWarnings() @@ -296,20 +278,15 @@ func (n *EvalReadDataRefresh) Eval(ctx EvalContext) (interface{}, error) { // This may still have been refreshed with references to resources that // will be updated, but that will be caught as a change during plan. - outputState := &states.ResourceInstanceObject{ + *n.State = &states.ResourceInstanceObject{ Value: newVal, Status: states.ObjectReady, } - err := ctx.Hook(func(h Hook) (HookAction, error) { + if err := ctx.Hook(func(h Hook) (HookAction, error) { return h.PostRefresh(absAddr, states.CurrentGen, priorVal, newVal) - }) - if err != nil { - return nil, err - } - - if n.State != nil { - *n.State = outputState + }); err != nil { + diags = diags.Append(err) } return nil, diags.ErrWithWarnings() diff --git a/terraform/eval_read_data_apply.go b/terraform/eval_read_data_apply.go index ff9b4fb94..5d70fc9f3 100644 --- a/terraform/eval_read_data_apply.go +++ b/terraform/eval_read_data_apply.go @@ -6,7 +6,6 @@ import ( "github.com/hashicorp/terraform/plans" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/tfdiags" - "github.com/zclconf/go-cty/cty" ) // EvalReadDataApply is an EvalNode implementation that deals with the main part @@ -48,34 +47,43 @@ func (n *EvalReadDataApply) Eval(ctx EvalContext) (interface{}, error) { // we have a change and it is complete, which means we read the data // source during plan and only need to store it in state. if planned.Action == plans.Update { - outputState := &states.ResourceInstanceObject{ + if err := ctx.Hook(func(h Hook) (HookAction, error) { + return h.PostApply(absAddr, states.CurrentGen, planned.After, nil) + }); err != nil { + diags = diags.Append(err) + } + + *n.State = &states.ResourceInstanceObject{ Value: planned.After, Status: states.ObjectReady, } - - err := ctx.Hook(func(h Hook) (HookAction, error) { - return h.PostApply(absAddr, states.CurrentGen, planned.After, nil) - }) - if err != nil { - return nil, err - } - - if n.OutputChange != nil { - *n.OutputChange = planned - } - if n.State != nil { - *n.State = outputState - } return nil, diags.ErrWithWarnings() } - newVal, readDiags := n.readDataSource(ctx, cty.NilVal) + config := *n.Config + providerSchema := *n.ProviderSchema + 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) + } + + forEach, _ := evaluateForEachExpression(config.ForEach, ctx) + keyData := EvalDataForInstanceKey(n.Addr.Key, forEach) + + configVal, _, configDiags := ctx.EvaluateBlock(config.Config, schema, nil, keyData) + diags = diags.Append(configDiags) + if configDiags.HasErrors() { + return nil, diags.ErrWithWarnings() + } + + newVal, readDiags := n.readDataSource(ctx, configVal) diags = diags.Append(readDiags) if diags.HasErrors() { return nil, diags.ErrWithWarnings() } - outputState := &states.ResourceInstanceObject{ + *n.State = &states.ResourceInstanceObject{ Value: newVal, Status: states.ObjectReady, } @@ -83,11 +91,7 @@ func (n *EvalReadDataApply) Eval(ctx EvalContext) (interface{}, error) { if err := ctx.Hook(func(h Hook) (HookAction, error) { return h.PostApply(absAddr, states.CurrentGen, newVal, diags.Err()) }); err != nil { - return nil, err - } - - if n.State != nil { - *n.State = outputState + diags = diags.Append(err) } return nil, diags.ErrWithWarnings() diff --git a/terraform/eval_read_data_plan.go b/terraform/eval_read_data_plan.go index fe0761056..96e79cdb1 100644 --- a/terraform/eval_read_data_plan.go +++ b/terraform/eval_read_data_plan.go @@ -57,7 +57,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.Err() + return nil, diags.ErrWithWarnings() } configKnown := configVal.IsWhollyKnown() @@ -74,14 +74,14 @@ func (n *EvalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) { proposedNewVal := objchange.PlannedDataResourceObject(schema, configVal) - err := ctx.Hook(func(h Hook) (HookAction, error) { + if err := ctx.Hook(func(h Hook) (HookAction, error) { return h.PreDiff(absAddr, states.CurrentGen, priorVal, proposedNewVal) - }) - if err != nil { - return nil, err + }); err != nil { + diags = diags.Append(err) + return nil, diags.ErrWithWarnings() } - change := &plans.ResourceInstanceChange{ + *n.OutputChange = &plans.ResourceInstanceChange{ Addr: absAddr, ProviderAddr: n.ProviderAddr, Change: plans.Change{ @@ -91,14 +91,17 @@ func (n *EvalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) { }, } - err = ctx.Hook(func(h Hook) (HookAction, error) { - return h.PostDiff(absAddr, states.CurrentGen, change.Action, priorVal, proposedNewVal) - }) - if err != nil { - return nil, err + *n.State = &states.ResourceInstanceObject{ + Value: cty.NullVal(objTy), + Status: states.ObjectPlanned, + } + + if err := ctx.Hook(func(h Hook) (HookAction, error) { + return h.PostDiff(absAddr, states.CurrentGen, plans.Read, priorVal, proposedNewVal) + }); err != nil { + diags = diags.Append(err) } - *n.OutputChange = change return nil, diags.ErrWithWarnings() } @@ -122,7 +125,7 @@ func (n *EvalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) { } // Produce a change regardless of the outcome. - change := &plans.ResourceInstanceChange{ + *n.OutputChange = &plans.ResourceInstanceChange{ Addr: absAddr, ProviderAddr: n.ProviderAddr, Change: plans.Change{ @@ -132,7 +135,7 @@ func (n *EvalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) { }, } - outputState := &states.ResourceInstanceObject{ + *n.State = &states.ResourceInstanceObject{ Value: newVal, Status: states.ObjectPlanned, } @@ -143,9 +146,6 @@ func (n *EvalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) { return nil, err } - *n.OutputChange = change - *n.State = outputState - return nil, diags.ErrWithWarnings() }