From 300ad0293772bb04eb283bdb950ef9b4e96a54e1 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Fri, 28 Oct 2022 10:45:49 -0400 Subject: [PATCH] don't plan data source reads during refresh-only When executing a refresh-only plan, it is not valid to plan a data source read. If the data source config is not known during planning, the only valid update would be the prior state, if there is any. --- internal/terraform/context_refresh_test.go | 4 ++-- .../terraform/node_resource_abstract_instance.go | 13 ++++++++++++- internal/terraform/node_resource_plan_instance.go | 2 +- 3 files changed, 15 insertions(+), 4 deletions(-) diff --git a/internal/terraform/context_refresh_test.go b/internal/terraform/context_refresh_test.go index aa2239dbeddf..ca456cee9e72 100644 --- a/internal/terraform/context_refresh_test.go +++ b/internal/terraform/context_refresh_test.go @@ -201,12 +201,12 @@ func TestContext2Refresh_dataComputedModuleVar(t *testing.T) { }, }) - s, diags := ctx.Refresh(m, states.NewState(), &PlanOpts{Mode: plans.NormalMode}) + plan, diags := ctx.Plan(m, states.NewState(), &PlanOpts{Mode: plans.RefreshOnlyMode}) if diags.HasErrors() { t.Fatalf("refresh errors: %s", diags.Err()) } - checkStateString(t, s, ` + checkStateString(t, plan.PriorState, ` `) } diff --git a/internal/terraform/node_resource_abstract_instance.go b/internal/terraform/node_resource_abstract_instance.go index ba1aa3a17c60..b1d95277ffb6 100644 --- a/internal/terraform/node_resource_abstract_instance.go +++ b/internal/terraform/node_resource_abstract_instance.go @@ -1555,7 +1555,7 @@ func (n *NodeAbstractResourceInstance) providerMetas(ctx EvalContext) (cty.Value // value, but it still matches the previous state, then we can record a NoNop // change. If the states don't match then we record a Read change so that the // new value is applied to the state. -func (n *NodeAbstractResourceInstance) planDataSource(ctx EvalContext, checkRuleSeverity tfdiags.Severity) (*plans.ResourceInstanceChange, *states.ResourceInstanceObject, instances.RepetitionData, tfdiags.Diagnostics) { +func (n *NodeAbstractResourceInstance) planDataSource(ctx EvalContext, checkRuleSeverity tfdiags.Severity, skipPlanChanges bool) (*plans.ResourceInstanceChange, *states.ResourceInstanceObject, instances.RepetitionData, tfdiags.Diagnostics) { var diags tfdiags.Diagnostics var keyData instances.RepetitionData var configVal cty.Value @@ -1609,6 +1609,17 @@ func (n *NodeAbstractResourceInstance) planDataSource(ctx EvalContext, checkRule // producing a "Read" change for this resource, and a placeholder value for // it in the state. if depsPending || !configKnown { + // We can't plan any changes if we're only refreshing, so the only + // value we can set here is whatever was in state previously. + if skipPlanChanges { + plannedNewState := &states.ResourceInstanceObject{ + Value: priorVal, + Status: states.ObjectReady, + } + + return nil, plannedNewState, keyData, diags + } + var reason plans.ResourceInstanceChangeActionReason switch { case !configKnown: diff --git a/internal/terraform/node_resource_plan_instance.go b/internal/terraform/node_resource_plan_instance.go index 14bded923aa3..d50b59958450 100644 --- a/internal/terraform/node_resource_plan_instance.go +++ b/internal/terraform/node_resource_plan_instance.go @@ -87,7 +87,7 @@ func (n *NodePlannableResourceInstance) dataResourceExecute(ctx EvalContext) (di checkRuleSeverity = tfdiags.Warning } - change, state, repeatData, planDiags := n.planDataSource(ctx, checkRuleSeverity) + change, state, repeatData, planDiags := n.planDataSource(ctx, checkRuleSeverity, n.skipPlanChanges) diags = diags.Append(planDiags) if diags.HasErrors() { return diags