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