github.com/vnpaycloud-console/gophercloud/v2@v2.0.5/openstack/image/v2/images/requests.go (about)

     1  package images
     2  
     3  import (
     4  	"context"
     5  	"fmt"
     6  	"net/url"
     7  	"time"
     8  
     9  	"github.com/vnpaycloud-console/gophercloud/v2"
    10  	"github.com/vnpaycloud-console/gophercloud/v2/pagination"
    11  )
    12  
    13  // ListOptsBuilder allows extensions to add additional parameters to the
    14  // List request.
    15  type ListOptsBuilder interface {
    16  	ToImageListQuery() (string, error)
    17  }
    18  
    19  // ListOpts allows the filtering and sorting of paginated collections through
    20  // the API. Filtering is achieved by passing in struct field values that map to
    21  // the server attributes you want to see returned. Marker and Limit are used
    22  // for pagination.
    23  //
    24  // http://developer.openstack.org/api-ref-image-v2.html
    25  type ListOpts struct {
    26  	// ID is the ID of the image.
    27  	// Multiple IDs can be specified by constructing a string
    28  	// such as "in:uuid1,uuid2,uuid3".
    29  	ID string `q:"id"`
    30  
    31  	// Integer value for the limit of values to return.
    32  	Limit int `q:"limit"`
    33  
    34  	// UUID of the server at which you want to set a marker.
    35  	Marker string `q:"marker"`
    36  
    37  	// Name filters on the name of the image.
    38  	// Multiple names can be specified by constructing a string
    39  	// such as "in:name1,name2,name3".
    40  	Name string `q:"name"`
    41  
    42  	// Visibility filters on the visibility of the image.
    43  	Visibility ImageVisibility `q:"visibility"`
    44  
    45  	// Hidden filters on the hidden status of the image.
    46  	Hidden bool `q:"os_hidden"`
    47  
    48  	// MemberStatus filters on the member status of the image.
    49  	MemberStatus ImageMemberStatus `q:"member_status"`
    50  
    51  	// Owner filters on the project ID of the image.
    52  	Owner string `q:"owner"`
    53  
    54  	// Status filters on the status of the image.
    55  	// Multiple statuses can be specified by constructing a string
    56  	// such as "in:saving,queued".
    57  	Status ImageStatus `q:"status"`
    58  
    59  	// SizeMin filters on the size_min image property.
    60  	SizeMin int64 `q:"size_min"`
    61  
    62  	// SizeMax filters on the size_max image property.
    63  	SizeMax int64 `q:"size_max"`
    64  
    65  	// Sort sorts the results using the new style of sorting. See the OpenStack
    66  	// Image API reference for the exact syntax.
    67  	//
    68  	// Sort cannot be used with the classic sort options (sort_key and sort_dir).
    69  	Sort string `q:"sort"`
    70  
    71  	// SortKey will sort the results based on a specified image property.
    72  	SortKey string `q:"sort_key"`
    73  
    74  	// SortDir will sort the list results either ascending or decending.
    75  	SortDir string `q:"sort_dir"`
    76  
    77  	// Tags filters on specific image tags.
    78  	Tags []string `q:"tag"`
    79  
    80  	// CreatedAtQuery filters images based on their creation date.
    81  	CreatedAtQuery *ImageDateQuery
    82  
    83  	// UpdatedAtQuery filters images based on their updated date.
    84  	UpdatedAtQuery *ImageDateQuery
    85  
    86  	// ContainerFormat filters images based on the container_format.
    87  	// Multiple container formats can be specified by constructing a
    88  	// string such as "in:bare,ami".
    89  	ContainerFormat string `q:"container_format"`
    90  
    91  	// DiskFormat filters images based on the disk_format.
    92  	// Multiple disk formats can be specified by constructing a string
    93  	// such as "in:qcow2,iso".
    94  	DiskFormat string `q:"disk_format"`
    95  }
    96  
    97  // ToImageListQuery formats a ListOpts into a query string.
    98  func (opts ListOpts) ToImageListQuery() (string, error) {
    99  	q, err := gophercloud.BuildQueryString(opts)
   100  	params := q.Query()
   101  
   102  	if opts.CreatedAtQuery != nil {
   103  		createdAt := opts.CreatedAtQuery.Date.Format(time.RFC3339)
   104  		if v := opts.CreatedAtQuery.Filter; v != "" {
   105  			createdAt = fmt.Sprintf("%s:%s", v, createdAt)
   106  		}
   107  
   108  		params.Add("created_at", createdAt)
   109  	}
   110  
   111  	if opts.UpdatedAtQuery != nil {
   112  		updatedAt := opts.UpdatedAtQuery.Date.Format(time.RFC3339)
   113  		if v := opts.UpdatedAtQuery.Filter; v != "" {
   114  			updatedAt = fmt.Sprintf("%s:%s", v, updatedAt)
   115  		}
   116  
   117  		params.Add("updated_at", updatedAt)
   118  	}
   119  
   120  	q = &url.URL{RawQuery: params.Encode()}
   121  
   122  	return q.String(), err
   123  }
   124  
   125  // List implements image list request.
   126  func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
   127  	url := listURL(c)
   128  	if opts != nil {
   129  		query, err := opts.ToImageListQuery()
   130  		if err != nil {
   131  			return pagination.Pager{Err: err}
   132  		}
   133  		url += query
   134  	}
   135  	return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
   136  		imagePage := ImagePage{
   137  			serviceURL:     c.ServiceURL(),
   138  			LinkedPageBase: pagination.LinkedPageBase{PageResult: r},
   139  		}
   140  
   141  		return imagePage
   142  	})
   143  }
   144  
   145  // CreateOptsBuilder allows extensions to add parameters to the Create request.
   146  type CreateOptsBuilder interface {
   147  	// Returns value that can be passed to json.Marshal
   148  	ToImageCreateMap() (map[string]any, error)
   149  }
   150  
   151  // CreateOpts represents options used to create an image.
   152  type CreateOpts struct {
   153  	// Name is the name of the new image.
   154  	Name string `json:"name" required:"true"`
   155  
   156  	// Id is the the image ID.
   157  	ID string `json:"id,omitempty"`
   158  
   159  	// Visibility defines who can see/use the image.
   160  	Visibility *ImageVisibility `json:"visibility,omitempty"`
   161  
   162  	// Hidden is whether the image is listed in default image list or not.
   163  	Hidden *bool `json:"os_hidden,omitempty"`
   164  
   165  	// Tags is a set of image tags.
   166  	Tags []string `json:"tags,omitempty"`
   167  
   168  	// ContainerFormat is the format of the
   169  	// container. Valid values are ami, ari, aki, bare, and ovf.
   170  	ContainerFormat string `json:"container_format,omitempty"`
   171  
   172  	// DiskFormat is the format of the disk. If set,
   173  	// valid values are ami, ari, aki, vhd, vmdk, raw, qcow2, vdi,
   174  	// and iso.
   175  	DiskFormat string `json:"disk_format,omitempty"`
   176  
   177  	// MinDisk is the amount of disk space in
   178  	// GB that is required to boot the image.
   179  	MinDisk int `json:"min_disk,omitempty"`
   180  
   181  	// MinRAM is the amount of RAM in MB that
   182  	// is required to boot the image.
   183  	MinRAM int `json:"min_ram,omitempty"`
   184  
   185  	// protected is whether the image is not deletable.
   186  	Protected *bool `json:"protected,omitempty"`
   187  
   188  	// properties is a set of properties, if any, that
   189  	// are associated with the image.
   190  	Properties map[string]string `json:"-"`
   191  }
   192  
   193  // ToImageCreateMap assembles a request body based on the contents of
   194  // a CreateOpts.
   195  func (opts CreateOpts) ToImageCreateMap() (map[string]any, error) {
   196  	b, err := gophercloud.BuildRequestBody(opts, "")
   197  	if err != nil {
   198  		return nil, err
   199  	}
   200  
   201  	if opts.Properties != nil {
   202  		for k, v := range opts.Properties {
   203  			b[k] = v
   204  		}
   205  	}
   206  	return b, nil
   207  }
   208  
   209  // Create implements create image request.
   210  func Create(ctx context.Context, client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
   211  	b, err := opts.ToImageCreateMap()
   212  	if err != nil {
   213  		r.Err = err
   214  		return r
   215  	}
   216  	resp, err := client.Post(ctx, createURL(client), b, &r.Body, &gophercloud.RequestOpts{OkCodes: []int{201}})
   217  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   218  	return
   219  }
   220  
   221  // Delete implements image delete request.
   222  func Delete(ctx context.Context, client *gophercloud.ServiceClient, id string) (r DeleteResult) {
   223  	resp, err := client.Delete(ctx, deleteURL(client, id), nil)
   224  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   225  	return
   226  }
   227  
   228  // Get implements image get request.
   229  func Get(ctx context.Context, client *gophercloud.ServiceClient, id string) (r GetResult) {
   230  	resp, err := client.Get(ctx, getURL(client, id), &r.Body, nil)
   231  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   232  	return
   233  }
   234  
   235  // Update implements image updated request.
   236  func Update(ctx context.Context, client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
   237  	b, err := opts.ToImageUpdateMap()
   238  	if err != nil {
   239  		r.Err = err
   240  		return r
   241  	}
   242  	resp, err := client.Patch(ctx, updateURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
   243  		OkCodes:     []int{200},
   244  		MoreHeaders: map[string]string{"Content-Type": "application/openstack-images-v2.1-json-patch"},
   245  	})
   246  	_, r.Header, r.Err = gophercloud.ParseResponse(resp, err)
   247  	return
   248  }
   249  
   250  // UpdateOptsBuilder allows extensions to add additional parameters to the
   251  // Update request.
   252  type UpdateOptsBuilder interface {
   253  	// returns value implementing json.Marshaler which when marshaled matches
   254  	// the patch schema:
   255  	// http://specs.openstack.org/openstack/glance-specs/specs/api/v2/http-patch-image-api-v2.html
   256  	ToImageUpdateMap() ([]any, error)
   257  }
   258  
   259  // UpdateOpts implements UpdateOpts
   260  type UpdateOpts []Patch
   261  
   262  // ToImageUpdateMap assembles a request body based on the contents of
   263  // UpdateOpts.
   264  func (opts UpdateOpts) ToImageUpdateMap() ([]any, error) {
   265  	m := make([]any, len(opts))
   266  	for i, patch := range opts {
   267  		patchJSON := patch.ToImagePatchMap()
   268  		m[i] = patchJSON
   269  	}
   270  	return m, nil
   271  }
   272  
   273  // Patch represents a single update to an existing image. Multiple updates
   274  // to an image can be submitted at the same time.
   275  type Patch interface {
   276  	ToImagePatchMap() map[string]any
   277  }
   278  
   279  // UpdateVisibility represents an updated visibility property request.
   280  type UpdateVisibility struct {
   281  	Visibility ImageVisibility
   282  }
   283  
   284  // ToImagePatchMap assembles a request body based on UpdateVisibility.
   285  func (r UpdateVisibility) ToImagePatchMap() map[string]any {
   286  	return map[string]any{
   287  		"op":    "replace",
   288  		"path":  "/visibility",
   289  		"value": r.Visibility,
   290  	}
   291  }
   292  
   293  // ReplaceImageHidden represents an updated os_hidden property request.
   294  type ReplaceImageHidden struct {
   295  	NewHidden bool
   296  }
   297  
   298  // ToImagePatchMap assembles a request body based on ReplaceImageHidden.
   299  func (r ReplaceImageHidden) ToImagePatchMap() map[string]any {
   300  	return map[string]any{
   301  		"op":    "replace",
   302  		"path":  "/os_hidden",
   303  		"value": r.NewHidden,
   304  	}
   305  }
   306  
   307  // ReplaceImageName represents an updated image_name property request.
   308  type ReplaceImageName struct {
   309  	NewName string
   310  }
   311  
   312  // ToImagePatchMap assembles a request body based on ReplaceImageName.
   313  func (r ReplaceImageName) ToImagePatchMap() map[string]any {
   314  	return map[string]any{
   315  		"op":    "replace",
   316  		"path":  "/name",
   317  		"value": r.NewName,
   318  	}
   319  }
   320  
   321  // ReplaceImageChecksum represents an updated checksum property request.
   322  type ReplaceImageChecksum struct {
   323  	Checksum string
   324  }
   325  
   326  // ReplaceImageChecksum assembles a request body based on ReplaceImageChecksum.
   327  func (r ReplaceImageChecksum) ToImagePatchMap() map[string]any {
   328  	return map[string]any{
   329  		"op":    "replace",
   330  		"path":  "/checksum",
   331  		"value": r.Checksum,
   332  	}
   333  }
   334  
   335  // ReplaceImageTags represents an updated tags property request.
   336  type ReplaceImageTags struct {
   337  	NewTags []string
   338  }
   339  
   340  // ToImagePatchMap assembles a request body based on ReplaceImageTags.
   341  func (r ReplaceImageTags) ToImagePatchMap() map[string]any {
   342  	return map[string]any{
   343  		"op":    "replace",
   344  		"path":  "/tags",
   345  		"value": r.NewTags,
   346  	}
   347  }
   348  
   349  // ReplaceImageMinDisk represents an updated min_disk property request.
   350  type ReplaceImageMinDisk struct {
   351  	NewMinDisk int
   352  }
   353  
   354  // ToImagePatchMap assembles a request body based on ReplaceImageTags.
   355  func (r ReplaceImageMinDisk) ToImagePatchMap() map[string]any {
   356  	return map[string]any{
   357  		"op":    "replace",
   358  		"path":  "/min_disk",
   359  		"value": r.NewMinDisk,
   360  	}
   361  }
   362  
   363  // ReplaceImageMinRam represents an updated min_ram property request.
   364  type ReplaceImageMinRam struct {
   365  	NewMinRam int
   366  }
   367  
   368  // ToImagePatchMap assembles a request body based on ReplaceImageTags.
   369  func (r ReplaceImageMinRam) ToImagePatchMap() map[string]any {
   370  	return map[string]any{
   371  		"op":    "replace",
   372  		"path":  "/min_ram",
   373  		"value": r.NewMinRam,
   374  	}
   375  }
   376  
   377  // ReplaceImageProtected represents an updated protected property request.
   378  type ReplaceImageProtected struct {
   379  	NewProtected bool
   380  }
   381  
   382  // ToImagePatchMap assembles a request body based on ReplaceImageProtected
   383  func (r ReplaceImageProtected) ToImagePatchMap() map[string]any {
   384  	return map[string]any{
   385  		"op":    "replace",
   386  		"path":  "/protected",
   387  		"value": r.NewProtected,
   388  	}
   389  }
   390  
   391  // UpdateOp represents a valid update operation.
   392  type UpdateOp string
   393  
   394  const (
   395  	AddOp     UpdateOp = "add"
   396  	ReplaceOp UpdateOp = "replace"
   397  	RemoveOp  UpdateOp = "remove"
   398  )
   399  
   400  // UpdateImageProperty represents an update property request.
   401  type UpdateImageProperty struct {
   402  	Op    UpdateOp
   403  	Name  string
   404  	Value string
   405  }
   406  
   407  // ToImagePatchMap assembles a request body based on UpdateImageProperty.
   408  func (r UpdateImageProperty) ToImagePatchMap() map[string]any {
   409  	updateMap := map[string]any{
   410  		"op":   r.Op,
   411  		"path": fmt.Sprintf("/%s", r.Name),
   412  	}
   413  
   414  	if r.Op != RemoveOp {
   415  		updateMap["value"] = r.Value
   416  	}
   417  
   418  	return updateMap
   419  }