github.com/r3labs/terraform@v0.8.4/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 GraphTransformIf( 100 func() bool { return !b.Destroy }, 101 GraphTransformMulti( 102 &MissingProvisionerTransformer{Provisioners: b.Provisioners}, 103 &ProvisionerTransformer{}, 104 ), 105 ), 106 107 // Add root variables 108 &RootVariableTransformer{Module: b.Module}, 109 110 // Add the outputs 111 &OutputTransformer{Module: b.Module}, 112 113 // Add module variables 114 &ModuleVariableTransformer{Module: b.Module}, 115 116 // Connect references so ordering is correct 117 &ReferenceTransformer{}, 118 119 // Add the node to fix the state count boundaries 120 &CountBoundaryTransformer{}, 121 122 // Single root 123 &RootTransformer{}, 124 } 125 126 if !b.DisableReduce { 127 // Perform the transitive reduction to make our graph a bit 128 // more sane if possible (it usually is possible). 129 steps = append(steps, &TransitiveReductionTransformer{}) 130 } 131 132 return steps 133 }