results.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201
  1. package images
  2. import (
  3. "encoding/json"
  4. "fmt"
  5. "reflect"
  6. "time"
  7. "devel.mephi.ru/iacherepanov/openstack-gophercloud"
  8. "devel.mephi.ru/iacherepanov/openstack-gophercloud/internal"
  9. "devel.mephi.ru/iacherepanov/openstack-gophercloud/pagination"
  10. )
  11. // Image represents an image found in the OpenStack Image service.
  12. type Image struct {
  13. // ID is the image UUID.
  14. ID string `json:"id"`
  15. // Name is the human-readable display name for the image.
  16. Name string `json:"name"`
  17. // Status is the image status. It can be "queued" or "active"
  18. // See imageservice/v2/images/type.go
  19. Status ImageStatus `json:"status"`
  20. // Tags is a list of image tags. Tags are arbitrarily defined strings
  21. // attached to an image.
  22. Tags []string `json:"tags"`
  23. // ContainerFormat is the format of the container.
  24. // Valid values are ami, ari, aki, bare, and ovf.
  25. ContainerFormat string `json:"container_format"`
  26. // DiskFormat is the format of the disk.
  27. // If set, valid values are ami, ari, aki, vhd, vmdk, raw, qcow2, vdi,
  28. // and iso.
  29. DiskFormat string `json:"disk_format"`
  30. // MinDiskGigabytes is the amount of disk space in GB that is required to
  31. // boot the image.
  32. MinDiskGigabytes int `json:"min_disk"`
  33. // MinRAMMegabytes [optional] is the amount of RAM in MB that is required to
  34. // boot the image.
  35. MinRAMMegabytes int `json:"min_ram"`
  36. // Owner is the tenant ID the image belongs to.
  37. Owner string `json:"owner"`
  38. // Protected is whether the image is deletable or not.
  39. Protected bool `json:"protected"`
  40. // Visibility defines who can see/use the image.
  41. Visibility ImageVisibility `json:"visibility"`
  42. // Checksum is the checksum of the data that's associated with the image.
  43. Checksum string `json:"checksum"`
  44. // SizeBytes is the size of the data that's associated with the image.
  45. SizeBytes int64 `json:"size"`
  46. // Metadata is a set of metadata associated with the image.
  47. // Image metadata allow for meaningfully define the image properties
  48. // and tags.
  49. // See http://docs.openstack.org/developer/glance/metadefs-concepts.html.
  50. Metadata map[string]string `json:"metadata"`
  51. // Properties is a set of key-value pairs, if any, that are associated with
  52. // the image.
  53. Properties map[string]interface{} `json:"-"`
  54. // CreatedAt is the date when the image has been created.
  55. CreatedAt time.Time `json:"created_at"`
  56. // UpdatedAt is the date when the last change has been made to the image or
  57. // it's properties.
  58. UpdatedAt time.Time `json:"updated_at"`
  59. // File is the trailing path after the glance endpoint that represent the
  60. // location of the image or the path to retrieve it.
  61. File string `json:"file"`
  62. // Schema is the path to the JSON-schema that represent the image or image
  63. // entity.
  64. Schema string `json:"schema"`
  65. // VirtualSize is the virtual size of the image
  66. VirtualSize int64 `json:"virtual_size"`
  67. }
  68. func (r *Image) UnmarshalJSON(b []byte) error {
  69. type tmp Image
  70. var s struct {
  71. tmp
  72. SizeBytes interface{} `json:"size"`
  73. }
  74. err := json.Unmarshal(b, &s)
  75. if err != nil {
  76. return err
  77. }
  78. *r = Image(s.tmp)
  79. switch t := s.SizeBytes.(type) {
  80. case nil:
  81. r.SizeBytes = 0
  82. case float32:
  83. r.SizeBytes = int64(t)
  84. case float64:
  85. r.SizeBytes = int64(t)
  86. default:
  87. return fmt.Errorf("Unknown type for SizeBytes: %v (value: %v)", reflect.TypeOf(t), t)
  88. }
  89. // Bundle all other fields into Properties
  90. var result interface{}
  91. err = json.Unmarshal(b, &result)
  92. if err != nil {
  93. return err
  94. }
  95. if resultMap, ok := result.(map[string]interface{}); ok {
  96. delete(resultMap, "self")
  97. r.Properties = internal.RemainingKeys(Image{}, resultMap)
  98. }
  99. return err
  100. }
  101. type commonResult struct {
  102. gophercloud.Result
  103. }
  104. // Extract interprets any commonResult as an Image.
  105. func (r commonResult) Extract() (*Image, error) {
  106. var s *Image
  107. err := r.ExtractInto(&s)
  108. return s, err
  109. }
  110. // CreateResult represents the result of a Create operation. Call its Extract
  111. // method to interpret it as an Image.
  112. type CreateResult struct {
  113. commonResult
  114. }
  115. // UpdateResult represents the result of an Update operation. Call its Extract
  116. // method to interpret it as an Image.
  117. type UpdateResult struct {
  118. commonResult
  119. }
  120. // GetResult represents the result of a Get operation. Call its Extract
  121. // method to interpret it as an Image.
  122. type GetResult struct {
  123. commonResult
  124. }
  125. // DeleteResult represents the result of a Delete operation. Call its
  126. // ExtractErr method to interpret it as an Image.
  127. type DeleteResult struct {
  128. gophercloud.ErrResult
  129. }
  130. // ImagePage represents the results of a List request.
  131. type ImagePage struct {
  132. pagination.LinkedPageBase
  133. }
  134. // IsEmpty returns true if an ImagePage contains no Images results.
  135. func (r ImagePage) IsEmpty() (bool, error) {
  136. images, err := ExtractImages(r)
  137. return len(images) == 0, err
  138. }
  139. // NextPageURL uses the response's embedded link reference to navigate to
  140. // the next page of results.
  141. func (r ImagePage) NextPageURL() (string, error) {
  142. var s struct {
  143. Next string `json:"next"`
  144. }
  145. err := r.ExtractInto(&s)
  146. if err != nil {
  147. return "", err
  148. }
  149. if s.Next == "" {
  150. return "", nil
  151. }
  152. return nextPageURL(r.URL.String(), s.Next)
  153. }
  154. // ExtractImages interprets the results of a single page from a List() call,
  155. // producing a slice of Image entities.
  156. func ExtractImages(r pagination.Page) ([]Image, error) {
  157. var s struct {
  158. Images []Image `json:"images"`
  159. }
  160. err := (r.(ImagePage)).ExtractInto(&s)
  161. return s.Images, err
  162. }