requests.go 9.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318
  1. package images
  2. import (
  3. "fmt"
  4. "net/url"
  5. "time"
  6. "devel.mephi.ru/iacherepanov/openstack-gophercloud"
  7. "devel.mephi.ru/iacherepanov/openstack-gophercloud/pagination"
  8. )
  9. // ListOptsBuilder allows extensions to add additional parameters to the
  10. // List request.
  11. type ListOptsBuilder interface {
  12. ToImageListQuery() (string, error)
  13. }
  14. // ListOpts allows the filtering and sorting of paginated collections through
  15. // the API. Filtering is achieved by passing in struct field values that map to
  16. // the server attributes you want to see returned. Marker and Limit are used
  17. // for pagination.
  18. //
  19. // http://developer.openstack.org/api-ref-image-v2.html
  20. type ListOpts struct {
  21. // ID is the ID of the image.
  22. // Multiple IDs can be specified by constructing a string
  23. // such as "in:uuid1,uuid2,uuid3".
  24. ID string `q:"id"`
  25. // Integer value for the limit of values to return.
  26. Limit int `q:"limit"`
  27. // UUID of the server at which you want to set a marker.
  28. Marker string `q:"marker"`
  29. // Name filters on the name of the image.
  30. // Multiple names can be specified by constructing a string
  31. // such as "in:name1,name2,name3".
  32. Name string `q:"name"`
  33. // Visibility filters on the visibility of the image.
  34. Visibility ImageVisibility `q:"visibility"`
  35. // MemberStatus filters on the member status of the image.
  36. MemberStatus ImageMemberStatus `q:"member_status"`
  37. // Owner filters on the project ID of the image.
  38. Owner string `q:"owner"`
  39. // Status filters on the status of the image.
  40. // Multiple statuses can be specified by constructing a string
  41. // such as "in:saving,queued".
  42. Status ImageStatus `q:"status"`
  43. // SizeMin filters on the size_min image property.
  44. SizeMin int64 `q:"size_min"`
  45. // SizeMax filters on the size_max image property.
  46. SizeMax int64 `q:"size_max"`
  47. // Sort sorts the results using the new style of sorting. See the OpenStack
  48. // Image API reference for the exact syntax.
  49. //
  50. // Sort cannot be used with the classic sort options (sort_key and sort_dir).
  51. Sort string `q:"sort"`
  52. // SortKey will sort the results based on a specified image property.
  53. SortKey string `q:"sort_key"`
  54. // SortDir will sort the list results either ascending or decending.
  55. SortDir string `q:"sort_dir"`
  56. // Tags filters on specific image tags.
  57. Tags []string `q:"tag"`
  58. // CreatedAtQuery filters images based on their creation date.
  59. CreatedAtQuery *ImageDateQuery
  60. // UpdatedAtQuery filters images based on their updated date.
  61. UpdatedAtQuery *ImageDateQuery
  62. // ContainerFormat filters images based on the container_format.
  63. // Multiple container formats can be specified by constructing a
  64. // string such as "in:bare,ami".
  65. ContainerFormat string `q:"container_format"`
  66. // DiskFormat filters images based on the disk_format.
  67. // Multiple disk formats can be specified by constructing a string
  68. // such as "in:qcow2,iso".
  69. DiskFormat string `q:"disk_format"`
  70. }
  71. // ToImageListQuery formats a ListOpts into a query string.
  72. func (opts ListOpts) ToImageListQuery() (string, error) {
  73. q, err := gophercloud.BuildQueryString(opts)
  74. params := q.Query()
  75. if opts.CreatedAtQuery != nil {
  76. createdAt := opts.CreatedAtQuery.Date.Format(time.RFC3339)
  77. if v := opts.CreatedAtQuery.Filter; v != "" {
  78. createdAt = fmt.Sprintf("%s:%s", v, createdAt)
  79. }
  80. params.Add("created_at", createdAt)
  81. }
  82. if opts.UpdatedAtQuery != nil {
  83. updatedAt := opts.UpdatedAtQuery.Date.Format(time.RFC3339)
  84. if v := opts.UpdatedAtQuery.Filter; v != "" {
  85. updatedAt = fmt.Sprintf("%s:%s", v, updatedAt)
  86. }
  87. params.Add("updated_at", updatedAt)
  88. }
  89. q = &url.URL{RawQuery: params.Encode()}
  90. return q.String(), err
  91. }
  92. // List implements image list request.
  93. func List(c *gophercloud.ServiceClient, opts ListOptsBuilder) pagination.Pager {
  94. url := listURL(c)
  95. if opts != nil {
  96. query, err := opts.ToImageListQuery()
  97. if err != nil {
  98. return pagination.Pager{Err: err}
  99. }
  100. url += query
  101. }
  102. return pagination.NewPager(c, url, func(r pagination.PageResult) pagination.Page {
  103. return ImagePage{pagination.LinkedPageBase{PageResult: r}}
  104. })
  105. }
  106. // CreateOptsBuilder allows extensions to add parameters to the Create request.
  107. type CreateOptsBuilder interface {
  108. // Returns value that can be passed to json.Marshal
  109. ToImageCreateMap() (map[string]interface{}, error)
  110. }
  111. // CreateOpts represents options used to create an image.
  112. type CreateOpts struct {
  113. // Name is the name of the new image.
  114. Name string `json:"name" required:"true"`
  115. // Id is the the image ID.
  116. ID string `json:"id,omitempty"`
  117. // Visibility defines who can see/use the image.
  118. Visibility *ImageVisibility `json:"visibility,omitempty"`
  119. // Tags is a set of image tags.
  120. Tags []string `json:"tags,omitempty"`
  121. // ContainerFormat is the format of the
  122. // container. Valid values are ami, ari, aki, bare, and ovf.
  123. ContainerFormat string `json:"container_format,omitempty"`
  124. // DiskFormat is the format of the disk. If set,
  125. // valid values are ami, ari, aki, vhd, vmdk, raw, qcow2, vdi,
  126. // and iso.
  127. DiskFormat string `json:"disk_format,omitempty"`
  128. // MinDisk is the amount of disk space in
  129. // GB that is required to boot the image.
  130. MinDisk int `json:"min_disk,omitempty"`
  131. // MinRAM is the amount of RAM in MB that
  132. // is required to boot the image.
  133. MinRAM int `json:"min_ram,omitempty"`
  134. // protected is whether the image is not deletable.
  135. Protected *bool `json:"protected,omitempty"`
  136. // properties is a set of properties, if any, that
  137. // are associated with the image.
  138. Properties map[string]string `json:"-"`
  139. }
  140. // ToImageCreateMap assembles a request body based on the contents of
  141. // a CreateOpts.
  142. func (opts CreateOpts) ToImageCreateMap() (map[string]interface{}, error) {
  143. b, err := gophercloud.BuildRequestBody(opts, "")
  144. if err != nil {
  145. return nil, err
  146. }
  147. if opts.Properties != nil {
  148. for k, v := range opts.Properties {
  149. b[k] = v
  150. }
  151. }
  152. return b, nil
  153. }
  154. // Create implements create image request.
  155. func Create(client *gophercloud.ServiceClient, opts CreateOptsBuilder) (r CreateResult) {
  156. b, err := opts.ToImageCreateMap()
  157. if err != nil {
  158. r.Err = err
  159. return r
  160. }
  161. _, r.Err = client.Post(createURL(client), b, &r.Body, &gophercloud.RequestOpts{OkCodes: []int{201}})
  162. return
  163. }
  164. // Delete implements image delete request.
  165. func Delete(client *gophercloud.ServiceClient, id string) (r DeleteResult) {
  166. _, r.Err = client.Delete(deleteURL(client, id), nil)
  167. return
  168. }
  169. // Get implements image get request.
  170. func Get(client *gophercloud.ServiceClient, id string) (r GetResult) {
  171. _, r.Err = client.Get(getURL(client, id), &r.Body, nil)
  172. return
  173. }
  174. // Update implements image updated request.
  175. func Update(client *gophercloud.ServiceClient, id string, opts UpdateOptsBuilder) (r UpdateResult) {
  176. b, err := opts.ToImageUpdateMap()
  177. if err != nil {
  178. r.Err = err
  179. return r
  180. }
  181. _, r.Err = client.Patch(updateURL(client, id), b, &r.Body, &gophercloud.RequestOpts{
  182. OkCodes: []int{200},
  183. MoreHeaders: map[string]string{"Content-Type": "application/openstack-images-v2.1-json-patch"},
  184. })
  185. return
  186. }
  187. // UpdateOptsBuilder allows extensions to add additional parameters to the
  188. // Update request.
  189. type UpdateOptsBuilder interface {
  190. // returns value implementing json.Marshaler which when marshaled matches
  191. // the patch schema:
  192. // http://specs.openstack.org/openstack/glance-specs/specs/api/v2/http-patch-image-api-v2.html
  193. ToImageUpdateMap() ([]interface{}, error)
  194. }
  195. // UpdateOpts implements UpdateOpts
  196. type UpdateOpts []Patch
  197. // ToImageUpdateMap assembles a request body based on the contents of
  198. // UpdateOpts.
  199. func (opts UpdateOpts) ToImageUpdateMap() ([]interface{}, error) {
  200. m := make([]interface{}, len(opts))
  201. for i, patch := range opts {
  202. patchJSON := patch.ToImagePatchMap()
  203. m[i] = patchJSON
  204. }
  205. return m, nil
  206. }
  207. // Patch represents a single update to an existing image. Multiple updates
  208. // to an image can be submitted at the same time.
  209. type Patch interface {
  210. ToImagePatchMap() map[string]interface{}
  211. }
  212. // UpdateVisibility represents an updated visibility property request.
  213. type UpdateVisibility struct {
  214. Visibility ImageVisibility
  215. }
  216. // ToImagePatchMap assembles a request body based on UpdateVisibility.
  217. func (u UpdateVisibility) ToImagePatchMap() map[string]interface{} {
  218. return map[string]interface{}{
  219. "op": "replace",
  220. "path": "/visibility",
  221. "value": u.Visibility,
  222. }
  223. }
  224. // ReplaceImageName represents an updated image_name property request.
  225. type ReplaceImageName struct {
  226. NewName string
  227. }
  228. // ToImagePatchMap assembles a request body based on ReplaceImageName.
  229. func (r ReplaceImageName) ToImagePatchMap() map[string]interface{} {
  230. return map[string]interface{}{
  231. "op": "replace",
  232. "path": "/name",
  233. "value": r.NewName,
  234. }
  235. }
  236. // ReplaceImageChecksum represents an updated checksum property request.
  237. type ReplaceImageChecksum struct {
  238. Checksum string
  239. }
  240. // ReplaceImageChecksum assembles a request body based on ReplaceImageChecksum.
  241. func (rc ReplaceImageChecksum) ToImagePatchMap() map[string]interface{} {
  242. return map[string]interface{}{
  243. "op": "replace",
  244. "path": "/checksum",
  245. "value": rc.Checksum,
  246. }
  247. }
  248. // ReplaceImageTags represents an updated tags property request.
  249. type ReplaceImageTags struct {
  250. NewTags []string
  251. }
  252. // ToImagePatchMap assembles a request body based on ReplaceImageTags.
  253. func (r ReplaceImageTags) ToImagePatchMap() map[string]interface{} {
  254. return map[string]interface{}{
  255. "op": "replace",
  256. "path": "/tags",
  257. "value": r.NewTags,
  258. }
  259. }