11package terraform
22
33import (
4+ "log"
5+
46 "github.com/hashicorp/terraform/internal/addrs"
57 "github.com/hashicorp/terraform/internal/configs"
68 "github.com/hashicorp/terraform/internal/dag"
@@ -63,12 +65,16 @@ type PlanGraphBuilder struct {
6365 ConcreteResourceInstanceDeposed ConcreteResourceInstanceDeposedNodeFunc
6466 ConcreteModule ConcreteModuleNodeFunc
6567
66- // destroy is set to true when create a full destroy plan.
67- destroy bool
68+ // Plan Operation this graph will be used for.
69+ Operation walkOperation
70+
71+ // ImportTargets are the list of resources to import.
72+ ImportTargets []* ImportTarget
6873}
6974
7075// See GraphBuilder
7176func (b * PlanGraphBuilder ) Build (path addrs.ModuleInstance ) (* Graph , tfdiags.Diagnostics ) {
77+ log .Printf ("[TRACE] building graph for %s" , b .Operation )
7278 return (& BasicGraphBuilder {
7379 Steps : b .Steps (),
7480 Name : "PlanGraphBuilder" ,
@@ -77,14 +83,29 @@ func (b *PlanGraphBuilder) Build(path addrs.ModuleInstance) (*Graph, tfdiags.Dia
7783
7884// See GraphBuilder
7985func (b * PlanGraphBuilder ) Steps () []GraphTransformer {
80- b .init ()
86+ switch b .Operation {
87+ case walkPlan :
88+ b .initPlan ()
89+ case walkPlanDestroy :
90+ b .initDestroy ()
91+ case walkValidate :
92+ b .initValidate ()
93+ case walkImport :
94+ b .initImport ()
95+ default :
96+ panic ("invalid plan operation: " + b .Operation .String ())
97+ }
8198
8299 steps := []GraphTransformer {
83100 // Creates all the resources represented in the config
84101 & ConfigTransformer {
85102 Concrete : b .ConcreteResource ,
86103 Config : b .Config ,
87- skip : b .destroy ,
104+
105+ // Resources are not added from the config on destroy.
106+ skip : b .Operation == walkPlanDestroy ,
107+
108+ importTargets : b .ImportTargets ,
88109 },
89110
90111 // Add dynamic values
@@ -94,21 +115,22 @@ func (b *PlanGraphBuilder) Steps() []GraphTransformer {
94115 & OutputTransformer {
95116 Config : b .Config ,
96117 RefreshOnly : b .skipPlanChanges ,
97- removeRootOutputs : b .destroy ,
118+ removeRootOutputs : b .Operation == walkPlanDestroy ,
98119 },
99120
100121 // Add orphan resources
101122 & OrphanResourceInstanceTransformer {
102123 Concrete : b .ConcreteResourceOrphan ,
103124 State : b .State ,
104125 Config : b .Config ,
105- skip : b .destroy ,
126+ skip : b .Operation == walkPlanDestroy ,
106127 },
107128
108129 // We also need nodes for any deposed instance objects present in the
109- // state, so we can plan to destroy them. (This intentionally
110- // skips creating nodes for _current_ objects, since ConfigTransformer
111- // created nodes that will do that during DynamicExpand.)
130+ // state, so we can plan to destroy them. (During plan this will
131+ // intentionally skips creating nodes for _current_ objects, since
132+ // ConfigTransformer created nodes that will do that during
133+ // DynamicExpand.)
112134 & StateTransformer {
113135 ConcreteCurrent : b .ConcreteResourceInstance ,
114136 ConcreteDeposed : b .ConcreteResourceInstanceDeposed ,
@@ -172,12 +194,7 @@ func (b *PlanGraphBuilder) Steps() []GraphTransformer {
172194 return steps
173195}
174196
175- func (b * PlanGraphBuilder ) init () {
176- // Do nothing if the user requests customizing the fields
177- if b .CustomConcrete {
178- return
179- }
180-
197+ func (b * PlanGraphBuilder ) initPlan () {
181198 b .ConcreteProvider = func (a * NodeAbstractProvider ) dag.Vertex {
182199 return & NodeApplyableProvider {
183200 NodeAbstractProvider : a ,
@@ -210,5 +227,61 @@ func (b *PlanGraphBuilder) init() {
210227 skipPlanChanges : b .skipPlanChanges ,
211228 }
212229 }
230+ }
231+
232+ func (b * PlanGraphBuilder ) initDestroy () {
233+ b .initPlan ()
234+
235+ b .ConcreteResourceInstance = func (a * NodeAbstractResourceInstance ) dag.Vertex {
236+ return & NodePlanDestroyableResourceInstance {
237+ NodeAbstractResourceInstance : a ,
238+ skipRefresh : b .skipRefresh ,
239+ }
240+ }
241+ }
213242
243+ func (b * PlanGraphBuilder ) initValidate () {
244+ // Set the provider to the normal provider. This will ask for input.
245+ b .ConcreteProvider = func (a * NodeAbstractProvider ) dag.Vertex {
246+ return & NodeApplyableProvider {
247+ NodeAbstractProvider : a ,
248+ }
249+ }
250+
251+ b .ConcreteResource = func (a * NodeAbstractResource ) dag.Vertex {
252+ return & NodeValidatableResource {
253+ NodeAbstractResource : a ,
254+ }
255+ }
256+
257+ b .ConcreteModule = func (n * nodeExpandModule ) dag.Vertex {
258+ return & nodeValidateModule {
259+ nodeExpandModule : * n ,
260+ }
261+ }
262+ }
263+
264+ func (b * PlanGraphBuilder ) initImport () {
265+ b .ConcreteProvider = func (a * NodeAbstractProvider ) dag.Vertex {
266+ return & NodeApplyableProvider {
267+ NodeAbstractProvider : a ,
268+ }
269+ }
270+
271+ b .ConcreteResource = func (a * NodeAbstractResource ) dag.Vertex {
272+ return & nodeExpandPlannableResource {
273+ NodeAbstractResource : a ,
274+
275+ // For now we always skip planning changes for import, since we are
276+ // not going to combine importing with other changes. This is
277+ // temporary to try and maintain existing import behaviors, but
278+ // planning will need to be allowed for more complex configurations.
279+ skipPlanChanges : true ,
280+
281+ // We also skip refresh for now, since the plan output is written
282+ // as the new state, and users are not expecting the import process
283+ // to update any other instances in state.
284+ skipRefresh : true ,
285+ }
286+ }
214287}
0 commit comments