blob: 50b900d142622b95c053b7eb187a5c60e0885c44 [file] [log] [blame]
Jon Perritt35e27e42014-12-05 11:10:46 -07001package stacks
2
3import (
4 "errors"
5
6 "github.com/racker/perigee"
7 "github.com/rackspace/gophercloud"
8 "github.com/rackspace/gophercloud/pagination"
9)
10
11// CreateOptsBuilder is the interface options structs have to satisfy in order
12// to be used in the main Create operation in this package. Since many
13// extensions decorate or modify the common logic, it is useful for them to
14// satisfy a basic interface in order for them to be used.
15type CreateOptsBuilder interface {
16 ToStackCreateMap() (map[string]interface{}, error)
17}
18
19// CreateOpts is the common options struct used in this package's Create
20// operation.
21type CreateOpts struct {
22 DisableRollback *bool
23 Environment string
24 Files map[string]interface{}
25 Name string
26 Parameters map[string]string
27 Template string
28 TemplateURL string
29 Timeout int
30}
31
32// ToStackCreateMap casts a CreateOpts struct to a map.
33func (opts CreateOpts) ToStackCreateMap() (map[string]interface{}, error) {
34 s := make(map[string]interface{})
35
36 if opts.Name == "" {
37 return s, errors.New("Required field 'Name' not provided.")
38 }
39 s["stack_name"] = opts.Name
40
41 if opts.Template != "" {
42 s["template"] = opts.Template
43 } else if opts.TemplateURL != "" {
44 s["template_url"] = opts.TemplateURL
45 } else {
46 return s, errors.New("Either Template or TemplateURL must be provided.")
47 }
48
49 if opts.DisableRollback != nil {
50 s["disable_rollback"] = &opts.DisableRollback
51 }
52
53 if opts.Environment != "" {
54 s["environment"] = opts.Environment
55 }
56 if opts.Files != nil {
57 s["files"] = opts.Files
58 }
59 if opts.Parameters != nil {
60 s["parameters"] = opts.Parameters
61 }
62
63 if opts.Timeout != 0 {
64 s["timeout_mins"] = opts.Timeout
65 }
66
67 return s, nil
68}
69
70// Create accepts a CreateOpts struct and creates a new stack using the values
71// provided.
72func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
73 var res CreateResult
74
75 reqBody, err := opts.ToStackCreateMap()
76 if err != nil {
77 res.Err = err
78 return res
79 }
80
81 // Send request to API
82 _, res.Err = perigee.Request("POST", createURL(c), perigee.Options{
83 MoreHeaders: c.AuthenticatedHeaders(),
84 ReqBody: &reqBody,
85 Results: &res.Body,
86 OkCodes: []int{201},
87 })
88 return res
89}
90
91// AdoptOptsBuilder is the interface options structs have to satisfy in order
92// to be used in the Adopt function in this package. Since many
93// extensions decorate or modify the common logic, it is useful for them to
94// satisfy a basic interface in order for them to be used.
95type AdoptOptsBuilder interface {
96 ToStackAdoptMap() (map[string]interface{}, error)
97}
98
99// AdoptOpts is the common options struct used in this package's Adopt
100// operation.
101type AdoptOpts struct {
102 AdoptStackData string
103 DisableRollback *bool
104 Environment string
105 Files map[string]interface{}
106 Name string
107 Parameters map[string]string
108 Template string
109 TemplateURL string
110 Timeout int
111}
112
113// ToStackAdoptMap casts a CreateOpts struct to a map.
114func (opts AdoptOpts) ToStackAdoptMap() (map[string]interface{}, error) {
115 s := make(map[string]interface{})
116
117 if opts.Name == "" {
118 return s, errors.New("Required field 'Name' not provided.")
119 }
120 s["stack_name"] = opts.Name
121
122 if opts.Template != "" {
123 s["template"] = opts.Template
124 } else if opts.TemplateURL != "" {
125 s["template_url"] = opts.TemplateURL
126 } else {
127 return s, errors.New("Either Template or TemplateURL must be provided.")
128 }
129
130 if opts.AdoptStackData == "" {
131 return s, errors.New("Required field 'AdoptStackData' not provided.")
132 }
133 s["adopt_stack_data"] = opts.AdoptStackData
134
135 if opts.DisableRollback != nil {
136 s["disable_rollback"] = &opts.DisableRollback
137 }
138
139 if opts.Environment != "" {
140 s["environment"] = opts.Environment
141 }
142 if opts.Files != nil {
143 s["files"] = opts.Files
144 }
145 if opts.Parameters != nil {
146 s["parameters"] = opts.Parameters
147 }
148
149 if opts.Timeout != 0 {
150 s["timeout_mins"] = opts.Timeout
151 }
152
153 return map[string]interface{}{"stack": s}, nil
154}
155
156// Adopt accepts an AdoptOpts struct and creates a new stack using the resources
157// from another stack.
158func Adopt(c *gophercloud.ServiceClient, opts AdoptOptsBuilder) CreateResult {
159 var res CreateResult
160
161 reqBody, err := opts.ToStackAdoptMap()
162 if err != nil {
163 res.Err = err
164 return res
165 }
166
167 // Send request to API
168 _, res.Err = perigee.Request("POST", adoptURL(c), perigee.Options{
169 MoreHeaders: c.AuthenticatedHeaders(),
170 ReqBody: &reqBody,
171 Results: &res.Body,
172 OkCodes: []int{201},
173 })
174 return res
175}
176
177// SortDir is a type for specifying in which direction to sort a list of stacks.
178type SortDir string
179
180// SortKey is a type for specifying by which key to sort a list of stacks.
181type SortKey string
182
183var (
184 // SortAsc is used to sort a list of stacks in ascending order.
185 SortAsc SortDir = "asc"
186 // SortDesc is used to sort a list of stacks in descending order.
187 SortDesc SortDir = "desc"
188 // SortName is used to sort a list of stacks by name.
189 SortName SortKey = "name"
190 // SortStatus is used to sort a list of stacks by status.
191 SortStatus SortKey = "status"
192 // SortCreatedAt is used to sort a list of stacks by date created.
193 SortCreatedAt SortKey = "created_at"
194 // SortUpdatedAt is used to sort a list of stacks by date updated.
195 SortUpdatedAt SortKey = "updated_at"
196)
197
198// ListOptsBuilder allows extensions to add additional parameters to the
199// List request.
200type ListOptsBuilder interface {
201 ToStackListQuery() (string, error)
202}
203
204// ListOpts allows the filtering and sorting of paginated collections through
205// the API. Filtering is achieved by passing in struct field values that map to
206// the network attributes you want to see returned. SortKey allows you to sort
207// by a particular network attribute. SortDir sets the direction, and is either
208// `asc' or `desc'. Marker and Limit are used for pagination.
209type ListOpts struct {
210 Status string `q:"status"`
211 Name string `q:"name"`
212 Marker string `q:"marker"`
213 Limit int `q:"limit"`
214 SortKey SortKey `q:"sort_keys"`
215 SortDir SortDir `q:"sort_dir"`
216}
217
218// ToStackListQuery formats a ListOpts into a query string.
219func (opts ListOpts) ToStackListQuery() (string, error) {
220 q, err := gophercloud.BuildQueryString(opts)
221 if err != nil {
222 return "", err
223 }
224 return q.String(), nil
225}
226
227// List returns a Pager which allows you to iterate over a collection of
228// stacks. It accepts a ListOpts struct, which allows you to filter and sort
229// the returned collection for greater efficiency.
230func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
231 url := listURL(c)
232 if opts != nil {
233 query, err := opts.ToStackListQuery()
234 if err != nil {
235 return pagination.Pager{Err: err}
236 }
237 url += query
238 }
239
240 createPage := func(r pagination.PageResult) pagination.Page {
241 return StackPage{pagination.SinglePageBase(r)}
242 }
243 return pagination.NewPager(c, url, createPage)
244}
245
246// Get retreives a stack based on the stack name and stack ID.
247func Get(c *gophercloud.ServiceClient, stackName, stackID string) GetResult {
248 var res GetResult
249
250 // Send request to API
251 _, res.Err = perigee.Request("GET", getURL(c, stackName, stackID), perigee.Options{
252 MoreHeaders: c.AuthenticatedHeaders(),
253 Results: &res.Body,
254 OkCodes: []int{200},
255 })
256 return res
257}
258
259// UpdateOptsBuilder is the interface options structs have to satisfy in order
260// to be used in the Update operation in this package.
261type UpdateOptsBuilder interface {
262 ToStackUpdateMap() (map[string]interface{}, error)
263}
264
265// UpdateOpts contains the common options struct used in this package's Update
266// operation.
267type UpdateOpts struct {
268 Environment string
269 Files map[string]interface{}
270 Parameters map[string]string
271 Template string
272 TemplateURL string
273 Timeout int
274}
275
276// ToStackUpdateMap casts a CreateOpts struct to a map.
277func (opts UpdateOpts) ToStackUpdateMap() (map[string]interface{}, error) {
278 s := make(map[string]interface{})
279
280 if opts.Template != "" {
281 s["template"] = opts.Template
282 } else if opts.TemplateURL != "" {
283 s["template_url"] = opts.TemplateURL
284 } else {
285 return s, errors.New("Either Template or TemplateURL must be provided.")
286 }
287
288 if opts.Environment != "" {
289 s["environment"] = opts.Environment
290 }
291
292 if opts.Files != nil {
293 s["files"] = opts.Files
294 }
295
296 if opts.Parameters != nil {
297 s["parameters"] = opts.Parameters
298 }
299
300 if opts.Timeout != 0 {
301 s["timeout_mins"] = opts.Timeout
302 }
303
304 return s, nil
305}
306
307// Update accepts an UpdateOpts struct and updates an existing stack using the values
308// provided.
309func Update(c *gophercloud.ServiceClient, stackName, stackID string, opts UpdateOptsBuilder) UpdateResult {
310 var res UpdateResult
311
312 reqBody, err := opts.ToStackUpdateMap()
313 if err != nil {
314 res.Err = err
315 return res
316 }
317
318 // Send request to API
319 _, res.Err = perigee.Request("PUT", updateURL(c, stackName, stackID), perigee.Options{
320 MoreHeaders: c.AuthenticatedHeaders(),
321 ReqBody: &reqBody,
322 OkCodes: []int{202},
323 })
324 return res
325}
326
327// Delete deletes a stack based on the stack name and stack ID.
328func Delete(c *gophercloud.ServiceClient, stackName, stackID string) DeleteResult {
329 var res DeleteResult
330
331 // Send request to API
332 _, res.Err = perigee.Request("DELETE", deleteURL(c, stackName, stackID), perigee.Options{
333 MoreHeaders: c.AuthenticatedHeaders(),
334 OkCodes: []int{204},
335 })
336 return res
337}
338
339// PreviewOptsBuilder is the interface options structs have to satisfy in order
340// to be used in the Preview operation in this package.
341type PreviewOptsBuilder interface {
342 ToStackPreviewMap() (map[string]interface{}, error)
343}
344
345// PreviewOpts contains the common options struct used in this package's Preview
346// operation.
347type PreviewOpts struct {
348 DisableRollback *bool
349 Environment string
350 Files map[string]interface{}
351 Name string
352 Parameters map[string]string
353 Template string
354 TemplateURL string
355 Timeout int
356}
357
358// ToStackPreviewMap casts a PreviewOpts struct to a map.
359func (opts PreviewOpts) ToStackPreviewMap() (map[string]interface{}, error) {
360 s := make(map[string]interface{})
361
362 if opts.Name == "" {
363 return s, errors.New("Required field 'Name' not provided.")
364 }
365 s["stack_name"] = opts.Name
366
367 if opts.Template != "" {
368 s["template"] = opts.Template
369 } else if opts.TemplateURL != "" {
370 s["template_url"] = opts.TemplateURL
371 } else {
372 return s, errors.New("Either Template or TemplateURL must be provided.")
373 }
374
375 if opts.DisableRollback != nil {
376 s["disable_rollback"] = &opts.DisableRollback
377 }
378
379 if opts.Environment != "" {
380 s["environment"] = opts.Environment
381 }
382 if opts.Files != nil {
383 s["files"] = opts.Files
384 }
385 if opts.Parameters != nil {
386 s["parameters"] = opts.Parameters
387 }
388
389 if opts.Timeout != 0 {
390 s["timeout_mins"] = opts.Timeout
391 }
392
393 return s, nil
394}
395
396// Preview accepts a PreviewOptsBuilder interface and creates a preview of a stack using the values
397// provided.
398func Preview(c *gophercloud.ServiceClient, opts PreviewOptsBuilder) PreviewResult {
399 var res PreviewResult
400
401 reqBody, err := opts.ToStackPreviewMap()
402 if err != nil {
403 res.Err = err
404 return res
405 }
406
407 // Send request to API
408 _, res.Err = perigee.Request("POST", previewURL(c), perigee.Options{
409 MoreHeaders: c.AuthenticatedHeaders(),
410 ReqBody: &reqBody,
411 Results: &res.Body,
412 OkCodes: []int{200},
413 })
414 return res
415}
416
417// Abandon deletes the stack with the provided stackName and stackID, but leaves its
418// resources intact, and returns data describing the stack and its resources.
419func Abandon(c *gophercloud.ServiceClient, stackName, stackID string) AbandonResult {
420 var res AbandonResult
421
422 // Send request to API
423 _, res.Err = perigee.Request("POST", previewURL(c), perigee.Options{
424 MoreHeaders: c.AuthenticatedHeaders(),
425 Results: &res.Body,
426 OkCodes: []int{200},
427 })
428 return res
429}