From 669da06515ed56fe217aeb1749824f3553dcd5ab Mon Sep 17 00:00:00 2001 From: James Bardin Date: Thu, 17 Sep 2020 17:12:10 -0400 Subject: [PATCH] saved read data in the refresh state during plan This only changes the refreshed state stored in the plan file. Since the change is stored in the plan, the applied result would be the same, but we should still store the refreshed data in the plan file for tools that consume the plan file. This will also be needed in order to implement a new refresh command based on the plan itself. --- terraform/context_plan_test.go | 37 ++++++++++++++++++++++++ terraform/eval_read_data_plan.go | 4 ++- terraform/node_resource_plan_instance.go | 10 +++++++ 3 files changed, 50 insertions(+), 1 deletion(-) diff --git a/terraform/context_plan_test.go b/terraform/context_plan_test.go index e113ae6f5..e9cb4a1d4 100644 --- a/terraform/context_plan_test.go +++ b/terraform/context_plan_test.go @@ -6333,3 +6333,40 @@ func TestContext2Plan_targetedModuleInstance(t *testing.T) { } } } + +func TestContext2Plan_dataRefreshedInPlan(t *testing.T) { + m := testModuleInline(t, map[string]string{ + "main.tf": ` +data "test_data_source" "d" { +} +`}) + + p := testProvider("test") + p.ReadDataSourceResponse = providers.ReadDataSourceResponse{ + State: cty.ObjectVal(map[string]cty.Value{ + "id": cty.StringVal("this"), + "foo": cty.NullVal(cty.String), + }), + } + + ctx := testContext2(t, &ContextOpts{ + Config: m, + Providers: map[addrs.Provider]providers.Factory{ + addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), + }, + }) + + plan, diags := ctx.Plan() + if diags.HasErrors() { + t.Fatal(diags.ErrWithWarnings()) + } + + d := plan.State.ResourceInstance(mustResourceInstanceAddr("data.test_data_source.d")) + if d == nil || d.Current == nil { + t.Fatal("data.test_data_source.d not found in state:", plan.State) + } + + if d.Current.Status != states.ObjectReady { + t.Fatal("expected data.test_data_source.d to be fully read in refreshed state, got status", d.Current.Status) + } +} diff --git a/terraform/eval_read_data_plan.go b/terraform/eval_read_data_plan.go index f13381855..e65ddca2e 100644 --- a/terraform/eval_read_data_plan.go +++ b/terraform/eval_read_data_plan.go @@ -138,6 +138,8 @@ func (n *evalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) { } } + // We still default to read here, to indicate any changes in the plan, even + // though this will already be written in the refreshed state. action := plans.Read if priorVal.Equals(newVal).True() { action = plans.NoOp @@ -159,7 +161,7 @@ func (n *evalReadDataPlan) Eval(ctx EvalContext) (interface{}, error) { *n.State = &states.ResourceInstanceObject{ Value: newVal, - Status: states.ObjectPlanned, + Status: states.ObjectReady, } if err := ctx.Hook(func(h Hook) (HookAction, error) { diff --git a/terraform/node_resource_plan_instance.go b/terraform/node_resource_plan_instance.go index 12bbd5c7d..7cad9d4a4 100644 --- a/terraform/node_resource_plan_instance.go +++ b/terraform/node_resource_plan_instance.go @@ -86,6 +86,16 @@ func (n *NodePlannableResourceInstance) evalTreeDataResource(addr addrs.AbsResou }, }, + // write the data source into both the refresh state and the + // working state + &EvalWriteState{ + Addr: addr.Resource, + ProviderAddr: n.ResolvedProvider, + ProviderSchema: &providerSchema, + State: &state, + targetState: refreshState, + }, + &EvalWriteState{ Addr: addr.Resource, ProviderAddr: n.ResolvedProvider,