blob: 230525ceeff6d2c16787418b385b9c3a18b49234 [file] [log] [blame]
Jon Perritt35e27e42014-12-05 11:10:46 -07001package stacks
2
3import (
4 "errors"
Pratik Mallya827c03e2015-09-17 00:10:47 -05005 "strings"
Jon Perritt35e27e42014-12-05 11:10:46 -07006
Jon Perritt35e27e42014-12-05 11:10:46 -07007 "github.com/rackspace/gophercloud"
8 "github.com/rackspace/gophercloud/pagination"
9)
10
Jon Perritt9209df42015-02-05 12:55:33 -070011// Rollback is used to specify whether or not a stack can be rolled back.
Jon Perrittb20ba0b2015-02-03 13:13:42 -070012type Rollback *bool
13
14var (
Jon Perritt9209df42015-02-05 12:55:33 -070015 disable = true
16 // Disable is used to specify that a stack cannot be rolled back.
Jon Perrittb20ba0b2015-02-03 13:13:42 -070017 Disable Rollback = &disable
18 enable = false
Jon Perritt9209df42015-02-05 12:55:33 -070019 // Enable is used to specify that a stack can be rolled back.
20 Enable Rollback = &enable
Jon Perrittb20ba0b2015-02-03 13:13:42 -070021)
22
Jon Perritt35e27e42014-12-05 11:10:46 -070023// CreateOptsBuilder is the interface options structs have to satisfy in order
24// to be used in the main Create operation in this package. Since many
25// extensions decorate or modify the common logic, it is useful for them to
26// satisfy a basic interface in order for them to be used.
27type CreateOptsBuilder interface {
28 ToStackCreateMap() (map[string]interface{}, error)
29}
30
31// CreateOpts is the common options struct used in this package's Create
32// operation.
33type CreateOpts struct {
Jon Perritt952f3e12015-02-03 12:13:24 -070034 // (REQUIRED) The name of the stack. It must start with an alphabetic character.
35 Name string
Pratik Mallya5fddb2a2015-09-14 14:04:49 -050036 // (REQUIRED) A structure that contains either the template file or url. Call the
37 // associated methods to extract the information relevant to send in a create request.
38 TemplateOpts *Template
39 // (DEPRECATED): Please use TemplateOpts for providing the template. If
40 // TemplateOpts is provided, TemplateURL will be ignored
Jon Perritt952f3e12015-02-03 12:13:24 -070041 // (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate.
42 // This value is ignored if Template is supplied inline.
43 TemplateURL string
Pratik Mallya5fddb2a2015-09-14 14:04:49 -050044 // (DEPRECATED): Please use TemplateOpts for providing the template. If
45 // TemplateOpts is provided, Template will be ignored
Jon Perritt952f3e12015-02-03 12:13:24 -070046 // (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value
47 // is a stringified version of the JSON/YAML template. Since the template will likely
48 // be located in a file, one way to set this variable is by using ioutil.ReadFile:
49 // import "io/ioutil"
50 // var opts stacks.CreateOpts
51 // b, err := ioutil.ReadFile("path/to/you/template/file.json")
52 // if err != nil {
53 // // handle error...
54 // }
55 // opts.Template = string(b)
56 Template string
57 // (OPTIONAL) Enables or disables deletion of all stack resources when a stack
58 // creation fails. Default is true, meaning all resources are not deleted when
59 // stack creation fails.
Jon Perritt37f97742015-02-04 18:55:05 -070060 DisableRollback Rollback
Pratik Mallya5fddb2a2015-09-14 14:04:49 -050061 // (OPTIONAL) A structure that contains details for the environment of the stack.
62 EnvironmentOpts *Environment
63 // (DEPRECATED): Please use EnvironmentOpts to provide Environment data
Jon Perritt952f3e12015-02-03 12:13:24 -070064 // (OPTIONAL) A stringified JSON environment for the stack.
65 Environment string
Pratik Mallya5fddb2a2015-09-14 14:04:49 -050066 // (DEPRECATED): Files is automatically determined
67 // by parsing the template and environment passed as TemplateOpts and
68 // EnvironmentOpts respectively.
Jon Perritt952f3e12015-02-03 12:13:24 -070069 // (OPTIONAL) A map that maps file names to file contents. It can also be used
70 // to pass provider template contents. Example:
71 // Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}`
72 Files map[string]interface{}
73 // (OPTIONAL) User-defined parameters to pass to the template.
74 Parameters map[string]string
Jon Perritt91709892015-02-11 17:53:43 -070075 // (OPTIONAL) The timeout for stack creation in minutes.
76 Timeout int
Pratik Mallya827c03e2015-09-17 00:10:47 -050077 // (OPTIONAL) A list of tags to assosciate with the Stack
78 Tags []string
Jon Perritt35e27e42014-12-05 11:10:46 -070079}
80
81// ToStackCreateMap casts a CreateOpts struct to a map.
82func (opts CreateOpts) ToStackCreateMap() (map[string]interface{}, error) {
83 s := make(map[string]interface{})
84
85 if opts.Name == "" {
86 return s, errors.New("Required field 'Name' not provided.")
87 }
88 s["stack_name"] = opts.Name
Pratik Mallya5fddb2a2015-09-14 14:04:49 -050089 Files := make(map[string]string)
90 if opts.TemplateOpts == nil {
91 if opts.Template != "" {
92 s["template"] = opts.Template
93 } else if opts.TemplateURL != "" {
94 s["template_url"] = opts.TemplateURL
95 } else {
96 return s, errors.New("Either Template or TemplateURL must be provided.")
97 }
Jon Perritt35e27e42014-12-05 11:10:46 -070098 } else {
Pratik Mallya5fddb2a2015-09-14 14:04:49 -050099 if err := opts.TemplateOpts.Parse(); err != nil {
100 return nil, err
101 }
102
Pratik Mallyae3086ae2015-09-21 15:25:16 -0500103 if err := opts.TemplateOpts.GetFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500104 return nil, err
105 }
106 opts.TemplateOpts.FixFileRefs()
107 s["template"] = string(opts.TemplateOpts.Bin)
108
109 for k, v := range opts.TemplateOpts.Files {
110 Files[k] = v
111 }
112 }
113 if opts.DisableRollback != nil {
114 s["disable_rollback"] = &opts.DisableRollback
115 }
116
117 if opts.EnvironmentOpts != nil {
118 if err := opts.EnvironmentOpts.Parse(); err != nil {
119 return nil, err
120 }
Pratik Mallyae3086ae2015-09-21 15:25:16 -0500121 if err := opts.EnvironmentOpts.GetRRFileContents(ignoreIfEnvironment); err != nil {
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500122 return nil, err
123 }
124 opts.EnvironmentOpts.FixFileRefs()
125 for k, v := range opts.EnvironmentOpts.Files {
126 Files[k] = v
127 }
128 s["environment"] = string(opts.EnvironmentOpts.Bin)
129 } else if opts.Environment != "" {
130 s["environment"] = opts.Environment
131 }
132
133 if opts.Files != nil {
134 s["files"] = opts.Files
135 } else {
136 s["files"] = Files
Jon Perritt35e27e42014-12-05 11:10:46 -0700137 }
138
139 if opts.DisableRollback != nil {
140 s["disable_rollback"] = &opts.DisableRollback
141 }
142
Jon Perritt35e27e42014-12-05 11:10:46 -0700143 if opts.Parameters != nil {
144 s["parameters"] = opts.Parameters
145 }
146
Jon Perritt91709892015-02-11 17:53:43 -0700147 if opts.Timeout != 0 {
148 s["timeout_mins"] = opts.Timeout
Jon Perritt35e27e42014-12-05 11:10:46 -0700149 }
150
Pratik Mallya827c03e2015-09-17 00:10:47 -0500151 if opts.Tags != nil {
152 s["tags"] = strings.Join(opts.Tags, ",")
153 }
Jon Perritt35e27e42014-12-05 11:10:46 -0700154 return s, nil
155}
156
157// Create accepts a CreateOpts struct and creates a new stack using the values
158// provided.
159func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) CreateResult {
160 var res CreateResult
161
162 reqBody, err := opts.ToStackCreateMap()
163 if err != nil {
164 res.Err = err
165 return res
166 }
167
Jamie Hannaford1d27afa2015-03-24 16:20:45 +0100168 _, res.Err = c.Post(createURL(c), reqBody, &res.Body, nil)
Jon Perritt35e27e42014-12-05 11:10:46 -0700169 return res
170}
171
172// AdoptOptsBuilder is the interface options structs have to satisfy in order
173// to be used in the Adopt function in this package. Since many
174// extensions decorate or modify the common logic, it is useful for them to
175// satisfy a basic interface in order for them to be used.
176type AdoptOptsBuilder interface {
177 ToStackAdoptMap() (map[string]interface{}, error)
178}
179
180// AdoptOpts is the common options struct used in this package's Adopt
181// operation.
182type AdoptOpts struct {
Jon Perritt9741dd92015-02-04 12:05:47 -0700183 // (REQUIRED) Existing resources data represented as a string to add to the
184 // new stack. Data returned by Abandon could be provided as AdoptsStackData.
185 AdoptStackData string
186 // (REQUIRED) The name of the stack. It must start with an alphabetic character.
187 Name string
188 // (REQUIRED) The timeout for stack creation in minutes.
189 Timeout int
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500190 // (REQUIRED) A structure that contains either the template file or url. Call the
191 // associated methods to extract the information relevant to send in a create request.
192 TemplateOpts *Template
193 // (DEPRECATED): Please use TemplateOpts for providing the template. If
194 // TemplateOpts is provided, TemplateURL will be ignored
Jon Perritt9741dd92015-02-04 12:05:47 -0700195 // (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate.
196 // This value is ignored if Template is supplied inline.
197 TemplateURL string
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500198 // (DEPRECATED): Please use TemplateOpts for providing the template. If
199 // TemplateOpts is provided, Template will be ignored
Jon Perritt9741dd92015-02-04 12:05:47 -0700200 // (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value
201 // is a stringified version of the JSON/YAML template. Since the template will likely
202 // be located in a file, one way to set this variable is by using ioutil.ReadFile:
203 // import "io/ioutil"
204 // var opts stacks.CreateOpts
205 // b, err := ioutil.ReadFile("path/to/you/template/file.json")
206 // if err != nil {
207 // // handle error...
208 // }
209 // opts.Template = string(b)
210 Template string
211 // (OPTIONAL) Enables or disables deletion of all stack resources when a stack
212 // creation fails. Default is true, meaning all resources are not deleted when
213 // stack creation fails.
Jon Perritt37f97742015-02-04 18:55:05 -0700214 DisableRollback Rollback
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500215 // (OPTIONAL) A structure that contains details for the environment of the stack.
216 EnvironmentOpts *Environment
217 // (DEPRECATED): Please use EnvironmentOpts to provide Environment data
Jon Perritt9741dd92015-02-04 12:05:47 -0700218 // (OPTIONAL) A stringified JSON environment for the stack.
219 Environment string
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500220 // (DEPRECATED): Files is automatically determined
221 // by parsing the template and environment passed as TemplateOpts and
222 // EnvironmentOpts respectively.
Jon Perritt9741dd92015-02-04 12:05:47 -0700223 // (OPTIONAL) A map that maps file names to file contents. It can also be used
224 // to pass provider template contents. Example:
225 // Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}`
226 Files map[string]interface{}
227 // (OPTIONAL) User-defined parameters to pass to the template.
228 Parameters map[string]string
Jon Perritt35e27e42014-12-05 11:10:46 -0700229}
230
231// ToStackAdoptMap casts a CreateOpts struct to a map.
232func (opts AdoptOpts) ToStackAdoptMap() (map[string]interface{}, error) {
233 s := make(map[string]interface{})
234
235 if opts.Name == "" {
236 return s, errors.New("Required field 'Name' not provided.")
237 }
238 s["stack_name"] = opts.Name
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500239 Files := make(map[string]string)
240 if opts.TemplateOpts == nil {
241 if opts.Template != "" {
242 s["template"] = opts.Template
243 } else if opts.TemplateURL != "" {
244 s["template_url"] = opts.TemplateURL
245 } else {
246 return s, errors.New("Either Template or TemplateURL must be provided.")
247 }
Jon Perritt35e27e42014-12-05 11:10:46 -0700248 } else {
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500249 if err := opts.TemplateOpts.Parse(); err != nil {
250 return nil, err
251 }
Jon Perritt35e27e42014-12-05 11:10:46 -0700252
Pratik Mallyae3086ae2015-09-21 15:25:16 -0500253 if err := opts.TemplateOpts.GetFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500254 return nil, err
255 }
256 opts.TemplateOpts.FixFileRefs()
257 s["template"] = string(opts.TemplateOpts.Bin)
258
259 for k, v := range opts.TemplateOpts.Files {
260 Files[k] = v
261 }
262 }
Jon Perritt35e27e42014-12-05 11:10:46 -0700263 if opts.AdoptStackData == "" {
264 return s, errors.New("Required field 'AdoptStackData' not provided.")
265 }
266 s["adopt_stack_data"] = opts.AdoptStackData
267
268 if opts.DisableRollback != nil {
269 s["disable_rollback"] = &opts.DisableRollback
270 }
271
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500272 if opts.EnvironmentOpts != nil {
273 if err := opts.EnvironmentOpts.Parse(); err != nil {
274 return nil, err
275 }
Pratik Mallyae3086ae2015-09-21 15:25:16 -0500276 if err := opts.EnvironmentOpts.GetRRFileContents(ignoreIfEnvironment); err != nil {
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500277 return nil, err
278 }
279 opts.EnvironmentOpts.FixFileRefs()
280 for k, v := range opts.EnvironmentOpts.Files {
281 Files[k] = v
282 }
283 s["environment"] = string(opts.EnvironmentOpts.Bin)
284 } else if opts.Environment != "" {
Jon Perritt35e27e42014-12-05 11:10:46 -0700285 s["environment"] = opts.Environment
286 }
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500287
Jon Perritt35e27e42014-12-05 11:10:46 -0700288 if opts.Files != nil {
289 s["files"] = opts.Files
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500290 } else {
291 s["files"] = Files
Jon Perritt35e27e42014-12-05 11:10:46 -0700292 }
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500293
Jon Perritt35e27e42014-12-05 11:10:46 -0700294 if opts.Parameters != nil {
295 s["parameters"] = opts.Parameters
296 }
297
Pratik Mallya827c03e2015-09-17 00:10:47 -0500298 if opts.Timeout != 0 {
299 s["timeout"] = opts.Timeout
Jon Perritt35e27e42014-12-05 11:10:46 -0700300 }
Jon Perritt9741dd92015-02-04 12:05:47 -0700301 s["timeout_mins"] = opts.Timeout
Jon Perritt35e27e42014-12-05 11:10:46 -0700302
Pratik Mallya827c03e2015-09-17 00:10:47 -0500303 return s, nil
Jon Perritt35e27e42014-12-05 11:10:46 -0700304}
305
306// Adopt accepts an AdoptOpts struct and creates a new stack using the resources
307// from another stack.
Jon Perritt9741dd92015-02-04 12:05:47 -0700308func Adopt(c *gophercloud.ServiceClient, opts AdoptOptsBuilder) AdoptResult {
309 var res AdoptResult
Jon Perritt35e27e42014-12-05 11:10:46 -0700310
311 reqBody, err := opts.ToStackAdoptMap()
312 if err != nil {
313 res.Err = err
314 return res
315 }
316
Jamie Hannaford1d27afa2015-03-24 16:20:45 +0100317 _, res.Err = c.Post(adoptURL(c), reqBody, &res.Body, nil)
Jon Perritt35e27e42014-12-05 11:10:46 -0700318 return res
319}
320
321// SortDir is a type for specifying in which direction to sort a list of stacks.
322type SortDir string
323
324// SortKey is a type for specifying by which key to sort a list of stacks.
325type SortKey string
326
327var (
328 // SortAsc is used to sort a list of stacks in ascending order.
329 SortAsc SortDir = "asc"
330 // SortDesc is used to sort a list of stacks in descending order.
331 SortDesc SortDir = "desc"
332 // SortName is used to sort a list of stacks by name.
333 SortName SortKey = "name"
334 // SortStatus is used to sort a list of stacks by status.
335 SortStatus SortKey = "status"
336 // SortCreatedAt is used to sort a list of stacks by date created.
337 SortCreatedAt SortKey = "created_at"
338 // SortUpdatedAt is used to sort a list of stacks by date updated.
339 SortUpdatedAt SortKey = "updated_at"
340)
341
342// ListOptsBuilder allows extensions to add additional parameters to the
343// List request.
344type ListOptsBuilder interface {
345 ToStackListQuery() (string, error)
346}
347
348// ListOpts allows the filtering and sorting of paginated collections through
349// the API. Filtering is achieved by passing in struct field values that map to
350// the network attributes you want to see returned. SortKey allows you to sort
351// by a particular network attribute. SortDir sets the direction, and is either
352// `asc' or `desc'. Marker and Limit are used for pagination.
353type ListOpts struct {
354 Status string `q:"status"`
355 Name string `q:"name"`
356 Marker string `q:"marker"`
357 Limit int `q:"limit"`
358 SortKey SortKey `q:"sort_keys"`
359 SortDir SortDir `q:"sort_dir"`
360}
361
362// ToStackListQuery formats a ListOpts into a query string.
363func (opts ListOpts) ToStackListQuery() (string, error) {
364 q, err := gophercloud.BuildQueryString(opts)
365 if err != nil {
366 return "", err
367 }
368 return q.String(), nil
369}
370
371// List returns a Pager which allows you to iterate over a collection of
372// stacks. It accepts a ListOpts struct, which allows you to filter and sort
373// the returned collection for greater efficiency.
374func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
375 url := listURL(c)
376 if opts != nil {
377 query, err := opts.ToStackListQuery()
378 if err != nil {
379 return pagination.Pager{Err: err}
380 }
381 url += query
382 }
383
384 createPage := func(r pagination.PageResult) pagination.Page {
385 return StackPage{pagination.SinglePageBase(r)}
386 }
387 return pagination.NewPager(c, url, createPage)
388}
389
390// Get retreives a stack based on the stack name and stack ID.
391func Get(c *gophercloud.ServiceClient, stackName, stackID string) GetResult {
392 var res GetResult
Jamie Hannaford1d27afa2015-03-24 16:20:45 +0100393 _, res.Err = c.Get(getURL(c, stackName, stackID), &res.Body, nil)
Jon Perritt35e27e42014-12-05 11:10:46 -0700394 return res
395}
396
397// UpdateOptsBuilder is the interface options structs have to satisfy in order
398// to be used in the Update operation in this package.
399type UpdateOptsBuilder interface {
400 ToStackUpdateMap() (map[string]interface{}, error)
401}
402
403// UpdateOpts contains the common options struct used in this package's Update
404// operation.
405type UpdateOpts struct {
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500406 // (REQUIRED) A structure that contains either the template file or url. Call the
407 // associated methods to extract the information relevant to send in a create request.
408 TemplateOpts *Template
409 // (DEPRECATED): Please use TemplateOpts for providing the template. If
410 // TemplateOpts is provided, TemplateURL will be ignored
Jon Perritt37f97742015-02-04 18:55:05 -0700411 // (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate.
412 // This value is ignored if Template is supplied inline.
Jon Perritt35e27e42014-12-05 11:10:46 -0700413 TemplateURL string
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500414 // (DEPRECATED): Please use TemplateOpts for providing the template. If
415 // TemplateOpts is provided, Template will be ignored
Jon Perritt37f97742015-02-04 18:55:05 -0700416 // (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value
417 // is a stringified version of the JSON/YAML template. Since the template will likely
418 // be located in a file, one way to set this variable is by using ioutil.ReadFile:
419 // import "io/ioutil"
420 // var opts stacks.CreateOpts
421 // b, err := ioutil.ReadFile("path/to/you/template/file.json")
422 // if err != nil {
423 // // handle error...
424 // }
425 // opts.Template = string(b)
426 Template string
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500427 // (OPTIONAL) A structure that contains details for the environment of the stack.
428 EnvironmentOpts *Environment
429 // (DEPRECATED): Please use EnvironmentOpts to provide Environment data
Jon Perritt37f97742015-02-04 18:55:05 -0700430 // (OPTIONAL) A stringified JSON environment for the stack.
431 Environment string
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500432 // (DEPRECATED): Files is automatically determined
433 // by parsing the template and environment passed as TemplateOpts and
434 // EnvironmentOpts respectively.
Jon Perritt37f97742015-02-04 18:55:05 -0700435 // (OPTIONAL) A map that maps file names to file contents. It can also be used
436 // to pass provider template contents. Example:
437 // Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}`
438 Files map[string]interface{}
439 // (OPTIONAL) User-defined parameters to pass to the template.
440 Parameters map[string]string
Jon Perritt51107182015-02-11 18:18:19 -0700441 // (OPTIONAL) The timeout for stack creation in minutes.
442 Timeout int
Pratik Mallya827c03e2015-09-17 00:10:47 -0500443 // (OPTIONAL) A list of tags to assosciate with the Stack
444 Tags []string
Jon Perritt35e27e42014-12-05 11:10:46 -0700445}
446
447// ToStackUpdateMap casts a CreateOpts struct to a map.
448func (opts UpdateOpts) ToStackUpdateMap() (map[string]interface{}, error) {
449 s := make(map[string]interface{})
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500450 Files := make(map[string]string)
451 if opts.TemplateOpts == nil {
452 if opts.Template != "" {
453 s["template"] = opts.Template
454 } else if opts.TemplateURL != "" {
455 s["template_url"] = opts.TemplateURL
456 } else {
457 return s, errors.New("Either Template or TemplateURL must be provided.")
458 }
Jon Perritt35e27e42014-12-05 11:10:46 -0700459 } else {
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500460 if err := opts.TemplateOpts.Parse(); err != nil {
461 return nil, err
462 }
463
Pratik Mallyae3086ae2015-09-21 15:25:16 -0500464 if err := opts.TemplateOpts.GetFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500465 return nil, err
466 }
467 opts.TemplateOpts.FixFileRefs()
468 s["template"] = string(opts.TemplateOpts.Bin)
469
470 for k, v := range opts.TemplateOpts.Files {
471 Files[k] = v
472 }
Jon Perritt35e27e42014-12-05 11:10:46 -0700473 }
474
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500475 if opts.EnvironmentOpts != nil {
476 if err := opts.EnvironmentOpts.Parse(); err != nil {
477 return nil, err
478 }
Pratik Mallyae3086ae2015-09-21 15:25:16 -0500479 if err := opts.EnvironmentOpts.GetRRFileContents(ignoreIfEnvironment); err != nil {
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500480 return nil, err
481 }
482 opts.EnvironmentOpts.FixFileRefs()
483 for k, v := range opts.EnvironmentOpts.Files {
484 Files[k] = v
485 }
486 s["environment"] = string(opts.EnvironmentOpts.Bin)
487 } else if opts.Environment != "" {
Jon Perritt35e27e42014-12-05 11:10:46 -0700488 s["environment"] = opts.Environment
489 }
490
491 if opts.Files != nil {
492 s["files"] = opts.Files
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500493 } else {
494 s["files"] = Files
Jon Perritt35e27e42014-12-05 11:10:46 -0700495 }
496
497 if opts.Parameters != nil {
498 s["parameters"] = opts.Parameters
499 }
500
501 if opts.Timeout != 0 {
502 s["timeout_mins"] = opts.Timeout
503 }
504
Pratik Mallya827c03e2015-09-17 00:10:47 -0500505 if opts.Tags != nil {
506 s["tags"] = strings.Join(opts.Tags, ",")
507 }
508
Jon Perritt35e27e42014-12-05 11:10:46 -0700509 return s, nil
510}
511
512// Update accepts an UpdateOpts struct and updates an existing stack using the values
513// provided.
514func Update(c *gophercloud.ServiceClient, stackName, stackID string, opts UpdateOptsBuilder) UpdateResult {
515 var res UpdateResult
516
517 reqBody, err := opts.ToStackUpdateMap()
518 if err != nil {
519 res.Err = err
520 return res
521 }
522
Jamie Hannaford1d27afa2015-03-24 16:20:45 +0100523 _, res.Err = c.Put(updateURL(c, stackName, stackID), reqBody, nil, nil)
Jon Perritt35e27e42014-12-05 11:10:46 -0700524 return res
525}
526
527// Delete deletes a stack based on the stack name and stack ID.
528func Delete(c *gophercloud.ServiceClient, stackName, stackID string) DeleteResult {
529 var res DeleteResult
Jamie Hannaford1d27afa2015-03-24 16:20:45 +0100530 _, res.Err = c.Delete(deleteURL(c, stackName, stackID), nil)
Jon Perritt35e27e42014-12-05 11:10:46 -0700531 return res
532}
533
534// PreviewOptsBuilder is the interface options structs have to satisfy in order
535// to be used in the Preview operation in this package.
536type PreviewOptsBuilder interface {
537 ToStackPreviewMap() (map[string]interface{}, error)
538}
539
540// PreviewOpts contains the common options struct used in this package's Preview
541// operation.
542type PreviewOpts struct {
Jon Perritt37f97742015-02-04 18:55:05 -0700543 // (REQUIRED) The name of the stack. It must start with an alphabetic character.
544 Name string
545 // (REQUIRED) The timeout for stack creation in minutes.
546 Timeout int
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500547 // (REQUIRED) A structure that contains either the template file or url. Call the
548 // associated methods to extract the information relevant to send in a create request.
549 TemplateOpts *Template
550 // (DEPRECATED): Please use TemplateOpts for providing the template. If
551 // TemplateOpts is provided, TemplateURL will be ignored
Jon Perritt37f97742015-02-04 18:55:05 -0700552 // (OPTIONAL; REQUIRED IF Template IS EMPTY) The URL of the template to instantiate.
553 // This value is ignored if Template is supplied inline.
554 TemplateURL string
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500555 // (DEPRECATED): Please use TemplateOpts for providing the template. If
556 // TemplateOpts is provided, Template will be ignored
Jon Perritt37f97742015-02-04 18:55:05 -0700557 // (OPTIONAL; REQUIRED IF TemplateURL IS EMPTY) A template to instantiate. The value
558 // is a stringified version of the JSON/YAML template. Since the template will likely
559 // be located in a file, one way to set this variable is by using ioutil.ReadFile:
560 // import "io/ioutil"
561 // var opts stacks.CreateOpts
562 // b, err := ioutil.ReadFile("path/to/you/template/file.json")
563 // if err != nil {
564 // // handle error...
565 // }
566 // opts.Template = string(b)
567 Template string
568 // (OPTIONAL) Enables or disables deletion of all stack resources when a stack
569 // creation fails. Default is true, meaning all resources are not deleted when
570 // stack creation fails.
571 DisableRollback Rollback
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500572 // (OPTIONAL) A structure that contains details for the environment of the stack.
573 EnvironmentOpts *Environment
574 // (DEPRECATED): Please use EnvironmentOpts to provide Environment data
Jon Perritt37f97742015-02-04 18:55:05 -0700575 // (OPTIONAL) A stringified JSON environment for the stack.
576 Environment string
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500577 // (DEPRECATED): Files is automatically determined
578 // by parsing the template and environment passed as TemplateOpts and
579 // EnvironmentOpts respectively.
Jon Perritt37f97742015-02-04 18:55:05 -0700580 // (OPTIONAL) A map that maps file names to file contents. It can also be used
581 // to pass provider template contents. Example:
582 // Files: `{"myfile": "#!/bin/bash\necho 'Hello world' > /root/testfile.txt"}`
583 Files map[string]interface{}
584 // (OPTIONAL) User-defined parameters to pass to the template.
585 Parameters map[string]string
Jon Perritt35e27e42014-12-05 11:10:46 -0700586}
587
588// ToStackPreviewMap casts a PreviewOpts struct to a map.
589func (opts PreviewOpts) ToStackPreviewMap() (map[string]interface{}, error) {
590 s := make(map[string]interface{})
591
592 if opts.Name == "" {
593 return s, errors.New("Required field 'Name' not provided.")
594 }
595 s["stack_name"] = opts.Name
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500596 Files := make(map[string]string)
597 if opts.TemplateOpts == nil {
598 if opts.Template != "" {
599 s["template"] = opts.Template
600 } else if opts.TemplateURL != "" {
601 s["template_url"] = opts.TemplateURL
602 } else {
603 return s, errors.New("Either Template or TemplateURL must be provided.")
604 }
Jon Perritt35e27e42014-12-05 11:10:46 -0700605 } else {
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500606 if err := opts.TemplateOpts.Parse(); err != nil {
607 return nil, err
608 }
Jon Perritt35e27e42014-12-05 11:10:46 -0700609
Pratik Mallyae3086ae2015-09-21 15:25:16 -0500610 if err := opts.TemplateOpts.GetFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil {
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500611 return nil, err
612 }
613 opts.TemplateOpts.FixFileRefs()
614 s["template"] = string(opts.TemplateOpts.Bin)
615
616 for k, v := range opts.TemplateOpts.Files {
617 Files[k] = v
618 }
619 }
Jon Perritt35e27e42014-12-05 11:10:46 -0700620 if opts.DisableRollback != nil {
621 s["disable_rollback"] = &opts.DisableRollback
622 }
623
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500624 if opts.EnvironmentOpts != nil {
625 if err := opts.EnvironmentOpts.Parse(); err != nil {
626 return nil, err
627 }
Pratik Mallyae3086ae2015-09-21 15:25:16 -0500628 if err := opts.EnvironmentOpts.GetRRFileContents(ignoreIfEnvironment); err != nil {
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500629 return nil, err
630 }
631 opts.EnvironmentOpts.FixFileRefs()
632 for k, v := range opts.EnvironmentOpts.Files {
633 Files[k] = v
634 }
635 s["environment"] = string(opts.EnvironmentOpts.Bin)
636 } else if opts.Environment != "" {
Jon Perritt35e27e42014-12-05 11:10:46 -0700637 s["environment"] = opts.Environment
638 }
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500639
Jon Perritt35e27e42014-12-05 11:10:46 -0700640 if opts.Files != nil {
641 s["files"] = opts.Files
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500642 } else {
643 s["files"] = Files
Jon Perritt35e27e42014-12-05 11:10:46 -0700644 }
Pratik Mallya5fddb2a2015-09-14 14:04:49 -0500645
Jon Perritt35e27e42014-12-05 11:10:46 -0700646 if opts.Parameters != nil {
647 s["parameters"] = opts.Parameters
648 }
649
650 if opts.Timeout != 0 {
651 s["timeout_mins"] = opts.Timeout
652 }
653
654 return s, nil
655}
656
657// Preview accepts a PreviewOptsBuilder interface and creates a preview of a stack using the values
658// provided.
659func Preview(c *gophercloud.ServiceClient, opts PreviewOptsBuilder) PreviewResult {
660 var res PreviewResult
661
662 reqBody, err := opts.ToStackPreviewMap()
663 if err != nil {
664 res.Err = err
665 return res
666 }
667
668 // Send request to API
Jamie Hannaford1d27afa2015-03-24 16:20:45 +0100669 _, res.Err = c.Post(previewURL(c), reqBody, &res.Body, &gophercloud.RequestOpts{
670 OkCodes: []int{200},
Jon Perritt35e27e42014-12-05 11:10:46 -0700671 })
672 return res
673}
674
675// Abandon deletes the stack with the provided stackName and stackID, but leaves its
676// resources intact, and returns data describing the stack and its resources.
677func Abandon(c *gophercloud.ServiceClient, stackName, stackID string) AbandonResult {
678 var res AbandonResult
Jamie Hannaford1d27afa2015-03-24 16:20:45 +0100679 _, res.Err = c.Delete(abandonURL(c, stackName, stackID), &gophercloud.RequestOpts{
Ash Wilsondecfed72015-02-13 09:14:55 -0500680 JSONResponse: &res.Body,
681 OkCodes: []int{200},
Jon Perritt35e27e42014-12-05 11:10:46 -0700682 })
683 return res
684}