From be757bd41657a758c9a6edffe3f0b6486a79e8d3 Mon Sep 17 00:00:00 2001 From: James Bardin Date: Mon, 27 Jul 2020 16:35:55 -0400 Subject: [PATCH] Refresh instances during plan This change refreshes the instance state during plan, so a complete Refresh no longer needs to happen before Plan. --- backend/local/backend_apply.go | 12 ------ backend/local/backend_plan.go | 26 ++----------- terraform/node_resource_plan_instance.go | 47 +++++++++++++++++------- 3 files changed, 37 insertions(+), 48 deletions(-) diff --git a/backend/local/backend_apply.go b/backend/local/backend_apply.go index bfcf7f506..d754573d4 100644 --- a/backend/local/backend_apply.go +++ b/backend/local/backend_apply.go @@ -80,18 +80,6 @@ func (b *Local) opApply( // If we weren't given a plan, then we refresh/plan if op.PlanFile == nil { - // If we're refreshing before apply, perform that - if op.PlanRefresh { - log.Printf("[INFO] backend/local: apply calling Refresh") - _, refreshDiags := tfCtx.Refresh() - diags = diags.Append(refreshDiags) - if diags.HasErrors() { - runningOp.Result = backend.OperationFailure - b.ShowDiagnostics(diags) - return - } - } - // Perform the plan log.Printf("[INFO] backend/local: apply calling Plan") plan, planDiags := tfCtx.Plan() diff --git a/backend/local/backend_plan.go b/backend/local/backend_plan.go index 4ce5f893c..da82e3116 100644 --- a/backend/local/backend_plan.go +++ b/backend/local/backend_plan.go @@ -97,27 +97,6 @@ func (b *Local) opPlan( runningOp.State = tfCtx.State() - // If we're refreshing before plan, perform that - baseState := runningOp.State - if op.PlanRefresh { - log.Printf("[INFO] backend/local: plan calling Refresh") - - if b.CLI != nil { - b.CLI.Output(b.Colorize().Color(strings.TrimSpace(planRefreshing) + "\n")) - } - - refreshedState, refreshDiags := tfCtx.Refresh() - diags = diags.Append(refreshDiags) - if diags.HasErrors() { - b.ReportResult(runningOp, diags) - return - } - baseState = refreshedState // plan will be relative to our refreshed state - if b.CLI != nil { - b.CLI.Output("\n------------------------------------------------------------------------") - } - } - // Perform the plan in a goroutine so we can be interrupted var plan *plans.Plan var planDiags tfdiags.Diagnostics @@ -142,6 +121,7 @@ func (b *Local) opPlan( b.ReportResult(runningOp, diags) return } + // Record whether this plan includes any side-effects that could be applied. runningOp.PlanEmpty = !planHasSideEffects(priorState, plan.Changes) @@ -161,7 +141,7 @@ func (b *Local) opPlan( // We may have updated the state in the refresh step above, but we // will freeze that updated state in the plan file for now and // only write it if this plan is subsequently applied. - plannedStateFile := statemgr.PlannedStateUpdate(opState, baseState) + plannedStateFile := statemgr.PlannedStateUpdate(opState, plan.State) log.Printf("[INFO] backend/local: writing plan output to: %s", path) err := planfile.Create(path, configSnap, plannedStateFile, plan) @@ -187,7 +167,7 @@ func (b *Local) opPlan( return } - b.renderPlan(plan, baseState, priorState, schemas) + b.renderPlan(plan, plan.State, priorState, schemas) // If we've accumulated any warnings along the way then we'll show them // here just before we show the summary and next steps. If we encountered diff --git a/terraform/node_resource_plan_instance.go b/terraform/node_resource_plan_instance.go index 4b9c2bde4..2071c5278 100644 --- a/terraform/node_resource_plan_instance.go +++ b/terraform/node_resource_plan_instance.go @@ -63,8 +63,7 @@ func (n *NodePlannableResourceInstance) evalTreeDataResource(addr addrs.AbsResou Addr: addr.Resource, Provider: &provider, ProviderSchema: &providerSchema, - - Output: &state, + Output: &state, }, &EvalValidateSelfRef{ @@ -108,7 +107,8 @@ func (n *NodePlannableResourceInstance) evalTreeManagedResource(addr addrs.AbsRe var provider providers.Interface var providerSchema *ProviderSchema var change *plans.ResourceInstanceChange - var state *states.ResourceInstanceObject + var refreshState *states.ResourceInstanceObject + var planState *states.ResourceInstanceObject return &EvalSequence{ Nodes: []EvalNode{ @@ -118,19 +118,40 @@ func (n *NodePlannableResourceInstance) evalTreeManagedResource(addr addrs.AbsRe Schema: &providerSchema, }, - &EvalReadState{ - Addr: addr.Resource, - Provider: &provider, - ProviderSchema: &providerSchema, - Output: &state, - }, - &EvalValidateSelfRef{ Addr: addr.Resource, Config: config.Config, ProviderSchema: &providerSchema, }, + // Refresh the instance + &EvalReadState{ + Addr: addr.Resource, + Provider: &provider, + ProviderSchema: &providerSchema, + Output: &refreshState, + }, + &EvalRefreshDependencies{ + State: &refreshState, + Dependencies: &n.Dependencies, + }, + &EvalRefresh{ + Addr: addr.Resource, + ProviderAddr: n.ResolvedProvider, + Provider: &provider, + ProviderMetas: n.ProviderMetas, + ProviderSchema: &providerSchema, + State: &refreshState, + Output: &refreshState, + }, + &EvalWriteState{ + Addr: addr.Resource, + ProviderAddr: n.ResolvedProvider, + State: &refreshState, + ProviderSchema: &providerSchema, + }, + + // Plan the instance &EvalDiff{ Addr: addr.Resource, Config: n.Config, @@ -139,9 +160,9 @@ func (n *NodePlannableResourceInstance) evalTreeManagedResource(addr addrs.AbsRe ProviderAddr: n.ResolvedProvider, ProviderMetas: n.ProviderMetas, ProviderSchema: &providerSchema, - State: &state, + State: &refreshState, OutputChange: &change, - OutputState: &state, + OutputState: &planState, }, &EvalCheckPreventDestroy{ Addr: addr.Resource, @@ -151,7 +172,7 @@ func (n *NodePlannableResourceInstance) evalTreeManagedResource(addr addrs.AbsRe &EvalWriteState{ Addr: addr.Resource, ProviderAddr: n.ResolvedProvider, - State: &state, + State: &planState, ProviderSchema: &providerSchema, }, &EvalWriteDiff{