6 "github.com/hashicorp/terraform/config"
7 "github.com/hashicorp/terraform/config/module"
8 "github.com/hashicorp/terraform/dag"
11 // RefreshGraphBuilder implements GraphBuilder and is responsible for building
12 // a graph for refreshing (updating the Terraform state).
14 // The primary difference between this graph and others:
16 // * Based on the state since it represents the only resources that
17 // need to be refreshed.
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.
23 type RefreshGraphBuilder struct {
24 // Module is the root module for the graph to build.
27 // State is the current state
30 // Providers is the list of providers supported.
33 // Targets are resources to target
36 // DisableReduce, if true, will not reduce the graph. Great for testing.
39 // Validate will do structural validation of the graph.
44 func (b *RefreshGraphBuilder) Build(path []string) (*Graph, error) {
45 return (&BasicGraphBuilder{
48 Name: "RefreshGraphBuilder",
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,
61 concreteManagedResource := func(a *NodeAbstractResource) dag.Vertex {
62 return &NodeRefreshableManagedResource{
63 NodeAbstractCountResource: &NodeAbstractCountResource{
64 NodeAbstractResource: a,
69 concreteManagedResourceInstance := func(a *NodeAbstractResource) dag.Vertex {
70 return &NodeRefreshableManagedResourceInstance{
71 NodeAbstractResource: a,
75 concreteDataResource := func(a *NodeAbstractResource) dag.Vertex {
76 return &NodeRefreshableDataResource{
77 NodeAbstractCountResource: &NodeAbstractCountResource{
78 NodeAbstractResource: a,
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,
94 Mode: config.ManagedResourceMode,
97 log.Println("[TRACE] No managed resources in state during refresh, skipping managed resource transformer")
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.
104 Concrete: concreteDataResource,
108 Mode: config.DataResourceMode,
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
114 &OrphanResourceTransformer{
115 Concrete: concreteManagedResourceInstance,
121 &AttachStateTransformer{State: b.State},
123 // Attach the configuration to any resources
124 &AttachResourceConfigTransformer{Module: b.Module},
126 // Add root variables
127 &RootVariableTransformer{Module: b.Module},
129 // Create all the providers
130 &MissingProviderTransformer{Providers: b.Providers, Concrete: concreteProvider},
131 &ProviderTransformer{},
132 &DisableProviderTransformer{},
133 &ParentProviderTransformer{},
134 &AttachProviderConfigTransformer{Module: b.Module},
137 &OutputTransformer{Module: b.Module},
139 // Add module variables
140 &ModuleVariableTransformer{Module: b.Module},
142 // Connect so that the references are ready for targeting. We'll
143 // have to connect again later for providers and so on.
144 &ReferenceTransformer{},
150 // Resource nodes from config have not yet been expanded for
151 // "count", so we must apply targeting without indices. Exact
152 // targeting will be dealt with later when these resources
157 // Close opened plugin connections
158 &CloseProviderTransformer{},
164 if !b.DisableReduce {
165 // Perform the transitive reduction to make our graph a bit
166 // more sane if possible (it usually is possible).
167 steps = append(steps, &TransitiveReductionTransformer{})