blob: ff971e8b8bdd449ba2768509e39ced71dd8c184c [file] [log] [blame]
Jon Perritt35e27e42014-12-05 11:10:46 -07001package stacks
2
3import (
Jon Perritt3d381d52015-02-09 13:04:48 -07004 "encoding/json"
Jon Perritt35e27e42014-12-05 11:10:46 -07005 "time"
6
7 "github.com/mitchellh/mapstructure"
8 "github.com/rackspace/gophercloud"
9 "github.com/rackspace/gophercloud/pagination"
10)
11
Jon Perritt7726e492015-02-04 17:54:28 -070012// CreatedStack represents the object extracted from a Create operation.
Jon Perritt01972e22015-01-28 10:30:45 -070013type CreatedStack struct {
Jon Perritt35e27e42014-12-05 11:10:46 -070014 ID string `mapstructure:"id"`
15 Links []gophercloud.Link `mapstructure:"links"`
16}
17
Jon Perritt7726e492015-02-04 17:54:28 -070018// CreateResult represents the result of a Create operation.
Jon Perritt35e27e42014-12-05 11:10:46 -070019type CreateResult struct {
20 gophercloud.Result
21}
22
Jon Perritt7726e492015-02-04 17:54:28 -070023// Extract returns a pointer to a CreatedStack object and is called after a
24// Create operation.
Jon Perritt22325f42015-01-29 14:48:18 -070025func (r CreateResult) Extract() (*CreatedStack, error) {
Jon Perritt35e27e42014-12-05 11:10:46 -070026 if r.Err != nil {
27 return nil, r.Err
28 }
29
30 var res struct {
Jon Perritt22325f42015-01-29 14:48:18 -070031 Stack *CreatedStack `mapstructure:"stack"`
Jon Perritt35e27e42014-12-05 11:10:46 -070032 }
33
34 if err := mapstructure.Decode(r.Body, &res); err != nil {
35 return nil, err
36 }
37
38 return res.Stack, nil
39}
40
Jon Perritt7726e492015-02-04 17:54:28 -070041// AdoptResult represents the result of an Adopt operation. AdoptResult has the
42// same form as CreateResult.
Jon Perritt35e27e42014-12-05 11:10:46 -070043type AdoptResult struct {
Jon Perritt9741dd92015-02-04 12:05:47 -070044 CreateResult
Jon Perritt35e27e42014-12-05 11:10:46 -070045}
46
47// StackPage is a pagination.Pager that is returned from a call to the List function.
48type StackPage struct {
49 pagination.SinglePageBase
50}
51
52// IsEmpty returns true if a ListResult contains no Stacks.
53func (r StackPage) IsEmpty() (bool, error) {
54 stacks, err := ExtractStacks(r)
55 if err != nil {
56 return true, err
57 }
58 return len(stacks) == 0, nil
59}
60
Jon Perritt7726e492015-02-04 17:54:28 -070061// ListedStack represents an element in the slice extracted from a List operation.
Jon Perritt01972e22015-01-28 10:30:45 -070062type ListedStack struct {
Jon Perritt35e27e42014-12-05 11:10:46 -070063 CreationTime time.Time `mapstructure:"-"`
64 Description string `mapstructure:"description"`
65 ID string `mapstructure:"id"`
66 Links []gophercloud.Link `mapstructure:"links"`
67 Name string `mapstructure:"stack_name"`
68 Status string `mapstructure:"stack_status"`
Jon Perritt01972e22015-01-28 10:30:45 -070069 StatusReason string `mapstructure:"stack_status_reason"`
Jon Perritt35e27e42014-12-05 11:10:46 -070070 UpdatedTime time.Time `mapstructure:"-"`
71}
72
Jon Perritt7726e492015-02-04 17:54:28 -070073// ExtractStacks extracts and returns a slice of ListedStack. It is used while iterating
Jon Perritt35e27e42014-12-05 11:10:46 -070074// over a stacks.List call.
Jon Perritt22325f42015-01-29 14:48:18 -070075func ExtractStacks(page pagination.Page) ([]ListedStack, error) {
Jon Perritt35e27e42014-12-05 11:10:46 -070076 var res struct {
Jon Perritt22325f42015-01-29 14:48:18 -070077 Stacks []ListedStack `mapstructure:"stacks"`
Jon Perritt35e27e42014-12-05 11:10:46 -070078 }
79
80 err := mapstructure.Decode(page.(StackPage).Body, &res)
Jon Perritt01972e22015-01-28 10:30:45 -070081 if err != nil {
82 return nil, err
83 }
84
85 rawStacks := (((page.(StackPage).Body).(map[string]interface{}))["stacks"]).([]interface{})
86 for i := range rawStacks {
Jon Perritt9cd3d382015-02-04 15:49:41 -070087 thisStack := (rawStacks[i]).(map[string]interface{})
Jon Perritt01972e22015-01-28 10:30:45 -070088
Jon Perritt9cd3d382015-02-04 15:49:41 -070089 if t, ok := thisStack["creation_time"].(string); ok && t != "" {
90 creationTime, err := time.Parse(time.RFC3339, t)
91 if err != nil {
92 return res.Stacks, err
93 }
94 res.Stacks[i].CreationTime = creationTime
Jon Perritt01972e22015-01-28 10:30:45 -070095 }
Jon Perritt9cd3d382015-02-04 15:49:41 -070096
97 if t, ok := thisStack["updated_time"].(string); ok && t != "" {
98 updatedTime, err := time.Parse(time.RFC3339, t)
99 if err != nil {
100 return res.Stacks, err
101 }
102 res.Stacks[i].UpdatedTime = updatedTime
103 }
Jon Perritt01972e22015-01-28 10:30:45 -0700104 }
105
106 return res.Stacks, nil
Jon Perritt35e27e42014-12-05 11:10:46 -0700107}
108
Jon Perritt7726e492015-02-04 17:54:28 -0700109// RetrievedStack represents the object extracted from a Get operation.
Jon Perritt01972e22015-01-28 10:30:45 -0700110type RetrievedStack struct {
Jon Perritt7726e492015-02-04 17:54:28 -0700111 Capabilities []interface{} `mapstructure:"capabilities"`
112 CreationTime time.Time `mapstructure:"-"`
113 Description string `mapstructure:"description"`
114 DisableRollback bool `mapstructure:"disable_rollback"`
115 ID string `mapstructure:"id"`
116 Links []gophercloud.Link `mapstructure:"links"`
117 NotificationTopics []interface{} `mapstructure:"notification_topics"`
118 Outputs []map[string]interface{} `mapstructure:"outputs"`
119 Parameters map[string]string `mapstructure:"parameters"`
120 Name string `mapstructure:"stack_name"`
121 Status string `mapstructure:"stack_status"`
122 StatusReason string `mapstructure:"stack_status_reason"`
123 TemplateDescription string `mapstructure:"template_description"`
124 Timeout int `mapstructure:"timeout_mins"`
125 UpdatedTime time.Time `mapstructure:"-"`
Jon Perritt35e27e42014-12-05 11:10:46 -0700126}
127
Jon Perritt7726e492015-02-04 17:54:28 -0700128// GetResult represents the result of a Get operation.
Jon Perritt35e27e42014-12-05 11:10:46 -0700129type GetResult struct {
130 gophercloud.Result
131}
132
Jon Perritt7726e492015-02-04 17:54:28 -0700133// Extract returns a pointer to a RetrievedStack object and is called after a
134// Get operation.
Jon Perritt22325f42015-01-29 14:48:18 -0700135func (r GetResult) Extract() (*RetrievedStack, error) {
Jon Perritt35e27e42014-12-05 11:10:46 -0700136 if r.Err != nil {
137 return nil, r.Err
138 }
139
140 var res struct {
Jon Perritt22325f42015-01-29 14:48:18 -0700141 Stack *RetrievedStack `mapstructure:"stack"`
Jon Perritt35e27e42014-12-05 11:10:46 -0700142 }
143
144 config := &mapstructure.DecoderConfig{
145 Result: &res,
146 WeaklyTypedInput: true,
147 }
148 decoder, err := mapstructure.NewDecoder(config)
149 if err != nil {
150 return nil, err
151 }
152
153 if err := decoder.Decode(r.Body); err != nil {
154 return nil, err
155 }
156
157 b := r.Body.(map[string]interface{})["stack"].(map[string]interface{})
158
159 if date, ok := b["creation_time"]; ok && date != nil {
160 t, err := time.Parse(time.RFC3339, date.(string))
161 if err != nil {
162 return nil, err
163 }
164 res.Stack.CreationTime = t
165 }
166
167 if date, ok := b["updated_time"]; ok && date != nil {
168 t, err := time.Parse(time.RFC3339, date.(string))
169 if err != nil {
170 return nil, err
171 }
172 res.Stack.UpdatedTime = t
173 }
174
175 return res.Stack, err
176}
177
Jon Perritt7726e492015-02-04 17:54:28 -0700178// UpdateResult represents the result of a Update operation.
Jon Perritt35e27e42014-12-05 11:10:46 -0700179type UpdateResult struct {
180 gophercloud.ErrResult
181}
182
Jon Perritt7726e492015-02-04 17:54:28 -0700183// DeleteResult represents the result of a Delete operation.
Jon Perritt35e27e42014-12-05 11:10:46 -0700184type DeleteResult struct {
185 gophercloud.ErrResult
186}
187
Jon Perritt37f97742015-02-04 18:55:05 -0700188// PreviewedStack represents the result of a Preview operation.
Jon Perritt01972e22015-01-28 10:30:45 -0700189type PreviewedStack struct {
Jon Perritt37f97742015-02-04 18:55:05 -0700190 Capabilities []interface{} `mapstructure:"capabilities"`
191 CreationTime time.Time `mapstructure:"-"`
192 Description string `mapstructure:"description"`
193 DisableRollback bool `mapstructure:"disable_rollback"`
194 ID string `mapstructure:"id"`
195 Links []gophercloud.Link `mapstructure:"links"`
196 Name string `mapstructure:"stack_name"`
197 NotificationTopics []interface{} `mapstructure:"notification_topics"`
198 Parameters map[string]string `mapstructure:"parameters"`
199 Resources []map[string]interface{} `mapstructure:"resources"`
200 Status string `mapstructure:"stack_status"`
201 StatusReason string `mapstructure:"stack_status_reason"`
202 TemplateDescription string `mapstructure:"template_description"`
203 Timeout int `mapstructure:"timeout_mins"`
204 UpdatedTime time.Time `mapstructure:"-"`
Jon Perritt35e27e42014-12-05 11:10:46 -0700205}
206
Jon Perritt37f97742015-02-04 18:55:05 -0700207// PreviewResult represents the result of a Preview operation.
Jon Perritt35e27e42014-12-05 11:10:46 -0700208type PreviewResult struct {
209 gophercloud.Result
210}
211
Jon Perritt37f97742015-02-04 18:55:05 -0700212// Extract returns a pointer to a PreviewedStack object and is called after a
213// Preview operation.
Jon Perritt22325f42015-01-29 14:48:18 -0700214func (r PreviewResult) Extract() (*PreviewedStack, error) {
Jon Perritt35e27e42014-12-05 11:10:46 -0700215 if r.Err != nil {
216 return nil, r.Err
217 }
218
219 var res struct {
Jon Perritt22325f42015-01-29 14:48:18 -0700220 Stack *PreviewedStack `mapstructure:"stack"`
Jon Perritt35e27e42014-12-05 11:10:46 -0700221 }
222
223 config := &mapstructure.DecoderConfig{
224 Result: &res,
225 WeaklyTypedInput: true,
226 }
227 decoder, err := mapstructure.NewDecoder(config)
228 if err != nil {
229 return nil, err
230 }
231
232 if err := decoder.Decode(r.Body); err != nil {
233 return nil, err
234 }
235
236 b := r.Body.(map[string]interface{})["stack"].(map[string]interface{})
237
238 if date, ok := b["creation_time"]; ok && date != nil {
239 t, err := time.Parse(time.RFC3339, date.(string))
240 if err != nil {
241 return nil, err
242 }
243 res.Stack.CreationTime = t
244 }
245
246 if date, ok := b["updated_time"]; ok && date != nil {
247 t, err := time.Parse(time.RFC3339, date.(string))
248 if err != nil {
249 return nil, err
250 }
251 res.Stack.UpdatedTime = t
252 }
253
254 return res.Stack, err
255}
256
Jon Perritt9209df42015-02-05 12:55:33 -0700257// AbandonedStack represents the result of an Abandon operation.
Jon Perritt01972e22015-01-28 10:30:45 -0700258type AbandonedStack struct {
Jon Perritt9209df42015-02-05 12:55:33 -0700259 Status string `mapstructure:"status"`
260 Name string `mapstructure:"name"`
Jon Perritt6ec27cf2015-02-09 12:51:41 -0700261 Template map[string]interface{} `mapstructure:"template"`
Jon Perritt9209df42015-02-05 12:55:33 -0700262 Action string `mapstructure:"action"`
263 ID string `mapstructure:"id"`
264 Resources map[string]interface{} `mapstructure:"resources"`
Jon Perritt35e27e42014-12-05 11:10:46 -0700265}
266
Jon Perritt9209df42015-02-05 12:55:33 -0700267// AbandonResult represents the result of an Abandon operation.
Jon Perritt35e27e42014-12-05 11:10:46 -0700268type AbandonResult struct {
269 gophercloud.Result
270}
Jon Perritt9209df42015-02-05 12:55:33 -0700271
272// Extract returns a pointer to an AbandonedStack object and is called after an
273// Abandon operation.
274func (r AbandonResult) Extract() (*AbandonedStack, error) {
275 if r.Err != nil {
276 return nil, r.Err
277 }
278
279 var res AbandonedStack
280
281 if err := mapstructure.Decode(r.Body, &res); err != nil {
282 return nil, err
283 }
284
285 return &res, nil
286}
Jon Perritt3d381d52015-02-09 13:04:48 -0700287
Jon Perrittdb0d26a2015-02-09 13:06:16 -0700288// String converts an AbandonResult to a string. This is useful to when passing
289// the result of an Abandon operation to an AdoptOpts AdoptStackData field.
Jon Perritt3d381d52015-02-09 13:04:48 -0700290func (r AbandonResult) String() (string, error) {
291 out, err := json.Marshal(r)
292 if err != nil {
293 return "", err
294 }
295 return string(out), nil
296}