github.com/gophercloud/gophercloud@v1.11.0/openstack/orchestration/v1/stacks/requests.go (about) 1 package stacks 2 3 import ( 4 "fmt" 5 "strings" 6 7 "github.com/gophercloud/gophercloud" 8 "github.com/gophercloud/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. 15 type 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. 21 type CreateOpts struct { 22 // The name of the stack. It must start with an alphabetic character. 23 Name string `json:"stack_name" required:"true"` 24 // A structure that contains either the template file or url. Call the 25 // associated methods to extract the information relevant to send in a create request. 26 TemplateOpts *Template `json:"-" required:"true"` 27 // Enables or disables deletion of all stack resources when a stack 28 // creation fails. Default is true, meaning all resources are not deleted when 29 // stack creation fails. 30 DisableRollback *bool `json:"disable_rollback,omitempty"` 31 // A structure that contains details for the environment of the stack. 32 EnvironmentOpts *Environment `json:"-"` 33 // User-defined parameters to pass to the template. 34 Parameters map[string]interface{} `json:"parameters,omitempty"` 35 // The timeout for stack creation in minutes. 36 Timeout int `json:"timeout_mins,omitempty"` 37 // A list of tags to assosciate with the Stack 38 Tags []string `json:"-"` 39 } 40 41 // ToStackCreateMap casts a CreateOpts struct to a map. 42 func (opts CreateOpts) ToStackCreateMap() (map[string]interface{}, error) { 43 b, err := gophercloud.BuildRequestBody(opts, "") 44 if err != nil { 45 return nil, err 46 } 47 48 if err := opts.TemplateOpts.Parse(); err != nil { 49 return nil, err 50 } 51 52 if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil { 53 return nil, err 54 } 55 opts.TemplateOpts.fixFileRefs() 56 b["template"] = string(opts.TemplateOpts.Bin) 57 58 files := make(map[string]string) 59 for k, v := range opts.TemplateOpts.Files { 60 files[k] = v 61 } 62 63 if opts.EnvironmentOpts != nil { 64 if err := opts.EnvironmentOpts.Parse(); err != nil { 65 return nil, err 66 } 67 if err := opts.EnvironmentOpts.getRRFileContents(ignoreIfEnvironment); err != nil { 68 return nil, err 69 } 70 opts.EnvironmentOpts.fixFileRefs() 71 for k, v := range opts.EnvironmentOpts.Files { 72 files[k] = v 73 } 74 b["environment"] = string(opts.EnvironmentOpts.Bin) 75 } 76 77 if len(files) > 0 { 78 b["files"] = files 79 } 80 81 if opts.Tags != nil { 82 b["tags"] = strings.Join(opts.Tags, ",") 83 } 84 85 return b, nil 86 } 87 88 // Create accepts a CreateOpts struct and creates a new stack using the values 89 // provided. 90 func Create(c *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) { 91 b, err := opts.ToStackCreateMap() 92 if err != nil { 93 r.Err = fmt.Errorf("error creating the options map: %w", err) 94 return 95 } 96 resp, err := c.Post(createURL(c), b, &r.Body, nil) 97 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 98 return 99 } 100 101 // AdoptOptsBuilder is the interface options structs have to satisfy in order 102 // to be used in the Adopt function in this package. Since many 103 // extensions decorate or modify the common logic, it is useful for them to 104 // satisfy a basic interface in order for them to be used. 105 type AdoptOptsBuilder interface { 106 ToStackAdoptMap() (map[string]interface{}, error) 107 } 108 109 // AdoptOpts is the common options struct used in this package's Adopt 110 // operation. 111 type AdoptOpts struct { 112 // Existing resources data represented as a string to add to the 113 // new stack. Data returned by Abandon could be provided as AdoptsStackData. 114 AdoptStackData string `json:"adopt_stack_data" required:"true"` 115 // The name of the stack. It must start with an alphabetic character. 116 Name string `json:"stack_name" required:"true"` 117 // A structure that contains either the template file or url. Call the 118 // associated methods to extract the information relevant to send in a create request. 119 TemplateOpts *Template `json:"-" required:"true"` 120 // The timeout for stack creation in minutes. 121 Timeout int `json:"timeout_mins,omitempty"` 122 // A structure that contains either the template file or url. Call the 123 // associated methods to extract the information relevant to send in a create request. 124 //TemplateOpts *Template `json:"-" required:"true"` 125 // Enables or disables deletion of all stack resources when a stack 126 // creation fails. Default is true, meaning all resources are not deleted when 127 // stack creation fails. 128 DisableRollback *bool `json:"disable_rollback,omitempty"` 129 // A structure that contains details for the environment of the stack. 130 EnvironmentOpts *Environment `json:"-"` 131 // User-defined parameters to pass to the template. 132 Parameters map[string]interface{} `json:"parameters,omitempty"` 133 } 134 135 // ToStackAdoptMap casts a CreateOpts struct to a map. 136 func (opts AdoptOpts) ToStackAdoptMap() (map[string]interface{}, error) { 137 b, err := gophercloud.BuildRequestBody(opts, "") 138 if err != nil { 139 return nil, err 140 } 141 142 if err := opts.TemplateOpts.Parse(); err != nil { 143 return nil, err 144 } 145 146 if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil { 147 return nil, err 148 } 149 opts.TemplateOpts.fixFileRefs() 150 b["template"] = string(opts.TemplateOpts.Bin) 151 152 files := make(map[string]string) 153 for k, v := range opts.TemplateOpts.Files { 154 files[k] = v 155 } 156 157 if opts.EnvironmentOpts != nil { 158 if err := opts.EnvironmentOpts.Parse(); err != nil { 159 return nil, err 160 } 161 if err := opts.EnvironmentOpts.getRRFileContents(ignoreIfEnvironment); err != nil { 162 return nil, err 163 } 164 opts.EnvironmentOpts.fixFileRefs() 165 for k, v := range opts.EnvironmentOpts.Files { 166 files[k] = v 167 } 168 b["environment"] = string(opts.EnvironmentOpts.Bin) 169 } 170 171 if len(files) > 0 { 172 b["files"] = files 173 } 174 175 return b, nil 176 } 177 178 // Adopt accepts an AdoptOpts struct and creates a new stack using the resources 179 // from another stack. 180 func Adopt(c *gophercloud.ServiceClient, opts AdoptOptsBuilder) (r AdoptResult) { 181 b, err := opts.ToStackAdoptMap() 182 if err != nil { 183 r.Err = err 184 return 185 } 186 resp, err := c.Post(adoptURL(c), b, &r.Body, nil) 187 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 188 return 189 } 190 191 // SortDir is a type for specifying in which direction to sort a list of stacks. 192 type SortDir string 193 194 // SortKey is a type for specifying by which key to sort a list of stacks. 195 type SortKey string 196 197 var ( 198 // SortAsc is used to sort a list of stacks in ascending order. 199 SortAsc SortDir = "asc" 200 // SortDesc is used to sort a list of stacks in descending order. 201 SortDesc SortDir = "desc" 202 // SortName is used to sort a list of stacks by name. 203 SortName SortKey = "name" 204 // SortStatus is used to sort a list of stacks by status. 205 SortStatus SortKey = "status" 206 // SortCreatedAt is used to sort a list of stacks by date created. 207 SortCreatedAt SortKey = "created_at" 208 // SortUpdatedAt is used to sort a list of stacks by date updated. 209 SortUpdatedAt SortKey = "updated_at" 210 ) 211 212 // ListOptsBuilder allows extensions to add additional parameters to the 213 // List request. 214 type ListOptsBuilder interface { 215 ToStackListQuery() (string, error) 216 } 217 218 // ListOpts allows the filtering and sorting of paginated collections through 219 // the API. Filtering is achieved by passing in struct field values that map to 220 // the network attributes you want to see returned. 221 type ListOpts struct { 222 // TenantID is the UUID of the tenant. A tenant is also known as 223 // a project. 224 TenantID string `q:"tenant_id"` 225 226 // ID filters the stack list by a stack ID 227 ID string `q:"id"` 228 229 // Status filters the stack list by a status. 230 Status string `q:"status"` 231 232 // Name filters the stack list by a name. 233 Name string `q:"name"` 234 235 // Marker is the ID of last-seen item. 236 Marker string `q:"marker"` 237 238 // Limit is an integer value for the limit of values to return. 239 Limit int `q:"limit"` 240 241 // SortKey allows you to sort by stack_name, stack_status, creation_time, or 242 // update_time key. 243 SortKey SortKey `q:"sort_keys"` 244 245 // SortDir sets the direction, and is either `asc` or `desc`. 246 SortDir SortDir `q:"sort_dir"` 247 248 // AllTenants is a bool to show all tenants. 249 AllTenants bool `q:"global_tenant"` 250 251 // ShowDeleted set to `true` to include deleted stacks in the list. 252 ShowDeleted bool `q:"show_deleted"` 253 254 // ShowNested set to `true` to include nested stacks in the list. 255 ShowNested bool `q:"show_nested"` 256 257 // ShowHidden set to `true` to include hiddened stacks in the list. 258 ShowHidden bool `q:"show_hidden"` 259 260 // Tags lists stacks that contain one or more simple string tags. 261 Tags string `q:"tags"` 262 263 // TagsAny lists stacks that contain one or more simple string tags. 264 TagsAny string `q:"tags_any"` 265 266 // NotTags lists stacks that do not contain one or more simple string tags. 267 NotTags string `q:"not_tags"` 268 269 // NotTagsAny lists stacks that do not contain one or more simple string tags. 270 NotTagsAny string `q:"not_tags_any"` 271 } 272 273 // ToStackListQuery formats a ListOpts into a query string. 274 func (opts ListOpts) ToStackListQuery() (string, error) { 275 q, err := gophercloud.BuildQueryString(opts) 276 if err != nil { 277 return "", err 278 } 279 return q.String(), nil 280 } 281 282 // List returns a Pager which allows you to iterate over a collection of 283 // stacks. It accepts a ListOpts struct, which allows you to filter and sort 284 // the returned collection for greater efficiency. 285 func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager { 286 url := listURL(c) 287 if opts != nil { 288 query, err := opts.ToStackListQuery() 289 if err != nil { 290 return pagination.Pager{Err: err} 291 } 292 url += query 293 } 294 createPage := func(r pagination.PageResult) pagination.Page { 295 return StackPage{pagination.SinglePageBase(r)} 296 } 297 return pagination.NewPager(c, url, createPage) 298 } 299 300 // Get retreives a stack based on the stack name and stack ID. 301 func Get(c *gophercloud.ServiceClient, stackName, stackID string) (r GetResult) { 302 resp, err := c.Get(getURL(c, stackName, stackID), &r.Body, nil) 303 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 304 return 305 } 306 307 // Find retrieves a stack based on the stack name or stack ID. 308 func Find(c *gophercloud.ServiceClient, stackIdentity string) (r GetResult) { 309 resp, err := c.Get(findURL(c, stackIdentity), &r.Body, nil) 310 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 311 return 312 } 313 314 // UpdateOptsBuilder is the interface options structs have to satisfy in order 315 // to be used in the Update operation in this package. 316 type UpdateOptsBuilder interface { 317 ToStackUpdateMap() (map[string]interface{}, error) 318 } 319 320 // UpdatePatchOptsBuilder is the interface options structs have to satisfy in order 321 // to be used in the UpdatePatch operation in this package 322 type UpdatePatchOptsBuilder interface { 323 ToStackUpdatePatchMap() (map[string]interface{}, error) 324 } 325 326 // UpdateOpts contains the common options struct used in this package's Update 327 // and UpdatePatch operations. 328 type UpdateOpts struct { 329 // A structure that contains either the template file or url. Call the 330 // associated methods to extract the information relevant to send in a create request. 331 TemplateOpts *Template `json:"-"` 332 // A structure that contains details for the environment of the stack. 333 EnvironmentOpts *Environment `json:"-"` 334 // User-defined parameters to pass to the template. 335 Parameters map[string]interface{} `json:"parameters,omitempty"` 336 // The timeout for stack creation in minutes. 337 Timeout int `json:"timeout_mins,omitempty"` 338 // A list of tags to associate with the Stack 339 Tags []string `json:"-"` 340 } 341 342 // ToStackUpdateMap validates that a template was supplied and calls 343 // the toStackUpdateMap private function. 344 func (opts UpdateOpts) ToStackUpdateMap() (map[string]interface{}, error) { 345 if opts.TemplateOpts == nil { 346 return nil, ErrTemplateRequired{} 347 } 348 return toStackUpdateMap(opts) 349 } 350 351 // ToStackUpdatePatchMap calls the private function toStackUpdateMap 352 // directly. 353 func (opts UpdateOpts) ToStackUpdatePatchMap() (map[string]interface{}, error) { 354 return toStackUpdateMap(opts) 355 } 356 357 // ToStackUpdateMap casts a CreateOpts struct to a map. 358 func toStackUpdateMap(opts UpdateOpts) (map[string]interface{}, error) { 359 b, err := gophercloud.BuildRequestBody(opts, "") 360 if err != nil { 361 return nil, err 362 } 363 364 files := make(map[string]string) 365 366 if opts.TemplateOpts != nil { 367 if err := opts.TemplateOpts.Parse(); err != nil { 368 return nil, err 369 } 370 371 if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil { 372 return nil, err 373 } 374 opts.TemplateOpts.fixFileRefs() 375 b["template"] = string(opts.TemplateOpts.Bin) 376 377 for k, v := range opts.TemplateOpts.Files { 378 files[k] = v 379 } 380 } 381 382 if opts.EnvironmentOpts != nil { 383 if err := opts.EnvironmentOpts.Parse(); err != nil { 384 return nil, err 385 } 386 if err := opts.EnvironmentOpts.getRRFileContents(ignoreIfEnvironment); err != nil { 387 return nil, err 388 } 389 opts.EnvironmentOpts.fixFileRefs() 390 for k, v := range opts.EnvironmentOpts.Files { 391 files[k] = v 392 } 393 b["environment"] = string(opts.EnvironmentOpts.Bin) 394 } 395 396 if len(files) > 0 { 397 b["files"] = files 398 } 399 400 if opts.Tags != nil { 401 b["tags"] = strings.Join(opts.Tags, ",") 402 } 403 404 return b, nil 405 } 406 407 // Update accepts an UpdateOpts struct and updates an existing stack using the 408 // 409 // http PUT verb with the values provided. opts.TemplateOpts is required. 410 func Update(c *gophercloud.ServiceClient, stackName, stackID string, opts UpdateOptsBuilder) (r UpdateResult) { 411 b, err := opts.ToStackUpdateMap() 412 if err != nil { 413 r.Err = err 414 return 415 } 416 resp, err := c.Put(updateURL(c, stackName, stackID), b, nil, nil) 417 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 418 return 419 } 420 421 // Update accepts an UpdateOpts struct and updates an existing stack using the 422 // 423 // http PATCH verb with the values provided. opts.TemplateOpts is not required. 424 func UpdatePatch(c *gophercloud.ServiceClient, stackName, stackID string, opts UpdatePatchOptsBuilder) (r UpdateResult) { 425 b, err := opts.ToStackUpdatePatchMap() 426 if err != nil { 427 r.Err = err 428 return 429 } 430 resp, err := c.Patch(updateURL(c, stackName, stackID), b, nil, nil) 431 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 432 return 433 } 434 435 // Delete deletes a stack based on the stack name and stack ID. 436 func Delete(c *gophercloud.ServiceClient, stackName, stackID string) (r DeleteResult) { 437 resp, err := c.Delete(deleteURL(c, stackName, stackID), nil) 438 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 439 return 440 } 441 442 // PreviewOptsBuilder is the interface options structs have to satisfy in order 443 // to be used in the Preview operation in this package. 444 type PreviewOptsBuilder interface { 445 ToStackPreviewMap() (map[string]interface{}, error) 446 } 447 448 // PreviewOpts contains the common options struct used in this package's Preview 449 // operation. 450 type PreviewOpts struct { 451 // The name of the stack. It must start with an alphabetic character. 452 Name string `json:"stack_name" required:"true"` 453 // The timeout for stack creation in minutes. 454 Timeout int `json:"timeout_mins" required:"true"` 455 // A structure that contains either the template file or url. Call the 456 // associated methods to extract the information relevant to send in a create request. 457 TemplateOpts *Template `json:"-" required:"true"` 458 // Enables or disables deletion of all stack resources when a stack 459 // creation fails. Default is true, meaning all resources are not deleted when 460 // stack creation fails. 461 DisableRollback *bool `json:"disable_rollback,omitempty"` 462 // A structure that contains details for the environment of the stack. 463 EnvironmentOpts *Environment `json:"-"` 464 // User-defined parameters to pass to the template. 465 Parameters map[string]interface{} `json:"parameters,omitempty"` 466 } 467 468 // ToStackPreviewMap casts a PreviewOpts struct to a map. 469 func (opts PreviewOpts) ToStackPreviewMap() (map[string]interface{}, error) { 470 b, err := gophercloud.BuildRequestBody(opts, "") 471 if err != nil { 472 return nil, err 473 } 474 475 if err := opts.TemplateOpts.Parse(); err != nil { 476 return nil, err 477 } 478 479 if err := opts.TemplateOpts.getFileContents(opts.TemplateOpts.Parsed, ignoreIfTemplate, true); err != nil { 480 return nil, err 481 } 482 opts.TemplateOpts.fixFileRefs() 483 b["template"] = string(opts.TemplateOpts.Bin) 484 485 files := make(map[string]string) 486 for k, v := range opts.TemplateOpts.Files { 487 files[k] = v 488 } 489 490 if opts.EnvironmentOpts != nil { 491 if err := opts.EnvironmentOpts.Parse(); err != nil { 492 return nil, err 493 } 494 if err := opts.EnvironmentOpts.getRRFileContents(ignoreIfEnvironment); err != nil { 495 return nil, err 496 } 497 opts.EnvironmentOpts.fixFileRefs() 498 for k, v := range opts.EnvironmentOpts.Files { 499 files[k] = v 500 } 501 b["environment"] = string(opts.EnvironmentOpts.Bin) 502 } 503 504 if len(files) > 0 { 505 b["files"] = files 506 } 507 508 return b, nil 509 } 510 511 // Preview accepts a PreviewOptsBuilder interface and creates a preview of a stack using the values 512 // provided. 513 func Preview(c *gophercloud.ServiceClient, opts PreviewOptsBuilder) (r PreviewResult) { 514 b, err := opts.ToStackPreviewMap() 515 if err != nil { 516 r.Err = err 517 return 518 } 519 resp, err := c.Post(previewURL(c), b, &r.Body, &gophercloud.RequestOpts{ 520 OkCodes: []int{200}, 521 }) 522 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 523 return 524 } 525 526 // Abandon deletes the stack with the provided stackName and stackID, but leaves its 527 // resources intact, and returns data describing the stack and its resources. 528 func Abandon(c *gophercloud.ServiceClient, stackName, stackID string) (r AbandonResult) { 529 resp, err := c.Delete(abandonURL(c, stackName, stackID), &gophercloud.RequestOpts{ 530 JSONResponse: &r.Body, 531 OkCodes: []int{200}, 532 }) 533 _, r.Header, r.Err = gophercloud.ParseResponse(resp, err) 534 return 535 }