github.com/pbthorste/terraform@v0.8.6-0.20170127005045-deb56bd93da2/terraform/graph_builder_apply.go (about) 1 package terraform 2 3 import ( 4 "github.com/hashicorp/terraform/config/module" 5 "github.com/hashicorp/terraform/dag" 6 ) 7 8 // ApplyGraphBuilder implements GraphBuilder and is responsible for building 9 // a graph for applying a Terraform diff. 10 // 11 // Because the graph is built from the diff (vs. the config or state), 12 // this helps ensure that the apply-time graph doesn't modify any resources 13 // that aren't explicitly in the diff. There are other scenarios where the 14 // diff can be deviated, so this is just one layer of protection. 15 type ApplyGraphBuilder struct { 16 // Module is the root module for the graph to build. 17 Module *module.Tree 18 19 // Diff is the diff to apply. 20 Diff *Diff 21 22 // State is the current state 23 State *State 24 25 // Providers is the list of providers supported. 26 Providers []string 27 28 // Provisioners is the list of provisioners supported. 29 Provisioners []string 30 31 // DisableReduce, if true, will not reduce the graph. Great for testing. 32 DisableReduce bool 33 34 // Destroy, if true, represents a pure destroy operation 35 Destroy bool 36 37 // Validate will do structural validation of the graph. 38 Validate bool 39 } 40 41 // See GraphBuilder 42 func (b *ApplyGraphBuilder) Build(path []string) (*Graph, error) { 43 return (&BasicGraphBuilder{ 44 Steps: b.Steps(), 45 Validate: b.Validate, 46 Name: "ApplyGraphBuilder", 47 }).Build(path) 48 } 49 50 // See GraphBuilder 51 func (b *ApplyGraphBuilder) Steps() []GraphTransformer { 52 // Custom factory for creating providers. 53 concreteProvider := func(a *NodeAbstractProvider) dag.Vertex { 54 return &NodeApplyableProvider{ 55 NodeAbstractProvider: a, 56 } 57 } 58 59 concreteResource := func(a *NodeAbstractResource) dag.Vertex { 60 return &NodeApplyableResource{ 61 NodeAbstractResource: a, 62 } 63 } 64 65 steps := []GraphTransformer{ 66 // Creates all the nodes represented in the diff. 67 &DiffTransformer{ 68 Concrete: concreteResource, 69 70 Diff: b.Diff, 71 Module: b.Module, 72 State: b.State, 73 }, 74 75 // Create orphan output nodes 76 &OrphanOutputTransformer{Module: b.Module, State: b.State}, 77 78 // Attach the configuration to any resources 79 &AttachResourceConfigTransformer{Module: b.Module}, 80 81 // Attach the state 82 &AttachStateTransformer{State: b.State}, 83 84 // Create all the providers 85 &MissingProviderTransformer{Providers: b.Providers, Concrete: concreteProvider}, 86 &ProviderTransformer{}, 87 &DisableProviderTransformer{}, 88 &ParentProviderTransformer{}, 89 &AttachProviderConfigTransformer{Module: b.Module}, 90 91 // Destruction ordering 92 &DestroyEdgeTransformer{Module: b.Module, State: b.State}, 93 GraphTransformIf( 94 func() bool { return !b.Destroy }, 95 &CBDEdgeTransformer{Module: b.Module, State: b.State}, 96 ), 97 98 // Provisioner-related transformations 99 &MissingProvisionerTransformer{Provisioners: b.Provisioners}, 100 &ProvisionerTransformer{}, 101 102 // Add root variables 103 &RootVariableTransformer{Module: b.Module}, 104 105 // Add the outputs 106 &OutputTransformer{Module: b.Module}, 107 108 // Add module variables 109 &ModuleVariableTransformer{Module: b.Module}, 110 111 // Connect references so ordering is correct 112 &ReferenceTransformer{}, 113 114 // Add the node to fix the state count boundaries 115 &CountBoundaryTransformer{}, 116 117 // Single root 118 &RootTransformer{}, 119 } 120 121 if !b.DisableReduce { 122 // Perform the transitive reduction to make our graph a bit 123 // more sane if possible (it usually is possible). 124 steps = append(steps, &TransitiveReductionTransformer{}) 125 } 126 127 return steps 128 }