diff options
Diffstat (limited to 'vendor/github.com/hashicorp/terraform/states/resource.go')
-rw-r--r-- | vendor/github.com/hashicorp/terraform/states/resource.go | 239 |
1 files changed, 239 insertions, 0 deletions
diff --git a/vendor/github.com/hashicorp/terraform/states/resource.go b/vendor/github.com/hashicorp/terraform/states/resource.go new file mode 100644 index 0000000..e2a2b85 --- /dev/null +++ b/vendor/github.com/hashicorp/terraform/states/resource.go | |||
@@ -0,0 +1,239 @@ | |||
1 | package states | ||
2 | |||
3 | import ( | ||
4 | "fmt" | ||
5 | "math/rand" | ||
6 | "time" | ||
7 | |||
8 | "github.com/hashicorp/terraform/addrs" | ||
9 | ) | ||
10 | |||
11 | // Resource represents the state of a resource. | ||
12 | type Resource struct { | ||
13 | // Addr is the module-relative address for the resource this state object | ||
14 | // belongs to. | ||
15 | Addr addrs.Resource | ||
16 | |||
17 | // EachMode is the multi-instance mode currently in use for this resource, | ||
18 | // or NoEach if this is a single-instance resource. This dictates what | ||
19 | // type of value is returned when accessing this resource via expressions | ||
20 | // in the Terraform language. | ||
21 | EachMode EachMode | ||
22 | |||
23 | // Instances contains the potentially-multiple instances associated with | ||
24 | // this resource. This map can contain a mixture of different key types, | ||
25 | // but only the ones of InstanceKeyType are considered current. | ||
26 | Instances map[addrs.InstanceKey]*ResourceInstance | ||
27 | |||
28 | // ProviderConfig is the absolute address for the provider configuration that | ||
29 | // most recently managed this resource. This is used to connect a resource | ||
30 | // with a provider configuration when the resource configuration block is | ||
31 | // not available, such as if it has been removed from configuration | ||
32 | // altogether. | ||
33 | ProviderConfig addrs.AbsProviderConfig | ||
34 | } | ||
35 | |||
36 | // Instance returns the state for the instance with the given key, or nil | ||
37 | // if no such instance is tracked within the state. | ||
38 | func (rs *Resource) Instance(key addrs.InstanceKey) *ResourceInstance { | ||
39 | return rs.Instances[key] | ||
40 | } | ||
41 | |||
42 | // EnsureInstance returns the state for the instance with the given key, | ||
43 | // creating a new empty state for it if one doesn't already exist. | ||
44 | // | ||
45 | // Because this may create and save a new state, it is considered to be | ||
46 | // a write operation. | ||
47 | func (rs *Resource) EnsureInstance(key addrs.InstanceKey) *ResourceInstance { | ||
48 | ret := rs.Instance(key) | ||
49 | if ret == nil { | ||
50 | ret = NewResourceInstance() | ||
51 | rs.Instances[key] = ret | ||
52 | } | ||
53 | return ret | ||
54 | } | ||
55 | |||
56 | // ResourceInstance represents the state of a particular instance of a resource. | ||
57 | type ResourceInstance struct { | ||
58 | // Current, if non-nil, is the remote object that is currently represented | ||
59 | // by the corresponding resource instance. | ||
60 | Current *ResourceInstanceObjectSrc | ||
61 | |||
62 | // Deposed, if len > 0, contains any remote objects that were previously | ||
63 | // represented by the corresponding resource instance but have been | ||
64 | // replaced and are pending destruction due to the create_before_destroy | ||
65 | // lifecycle mode. | ||
66 | Deposed map[DeposedKey]*ResourceInstanceObjectSrc | ||
67 | } | ||
68 | |||
69 | // NewResourceInstance constructs and returns a new ResourceInstance, ready to | ||
70 | // use. | ||
71 | func NewResourceInstance() *ResourceInstance { | ||
72 | return &ResourceInstance{ | ||
73 | Deposed: map[DeposedKey]*ResourceInstanceObjectSrc{}, | ||
74 | } | ||
75 | } | ||
76 | |||
77 | // HasCurrent returns true if this resource instance has a "current"-generation | ||
78 | // object. Most instances do, but this can briefly be false during a | ||
79 | // create-before-destroy replace operation when the current has been deposed | ||
80 | // but its replacement has not yet been created. | ||
81 | func (i *ResourceInstance) HasCurrent() bool { | ||
82 | return i != nil && i.Current != nil | ||
83 | } | ||
84 | |||
85 | // HasDeposed returns true if this resource instance has a deposed object | ||
86 | // with the given key. | ||
87 | func (i *ResourceInstance) HasDeposed(key DeposedKey) bool { | ||
88 | return i != nil && i.Deposed[key] != nil | ||
89 | } | ||
90 | |||
91 | // HasAnyDeposed returns true if this resource instance has one or more | ||
92 | // deposed objects. | ||
93 | func (i *ResourceInstance) HasAnyDeposed() bool { | ||
94 | return i != nil && len(i.Deposed) > 0 | ||
95 | } | ||
96 | |||
97 | // HasObjects returns true if this resource has any objects at all, whether | ||
98 | // current or deposed. | ||
99 | func (i *ResourceInstance) HasObjects() bool { | ||
100 | return i.Current != nil || len(i.Deposed) != 0 | ||
101 | } | ||
102 | |||
103 | // deposeCurrentObject is part of the real implementation of | ||
104 | // SyncState.DeposeResourceInstanceObject. The exported method uses a lock | ||
105 | // to ensure that we can safely allocate an unused deposed key without | ||
106 | // collision. | ||
107 | func (i *ResourceInstance) deposeCurrentObject(forceKey DeposedKey) DeposedKey { | ||
108 | if !i.HasCurrent() { | ||
109 | return NotDeposed | ||
110 | } | ||
111 | |||
112 | key := forceKey | ||
113 | if key == NotDeposed { | ||
114 | key = i.findUnusedDeposedKey() | ||
115 | } else { | ||
116 | if _, exists := i.Deposed[key]; exists { | ||
117 | panic(fmt.Sprintf("forced key %s is already in use", forceKey)) | ||
118 | } | ||
119 | } | ||
120 | i.Deposed[key] = i.Current | ||
121 | i.Current = nil | ||
122 | return key | ||
123 | } | ||
124 | |||
125 | // GetGeneration retrieves the object of the given generation from the | ||
126 | // ResourceInstance, or returns nil if there is no such object. | ||
127 | // | ||
128 | // If the given generation is nil or invalid, this method will panic. | ||
129 | func (i *ResourceInstance) GetGeneration(gen Generation) *ResourceInstanceObjectSrc { | ||
130 | if gen == CurrentGen { | ||
131 | return i.Current | ||
132 | } | ||
133 | if dk, ok := gen.(DeposedKey); ok { | ||
134 | return i.Deposed[dk] | ||
135 | } | ||
136 | if gen == nil { | ||
137 | panic(fmt.Sprintf("get with nil Generation")) | ||
138 | } | ||
139 | // Should never fall out here, since the above covers all possible | ||
140 | // Generation values. | ||
141 | panic(fmt.Sprintf("get invalid Generation %#v", gen)) | ||
142 | } | ||
143 | |||
144 | // FindUnusedDeposedKey generates a unique DeposedKey that is guaranteed not to | ||
145 | // already be in use for this instance at the time of the call. | ||
146 | // | ||
147 | // Note that the validity of this result may change if new deposed keys are | ||
148 | // allocated before it is used. To avoid this risk, instead use the | ||
149 | // DeposeResourceInstanceObject method on the SyncState wrapper type, which | ||
150 | // allocates a key and uses it atomically. | ||
151 | func (i *ResourceInstance) FindUnusedDeposedKey() DeposedKey { | ||
152 | return i.findUnusedDeposedKey() | ||
153 | } | ||
154 | |||
155 | // findUnusedDeposedKey generates a unique DeposedKey that is guaranteed not to | ||
156 | // already be in use for this instance. | ||
157 | func (i *ResourceInstance) findUnusedDeposedKey() DeposedKey { | ||
158 | for { | ||
159 | key := NewDeposedKey() | ||
160 | if _, exists := i.Deposed[key]; !exists { | ||
161 | return key | ||
162 | } | ||
163 | // Spin until we find a unique one. This shouldn't take long, because | ||
164 | // we have a 32-bit keyspace and there's rarely more than one deposed | ||
165 | // instance. | ||
166 | } | ||
167 | } | ||
168 | |||
169 | // EachMode specifies the multi-instance mode for a resource. | ||
170 | type EachMode rune | ||
171 | |||
172 | const ( | ||
173 | NoEach EachMode = 0 | ||
174 | EachList EachMode = 'L' | ||
175 | EachMap EachMode = 'M' | ||
176 | ) | ||
177 | |||
178 | //go:generate stringer -type EachMode | ||
179 | |||
180 | func eachModeForInstanceKey(key addrs.InstanceKey) EachMode { | ||
181 | switch key.(type) { | ||
182 | case addrs.IntKey: | ||
183 | return EachList | ||
184 | case addrs.StringKey: | ||
185 | return EachMap | ||
186 | default: | ||
187 | if key == addrs.NoKey { | ||
188 | return NoEach | ||
189 | } | ||
190 | panic(fmt.Sprintf("don't know an each mode for instance key %#v", key)) | ||
191 | } | ||
192 | } | ||
193 | |||
194 | // DeposedKey is a 8-character hex string used to uniquely identify deposed | ||
195 | // instance objects in the state. | ||
196 | type DeposedKey string | ||
197 | |||
198 | // NotDeposed is a special invalid value of DeposedKey that is used to represent | ||
199 | // the absense of a deposed key. It must not be used as an actual deposed key. | ||
200 | const NotDeposed = DeposedKey("") | ||
201 | |||
202 | var deposedKeyRand = rand.New(rand.NewSource(time.Now().UnixNano())) | ||
203 | |||
204 | // NewDeposedKey generates a pseudo-random deposed key. Because of the short | ||
205 | // length of these keys, uniqueness is not a natural consequence and so the | ||
206 | // caller should test to see if the generated key is already in use and generate | ||
207 | // another if so, until a unique key is found. | ||
208 | func NewDeposedKey() DeposedKey { | ||
209 | v := deposedKeyRand.Uint32() | ||
210 | return DeposedKey(fmt.Sprintf("%08x", v)) | ||
211 | } | ||
212 | |||
213 | func (k DeposedKey) String() string { | ||
214 | return string(k) | ||
215 | } | ||
216 | |||
217 | func (k DeposedKey) GoString() string { | ||
218 | ks := string(k) | ||
219 | switch { | ||
220 | case ks == "": | ||
221 | return "states.NotDeposed" | ||
222 | default: | ||
223 | return fmt.Sprintf("states.DeposedKey(%s)", ks) | ||
224 | } | ||
225 | } | ||
226 | |||
227 | // Generation is a helper method to convert a DeposedKey into a Generation. | ||
228 | // If the reciever is anything other than NotDeposed then the result is | ||
229 | // just the same value as a Generation. If the receiver is NotDeposed then | ||
230 | // the result is CurrentGen. | ||
231 | func (k DeposedKey) Generation() Generation { | ||
232 | if k == NotDeposed { | ||
233 | return CurrentGen | ||
234 | } | ||
235 | return k | ||
236 | } | ||
237 | |||
238 | // generation is an implementation of Generation. | ||
239 | func (k DeposedKey) generation() {} | ||