github.com/wikibal01/hashicorp-terraform@v0.11.12-beta1/terraform/graph_builder_plan.go (about) 1 package terraform 2 3 import ( 4 "sync" 5 6 "github.com/hashicorp/terraform/config/module" 7 "github.com/hashicorp/terraform/dag" 8 ) 9 10 // PlanGraphBuilder implements GraphBuilder and is responsible for building 11 // a graph for planning (creating a Terraform Diff). 12 // 13 // The primary difference between this graph and others: 14 // 15 // * Based on the config since it represents the target state 16 // 17 // * Ignores lifecycle options since no lifecycle events occur here. This 18 // simplifies the graph significantly since complex transforms such as 19 // create-before-destroy can be completely ignored. 20 // 21 type PlanGraphBuilder struct { 22 // Module is the root module for the graph to build. 23 Module *module.Tree 24 25 // State is the current state 26 State *State 27 28 // Providers is the list of providers supported. 29 Providers []string 30 31 // Provisioners is the list of provisioners supported. 32 Provisioners []string 33 34 // Targets are resources to target 35 Targets []string 36 37 // DisableReduce, if true, will not reduce the graph. Great for testing. 38 DisableReduce bool 39 40 // Validate will do structural validation of the graph. 41 Validate bool 42 43 // CustomConcrete can be set to customize the node types created 44 // for various parts of the plan. This is useful in order to customize 45 // the plan behavior. 46 CustomConcrete bool 47 ConcreteProvider ConcreteProviderNodeFunc 48 ConcreteResource ConcreteResourceNodeFunc 49 ConcreteResourceOrphan ConcreteResourceNodeFunc 50 51 once sync.Once 52 } 53 54 // See GraphBuilder 55 func (b *PlanGraphBuilder) Build(path []string) (*Graph, error) { 56 return (&BasicGraphBuilder{ 57 Steps: b.Steps(), 58 Validate: b.Validate, 59 Name: "PlanGraphBuilder", 60 }).Build(path) 61 } 62 63 // See GraphBuilder 64 func (b *PlanGraphBuilder) Steps() []GraphTransformer { 65 b.once.Do(b.init) 66 67 steps := []GraphTransformer{ 68 // Creates all the resources represented in the config 69 &ConfigTransformer{ 70 Concrete: b.ConcreteResource, 71 Module: b.Module, 72 }, 73 74 // Add the local values 75 &LocalTransformer{Module: b.Module}, 76 77 // Add the outputs 78 &OutputTransformer{Module: b.Module}, 79 80 // Add orphan resources 81 &OrphanResourceTransformer{ 82 Concrete: b.ConcreteResourceOrphan, 83 State: b.State, 84 Module: b.Module, 85 }, 86 87 // Create orphan output nodes 88 &OrphanOutputTransformer{ 89 Module: b.Module, 90 State: b.State, 91 }, 92 93 // Attach the configuration to any resources 94 &AttachResourceConfigTransformer{Module: b.Module}, 95 96 // Attach the state 97 &AttachStateTransformer{State: b.State}, 98 99 // Add root variables 100 &RootVariableTransformer{Module: b.Module}, 101 102 TransformProviders(b.Providers, b.ConcreteProvider, b.Module), 103 104 // Provisioner-related transformations. Only add these if requested. 105 GraphTransformIf( 106 func() bool { return b.Provisioners != nil }, 107 GraphTransformMulti( 108 &MissingProvisionerTransformer{Provisioners: b.Provisioners}, 109 &ProvisionerTransformer{}, 110 ), 111 ), 112 113 // Add module variables 114 &ModuleVariableTransformer{ 115 Module: b.Module, 116 }, 117 118 // Remove modules no longer present in the config 119 &RemovedModuleTransformer{Module: b.Module, State: b.State}, 120 121 // Connect so that the references are ready for targeting. We'll 122 // have to connect again later for providers and so on. 123 &ReferenceTransformer{}, 124 125 // Add the node to fix the state count boundaries 126 &CountBoundaryTransformer{}, 127 128 // Target 129 &TargetsTransformer{ 130 Targets: b.Targets, 131 132 // Resource nodes from config have not yet been expanded for 133 // "count", so we must apply targeting without indices. Exact 134 // targeting will be dealt with later when these resources 135 // DynamicExpand. 136 IgnoreIndices: true, 137 }, 138 139 // Close opened plugin connections 140 &CloseProviderTransformer{}, 141 &CloseProvisionerTransformer{}, 142 143 // Single root 144 &RootTransformer{}, 145 } 146 147 if !b.DisableReduce { 148 // Perform the transitive reduction to make our graph a bit 149 // more sane if possible (it usually is possible). 150 steps = append(steps, &TransitiveReductionTransformer{}) 151 } 152 153 return steps 154 } 155 156 func (b *PlanGraphBuilder) init() { 157 // Do nothing if the user requests customizing the fields 158 if b.CustomConcrete { 159 return 160 } 161 162 b.ConcreteProvider = func(a *NodeAbstractProvider) dag.Vertex { 163 return &NodeApplyableProvider{ 164 NodeAbstractProvider: a, 165 } 166 } 167 168 b.ConcreteResource = func(a *NodeAbstractResource) dag.Vertex { 169 return &NodePlannableResource{ 170 NodeAbstractCountResource: &NodeAbstractCountResource{ 171 NodeAbstractResource: a, 172 }, 173 } 174 } 175 176 b.ConcreteResourceOrphan = func(a *NodeAbstractResource) dag.Vertex { 177 return &NodePlannableResourceOrphan{ 178 NodeAbstractResource: a, 179 } 180 } 181 }