github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/not-internal/terraform/graph_builder_plan.go (about) 1 package terraform 2 3 import ( 4 "sync" 5 6 "github.com/muratcelep/terraform/not-internal/addrs" 7 "github.com/muratcelep/terraform/not-internal/configs" 8 "github.com/muratcelep/terraform/not-internal/dag" 9 "github.com/muratcelep/terraform/not-internal/states" 10 "github.com/muratcelep/terraform/not-internal/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 // Plugins is a library of plug-in components (providers and 32 // provisioners) available for use. 33 Plugins *contextPlugins 34 35 // Targets are resources to target 36 Targets []addrs.Targetable 37 38 // ForceReplace are resource instances where if we would normally have 39 // generated a NoOp or Update action then we'll force generating a replace 40 // action instead. Create and Delete actions are not affected. 41 ForceReplace []addrs.AbsResourceInstance 42 43 // Validate will do structural validation of the graph. 44 Validate bool 45 46 // skipRefresh indicates that we should skip refreshing managed resources 47 skipRefresh bool 48 49 // skipPlanChanges indicates that we should skip the step of comparing 50 // prior state with configuration and generating planned changes to 51 // resource instances. (This is for the "refresh only" planning mode, 52 // where we _only_ do the refresh step.) 53 skipPlanChanges bool 54 55 // CustomConcrete can be set to customize the node types created 56 // for various parts of the plan. This is useful in order to customize 57 // the plan behavior. 58 CustomConcrete bool 59 ConcreteProvider ConcreteProviderNodeFunc 60 ConcreteResource ConcreteResourceNodeFunc 61 ConcreteResourceOrphan ConcreteResourceInstanceNodeFunc 62 ConcreteModule ConcreteModuleNodeFunc 63 64 once sync.Once 65 } 66 67 // See GraphBuilder 68 func (b *PlanGraphBuilder) Build(path addrs.ModuleInstance) (*Graph, tfdiags.Diagnostics) { 69 return (&BasicGraphBuilder{ 70 Steps: b.Steps(), 71 Validate: b.Validate, 72 Name: "PlanGraphBuilder", 73 }).Build(path) 74 } 75 76 // See GraphBuilder 77 func (b *PlanGraphBuilder) Steps() []GraphTransformer { 78 b.once.Do(b.init) 79 80 concreteResourceInstanceDeposed := func(a *NodeAbstractResourceInstance, key states.DeposedKey) dag.Vertex { 81 return &NodePlanDeposedResourceInstanceObject{ 82 NodeAbstractResourceInstance: a, 83 DeposedKey: key, 84 85 skipRefresh: b.skipRefresh, 86 skipPlanChanges: b.skipPlanChanges, 87 } 88 } 89 90 steps := []GraphTransformer{ 91 // Creates all the resources represented in the config 92 &ConfigTransformer{ 93 Concrete: b.ConcreteResource, 94 Config: b.Config, 95 }, 96 97 // Add dynamic values 98 &RootVariableTransformer{Config: b.Config}, 99 &ModuleVariableTransformer{Config: b.Config}, 100 &LocalTransformer{Config: b.Config}, 101 &OutputTransformer{Config: b.Config}, 102 103 // Add orphan resources 104 &OrphanResourceInstanceTransformer{ 105 Concrete: b.ConcreteResourceOrphan, 106 State: b.State, 107 Config: b.Config, 108 }, 109 110 // We also need nodes for any deposed instance objects present in the 111 // state, so we can plan to destroy them. (This intentionally 112 // skips creating nodes for _current_ objects, since ConfigTransformer 113 // created nodes that will do that during DynamicExpand.) 114 &StateTransformer{ 115 ConcreteDeposed: concreteResourceInstanceDeposed, 116 State: b.State, 117 }, 118 119 // Attach the state 120 &AttachStateTransformer{State: b.State}, 121 122 // Create orphan output nodes 123 &OrphanOutputTransformer{Config: b.Config, State: b.State}, 124 125 // Attach the configuration to any resources 126 &AttachResourceConfigTransformer{Config: b.Config}, 127 128 // add providers 129 transformProviders(b.ConcreteProvider, b.Config), 130 131 // Remove modules no longer present in the config 132 &RemovedModuleTransformer{Config: b.Config, State: b.State}, 133 134 // Must attach schemas before ReferenceTransformer so that we can 135 // analyze the configuration to find references. 136 &AttachSchemaTransformer{Plugins: b.Plugins, Config: b.Config}, 137 138 // Create expansion nodes for all of the module calls. This must 139 // come after all other transformers that create nodes representing 140 // objects that can belong to modules. 141 &ModuleExpansionTransformer{Concrete: b.ConcreteModule, Config: b.Config}, 142 143 // Connect so that the references are ready for targeting. We'll 144 // have to connect again later for providers and so on. 145 &ReferenceTransformer{}, 146 &AttachDependenciesTransformer{}, 147 148 // Make sure data sources are aware of any depends_on from the 149 // configuration 150 &attachDataResourceDependsOnTransformer{}, 151 152 // Target 153 &TargetsTransformer{Targets: b.Targets}, 154 155 // Detect when create_before_destroy must be forced on for a particular 156 // node due to dependency edges, to avoid graph cycles during apply. 157 &ForcedCBDTransformer{}, 158 159 // Close opened plugin connections 160 &CloseProviderTransformer{}, 161 162 // Close the root module 163 &CloseRootModuleTransformer{}, 164 165 // Perform the transitive reduction to make our graph a bit 166 // more understandable if possible (it usually is possible). 167 &TransitiveReductionTransformer{}, 168 } 169 170 return steps 171 } 172 173 func (b *PlanGraphBuilder) init() { 174 // Do nothing if the user requests customizing the fields 175 if b.CustomConcrete { 176 return 177 } 178 179 b.ConcreteProvider = func(a *NodeAbstractProvider) dag.Vertex { 180 return &NodeApplyableProvider{ 181 NodeAbstractProvider: a, 182 } 183 } 184 185 b.ConcreteResource = func(a *NodeAbstractResource) dag.Vertex { 186 return &nodeExpandPlannableResource{ 187 NodeAbstractResource: a, 188 skipRefresh: b.skipRefresh, 189 skipPlanChanges: b.skipPlanChanges, 190 forceReplace: b.ForceReplace, 191 } 192 } 193 194 b.ConcreteResourceOrphan = func(a *NodeAbstractResourceInstance) dag.Vertex { 195 return &NodePlannableResourceInstanceOrphan{ 196 NodeAbstractResourceInstance: a, 197 skipRefresh: b.skipRefresh, 198 skipPlanChanges: b.skipPlanChanges, 199 } 200 } 201 }