github.com/rstandt/terraform@v0.12.32-0.20230710220336-b1063613405c/terraform/graph_builder_plan.go (about) 1 package terraform 2 3 import ( 4 "sync" 5 6 "github.com/hashicorp/terraform/addrs" 7 "github.com/hashicorp/terraform/configs" 8 "github.com/hashicorp/terraform/dag" 9 "github.com/hashicorp/terraform/states" 10 "github.com/hashicorp/terraform/tfdiags" 11 ) 12 13 // PlanGraphBuilder implements GraphBuilder and is responsible for building 14 // a graph for planning (creating a Terraform Diff). 15 // 16 // The primary difference between this graph and others: 17 // 18 // * Based on the config since it represents the target state 19 // 20 // * Ignores lifecycle options since no lifecycle events occur here. This 21 // simplifies the graph significantly since complex transforms such as 22 // create-before-destroy can be completely ignored. 23 // 24 type PlanGraphBuilder struct { 25 // Config is the configuration tree to build a plan from. 26 Config *configs.Config 27 28 // State is the current state 29 State *states.State 30 31 // Components is a factory for the plug-in components (providers and 32 // provisioners) available for use. 33 Components contextComponentFactory 34 35 // Schemas is the repository of schemas we will draw from to analyse 36 // the configuration. 37 Schemas *Schemas 38 39 // Targets are resources to target 40 Targets []addrs.Targetable 41 42 // DisableReduce, if true, will not reduce the graph. Great for testing. 43 DisableReduce bool 44 45 // Validate will do structural validation of the graph. 46 Validate bool 47 48 // CustomConcrete can be set to customize the node types created 49 // for various parts of the plan. This is useful in order to customize 50 // the plan behavior. 51 CustomConcrete bool 52 ConcreteProvider ConcreteProviderNodeFunc 53 ConcreteResource ConcreteResourceNodeFunc 54 ConcreteResourceOrphan ConcreteResourceInstanceNodeFunc 55 56 once sync.Once 57 } 58 59 // See GraphBuilder 60 func (b *PlanGraphBuilder) Build(path addrs.ModuleInstance) (*Graph, tfdiags.Diagnostics) { 61 return (&BasicGraphBuilder{ 62 Steps: b.Steps(), 63 Validate: b.Validate, 64 Name: "PlanGraphBuilder", 65 }).Build(path) 66 } 67 68 // See GraphBuilder 69 func (b *PlanGraphBuilder) Steps() []GraphTransformer { 70 b.once.Do(b.init) 71 72 concreteResourceInstanceDeposed := func(a *NodeAbstractResourceInstance, key states.DeposedKey) dag.Vertex { 73 return &NodePlanDeposedResourceInstanceObject{ 74 NodeAbstractResourceInstance: a, 75 DeposedKey: key, 76 } 77 } 78 79 steps := []GraphTransformer{ 80 // Creates all the resources represented in the config 81 &ConfigTransformer{ 82 Concrete: b.ConcreteResource, 83 Config: b.Config, 84 }, 85 86 // Add the local values 87 &LocalTransformer{Config: b.Config}, 88 89 // Add the outputs 90 &OutputTransformer{Config: b.Config}, 91 92 // Add orphan resources 93 &OrphanResourceInstanceTransformer{ 94 Concrete: b.ConcreteResourceOrphan, 95 State: b.State, 96 Config: b.Config, 97 }, 98 99 // We also need nodes for any deposed instance objects present in the 100 // state, so we can plan to destroy them. (This intentionally 101 // skips creating nodes for _current_ objects, since ConfigTransformer 102 // created nodes that will do that during DynamicExpand.) 103 &StateTransformer{ 104 ConcreteDeposed: concreteResourceInstanceDeposed, 105 State: b.State, 106 }, 107 108 // Create orphan output nodes 109 &OrphanOutputTransformer{ 110 Config: b.Config, 111 State: b.State, 112 }, 113 114 // Attach the configuration to any resources 115 &AttachResourceConfigTransformer{Config: b.Config}, 116 117 // Attach the state 118 &AttachStateTransformer{State: b.State}, 119 120 // Add root variables 121 &RootVariableTransformer{Config: b.Config}, 122 123 &MissingProvisionerTransformer{Provisioners: b.Components.ResourceProvisioners()}, 124 &ProvisionerTransformer{}, 125 126 // Add module variables 127 &ModuleVariableTransformer{ 128 Config: b.Config, 129 }, 130 131 TransformProviders(b.Components.ResourceProviders(), b.ConcreteProvider, b.Config), 132 133 // Remove modules no longer present in the config 134 &RemovedModuleTransformer{Config: b.Config, State: b.State}, 135 136 // Must attach schemas before ReferenceTransformer so that we can 137 // analyze the configuration to find references. 138 &AttachSchemaTransformer{Schemas: b.Schemas}, 139 140 // Connect so that the references are ready for targeting. We'll 141 // have to connect again later for providers and so on. 142 &ReferenceTransformer{}, 143 144 // Add the node to fix the state count boundaries 145 &CountBoundaryTransformer{ 146 Config: b.Config, 147 }, 148 149 // Target 150 &TargetsTransformer{ 151 Targets: b.Targets, 152 153 // Resource nodes from config have not yet been expanded for 154 // "count", so we must apply targeting without indices. Exact 155 // targeting will be dealt with later when these resources 156 // DynamicExpand. 157 IgnoreIndices: true, 158 }, 159 160 // Detect when create_before_destroy must be forced on for a particular 161 // node due to dependency edges, to avoid graph cycles during apply. 162 &ForcedCBDTransformer{}, 163 164 // Close opened plugin connections 165 &CloseProviderTransformer{}, 166 &CloseProvisionerTransformer{}, 167 168 // Single root 169 &RootTransformer{}, 170 } 171 172 if !b.DisableReduce { 173 // Perform the transitive reduction to make our graph a bit 174 // more sane if possible (it usually is possible). 175 steps = append(steps, &TransitiveReductionTransformer{}) 176 } 177 178 return steps 179 } 180 181 func (b *PlanGraphBuilder) init() { 182 // Do nothing if the user requests customizing the fields 183 if b.CustomConcrete { 184 return 185 } 186 187 b.ConcreteProvider = func(a *NodeAbstractProvider) dag.Vertex { 188 return &NodeApplyableProvider{ 189 NodeAbstractProvider: a, 190 } 191 } 192 193 b.ConcreteResource = func(a *NodeAbstractResource) dag.Vertex { 194 return &NodePlannableResource{ 195 NodeAbstractResource: a, 196 } 197 } 198 199 b.ConcreteResourceOrphan = func(a *NodeAbstractResourceInstance) dag.Vertex { 200 return &NodePlannableResourceInstanceOrphan{ 201 NodeAbstractResourceInstance: a, 202 } 203 } 204 }