Skip to content
This repository was archived by the owner on Aug 1, 2023. It is now read-only.

Commit 1836997

Browse files
author
Samuel Ortiz
committed
imageservice: Simplify Image extraction
We can just call Decode() on it if we assume glance sets optional values properly. Signed-off-by: Samuel Ortiz <[email protected]>
1 parent 836043d commit 1836997

File tree

3 files changed

+26
-278
lines changed

3 files changed

+26
-278
lines changed

openstack/imageservice/v2/images/fixtures.go

Lines changed: 9 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -186,9 +186,9 @@ func HandleImageCreationSuccessfully(t *testing.T) {
186186
"owner": "b4eedccc6fb74fa8a7ad6b08382b852b",
187187
"min_ram": 0,
188188
"schema": "/v2/schemas/image",
189-
"size": "None",
190-
"checksum": "None",
191-
"virtual_size": "None"
189+
"size": 0,
190+
"checksum": "",
191+
"virtual_size": 0
192192
}`)
193193
})
194194
}
@@ -320,12 +320,12 @@ func HandleImageUpdateSuccessfully(t *testing.T) {
320320
"self": "/v2/images/da3b75d9-3f4a-40e7-8a2c-bfab23927dea",
321321
"file": "/v2/images/da3b75d9-3f4a-40e7-8a2c-bfab23927dea/file",
322322
"schema": "/v2/schemas/image",
323-
"owner": "None",
324-
"min_ram": "None",
325-
"min_disk": "None",
326-
"disk_format": "None",
327-
"virtual_size": "None",
328-
"container_format": "None"
323+
"owner": "",
324+
"min_ram": 0,
325+
"min_disk": 0,
326+
"disk_format": "",
327+
"virtual_size": 0,
328+
"container_format": ""
329329
}`)
330330
})
331331
}

openstack/imageservice/v2/images/requests_test.go

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -85,9 +85,6 @@ func TestCreateImage(t *testing.T) {
8585
Owner: owner,
8686

8787
Visibility: ImageVisibilityPrivate,
88-
89-
Metadata: make(map[string]string),
90-
Properties: make(map[string]string),
9188
}
9289

9390
th.AssertDeepEquals(t, &expectedImage, actualImage)
@@ -132,9 +129,6 @@ func TestCreateImageNulls(t *testing.T) {
132129
Owner: owner,
133130

134131
Visibility: ImageVisibilityPrivate,
135-
136-
Metadata: make(map[string]string),
137-
Properties: make(map[string]string),
138132
}
139133

140134
th.AssertDeepEquals(t, &expectedImage, actualImage)
@@ -178,9 +172,6 @@ func TestGetImage(t *testing.T) {
178172

179173
Checksum: checksum,
180174
SizeBytes: sizeBytes,
181-
182-
Metadata: make(map[string]string),
183-
Properties: make(map[string]string),
184175
}
185176

186177
th.AssertDeepEquals(t, &expectedImage, actualImage)
@@ -232,9 +223,6 @@ func TestUpdateImage(t *testing.T) {
232223

233224
DiskFormat: "",
234225
ContainerFormat: "",
235-
236-
Metadata: make(map[string]string),
237-
Properties: make(map[string]string),
238226
}
239227

240228
th.AssertDeepEquals(t, &expectedImage, actualImage)

openstack/imageservice/v2/images/results.go

