github.com/ns1/terraform@v0.7.10-0.20161109153551-8949419bef40/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 38 // See GraphBuilder 39 func (b *ApplyGraphBuilder) Build(path []string) (*Graph, error) { 40 return (&BasicGraphBuilder{ 41 Steps: b.Steps(), 42 Validate: true, 43 Name: "apply", 44 }).Build(path) 45 } 46 47 // See GraphBuilder 48 func (b *ApplyGraphBuilder) Steps() []GraphTransformer { 49 // Custom factory for creating providers. 50 providerFactory := func(name string, path []string) GraphNodeProvider { 51 return &NodeApplyableProvider{ 52 NameValue: name, 53 PathValue: path, 54 } 55 } 56 57 concreteResource := func(a *NodeAbstractResource) dag.Vertex { 58 return &NodeApplyableResource{ 59 NodeAbstractResource: a, 60 } 61 } 62 63 steps := []GraphTransformer{ 64 // Creates all the nodes represented in the diff. 65 &DiffTransformer{ 66 Concrete: concreteResource, 67 68 Diff: b.Diff, 69 Module: b.Module, 70 State: b.State, 71 }, 72 73 // Create orphan output nodes 74 &OrphanOutputTransformer{Module: b.Module, State: b.State}, 75 76 // Attach the configuration to any resources 77 &AttachResourceConfigTransformer{Module: b.Module}, 78 79 // Attach the state 80 &AttachStateTransformer{State: b.State}, 81 82 // Destruction ordering 83 &DestroyEdgeTransformer{Module: b.Module, State: b.State}, 84 GraphTransformIf( 85 func() bool { return !b.Destroy }, 86 &CBDEdgeTransformer{Module: b.Module, State: b.State}, 87 ), 88 89 // Create all the providers 90 &MissingProviderTransformer{Providers: b.Providers, Factory: providerFactory}, 91 &ProviderTransformer{}, 92 &DisableProviderTransformer{}, 93 &ParentProviderTransformer{}, 94 &AttachProviderConfigTransformer{Module: b.Module}, 95 96 // Provisioner-related transformations 97 GraphTransformIf( 98 func() bool { return !b.Destroy }, 99 GraphTransformMulti( 100 &MissingProvisionerTransformer{Provisioners: b.Provisioners}, 101 &ProvisionerTransformer{}, 102 ), 103 ), 104 105 // Add root variables 106 &RootVariableTransformer{Module: b.Module}, 107 108 // Add the outputs 109 &OutputTransformer{Module: b.Module}, 110 111 // Add module variables 112 &ModuleVariableTransformer{Module: b.Module}, 113 114 // Connect references so ordering is correct 115 &ReferenceTransformer{}, 116 117 // Add the node to fix the state count boundaries 118 &CountBoundaryTransformer{}, 119 120 // Single root 121 &RootTransformer{}, 122 } 123 124 if !b.DisableReduce { 125 // Perform the transitive reduction to make our graph a bit 126 // more sane if possible (it usually is possible). 127 steps = append(steps, &TransitiveReductionTransformer{}) 128 } 129 130 return steps 131 }