github.com/muratcelep/terraform@v1.1.0-beta2-not-internal-4/not-internal/terraform/graph_builder_apply.go (about) 1 package terraform 2 3 import ( 4 "github.com/muratcelep/terraform/not-internal/addrs" 5 "github.com/muratcelep/terraform/not-internal/configs" 6 "github.com/muratcelep/terraform/not-internal/dag" 7 "github.com/muratcelep/terraform/not-internal/plans" 8 "github.com/muratcelep/terraform/not-internal/states" 9 "github.com/muratcelep/terraform/not-internal/tfdiags" 10 ) 11 12 // ApplyGraphBuilder implements GraphBuilder and is responsible for building 13 // a graph for applying a Terraform diff. 14 // 15 // Because the graph is built from the diff (vs. the config or state), 16 // this helps ensure that the apply-time graph doesn't modify any resources 17 // that aren't explicitly in the diff. There are other scenarios where the 18 // diff can be deviated, so this is just one layer of protection. 19 type ApplyGraphBuilder struct { 20 // Config is the configuration tree that the diff was built from. 21 Config *configs.Config 22 23 // Changes describes the changes that we need apply. 24 Changes *plans.Changes 25 26 // State is the current state 27 State *states.State 28 29 // Plugins is a library of the plug-in components (providers and 30 // provisioners) available for use. 31 Plugins *contextPlugins 32 33 // Targets are resources to target. This is only required to make sure 34 // unnecessary outputs aren't included in the apply graph. The plan 35 // builder successfully handles targeting resources. In the future, 36 // outputs should go into the diff so that this is unnecessary. 37 Targets []addrs.Targetable 38 39 // ForceReplace are the resource instance addresses that the user 40 // requested to force replacement for when creating the plan, if any. 41 // The apply step refers to these as part of verifying that the planned 42 // actions remain consistent between plan and apply. 43 ForceReplace []addrs.AbsResourceInstance 44 45 // Validate will do structural validation of the graph. 46 Validate bool 47 } 48 49 // See GraphBuilder 50 func (b *ApplyGraphBuilder) Build(path addrs.ModuleInstance) (*Graph, tfdiags.Diagnostics) { 51 return (&BasicGraphBuilder{ 52 Steps: b.Steps(), 53 Validate: b.Validate, 54 Name: "ApplyGraphBuilder", 55 }).Build(path) 56 } 57 58 // See GraphBuilder 59 func (b *ApplyGraphBuilder) Steps() []GraphTransformer { 60 // Custom factory for creating providers. 61 concreteProvider := func(a *NodeAbstractProvider) dag.Vertex { 62 return &NodeApplyableProvider{ 63 NodeAbstractProvider: a, 64 } 65 } 66 67 concreteResource := func(a *NodeAbstractResource) dag.Vertex { 68 return &nodeExpandApplyableResource{ 69 NodeAbstractResource: a, 70 } 71 } 72 73 concreteResourceInstance := func(a *NodeAbstractResourceInstance) dag.Vertex { 74 return &NodeApplyableResourceInstance{ 75 NodeAbstractResourceInstance: a, 76 forceReplace: b.ForceReplace, 77 } 78 } 79 80 steps := []GraphTransformer{ 81 // Creates all the resources represented in the config. During apply, 82 // we use this just to ensure that the whole-resource metadata is 83 // updated to reflect things such as whether the count argument is 84 // set in config, or which provider configuration manages each resource. 85 &ConfigTransformer{ 86 Concrete: concreteResource, 87 Config: b.Config, 88 }, 89 90 // Add dynamic values 91 &RootVariableTransformer{Config: b.Config}, 92 &ModuleVariableTransformer{Config: b.Config}, 93 &LocalTransformer{Config: b.Config}, 94 &OutputTransformer{Config: b.Config, Changes: b.Changes}, 95 96 // Creates all the resource instances represented in the diff, along 97 // with dependency edges against the whole-resource nodes added by 98 // ConfigTransformer above. 99 &DiffTransformer{ 100 Concrete: concreteResourceInstance, 101 State: b.State, 102 Changes: b.Changes, 103 }, 104 105 // Attach the state 106 &AttachStateTransformer{State: b.State}, 107 108 // Create orphan output nodes 109 &OrphanOutputTransformer{Config: b.Config, State: b.State}, 110 111 // Attach the configuration to any resources 112 &AttachResourceConfigTransformer{Config: b.Config}, 113 114 // add providers 115 transformProviders(concreteProvider, b.Config), 116 117 // Remove modules no longer present in the config 118 &RemovedModuleTransformer{Config: b.Config, State: b.State}, 119 120 // Must attach schemas before ReferenceTransformer so that we can 121 // analyze the configuration to find references. 122 &AttachSchemaTransformer{Plugins: b.Plugins, Config: b.Config}, 123 124 // Create expansion nodes for all of the module calls. This must 125 // come after all other transformers that create nodes representing 126 // objects that can belong to modules. 127 &ModuleExpansionTransformer{Config: b.Config}, 128 129 // Connect references so ordering is correct 130 &ReferenceTransformer{}, 131 &AttachDependenciesTransformer{}, 132 133 // Detect when create_before_destroy must be forced on for a particular 134 // node due to dependency edges, to avoid graph cycles during apply. 135 &ForcedCBDTransformer{}, 136 137 // Destruction ordering 138 &DestroyEdgeTransformer{ 139 Config: b.Config, 140 State: b.State, 141 }, 142 &CBDEdgeTransformer{ 143 Config: b.Config, 144 State: b.State, 145 }, 146 147 // We need to remove configuration nodes that are not used at all, as 148 // they may not be able to evaluate, especially during destroy. 149 // These include variables, locals, and instance expanders. 150 &pruneUnusedNodesTransformer{}, 151 152 // Target 153 &TargetsTransformer{Targets: b.Targets}, 154 155 // Close opened plugin connections 156 &CloseProviderTransformer{}, 157 158 // close the root module 159 &CloseRootModuleTransformer{}, 160 161 // Perform the transitive reduction to make our graph a bit 162 // more understandable if possible (it usually is possible). 163 &TransitiveReductionTransformer{}, 164 } 165 166 return steps 167 }