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  }