@@ -14,10 +14,12 @@ import (
1414 "github.com/hashicorp/hcl/v2"
1515 "github.com/zclconf/go-cty/cty"
1616
17+ "github.com/hashicorp/terraform/internal/addrs"
1718 "github.com/hashicorp/terraform/internal/backend/backendrun"
1819 "github.com/hashicorp/terraform/internal/command/arguments"
1920 "github.com/hashicorp/terraform/internal/configs"
2021 "github.com/hashicorp/terraform/internal/configs/configload"
22+ "github.com/hashicorp/terraform/internal/depsfile"
2123 "github.com/hashicorp/terraform/internal/lang"
2224 "github.com/hashicorp/terraform/internal/plans/planfile"
2325 "github.com/hashicorp/terraform/internal/states/statemgr"
@@ -26,7 +28,7 @@ import (
2628)
2729
2830// backendrun.Local implementation.
29- func (b * Local ) LocalRun (op * backendrun.Operation ) (* backendrun.LocalRun , statemgr.Full , tfdiags.Diagnostics ) {
31+ func (b * Local ) LocalRun (ctx context. Context , op * backendrun.Operation ) (* backendrun.LocalRun , statemgr.Full , tfdiags.Diagnostics ) {
3032 // Make sure the type is invalid. We use this as a way to know not
3133 // to ask for input/validate. We're modifying this through a pointer,
3234 // so we're mutating an object that belongs to the caller here, which
@@ -35,7 +37,7 @@ func (b *Local) LocalRun(op *backendrun.Operation) (*backendrun.LocalRun, statem
3537 // happens to do.
3638 op .Type = backendrun .OperationTypeInvalid
3739
38- op .StateLocker = op .StateLocker .WithContext (context . Background () )
40+ op .StateLocker = op .StateLocker .WithContext (ctx )
3941
4042 lr , _ , stateMgr , diags := b .localRun (op )
4143 return lr , stateMgr , diags
@@ -70,8 +72,6 @@ func (b *Local) localRun(op *backendrun.Operation) (*backendrun.LocalRun, *confi
7072 return nil , nil , nil , diags
7173 }
7274
73- ret := & backendrun.LocalRun {}
74-
7575 // Initialize our context options
7676 var coreOpts terraform.ContextOpts
7777 if v := b .ContextOpts ; v != nil {
@@ -80,11 +80,16 @@ func (b *Local) localRun(op *backendrun.Operation) (*backendrun.LocalRun, *confi
8080 coreOpts .UIInput = op .UIIn
8181 coreOpts .Hooks = op .Hooks
8282
83+ // the run must be closed now
84+ ret := & backendrun.LocalRun {
85+ PolicyClient : op .PolicyClient ,
86+ }
87+
8388 var ctxDiags tfdiags.Diagnostics
8489 var configSnap * configload.Snapshot
8590 if op .PlanFile .IsCloud () {
8691 diags = diags .Append (fmt .Errorf ("error: using a saved cloud plan when executing Terraform locally is not supported" ))
87- return nil , nil , nil , diags
92+ return ret , nil , nil , diags
8893 }
8994
9095 if lp , ok := op .PlanFile .Local (); ok {
@@ -100,7 +105,7 @@ func (b *Local) localRun(op *backendrun.Operation) (*backendrun.LocalRun, *confi
100105 ret , configSnap , ctxDiags = b .localRunForPlanFile (op , lp , ret , & coreOpts , stateMeta )
101106 if ctxDiags .HasErrors () {
102107 diags = diags .Append (ctxDiags )
103- return nil , nil , nil , diags
108+ return ret , nil , nil , diags
104109 }
105110
106111 // Write sources into the cache of the main loader so that they are
@@ -112,7 +117,7 @@ func (b *Local) localRun(op *backendrun.Operation) (*backendrun.LocalRun, *confi
112117 }
113118 diags = diags .Append (ctxDiags )
114119 if diags .HasErrors () {
115- return nil , nil , nil , diags
120+ return ret , nil , nil , diags
116121 }
117122
118123 // If we have an operation, then we automatically do the input/validate
@@ -126,7 +131,7 @@ func (b *Local) localRun(op *backendrun.Operation) (*backendrun.LocalRun, *confi
126131 inputDiags := ret .Core .Input (ret .Config , mode )
127132 diags = diags .Append (inputDiags )
128133 if inputDiags .HasErrors () {
129- return nil , nil , nil , diags
134+ return ret , nil , nil , diags
130135 }
131136 }
132137
@@ -149,7 +154,7 @@ func (b *Local) localRunDirect(op *backendrun.Operation, run *backendrun.LocalRu
149154 rootMod , configDiags := op .ConfigLoader .LoadRootModule (op .ConfigDir )
150155 diags = diags .Append (configDiags )
151156 if configDiags .HasErrors () {
152- return nil , nil , diags
157+ return run , nil , diags
153158 }
154159
155160 var rawVariables map [string ]arguments.UnparsedVariableValue
@@ -170,7 +175,7 @@ func (b *Local) localRunDirect(op *backendrun.Operation, run *backendrun.LocalRu
170175 variables , varDiags := backendrun .ParseVariableValues (rawVariables , rootMod .Variables )
171176 diags = diags .Append (varDiags )
172177 if diags .HasErrors () {
173- return nil , nil , diags
178+ return run , nil , diags
174179 }
175180
176181 planOpts := & terraform.PlanOpts {
@@ -183,6 +188,8 @@ func (b *Local) localRunDirect(op *backendrun.Operation, run *backendrun.LocalRu
183188 GenerateConfigPath : op .GenerateConfigOut ,
184189 DeferralAllowed : op .DeferralAllowed ,
185190 Query : op .Query ,
191+ Locks : providerLocksSnapshot (op .DependencyLocks ),
192+ PolicyClient : run .PolicyClient ,
186193 }
187194 run .PlanOpts = planOpts
188195
@@ -193,7 +200,7 @@ func (b *Local) localRunDirect(op *backendrun.Operation, run *backendrun.LocalRu
193200 tfCtx , moreDiags := terraform .NewContext (coreOpts )
194201 diags = diags .Append (moreDiags )
195202 if moreDiags .HasErrors () {
196- return nil , nil , diags
203+ return run , nil , diags
197204 }
198205 run .Core = tfCtx
199206
@@ -261,7 +268,7 @@ func (b *Local) localRunForPlanFile(op *backendrun.Operation, pf *planfile.Reade
261268 errSummary ,
262269 fmt .Sprintf ("Failed to read configuration snapshot from plan file: %s." , err ),
263270 ))
264- return nil , snap , diags
271+ return run , snap , diags
265272 }
266273 loader := configload .NewLoaderFromSnapshot (snap )
267274 loader .AllowLanguageExperiments (op .ConfigLoader .AllowsLanguageExperiments ())
@@ -299,7 +306,7 @@ func (b *Local) localRunForPlanFile(op *backendrun.Operation, pf *planfile.Reade
299306 errSummary ,
300307 fmt .Sprintf ("Failed to read prior state snapshot from plan file: %s." , err ),
301308 ))
302- return nil , snap , diags
309+ return run , snap , diags
303310 }
304311
305312 if currentStateMeta != nil {
@@ -343,7 +350,7 @@ func (b *Local) localRunForPlanFile(op *backendrun.Operation, pf *planfile.Reade
343350 errSummary ,
344351 fmt .Sprintf ("Failed to read plan from plan file: %s." , err ),
345352 ))
346- return nil , snap , diags
353+ return run , snap , diags
347354 }
348355 // When we're applying a saved plan, we populate Plan instead of PlanOpts,
349356 // because a plan object incorporates the subset of data from PlanOps that
@@ -377,7 +384,7 @@ func (b *Local) localRunForPlanFile(op *backendrun.Operation, pf *planfile.Reade
377384 tfCtx , moreDiags := terraform .NewContext (coreOpts )
378385 diags = diags .Append (moreDiags )
379386 if moreDiags .HasErrors () {
380- return nil , nil , diags
387+ return run , nil , diags
381388 }
382389 run .Core = tfCtx
383390
@@ -596,3 +603,12 @@ func (v unparsedTestVariableValue) ParseVariableValue(mode configs.VariableParsi
596603 SourceRange : tfdiags .SourceRangeFromHCL (v .Expr .Range ()),
597604 }, diags
598605}
606+
607+ // providerLocksSnapshot returns a read-only snapshot of provider locks for
608+ // use during graph walks. Returns nil if locks is nil.
609+ func providerLocksSnapshot (locks * depsfile.Locks ) map [addrs.Provider ]* depsfile.ProviderLock {
610+ if locks == nil {
611+ return nil
612+ }
613+ return locks .AllProviders ()
614+ }
0 commit comments