github.com/leeclow-ops/gophercloud@v1.2.1/openstack/orchestration/v1/stacks/requests.go (about)

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