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  }