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