6 "github.com/hashicorp/terraform/states"
7 "github.com/hashicorp/terraform/tfdiags"
9 "github.com/hashicorp/terraform/addrs"
10 "github.com/hashicorp/terraform/configs"
11 "github.com/hashicorp/terraform/dag"
14 // RefreshGraphBuilder implements GraphBuilder and is responsible for building
15 // a graph for refreshing (updating the Terraform state).
17 // The primary difference between this graph and others:
19 // * Based on the state since it represents the only resources that
20 // need to be refreshed.
22 // * Ignores lifecycle options since no lifecycle events occur here. This
23 // simplifies the graph significantly since complex transforms such as
24 // create-before-destroy can be completely ignored.
26 type RefreshGraphBuilder struct {
27 // Config is the configuration tree.
28 Config *configs.Config
30 // State is the prior state
33 // Components is a factory for the plug-in components (providers and
34 // provisioners) available for use.
35 Components contextComponentFactory
37 // Schemas is the repository of schemas we will draw from to analyse
41 // Targets are resources to target
42 Targets []addrs.Targetable
44 // DisableReduce, if true, will not reduce the graph. Great for testing.
47 // Validate will do structural validation of the graph.
52 func (b *RefreshGraphBuilder) Build(path addrs.ModuleInstance) (*Graph, tfdiags.Diagnostics) {
53 return (&BasicGraphBuilder{
56 Name: "RefreshGraphBuilder",
61 func (b *RefreshGraphBuilder) Steps() []GraphTransformer {
62 // Custom factory for creating providers.
63 concreteProvider := func(a *NodeAbstractProvider) dag.Vertex {
64 return &NodeApplyableProvider{
65 NodeAbstractProvider: a,
69 concreteManagedResource := func(a *NodeAbstractResource) dag.Vertex {
70 return &NodeRefreshableManagedResource{
71 NodeAbstractResource: a,
75 concreteManagedResourceInstance := func(a *NodeAbstractResourceInstance) dag.Vertex {
76 return &NodeRefreshableManagedResourceInstance{
77 NodeAbstractResourceInstance: a,
81 concreteResourceInstanceDeposed := func(a *NodeAbstractResourceInstance, key states.DeposedKey) dag.Vertex {
82 // The "Plan" node type also handles refreshing behavior.
83 return &NodePlanDeposedResourceInstanceObject{
84 NodeAbstractResourceInstance: a,
89 concreteDataResource := func(a *NodeAbstractResource) dag.Vertex {
90 return &NodeRefreshableDataResource{
91 NodeAbstractResource: a,
95 steps := []GraphTransformer{
96 // Creates all the managed resources that aren't in the state, but only if
97 // we have a state already. No resources in state means there's not
98 // anything to refresh.
99 func() GraphTransformer {
100 if b.State.HasResources() {
101 return &ConfigTransformer{
102 Concrete: concreteManagedResource,
106 Mode: addrs.ManagedResourceMode,
109 log.Println("[TRACE] No managed resources in state during refresh; skipping managed resource transformer")
113 // Creates all the data resources that aren't in the state. This will also
114 // add any orphans from scaling in as destroy nodes.
116 Concrete: concreteDataResource,
120 Mode: addrs.DataResourceMode,
123 // Add any fully-orphaned resources from config (ones that have been
124 // removed completely, not ones that are just orphaned due to a scaled-in
126 &OrphanResourceInstanceTransformer{
127 Concrete: concreteManagedResourceInstance,
132 // We also need nodes for any deposed instance objects present in the
133 // state, so we can check if they still exist. (This intentionally
134 // skips creating nodes for _current_ objects, since ConfigTransformer
135 // created nodes that will do that during DynamicExpand.)
137 ConcreteDeposed: concreteResourceInstanceDeposed,
142 &AttachStateTransformer{State: b.State},
144 // Attach the configuration to any resources
145 &AttachResourceConfigTransformer{Config: b.Config},
147 // Add root variables
148 &RootVariableTransformer{Config: b.Config},
150 // Add the local values
151 &LocalTransformer{Config: b.Config},
154 &OutputTransformer{Config: b.Config},
156 // Add module variables
157 &ModuleVariableTransformer{Config: b.Config},
159 TransformProviders(b.Components.ResourceProviders(), concreteProvider, b.Config),
161 // Must attach schemas before ReferenceTransformer so that we can
162 // analyze the configuration to find references.
163 &AttachSchemaTransformer{Schemas: b.Schemas},
165 // Connect so that the references are ready for targeting. We'll
166 // have to connect again later for providers and so on.
167 &ReferenceTransformer{},
173 // Resource nodes from config have not yet been expanded for
174 // "count", so we must apply targeting without indices. Exact
175 // targeting will be dealt with later when these resources
180 // Close opened plugin connections
181 &CloseProviderTransformer{},
187 if !b.DisableReduce {
188 // Perform the transitive reduction to make our graph a bit
189 // more sane if possible (it usually is possible).
190 steps = append(steps, &TransitiveReductionTransformer{})