github.com/hooklift/terraform@v0.11.0-beta1.0.20171117000744-6786c1361ffe/terraform/graph_builder_refresh.go (about) 1 package terraform 2 3 import ( 4 "log" 5 6 "github.com/hashicorp/terraform/config" 7 "github.com/hashicorp/terraform/config/module" 8 "github.com/hashicorp/terraform/dag" 9 ) 10 11 // RefreshGraphBuilder implements GraphBuilder and is responsible for building 12 // a graph for refreshing (updating the Terraform state). 13 // 14 // The primary difference between this graph and others: 15 // 16 // * Based on the state since it represents the only resources that 17 // need to be refreshed. 18 // 19 // * Ignores lifecycle options since no lifecycle events occur here. This 20 // simplifies the graph significantly since complex transforms such as 21 // create-before-destroy can be completely ignored. 22 // 23 type RefreshGraphBuilder struct { 24 // Module is the root module for the graph to build. 25 Module *module.Tree 26 27 // State is the current state 28 State *State 29 30 // Providers is the list of providers supported. 31 Providers []string 32 33 // Targets are resources to target 34 Targets []string 35 36 // DisableReduce, if true, will not reduce the graph. Great for testing. 37 DisableReduce bool 38 39 // Validate will do structural validation of the graph. 40 Validate bool 41 } 42 43 // See GraphBuilder 44 func (b *RefreshGraphBuilder) Build(path []string) (*Graph, error) { 45 return (&BasicGraphBuilder{ 46 Steps: b.Steps(), 47 Validate: b.Validate, 48 Name: "RefreshGraphBuilder", 49 }).Build(path) 50 } 51 52 // See GraphBuilder 53 func (b *RefreshGraphBuilder) Steps() []GraphTransformer { 54 // Custom factory for creating providers. 55 concreteProvider := func(a *NodeAbstractProvider) dag.Vertex { 56 return &NodeApplyableProvider{ 57 NodeAbstractProvider: a, 58 } 59 } 60 61 concreteManagedResource := func(a *NodeAbstractResource) dag.Vertex { 62 return &NodeRefreshableManagedResource{ 63 NodeAbstractCountResource: &NodeAbstractCountResource{ 64 NodeAbstractResource: a, 65 }, 66 } 67 } 68 69 concreteManagedResourceInstance := func(a *NodeAbstractResource) dag.Vertex { 70 return &NodeRefreshableManagedResourceInstance{ 71 NodeAbstractResource: a, 72 } 73 } 74 75 concreteDataResource := func(a *NodeAbstractResource) dag.Vertex { 76 return &NodeRefreshableDataResource{ 77 NodeAbstractCountResource: &NodeAbstractCountResource{ 78 NodeAbstractResource: a, 79 }, 80 } 81 } 82 83 steps := []GraphTransformer{ 84 // Creates all the managed resources that aren't in the state, but only if 85 // we have a state already. No resources in state means there's not 86 // anything to refresh. 87 func() GraphTransformer { 88 if b.State.HasResources() { 89 return &ConfigTransformer{ 90 Concrete: concreteManagedResource, 91 Module: b.Module, 92 Unique: true, 93 ModeFilter: true, 94 Mode: config.ManagedResourceMode, 95 } 96 } 97 log.Println("[TRACE] No managed resources in state during refresh, skipping managed resource transformer") 98 return nil 99 }(), 100 101 // Creates all the data resources that aren't in the state. This will also 102 // add any orphans from scaling in as destroy nodes. 103 &ConfigTransformer{ 104 Concrete: concreteDataResource, 105 Module: b.Module, 106 Unique: true, 107 ModeFilter: true, 108 Mode: config.DataResourceMode, 109 }, 110 111 // Add any fully-orphaned resources from config (ones that have been 112 // removed completely, not ones that are just orphaned due to a scaled-in 113 // count. 114 &OrphanResourceTransformer{ 115 Concrete: concreteManagedResourceInstance, 116 State: b.State, 117 Module: b.Module, 118 }, 119 120 // Attach the state 121 &AttachStateTransformer{State: b.State}, 122 123 // Attach the configuration to any resources 124 &AttachResourceConfigTransformer{Module: b.Module}, 125 126 // Add root variables 127 &RootVariableTransformer{Module: b.Module}, 128 129 TransformProviders(b.Providers, concreteProvider, b.Module), 130 131 // Add the local values 132 &LocalTransformer{Module: b.Module}, 133 134 // Add the outputs 135 &OutputTransformer{Module: b.Module}, 136 137 // Add module variables 138 &ModuleVariableTransformer{Module: b.Module}, 139 140 // Connect so that the references are ready for targeting. We'll 141 // have to connect again later for providers and so on. 142 &ReferenceTransformer{}, 143 144 // Target 145 &TargetsTransformer{ 146 Targets: b.Targets, 147 148 // Resource nodes from config have not yet been expanded for 149 // "count", so we must apply targeting without indices. Exact 150 // targeting will be dealt with later when these resources 151 // DynamicExpand. 152 IgnoreIndices: true, 153 }, 154 155 // Close opened plugin connections 156 &CloseProviderTransformer{}, 157 158 // Single root 159 &RootTransformer{}, 160 } 161 162 if !b.DisableReduce { 163 // Perform the transitive reduction to make our graph a bit 164 // more sane if possible (it usually is possible). 165 steps = append(steps, &TransitiveReductionTransformer{}) 166 } 167 168 return steps 169 }