github.com/ggriffiths/terraform@v0.9.0-beta1.0.20170222213024-79c4935604cb/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 // Target 117 &TargetsTransformer{Targets: b.Targets}, 118 119 // Single root 120 &RootTransformer{}, 121 } 122 123 if !b.DisableReduce { 124 // Perform the transitive reduction to make our graph a bit 125 // more sane if possible (it usually is possible). 126 steps = append(steps, &TransitiveReductionTransformer{}) 127 } 128 129 return steps 130 } 131 132 func (b *PlanGraphBuilder) init() { 133 // Do nothing if the user requests customizing the fields 134 if b.CustomConcrete { 135 return 136 } 137 138 b.ConcreteProvider = func(a *NodeAbstractProvider) dag.Vertex { 139 return &NodeApplyableProvider{ 140 NodeAbstractProvider: a, 141 } 142 } 143 144 b.ConcreteResource = func(a *NodeAbstractResource) dag.Vertex { 145 return &NodePlannableResource{ 146 NodeAbstractCountResource: &NodeAbstractCountResource{ 147 NodeAbstractResource: a, 148 }, 149 } 150 } 151 152 b.ConcreteResourceOrphan = func(a *NodeAbstractResource) dag.Vertex { 153 return &NodePlannableResourceOrphan{ 154 NodeAbstractResource: a, 155 } 156 } 157 }