github.com/paybyphone/terraform@v0.9.5-0.20170613192930-9706042ddd51/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 outputs 75 &OutputTransformer{Module: b.Module}, 76 77 // Add orphan resources 78 &OrphanResourceTransformer{ 79 Concrete: b.ConcreteResourceOrphan, 80 State: b.State, 81 Module: b.Module, 82 }, 83 84 // Attach the configuration to any resources 85 &AttachResourceConfigTransformer{Module: b.Module}, 86 87 // Attach the state 88 &AttachStateTransformer{State: b.State}, 89 90 // Add root variables 91 &RootVariableTransformer{Module: b.Module}, 92 93 // Create all the providers 94 &MissingProviderTransformer{Providers: b.Providers, Concrete: b.ConcreteProvider}, 95 &ProviderTransformer{}, 96 &DisableProviderTransformer{}, 97 &ParentProviderTransformer{}, 98 &AttachProviderConfigTransformer{Module: b.Module}, 99 100 // Provisioner-related transformations. Only add these if requested. 101 GraphTransformIf( 102 func() bool { return b.Provisioners != nil }, 103 GraphTransformMulti( 104 &MissingProvisionerTransformer{Provisioners: b.Provisioners}, 105 &ProvisionerTransformer{}, 106 ), 107 ), 108 109 // Add module variables 110 &ModuleVariableTransformer{Module: b.Module}, 111 112 // Connect so that the references are ready for targeting. We'll 113 // have to connect again later for providers and so on. 114 &ReferenceTransformer{}, 115 116 // Add the node to fix the state count boundaries 117 &CountBoundaryTransformer{}, 118 119 // Target 120 &TargetsTransformer{Targets: b.Targets}, 121 122 // Close opened plugin connections 123 &CloseProviderTransformer{}, 124 &CloseProvisionerTransformer{}, 125 126 // Single root 127 &RootTransformer{}, 128 } 129 130 if !b.DisableReduce { 131 // Perform the transitive reduction to make our graph a bit 132 // more sane if possible (it usually is possible). 133 steps = append(steps, &TransitiveReductionTransformer{}) 134 } 135 136 return steps 137 } 138 139 func (b *PlanGraphBuilder) init() { 140 // Do nothing if the user requests customizing the fields 141 if b.CustomConcrete { 142 return 143 } 144 145 b.ConcreteProvider = func(a *NodeAbstractProvider) dag.Vertex { 146 return &NodeApplyableProvider{ 147 NodeAbstractProvider: a, 148 } 149 } 150 151 b.ConcreteResource = func(a *NodeAbstractResource) dag.Vertex { 152 return &NodePlannableResource{ 153 NodeAbstractCountResource: &NodeAbstractCountResource{ 154 NodeAbstractResource: a, 155 }, 156 } 157 } 158 159 b.ConcreteResourceOrphan = func(a *NodeAbstractResource) dag.Vertex { 160 return &NodePlannableResourceOrphan{ 161 NodeAbstractResource: a, 162 } 163 } 164 }