diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/states/module.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/states/module.go | 285 |
1 files changed, 285 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/states/module.go b/vendor/github.com/hashicorp/terraform/states/module.go new file mode 100644 index 0000000..d89e787 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/states/module.go | |||
@@ -0,0 +1,285 @@ | |||
1 | package states | ||
2 | |||
3 | import ( | ||
4 | "github.com/zclconf/go-cty/cty" | ||
5 | |||
6 | "github.com/hashicorp/terraform/addrs" | ||
7 | ) | ||
8 | |||
9 | // Module is a container for the states of objects within a particular module. | ||
10 | type Module struct { | ||
11 | Addr addrs.ModuleInstance | ||
12 | |||
13 | // Resources contains the state for each resource. The keys in this map are | ||
14 | // an implementation detail and must not be used by outside callers. | ||
15 | Resources map[string]*Resource | ||
16 | |||
17 | // OutputValues contains the state for each output value. The keys in this | ||
18 | // map are output value names. | ||
19 | OutputValues map[string]*OutputValue | ||
20 | |||
21 | // LocalValues contains the value for each named output value. The keys | ||
22 | // in this map are local value names. | ||
23 | LocalValues map[string]cty.Value | ||
24 | } | ||
25 | |||
26 | // NewModule constructs an empty module state for the given module address. | ||
27 | func NewModule(addr addrs.ModuleInstance) *Module { | ||
28 | return &Module{ | ||
29 | Addr: addr, | ||
30 | Resources: map[string]*Resource{}, | ||
31 | OutputValues: map[string]*OutputValue{}, | ||
32 | LocalValues: map[string]cty.Value{}, | ||
33 | } | ||
34 | } | ||
35 | |||
36 | // Resource returns the state for the resource with the given address within | ||
37 | // the receiving module state, or nil if the requested resource is not tracked | ||
38 | // in the state. | ||
39 | func (ms *Module) Resource(addr addrs.Resource) *Resource { | ||
40 | return ms.Resources[addr.String()] | ||
41 | } | ||
42 | |||
43 | // ResourceInstance returns the state for the resource instance with the given | ||
44 | // address within the receiving module state, or nil if the requested instance | ||
45 | // is not tracked in the state. | ||
46 | func (ms *Module) ResourceInstance(addr addrs.ResourceInstance) *ResourceInstance { | ||
47 | rs := ms.Resource(addr.Resource) | ||
48 | if rs == nil { | ||
49 | return nil | ||
50 | } | ||
51 | return rs.Instance(addr.Key) | ||
52 | } | ||
53 | |||
54 | // SetResourceMeta updates the resource-level metadata for the resource | ||
55 | // with the given address, creating the resource state for it if it doesn't | ||
56 | // already exist. | ||
57 | func (ms *Module) SetResourceMeta(addr addrs.Resource, eachMode EachMode, provider addrs.AbsProviderConfig) { | ||
58 | rs := ms.Resource(addr) | ||
59 | if rs == nil { | ||
60 | rs = &Resource{ | ||
61 | Addr: addr, | ||
62 | Instances: map[addrs.InstanceKey]*ResourceInstance{}, | ||
63 | } | ||
64 | ms.Resources[addr.String()] = rs | ||
65 | } | ||
66 | |||
67 | rs.EachMode = eachMode | ||
68 | rs.ProviderConfig = provider | ||
69 | } | ||
70 | |||
71 | // RemoveResource removes the entire state for the given resource, taking with | ||
72 | // it any instances associated with the resource. This should generally be | ||
73 | // called only for resource objects whose instances have all been destroyed. | ||
74 | func (ms *Module) RemoveResource(addr addrs.Resource) { | ||
75 | delete(ms.Resources, addr.String()) | ||
76 | } | ||
77 | |||
78 | // SetResourceInstanceCurrent saves the given instance object as the current | ||
79 | // generation of the resource instance with the given address, simulataneously | ||
80 | // updating the recorded provider configuration address, dependencies, and | ||
81 | // resource EachMode. | ||
82 | // | ||
83 | // Any existing current instance object for the given resource is overwritten. | ||
84 | // Set obj to nil to remove the primary generation object altogether. If there | ||
85 | // are no deposed objects then the instance will be removed altogether. | ||
86 | // | ||
87 | // The provider address and "each mode" are resource-wide settings and so they | ||
88 | // are updated for all other instances of the same resource as a side-effect of | ||
89 | // this call. | ||
90 | func (ms *Module) SetResourceInstanceCurrent(addr addrs.ResourceInstance, obj *ResourceInstanceObjectSrc, provider addrs.AbsProviderConfig) { | ||
91 | ms.SetResourceMeta(addr.Resource, eachModeForInstanceKey(addr.Key), provider) | ||
92 | |||
93 | rs := ms.Resource(addr.Resource) | ||
94 | is := rs.EnsureInstance(addr.Key) | ||
95 | |||
96 | is.Current = obj | ||
97 | |||
98 | if !is.HasObjects() { | ||
99 | // If we have no objects at all then we'll clean up. | ||
100 | delete(rs.Instances, addr.Key) | ||
101 | } | ||
102 | if rs.EachMode == NoEach && len(rs.Instances) == 0 { | ||
103 | // Also clean up if we only expect to have one instance anyway | ||
104 | // and there are none. We leave the resource behind if an each mode | ||
105 | // is active because an empty list or map of instances is a valid state. | ||
106 | delete(ms.Resources, addr.Resource.String()) | ||
107 | } | ||
108 | } | ||
109 | |||
110 | // SetResourceInstanceDeposed saves the given instance object as a deposed | ||
111 | // generation of the resource instance with the given address and deposed key. | ||
112 | // | ||
113 | // Call this method only for pre-existing deposed objects that already have | ||
114 | // a known DeposedKey. For example, this method is useful if reloading objects | ||
115 | // that were persisted to a state file. To mark the current object as deposed, | ||
116 | // use DeposeResourceInstanceObject instead. | ||
117 | // | ||
118 | // The resource that contains the given instance must already exist in the | ||
119 | // state, or this method will panic. Use Resource to check first if its | ||
120 | // presence is not already guaranteed. | ||
121 | // | ||
122 | // Any existing current instance object for the given resource and deposed key | ||
123 | // is overwritten. Set obj to nil to remove the deposed object altogether. If | ||
124 | // the instance is left with no objects after this operation then it will | ||
125 | // be removed from its containing resource altogether. | ||
126 | func (ms *Module) SetResourceInstanceDeposed(addr addrs.ResourceInstance, key DeposedKey, obj *ResourceInstanceObjectSrc, provider addrs.AbsProviderConfig) { | ||
127 | ms.SetResourceMeta(addr.Resource, eachModeForInstanceKey(addr.Key), provider) | ||
128 | |||
129 | rs := ms.Resource(addr.Resource) | ||
130 | is := rs.EnsureInstance(addr.Key) | ||
131 | if obj != nil { | ||
132 | is.Deposed[key] = obj | ||
133 | } else { | ||
134 | delete(is.Deposed, key) | ||
135 | } | ||
136 | |||
137 | if !is.HasObjects() { | ||
138 | // If we have no objects at all then we'll clean up. | ||
139 | delete(rs.Instances, addr.Key) | ||
140 | } | ||
141 | if rs.EachMode == NoEach && len(rs.Instances) == 0 { | ||
142 | // Also clean up if we only expect to have one instance anyway | ||
143 | // and there are none. We leave the resource behind if an each mode | ||
144 | // is active because an empty list or map of instances is a valid state. | ||
145 | delete(ms.Resources, addr.Resource.String()) | ||
146 | } | ||
147 | } | ||
148 | |||
149 | // ForgetResourceInstanceAll removes the record of all objects associated with | ||
150 | // the specified resource instance, if present. If not present, this is a no-op. | ||
151 | func (ms *Module) ForgetResourceInstanceAll(addr addrs.ResourceInstance) { | ||
152 | rs := ms.Resource(addr.Resource) | ||
153 | if rs == nil { | ||
154 | return | ||
155 | } | ||
156 | delete(rs.Instances, addr.Key) | ||
157 | |||
158 | if rs.EachMode == NoEach && len(rs.Instances) == 0 { | ||
159 | // Also clean up if we only expect to have one instance anyway | ||
160 | // and there are none. We leave the resource behind if an each mode | ||
161 | // is active because an empty list or map of instances is a valid state. | ||
162 | delete(ms.Resources, addr.Resource.String()) | ||
163 | } | ||
164 | } | ||
165 | |||
166 | // ForgetResourceInstanceDeposed removes the record of the deposed object with | ||
167 | // the given address and key, if present. If not present, this is a no-op. | ||
168 | func (ms *Module) ForgetResourceInstanceDeposed(addr addrs.ResourceInstance, key DeposedKey) { | ||
169 | rs := ms.Resource(addr.Resource) | ||
170 | if rs == nil { | ||
171 | return | ||
172 | } | ||
173 | is := rs.Instance(addr.Key) | ||
174 | if is == nil { | ||
175 | return | ||
176 | } | ||
177 | delete(is.Deposed, key) | ||
178 | |||
179 | if !is.HasObjects() { | ||
180 | // If we have no objects at all then we'll clean up. | ||
181 | delete(rs.Instances, addr.Key) | ||
182 | } | ||
183 | if rs.EachMode == NoEach && len(rs.Instances) == 0 { | ||
184 | // Also clean up if we only expect to have one instance anyway | ||
185 | // and there are none. We leave the resource behind if an each mode | ||
186 | // is active because an empty list or map of instances is a valid state. | ||
187 | delete(ms.Resources, addr.Resource.String()) | ||
188 | } | ||
189 | } | ||
190 | |||
191 | // deposeResourceInstanceObject is the real implementation of | ||
192 | // SyncState.DeposeResourceInstanceObject. | ||
193 | func (ms *Module) deposeResourceInstanceObject(addr addrs.ResourceInstance, forceKey DeposedKey) DeposedKey { | ||
194 | is := ms.ResourceInstance(addr) | ||
195 | if is == nil { | ||
196 | return NotDeposed | ||
197 | } | ||
198 | return is.deposeCurrentObject(forceKey) | ||
199 | } | ||
200 | |||
201 | // maybeRestoreResourceInstanceDeposed is the real implementation of | ||
202 | // SyncState.MaybeRestoreResourceInstanceDeposed. | ||
203 | func (ms *Module) maybeRestoreResourceInstanceDeposed(addr addrs.ResourceInstance, key DeposedKey) bool { | ||
204 | rs := ms.Resource(addr.Resource) | ||
205 | if rs == nil { | ||
206 | return false | ||
207 | } | ||
208 | is := rs.Instance(addr.Key) | ||
209 | if is == nil { | ||
210 | return false | ||
211 | } | ||
212 | if is.Current != nil { | ||
213 | return false | ||
214 | } | ||
215 | if len(is.Deposed) == 0 { | ||
216 | return false | ||
217 | } | ||
218 | is.Current = is.Deposed[key] | ||
219 | delete(is.Deposed, key) | ||
220 | return true | ||
221 | } | ||
222 | |||
223 | // SetOutputValue writes an output value into the state, overwriting any | ||
224 | // existing value of the same name. | ||
225 | func (ms *Module) SetOutputValue(name string, value cty.Value, sensitive bool) *OutputValue { | ||
226 | os := &OutputValue{ | ||
227 | Value: value, | ||
228 | Sensitive: sensitive, | ||
229 | } | ||
230 | ms.OutputValues[name] = os | ||
231 | return os | ||
232 | } | ||
233 | |||
234 | // RemoveOutputValue removes the output value of the given name from the state, | ||
235 | // if it exists. This method is a no-op if there is no value of the given | ||
236 | // name. | ||
237 | func (ms *Module) RemoveOutputValue(name string) { | ||
238 | delete(ms.OutputValues, name) | ||
239 | } | ||
240 | |||
241 | // SetLocalValue writes a local value into the state, overwriting any | ||
242 | // existing value of the same name. | ||
243 | func (ms *Module) SetLocalValue(name string, value cty.Value) { | ||
244 | ms.LocalValues[name] = value | ||
245 | } | ||
246 | |||
247 | // RemoveLocalValue removes the local value of the given name from the state, | ||
248 | // if it exists. This method is a no-op if there is no value of the given | ||
249 | // name. | ||
250 | func (ms *Module) RemoveLocalValue(name string) { | ||
251 | delete(ms.LocalValues, name) | ||
252 | } | ||
253 | |||
254 | // PruneResourceHusks is a specialized method that will remove any Resource | ||
255 | // objects that do not contain any instances, even if they have an EachMode. | ||
256 | // | ||
257 | // You probably shouldn't call this! See the method of the same name on | ||
258 | // type State for more information on what this is for and the rare situations | ||
259 | // where it is safe to use. | ||
260 | func (ms *Module) PruneResourceHusks() { | ||
261 | for _, rs := range ms.Resources { | ||
262 | if len(rs.Instances) == 0 { | ||
263 | ms.RemoveResource(rs.Addr) | ||
264 | } | ||
265 | } | ||
266 | } | ||
267 | |||
268 | // empty returns true if the receving module state is contributing nothing | ||
269 | // to the state. In other words, it returns true if the module could be | ||
270 | // removed from the state altogether without changing the meaning of the state. | ||
271 | // | ||
272 | // In practice a module containing no objects is the same as a non-existent | ||
273 | // module, and so we can opportunistically clean up once a module becomes | ||
274 | // empty on the assumption that it will be re-added if needed later. | ||
275 | func (ms *Module) empty() bool { | ||
276 | if ms == nil { | ||
277 | return true | ||
278 | } | ||
279 | |||
280 | // This must be updated to cover any new collections added to Module | ||
281 | // in future. | ||
282 | return (len(ms.Resources) == 0 && | ||
283 | len(ms.OutputValues) == 0 && | ||
284 | len(ms.LocalValues) == 0) | ||
285 | } | ||