blob: e5e914b1e2bd51be3b59112cbf4d6251ce897ea6 [file] [log] [blame]
Jon Perritt9f8b0152015-03-17 19:28:18 -06001package lbpools
2
3import (
4 "fmt"
5 "reflect"
6 "time"
7
8 "github.com/mitchellh/mapstructure"
9 "github.com/rackspace/gophercloud"
10 "github.com/rackspace/gophercloud/pagination"
11)
12
13// Pool represents a load balancer pool associated with a RackConnect configuration.
14type Pool struct {
15 // The unique ID of the load balancer pool.
16 ID string `mapstructure:"id"`
17 // The name of the load balancer pool.
18 Name string `mapstructure:"name"`
19 // The node counts associated witht the load balancer pool.
20 NodeCounts struct {
21 // The number of nodes associated with this LB pool for this account.
22 CloudServers int `mapstructure:"cloud_servers"`
23 // The number of nodes associated with this LB pool from other accounts.
24 External int `mapstructure:"external"`
25 // The total number of nodes associated with this LB pool.
26 Total int `mapstructure:"total"`
27 } `mapstructure:"node_counts"`
28 // The port of the LB pool
29 Port int `mapstructure:"port"`
30 // The status of the LB pool
31 Status string `mapstructure:"status"`
32 // The details of the status of the LB pool
33 StatusDetail string `mapstructure:"status_detail"`
34 // The virtual IP of the LB pool
35 VirtualIP string `mapstructure:"virtual_ip"`
36}
37
38// PoolPage is the page returned by a pager when traversing over a
39// collection of Pools.
40type PoolPage struct {
41 pagination.SinglePageBase
42}
43
44// IsEmpty returns true if a PoolPage contains no Pools.
45func (r PoolPage) IsEmpty() (bool, error) {
46 cns, err := ExtractPools(r)
47 if err != nil {
48 return true, err
49 }
50 return len(cns) == 0, nil
51}
52
53// ExtractPools extracts and returns Pools. It is used while iterating over
54// an lbpools.List call.
55func ExtractPools(page pagination.Page) ([]Pool, error) {
56 var res []Pool
57 err := mapstructure.Decode(page.(PoolPage).Body, &res)
58 return res, err
59}
60
61// GetResult represents the result of a Get operation.
62type GetResult struct {
63 gophercloud.Result
64}
65
66// Extract is a function that extracts an LBPool from a GetResult.
67func (r GetResult) Extract() (*Pool, error) {
68 if r.Err != nil {
69 return nil, r.Err
70 }
71 var res Pool
72 err := mapstructure.Decode(r.Body, &res)
73 return &res, err
74}
75
76// Node represents a load balancer pool node associated with a RackConnect configuration.
77type Node struct {
78 // The unique ID of the LB node.
79 ID string `mapstructure:"id"`
80 // The cloud server (node) of the load balancer pool.
81 CloudServer struct {
82 // The cloud server ID.
83 ID string `mapstructure:"id"`
84 } `mapstructure:"cloud_server"`
85 // The load balancer pool.
86 LoadBalancerPool struct {
87 // The LB pool ID.
88 ID string `mapstructure:"id"`
89 } `mapstructure:"load_balancer_pool"`
90 // The status of the LB pool.
91 Status string `mapstructure:"status"`
92 // The details of the status of the LB pool.
93 StatusDetail string `mapstructure:"status_detail"`
94 // The time the LB node was created.
95 CreatedAt time.Time `mapstructure:"-"`
96 // The time the LB node was last updated.
97 UpdatedAt time.Time `mapstructure:"-"`
98}
99
100// NodePage is the page returned by a pager when traversing over a
101// collection of Nodes.
102type NodePage struct {
103 pagination.SinglePageBase
104}
105
106// IsEmpty returns true if a NodePage contains no Nodes.
107func (r NodePage) IsEmpty() (bool, error) {
108 n, err := ExtractNodes(r)
109 if err != nil {
110 return true, err
111 }
112 return len(n) == 0, nil
113}
114
115// ExtractNodes extracts and returns a slice of Nodes. It is used while iterating over
116// an lbpools.ListNodes call.
117func ExtractNodes(page pagination.Page) ([]Node, error) {
118 var res []Node
119 casted := page.(NodePage).Body
120 err := mapstructure.Decode(casted, &res)
121
122 var rawNodes []interface{}
123 switch casted.(type) {
124 case interface{}:
125 rawNodes = casted.([]interface{})
126 default:
127 return res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
128 }
129
130 for i := range rawNodes {
131 thisNode := (rawNodes[i]).(map[string]interface{})
132
133 if t, ok := thisNode["created"].(string); ok && t != "" {
134 creationTime, err := time.Parse(time.RFC3339, t)
135 if err != nil {
136 return res, err
137 }
138 res[i].CreatedAt = creationTime
139 }
140
141 if t, ok := thisNode["updated"].(string); ok && t != "" {
142 updatedTime, err := time.Parse(time.RFC3339, t)
143 if err != nil {
144 return res, err
145 }
146 res[i].UpdatedAt = updatedTime
147 }
148 }
149
150 return res, err
151}
152
153// NodeResult represents a result that can be extracted as a Node.
154type NodeResult struct {
155 gophercloud.Result
156}
157
158// CreateNodeResult represents the result of an CreateNode operation.
159type CreateNodeResult struct {
160 NodeResult
161}
162
163// GetNodeResult represents the result of an GetNode operation.
164type GetNodeResult struct {
165 NodeResult
166}
167
168// Extract is a function that extracts a Node from a NodeResult.
169func (r NodeResult) Extract() (*Node, error) {
170 if r.Err != nil {
171 return nil, r.Err
172 }
173 var res Node
174 err := mapstructure.Decode(r.Body, &res)
175
176 b := r.Body.(map[string]interface{})
177
178 if date, ok := b["created"]; ok && date != nil {
179 t, err := time.Parse(time.RFC3339, date.(string))
180 if err != nil {
181 return nil, err
182 }
183 res.CreatedAt = t
184 }
185
186 if date, ok := b["updated"]; ok && date != nil {
187 t, err := time.Parse(time.RFC3339, date.(string))
188 if err != nil {
189 return nil, err
190 }
191 res.UpdatedAt = t
192 }
193
194 return &res, err
195}
196
197// NodeDetails represents a load balancer pool node associated with a RackConnect configuration
198// with all its details.
199type NodeDetails struct {
200 // The unique ID of the LB node.
201 ID string `mapstructure:"id"`
202 // The cloud server (node) of the load balancer pool.
203 CloudServer struct {
204 // The cloud server ID.
205 ID string `mapstructure:"id"`
206 // The name of the server.
207 Name string `mapstructure:"name"`
208 // The cloud network for the cloud server.
209 CloudNetwork struct {
210 // The network ID.
211 ID string `mapstructure:"id"`
212 // The network name.
213 Name string `mapstructure:"name"`
214 // The network's private IPv4 address.
215 PrivateIPv4 string `mapstructure:"private_ip_v4"`
216 // The IP range for the network.
217 CIDR string `mapstructure:"cidr"`
218 // The datetime the network was created.
219 CreatedAt time.Time `mapstructure:"-"`
220 // The last datetime the network was updated.
221 UpdatedAt time.Time `mapstructure:"-"`
222 } `mapstructure:"cloud_network"`
223 // The datetime the server was created.
224 CreatedAt time.Time `mapstructure:"-"`
225 // The datetime the server was last updated.
226 UpdatedAt time.Time `mapstructure:"-"`
227 } `mapstructure:"cloud_server"`
228 // The load balancer pool.
229 LoadBalancerPool Pool `mapstructure:"load_balancer_pool"`
230 // The status of the LB pool.
231 Status string `mapstructure:"status"`
232 // The details of the status of the LB pool.
233 StatusDetail string `mapstructure:"status_detail"`
234 // The time the LB node was created.
235 CreatedAt time.Time `mapstructure:"-"`
236 // The time the LB node was last updated.
237 UpdatedAt time.Time `mapstructure:"-"`
238}
239
240// NodeDetailsPage is the page returned by a pager when traversing over a
241// collection of NodeDetails.
242type NodeDetailsPage struct {
243 pagination.SinglePageBase
244}
245
246// IsEmpty returns true if a NodeDetailsPage contains no NodeDetails.
247func (r NodeDetailsPage) IsEmpty() (bool, error) {
248 n, err := ExtractNodesDetails(r)
249 if err != nil {
250 return true, err
251 }
252 return len(n) == 0, nil
253}
254
255// ExtractNodesDetails extracts and returns a slice of NodeDetails. It is used while iterating over
256// an lbpools.ListNodesDetails call.
257func ExtractNodesDetails(page pagination.Page) ([]NodeDetails, error) {
258 var res []NodeDetails
259 casted := page.(NodeDetailsPage).Body
260 err := mapstructure.Decode(casted, &res)
261
262 var rawNodesDetails []interface{}
263 switch casted.(type) {
264 case interface{}:
265 rawNodesDetails = casted.([]interface{})
266 default:
267 return res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
268 }
269
270 for i := range rawNodesDetails {
271 thisNodeDetails := (rawNodesDetails[i]).(map[string]interface{})
272
273 if t, ok := thisNodeDetails["created"].(string); ok && t != "" {
274 creationTime, err := time.Parse(time.RFC3339, t)
275 if err != nil {
276 return res, err
277 }
278 res[i].CreatedAt = creationTime
279 }
280
281 if t, ok := thisNodeDetails["updated"].(string); ok && t != "" {
282 updatedTime, err := time.Parse(time.RFC3339, t)
283 if err != nil {
284 return res, err
285 }
286 res[i].UpdatedAt = updatedTime
287 }
288
289 if cs, ok := thisNodeDetails["cloud_server"].(map[string]interface{}); ok {
290 if t, ok := cs["created"].(string); ok && t != "" {
291 creationTime, err := time.Parse(time.RFC3339, t)
292 if err != nil {
293 return res, err
294 }
295 res[i].CloudServer.CreatedAt = creationTime
296 }
297 if t, ok := cs["updated"].(string); ok && t != "" {
298 updatedTime, err := time.Parse(time.RFC3339, t)
299 if err != nil {
300 return res, err
301 }
302 res[i].CloudServer.UpdatedAt = updatedTime
303 }
304 if cn, ok := cs["cloud_network"].(map[string]interface{}); ok {
305 if t, ok := cn["created"].(string); ok && t != "" {
306 creationTime, err := time.Parse(time.RFC3339, t)
307 if err != nil {
308 return res, err
309 }
310 res[i].CloudServer.CloudNetwork.CreatedAt = creationTime
311 }
312 if t, ok := cn["updated"].(string); ok && t != "" {
313 updatedTime, err := time.Parse(time.RFC3339, t)
314 if err != nil {
315 return res, err
316 }
317 res[i].CloudServer.CloudNetwork.UpdatedAt = updatedTime
318 }
319 }
320 }
321 }
322
323 return res, err
324}
325
326// GetNodeDetailsResult represents the result of an NodeDetails operation.
327type GetNodeDetailsResult struct {
328 gophercloud.Result
329}
330
331// Extract is a function that extracts a NodeDetails from a NodeDetailsResult.
332func (r GetNodeDetailsResult) Extract() (*NodeDetails, error) {
333 if r.Err != nil {
334 return nil, r.Err
335 }
336 var res NodeDetails
337 err := mapstructure.Decode(r.Body, &res)
338
339 b := r.Body.(map[string]interface{})
340
341 if date, ok := b["created"]; ok && date != nil {
342 t, err := time.Parse(time.RFC3339, date.(string))
343 if err != nil {
344 return nil, err
345 }
346 res.CreatedAt = t
347 }
348
349 if date, ok := b["updated"]; ok && date != nil {
350 t, err := time.Parse(time.RFC3339, date.(string))
351 if err != nil {
352 return nil, err
353 }
354 res.UpdatedAt = t
355 }
356
357 if cs, ok := b["cloud_server"].(map[string]interface{}); ok {
358 if t, ok := cs["created"].(string); ok && t != "" {
359 creationTime, err := time.Parse(time.RFC3339, t)
360 if err != nil {
361 return &res, err
362 }
363 res.CloudServer.CreatedAt = creationTime
364 }
365 if t, ok := cs["updated"].(string); ok && t != "" {
366 updatedTime, err := time.Parse(time.RFC3339, t)
367 if err != nil {
368 return &res, err
369 }
370 res.CloudServer.UpdatedAt = updatedTime
371 }
372 if cn, ok := cs["cloud_network"].(map[string]interface{}); ok {
373 if t, ok := cn["created"].(string); ok && t != "" {
374 creationTime, err := time.Parse(time.RFC3339, t)
375 if err != nil {
376 return &res, err
377 }
378 res.CloudServer.CloudNetwork.CreatedAt = creationTime
379 }
380 if t, ok := cn["updated"].(string); ok && t != "" {
381 updatedTime, err := time.Parse(time.RFC3339, t)
382 if err != nil {
383 return &res, err
384 }
385 res.CloudServer.CloudNetwork.UpdatedAt = updatedTime
386 }
387 }
388 }
389
390 return &res, err
391}
392
393// DeleteNodeResult represents the result of a DeleteNode operation.
394type DeleteNodeResult struct {
395 gophercloud.ErrResult
396}
397
398// CreateNodesResult represents the result of a CreateNodes operation.
399type CreateNodesResult struct {
400 gophercloud.Result
401}
402
403// Extract is a function that extracts a slice of Nodes from a CreateNodesResult.
404func (r CreateNodesResult) Extract() ([]Node, error) {
405 if r.Err != nil {
406 return nil, r.Err
407 }
408 var res []Node
409 err := mapstructure.Decode(r.Body, &res)
410
411 b := r.Body.([]interface{})
412 for i := range b {
413 if date, ok := b[i].(map[string]interface{})["created"]; ok && date != nil {
414 t, err := time.Parse(time.RFC3339, date.(string))
415 if err != nil {
416 return nil, err
417 }
418 res[i].CreatedAt = t
419 }
420 if date, ok := b[i].(map[string]interface{})["updated"]; ok && date != nil {
421 t, err := time.Parse(time.RFC3339, date.(string))
422 if err != nil {
423 return nil, err
424 }
425 res[i].UpdatedAt = t
426 }
427 }
428
429 return res, err
430}
431
432// DeleteNodesResult represents the result of a DeleteNodes operation.
433type DeleteNodesResult struct {
434 gophercloud.ErrResult
435}
436
437// NodeDetailsForServer represents a load balancer pool node associated with a RackConnect configuration
438// with all its details for a particular server.
439type NodeDetailsForServer struct {
440 // The unique ID of the LB node.
441 ID string `mapstructure:"id"`
442 // The load balancer pool.
443 LoadBalancerPool Pool `mapstructure:"load_balancer_pool"`
444 // The status of the LB pool.
445 Status string `mapstructure:"status"`
446 // The details of the status of the LB pool.
447 StatusDetail string `mapstructure:"status_detail"`
448 // The time the LB node was created.
449 CreatedAt time.Time `mapstructure:"-"`
450 // The time the LB node was last updated.
451 UpdatedAt time.Time `mapstructure:"-"`
452}
453
454// NodeDetailsForServerPage is the page returned by a pager when traversing over a
455// collection of NodeDetailsForServer.
456type NodeDetailsForServerPage struct {
457 pagination.SinglePageBase
458}
459
460// IsEmpty returns true if a NodeDetailsForServerPage contains no NodeDetailsForServer.
461func (r NodeDetailsForServerPage) IsEmpty() (bool, error) {
462 n, err := ExtractNodesDetailsForServer(r)
463 if err != nil {
464 return true, err
465 }
466 return len(n) == 0, nil
467}
468
469// ExtractNodesDetailsForServer extracts and returns a slice of NodeDetailsForServer. It is used while iterating over
470// an lbpools.ListNodesDetailsForServer call.
471func ExtractNodesDetailsForServer(page pagination.Page) ([]NodeDetailsForServer, error) {
472 var res []NodeDetailsForServer
473 casted := page.(NodeDetailsForServerPage).Body
474 err := mapstructure.Decode(casted, &res)
475
476 var rawNodesDetails []interface{}
477 switch casted.(type) {
478 case interface{}:
479 rawNodesDetails = casted.([]interface{})
480 default:
481 return res, fmt.Errorf("Unknown type: %v", reflect.TypeOf(casted))
482 }
483
484 for i := range rawNodesDetails {
485 thisNodeDetails := (rawNodesDetails[i]).(map[string]interface{})
486
487 if t, ok := thisNodeDetails["created"].(string); ok && t != "" {
488 creationTime, err := time.Parse(time.RFC3339, t)
489 if err != nil {
490 return res, err
491 }
492 res[i].CreatedAt = creationTime
493 }
494
495 if t, ok := thisNodeDetails["updated"].(string); ok && t != "" {
496 updatedTime, err := time.Parse(time.RFC3339, t)
497 if err != nil {
498 return res, err
499 }
500 res[i].UpdatedAt = updatedTime
501 }
502 }
503
504 return res, err
505}