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