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