blob: 5df99ed0c91c65479802b7376974964612ef9545 [file] [log] [blame]
Jon Perritt8c93a302014-09-28 22:35:57 -05001package containers
2
3import (
4 "fmt"
5 "github.com/mitchellh/mapstructure"
6 "github.com/rackspace/gophercloud"
7 "github.com/rackspace/gophercloud/pagination"
8 "net/http"
9 "strings"
10)
11
Jon Perritt8aa40262014-09-29 15:41:32 -050012type Container struct {
Jon Perrittfdac6e52014-09-29 19:43:45 -050013 Bytes int `json:"bytes" mapstructure:"bytes"`
14 Count int `json:"count" mapstructure:"count"`
15 Name string `json:"name" mapstructure:"name"`
Jon Perritt8aa40262014-09-29 15:41:32 -050016}
Jon Perritt8c93a302014-09-28 22:35:57 -050017
18type commonResult struct {
19 gophercloud.CommonResult
20}
21
22func (r GetResult) Extract() (*Container, error) {
23 if r.Err != nil {
24 return nil, r.Err
25 }
26
27 var res struct {
28 Container *Container
29 }
30
31 err := mapstructure.Decode(r.Resp, &res)
32 if err != nil {
33 return nil, fmt.Errorf("Error decoding Object Storage Container: %v", err)
34 }
35
36 return res.Container, nil
37}
38
39type CreateResult struct {
40 commonResult
41}
42
43// GetResult represents the result of a get operation.
44type GetResult struct {
45 Resp *http.Response
46 Err error
47}
48
49// UpdateResult represents the result of an update operation.
50type UpdateResult commonResult
51
52// DeleteResult represents the result of a delete operation.
53type DeleteResult commonResult
54
55// ListResult is a *http.Response that is returned from a call to the List function.
56type ContainerPage struct {
57 pagination.MarkerPageBase
58}
59
60// IsEmpty returns true if a ListResult contains no container names.
61func (r ContainerPage) IsEmpty() (bool, error) {
62 names, err := ExtractNames(r)
63 if err != nil {
64 return true, err
65 }
66 return len(names) == 0, nil
67}
68
69// LastMarker returns the last container name in a ListResult.
70func (r ContainerPage) LastMarker() (string, error) {
71 names, err := ExtractNames(r)
72 if err != nil {
73 return "", err
74 }
75 if len(names) == 0 {
76 return "", nil
77 }
78 return names[len(names)-1], nil
79}
80
81// ExtractInfo is a function that takes a ListResult and returns the containers' information.
82func ExtractInfo(page pagination.Page) ([]Container, error) {
83 untyped := page.(ContainerPage).Body.([]interface{})
84 results := make([]Container, len(untyped))
85 for index, each := range untyped {
Jon Perritt8aa40262014-09-29 15:41:32 -050086 container := each.(map[string]interface{})
Jon Perrittfdac6e52014-09-29 19:43:45 -050087 err := mapstructure.Decode(container, &results[index])
Jon Perritt8aa40262014-09-29 15:41:32 -050088 if err != nil {
89 return results, err
90 }
Jon Perritt8c93a302014-09-28 22:35:57 -050091 }
92 return results, nil
93}
94
95// ExtractNames is a function that takes a ListResult and returns the containers' names.
96func ExtractNames(page pagination.Page) ([]string, error) {
97 casted := page.(ContainerPage)
98 ct := casted.Header.Get("Content-Type")
99
100 switch {
101 case strings.HasPrefix(ct, "application/json"):
102 parsed, err := ExtractInfo(page)
103 if err != nil {
104 return nil, err
105 }
106
107 names := make([]string, 0, len(parsed))
108 for _, container := range parsed {
Jon Perritt8aa40262014-09-29 15:41:32 -0500109 names = append(names, container.Name)
Jon Perritt8c93a302014-09-28 22:35:57 -0500110 }
111 return names, nil
112 case strings.HasPrefix(ct, "text/plain"):
113 names := make([]string, 0, 50)
114
115 body := string(page.(ContainerPage).Body.([]uint8))
116 for _, name := range strings.Split(body, "\n") {
117 if len(name) > 0 {
118 names = append(names, name)
119 }
120 }
121
122 return names, nil
123 default:
124 return nil, fmt.Errorf("Cannot extract names from response with content-type: [%s]", ct)
125 }
126}
127
128// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
129// and returns the custom metadata associated with the container.
130func (gr GetResult) ExtractMetadata() (map[string]string, error) {
131 if gr.Err != nil {
132 return nil, gr.Err
133 }
134 metadata := make(map[string]string)
135 for k, v := range gr.Resp.Header {
136 if strings.HasPrefix(k, "X-Container-Meta-") {
137 key := strings.TrimPrefix(k, "X-Container-Meta-")
138 metadata[key] = v[0]
139 }
140 }
141 return metadata, nil
142}