Lines changed: 17 additions & 257 deletions
Original file line numberDiff line numberDiff line change
@@ -34,33 +34,33 @@ type Image struct {
3434

3535
// DiskFormat is the format of the disk.
3636
// If set, valid values are ami, ari, aki, vhd, vmdk, raw, qcow2, vdi, and iso.
37-
DiskFormat string `mapstructure:"disk_format"`
37+
DiskFormat string `mapstructure:"disk_format"`
3838

3939
// MinDiskGigabytes is the amount of disk space in GB that is required to boot the image.
4040
MinDiskGigabytes int `mapstructure:"min_disk"`
4141

4242
// MinRAMMegabytes [optional] is the amount of RAM in MB that is required to boot the image.
43-
MinRAMMegabytes int `mapstructure:"min_ram"`
43+
MinRAMMegabytes int `mapstructure:"min_ram"`
4444

4545
// Owner is the tenant the image belongs to.
4646
Owner string
4747

4848
// Protected is whether the image is deletable or not.
49-
Protected bool
49+
Protected bool
5050

5151
// Visibility defines who can see/use the image.
5252
Visibility ImageVisibility
5353

5454
// Checksum is the checksum of the data that's associated with the image
55-
Checksum string
55+
Checksum string
5656

5757
// SizeBytes is the size of the data that's associated with the image.
5858
SizeBytes int `mapstructure:"size"`
5959

6060
// Metadata is a set of metadata associated with the image.
6161
// Image metadata allow for meaningfully define the image properties
6262
// and tags. See http://docs.openstack.org/developer/glance/metadefs-concepts.html.
63-
Metadata map[string]string
63+
Metadata map[string]string
6464

6565
// Properties is a set of key-value pairs, if any, that are associated with the image.
6666
Properties map[string]string
@@ -71,258 +71,12 @@ type CreateResult struct {
7171
gophercloud.Result
7272
}
7373

74-
func asBool(any interface{}) (bool, error) {
75-
if b, ok := any.(bool); ok {
76-
return b, nil
77-
}
78-
return false, fmt.Errorf("expected bool value, but found: %#v", any)
79-
}
80-
81-
func asInt(any interface{}) (int, error) {
82-
// FIXME integers decoded as float64s
83-
if f, ok := any.(float64); ok {
84-
i := int(f)
85-
return i, nil
86-
}
87-
return 0, fmt.Errorf("expected int value, but found: %#v", any)
88-
}
89-
90-
func asString(any interface{}, key string) (string, error) {
91-
if str, ok := any.(string); ok {
92-
return str, nil
93-
}
94-
return "", fmt.Errorf("expected string value for key '%s', but found: %#v", key, any)
95-
}
96-
97-
func asNoneableString(any interface{}, key string) (string, error) {
98-
// JSON null values could be also returned according to behaviour https://bugs.launchpad.net/glance/+bug/1481512
99-
if any == nil {
100-
return "", nil
101-
}
102-
if str, ok := any.(string); ok {
103-
if str == "None" || &str == nil {
104-
return "", nil
105-
}
106-
return str, nil
107-
}
108-
return "", fmt.Errorf("expected string value for key '%s', but found: %#v", key, any)
109-
}
110-
111-
func asNoneableInteger(any interface{}, key string) (int, error) {
112-
// FIXME problem here is that provider_client.go uses: json.NewDecoder(resp.Body).Decode(options.JSONResponse)
113-
// which apparently converts integers in JSON to float64 values
114-
// JSON null values could be also returned according to behaviour https://bugs.launchpad.net/glance/+bug/1481512
115-
if any == nil {
116-
return 0, nil
117-
}
118-
if f, ok := any.(float64); ok {
119-
i := int(f)
120-
return i, nil
121-
} else if s, ok := any.(string); ok {
122-
if s == "None" {
123-
return 0, nil
124-
}
125-
return 0, fmt.Errorf("expected \"None\" or integer value for key '%s', but found unexpected string: \"%s\"", key, s)
126-
}
127-
return 0, fmt.Errorf("expected \"None\" or integer value for key '%s', but found: %T(%#v)", key, any, any)
128-
}
129-
130-
func asMapStringString(any interface{}) (map[string]string, error) {
131-
if mss, ok := any.(map[string]string); ok {
132-
return mss, nil
133-
}
134-
return nil, fmt.Errorf("expected map[string]string, but found: %#v", any)
135-
}
136-
137-
func extractBoolAtKey(m map[string]interface{}, k string) (bool, error) {
138-
if any, ok := m[k]; ok {
139-
return asBool(any)
140-
}
141-
return false, fmt.Errorf("expected key \"%s\" in map, but this key is not present", k)
142-
}
143-
144-
func extractIntAtKey(m map[string]interface{}, k string) (int, error) {
145-
if any, ok := m[k]; ok {
146-
return asInt(any)
147-
}
148-
return 0, fmt.Errorf("expected key \"%s\" in map, but this key is not present", k)
149-
}
150-
151-
func extractStringAtKey(m map[string]interface{}, k string) (string, error) {
152-
if any, ok := m[k]; ok {
153-
return asString(any, k)
154-
}
155-
return "", fmt.Errorf("expected key \"%s\" in map, but this key is not present", k)
156-
}
157-
158-
func extractNoneableStringAtKey(m map[string]interface{}, k string) (string, error) {
159-
if any, ok := m[k]; ok {
160-
return asNoneableString(any, k)
161-
}
162-
return "", fmt.Errorf("expected key \"%s\" in map, but this key is not present", k)
163-
}
164-
165-
func extractNoneableIntegerAtKey(m map[string]interface{}, k string) (int, error) {
166-
if any, ok := m[k]; ok {
167-
return asNoneableInteger(any, k)
168-
}
169-
return 0, fmt.Errorf("expected key \"%s\" in map, but this key is not present", k)
170-
}
171-
172-
func extractStringSliceAtKey(m map[string]interface{}, key string) ([]string, error) {
173-
if any, ok := m[key]; ok {
174-
if slice, ok := any.([]interface{}); ok {
175-
res := make([]string, len(slice))
176-
for k, v := range slice {
177-
var err error
178-
if res[k], err = asString(v, key); err != nil {
179-
return nil, err
180-
}
181-
}
182-
return res, nil
183-
}
184-
return nil, fmt.Errorf("expected slice as \"%s\" value, but found: %#v", key, any)
185-
}
186-
return nil, fmt.Errorf("expected key \"%s\" in map, but this key is not present", key)
187-
}
188-
189-
func stringToImageStatus(s string) (ImageStatus, error) {
190-
if s == "queued" {
191-
return ImageStatusQueued, nil
192-
} else if s == "active" {
193-
return ImageStatusActive, nil
194-
} else {
195-
return "", fmt.Errorf("expected \"queued\" or \"active\" as image status, but found: \"%s\"", s)
196-
}
197-
}
198-
199-
func extractImageStatusAtKey(m map[string]interface{}, k string) (ImageStatus, error) {
200-
if any, ok := m[k]; ok {
201-
if str, ok := any.(string); ok {
202-
return stringToImageStatus(str)
203-
}
204-
return "", fmt.Errorf("expected string as \"%s\" value, but found: %#v", k, any)
205-
}
206-
return "", fmt.Errorf("expected key \"%s\" in map, but this key is not present", k)
207-
208-
}
209-
210-
func stringToImageVisibility(s string) (ImageVisibility, error) {
211-
if s == "public" {
212-
return ImageVisibilityPublic, nil
213-
} else if s == "private" {
214-
return ImageVisibilityPrivate, nil
215-
} else {
216-
return "", fmt.Errorf("expected \"public\" or \"private\" as image status, but found: \"%s\"", s)
217-
}
218-
}
219-
220-
func extractImageVisibilityAtKey(m map[string]interface{}, k string) (ImageVisibility, error) {
221-
if any, ok := m[k]; ok {
222-
if str, ok := any.(string); ok {
223-
return stringToImageVisibility(str)
224-
}
225-
return "", fmt.Errorf("expected string as \"%s\" value, but found: %#v", k, any)
226-
}
227-
return "", fmt.Errorf("expected key \"%s\" in map, but this key is not present", k)
228-
}
229-
230-
func extractBoolAtKeyOptional(m map[string]interface{}, k string, ifMissing bool) (bool, error) {
231-
if any, ok := m[k]; ok {
232-
return asBool(any)
233-
}
234-
return ifMissing, nil
235-
236-
}
237-
238-
func extractMapStringStringAtKeyOptional(m map[string]interface{}, k string, ifMissing map[string]string) (map[string]string, error) {
239-
if any, ok := m[k]; ok {
240-
return asMapStringString(any)
241-
}
242-
return ifMissing, nil
243-
}
244-
245-
func extractImage(res gophercloud.Result) (*Image, error) {
246-
if res.Err != nil {
247-
return nil, res.Err
248-
}
249-
250-
body, ok := res.Body.(map[string]interface{})
251-
if !ok {
252-
return nil, fmt.Errorf("expected map as result body, but found: %#v", res.Body)
253-
}
254-
255-
var image Image
256-
257-
var err error
258-
259-
if image.ID, err = extractStringAtKey(body, "id"); err != nil {
260-
return nil, err
261-
}
262-
263-
if image.Name, err = extractStringAtKey(body, "name"); err != nil {
264-
return nil, err
265-
}
266-
267-
if image.Status, err = extractImageStatusAtKey(body, "status"); err != nil {
268-
return nil, err
269-
}
270-
271-
if image.Tags, err = extractStringSliceAtKey(body, "tags"); err != nil {
272-
return nil, err
273-
}
274-
275-
if image.ContainerFormat, err = extractNoneableStringAtKey(body, "container_format"); err != nil {
276-
return nil, err
277-
}
278-
279-
if image.DiskFormat, err = extractNoneableStringAtKey(body, "disk_format"); err != nil {
280-
return nil, err
281-
}
282-
283-
if image.MinDiskGigabytes, err = extractNoneableIntegerAtKey(body, "min_disk"); err != nil {
284-
return nil, err
285-
}
286-
287-
if image.MinRAMMegabytes, err = extractNoneableIntegerAtKey(body, "min_ram"); err != nil {
288-
return nil, err
289-
}
290-
291-
if image.Owner, err = extractNoneableStringAtKey(body, "owner"); err != nil {
292-
return nil, err
293-
}
294-
295-
// FIXME should this key actually be optional? Is a missing key equivalent to "protected": false ?
296-
if image.Protected, err = extractBoolAtKeyOptional(body, "protected", false); err != nil {
297-
return nil, err
298-
}
299-
300-
if image.Visibility, err = extractImageVisibilityAtKey(body, "visibility"); err != nil {
301-
return nil, err
302-
}
303-
304-
if image.Checksum, err = extractNoneableStringAtKey(body, "checksum"); err != nil {
305-
return nil, err
306-
}
307-
308-
if image.SizeBytes, err = extractNoneableIntegerAtKey(body, "size"); err != nil {
309-
return nil, err
310-
}
311-
312-
if image.Metadata, err = extractMapStringStringAtKeyOptional(body, "metadata", make(map[string]string)); err != nil {
313-
return nil, err
314-
}
315-
316-
if image.Properties, err = extractMapStringStringAtKeyOptional(body, "properties", make(map[string]string)); err != nil {
317-
return nil, err
318-
}
319-
320-
return &image, nil
321-
}
322-
32374
// Extract build CreateResults from imput Image
32475
func (c CreateResult) Extract() (*Image, error) {
325-
return extractImage(c.Result)
76+
var image *Image
77+
78+
err := mapstructure.Decode(c.Result.Body, &image)
79+
return image, err
32680
}
32781

32882
//DeleteResult model
@@ -337,7 +91,10 @@ type GetResult struct {
33791

33892
// Extract builds GetResult
33993
func (c GetResult) Extract() (*Image, error) {
340-
return extractImage(c.Result)
94+
var image *Image
95+
96+
err := mapstructure.Decode(c.Result.Body, &image)
97+
return image, err
34198
}
34299

343100
// UpdateResult model
@@ -347,7 +104,10 @@ type UpdateResult struct {
347104

348105
// Extract builds UpdateResult
349106
func (u UpdateResult) Extract() (*Image, error) {
350-
return extractImage(u.Result)
107+
var image *Image
108+
109+
err := mapstructure.Decode(u.Result.Body, &image)
110+
return image, err
351111
}
352112

353113
// PutImageDataResult is model put image respose

0 commit comments

Comments
 (0)