]> git.immae.eu Git - github/fretlink/terraform-provider-statuscake.git/blame - vendor/github.com/hashicorp/terraform/terraform/node_data_refresh.go
update vendor and go.mod
[github/fretlink/terraform-provider-statuscake.git] / vendor / github.com / hashicorp / terraform / terraform / node_data_refresh.go
CommitLineData
bae9f6d2
JC
1package terraform
2
3import (
4 "github.com/hashicorp/terraform/dag"
107c1cdb
ND
5 "github.com/hashicorp/terraform/plans"
6 "github.com/hashicorp/terraform/providers"
7 "github.com/hashicorp/terraform/states"
8 "github.com/hashicorp/terraform/tfdiags"
9 "github.com/zclconf/go-cty/cty"
bae9f6d2
JC
10)
11
107c1cdb 12// NodeRefreshableDataResource represents a resource that is "refreshable".
bae9f6d2 13type NodeRefreshableDataResource struct {
107c1cdb 14 *NodeAbstractResource
bae9f6d2
JC
15}
16
107c1cdb
ND
17var (
18 _ GraphNodeSubPath = (*NodeRefreshableDataResource)(nil)
19 _ GraphNodeDynamicExpandable = (*NodeRefreshableDataResource)(nil)
20 _ GraphNodeReferenceable = (*NodeRefreshableDataResource)(nil)
21 _ GraphNodeReferencer = (*NodeRefreshableDataResource)(nil)
22 _ GraphNodeResource = (*NodeRefreshableDataResource)(nil)
23 _ GraphNodeAttachResourceConfig = (*NodeRefreshableDataResource)(nil)
24)
25
bae9f6d2
JC
26// GraphNodeDynamicExpandable
27func (n *NodeRefreshableDataResource) DynamicExpand(ctx EvalContext) (*Graph, error) {
107c1cdb
ND
28 var diags tfdiags.Diagnostics
29
30 count, countKnown, countDiags := evaluateResourceCountExpressionKnown(n.Config.Count, ctx)
31 diags = diags.Append(countDiags)
32 if countDiags.HasErrors() {
33 return nil, diags.Err()
34 }
35 if !countKnown {
36 // If the count isn't known yet, we'll skip refreshing and try expansion
37 // again during the plan walk.
38 return nil, nil
bae9f6d2
JC
39 }
40
863486a6
AG
41 forEachMap, forEachKnown, forEachDiags := evaluateResourceForEachExpressionKnown(n.Config.ForEach, ctx)
42 if forEachDiags.HasErrors() {
43 return nil, diags.Err()
44 }
45 if !forEachKnown {
46 // If the for_each isn't known yet, we'll skip refreshing and try expansion
47 // again during the plan walk.
48 return nil, nil
49 }
50
107c1cdb
ND
51 // Next we need to potentially rename an instance address in the state
52 // if we're transitioning whether "count" is set at all.
53 fixResourceCountSetTransition(ctx, n.ResourceAddr(), count != -1)
54
55 // Our graph transformers require access to the full state, so we'll
56 // temporarily lock it while we work on this.
57 state := ctx.State().Lock()
58 defer ctx.State().Unlock()
59
bae9f6d2 60 // The concrete resource factory we'll use
107c1cdb 61 concreteResource := func(a *NodeAbstractResourceInstance) dag.Vertex {
bae9f6d2
JC
62 // Add the config and state since we don't do that via transforms
63 a.Config = n.Config
15c0b25d 64 a.ResolvedProvider = n.ResolvedProvider
bae9f6d2
JC
65
66 return &NodeRefreshableDataResourceInstance{
107c1cdb 67 NodeAbstractResourceInstance: a,
bae9f6d2
JC
68 }
69 }
70
9b12e4fe
JC
71 // We also need a destroyable resource for orphans that are a result of a
72 // scaled-in count.
107c1cdb
ND
73 concreteResourceDestroyable := func(a *NodeAbstractResourceInstance) dag.Vertex {
74 // Add the config and provider since we don't do that via transforms
9b12e4fe 75 a.Config = n.Config
107c1cdb 76 a.ResolvedProvider = n.ResolvedProvider
9b12e4fe 77
107c1cdb
ND
78 return &NodeDestroyableDataResourceInstance{
79 NodeAbstractResourceInstance: a,
9b12e4fe
JC
80 }
81 }
82
bae9f6d2
JC
83 // Start creating the steps
84 steps := []GraphTransformer{
85 // Expand the count.
86 &ResourceCountTransformer{
87 Concrete: concreteResource,
107c1cdb 88 Schema: n.Schema,
bae9f6d2 89 Count: count,
863486a6 90 ForEach: forEachMap,
bae9f6d2
JC
91 Addr: n.ResourceAddr(),
92 },
93
9b12e4fe
JC
94 // Add the count orphans. As these are orphaned refresh nodes, we add them
95 // directly as NodeDestroyableDataResource.
96 &OrphanResourceCountTransformer{
97 Concrete: concreteResourceDestroyable,
98 Count: count,
863486a6 99 ForEach: forEachMap,
9b12e4fe
JC
100 Addr: n.ResourceAddr(),
101 State: state,
102 },
103
bae9f6d2
JC
104 // Attach the state
105 &AttachStateTransformer{State: state},
106
107 // Targeting
107c1cdb 108 &TargetsTransformer{Targets: n.Targets},
bae9f6d2
JC
109
110 // Connect references so ordering is correct
111 &ReferenceTransformer{},
112
113 // Make sure there is a single root
114 &RootTransformer{},
115 }
116
117 // Build the graph
118 b := &BasicGraphBuilder{
119 Steps: steps,
120 Validate: true,
121 Name: "NodeRefreshableDataResource",
122 }
123
107c1cdb
ND
124 graph, diags := b.Build(ctx.Path())
125 return graph, diags.ErrWithWarnings()
bae9f6d2
JC
126}
127
107c1cdb 128// NodeRefreshableDataResourceInstance represents a single resource instance
bae9f6d2
JC
129// that is refreshable.
130type NodeRefreshableDataResourceInstance struct {
107c1cdb 131 *NodeAbstractResourceInstance
bae9f6d2
JC
132}
133
134// GraphNodeEvalable
135func (n *NodeRefreshableDataResourceInstance) EvalTree() EvalNode {
107c1cdb 136 addr := n.ResourceInstanceAddr()
bae9f6d2 137
107c1cdb
ND
138 // These variables are the state for the eval sequence below, and are
139 // updated through pointers.
140 var provider providers.Interface
141 var providerSchema *ProviderSchema
142 var change *plans.ResourceInstanceChange
143 var state *states.ResourceInstanceObject
144 var configVal cty.Value
bae9f6d2
JC
145
146 return &EvalSequence{
147 Nodes: []EvalNode{
107c1cdb
ND
148 &EvalGetProvider{
149 Addr: n.ResolvedProvider,
150 Output: &provider,
151 Schema: &providerSchema,
152 },
153
bae9f6d2
JC
154 // Always destroy the existing state first, since we must
155 // make sure that values from a previous read will not
156 // get interpolated if we end up needing to defer our
157 // loading until apply time.
158 &EvalWriteState{
107c1cdb
ND
159 Addr: addr.Resource,
160 ProviderAddr: n.ResolvedProvider,
161 State: &state, // a pointer to nil, here
162 ProviderSchema: &providerSchema,
bae9f6d2
JC
163 },
164
bae9f6d2
JC
165 &EvalIf{
166 If: func(ctx EvalContext) (bool, error) {
bae9f6d2
JC
167 // If the config explicitly has a depends_on for this
168 // data source, assume the intention is to prevent
107c1cdb
ND
169 // refreshing ahead of that dependency, and therefore
170 // we need to deal with this resource during the apply
171 // phase..
bae9f6d2
JC
172 if len(n.Config.DependsOn) > 0 {
173 return true, EvalEarlyExitError{}
174 }
175
176 return true, nil
177 },
bae9f6d2
JC
178 Then: EvalNoop{},
179 },
180
107c1cdb
ND
181 // EvalReadData will _attempt_ to read the data source, but may
182 // generate an incomplete planned object if the configuration
183 // includes values that won't be known until apply.
184 &EvalReadData{
185 Addr: addr.Resource,
186 Config: n.Config,
187 Dependencies: n.StateReferences(),
188 Provider: &provider,
189 ProviderAddr: n.ResolvedProvider,
190 ProviderSchema: &providerSchema,
191 OutputChange: &change,
192 OutputConfigValue: &configVal,
193 OutputState: &state,
bae9f6d2
JC
194 },
195
107c1cdb
ND
196 &EvalIf{
197 If: func(ctx EvalContext) (bool, error) {
198 return (*state).Status != states.ObjectPlanned, nil
199 },
200 Then: &EvalSequence{
201 Nodes: []EvalNode{
202 &EvalWriteState{
203 Addr: addr.Resource,
204 ProviderAddr: n.ResolvedProvider,
205 State: &state,
206 ProviderSchema: &providerSchema,
207 },
208 &EvalUpdateStateHook{},
209 },
210 },
211 Else: &EvalSequence{
212 // We can't deal with this yet, so we'll repeat this step
213 // during the plan walk to produce a planned change to read
214 // this during the apply walk. However, we do still need to
215 // save the generated change and partial state so that
216 // results from it can be included in other data resources
217 // or provider configurations during the refresh walk.
218 // (The planned object we save in the state here will be
219 // pruned out at the end of the refresh walk, returning
220 // it back to being unset again for subsequent walks.)
221 Nodes: []EvalNode{
222 &EvalWriteDiff{
223 Addr: addr.Resource,
224 Change: &change,
225 ProviderSchema: &providerSchema,
226 },
227 &EvalWriteState{
228 Addr: addr.Resource,
229 ProviderAddr: n.ResolvedProvider,
230 State: &state,
231 ProviderSchema: &providerSchema,
232 },
233 },
234 },
bae9f6d2 235 },
bae9f6d2
JC
236 },
237 }
238}