blob: ebe6eba52e53c4fb72d1cf7de6732e6712319775 [file] [log] [blame]
Jon Perritt8c93a302014-09-28 22:35:57 -05001package containers
2
3import (
jrperritt655245a2016-08-31 15:30:27 -05004 "encoding/json"
Jon Perritt8c93a302014-09-28 22:35:57 -05005 "fmt"
jrperritt655245a2016-08-31 15:30:27 -05006 "strconv"
Jon Perritt8c93a302014-09-28 22:35:57 -05007 "strings"
Jon Perritt5db08922014-09-30 21:32:48 -05008
Jon Perritt27249f42016-02-18 10:35:59 -06009 "github.com/gophercloud/gophercloud"
10 "github.com/gophercloud/gophercloud/pagination"
Jon Perritt8c93a302014-09-28 22:35:57 -050011)
12
Jamie Hannaford4ff79962014-10-06 16:28:23 +020013// Container represents a container resource.
Jon Perritt8aa40262014-09-29 15:41:32 -050014type Container struct {
Jamie Hannaford4ff79962014-10-06 16:28:23 +020015 // The total number of bytes stored in the container.
jrperritt655245a2016-08-31 15:30:27 -050016 Bytes int64 `json:"bytes"`
Jamie Hannaford4ff79962014-10-06 16:28:23 +020017
18 // The total number of objects stored in the container.
jrperritt655245a2016-08-31 15:30:27 -050019 Count int64 `json:"count"`
Jamie Hannaford4ff79962014-10-06 16:28:23 +020020
21 // The name of the container.
Jon Perritt3c166472016-02-25 03:07:41 -060022 Name string `json:"name"`
Jon Perritt8aa40262014-09-29 15:41:32 -050023}
Jon Perritt8c93a302014-09-28 22:35:57 -050024
Jamie Hannaford4ff79962014-10-06 16:28:23 +020025// ContainerPage is the page returned by a pager when traversing over a
26// collection of containers.
Jon Perritt8c93a302014-09-28 22:35:57 -050027type ContainerPage struct {
28 pagination.MarkerPageBase
29}
30
Jon Perritt3c166472016-02-25 03:07:41 -060031//IsEmpty returns true if a ListResult contains no container names.
Jon Perritt8c93a302014-09-28 22:35:57 -050032func (r ContainerPage) IsEmpty() (bool, error) {
33 names, err := ExtractNames(r)
Jon Perritt3c166472016-02-25 03:07:41 -060034 return len(names) == 0, err
Jon Perritt8c93a302014-09-28 22:35:57 -050035}
36
37// LastMarker returns the last container name in a ListResult.
38func (r ContainerPage) LastMarker() (string, error) {
39 names, err := ExtractNames(r)
40 if err != nil {
41 return "", err
42 }
43 if len(names) == 0 {
44 return "", nil
45 }
46 return names[len(names)-1], nil
47}
48
49// ExtractInfo is a function that takes a ListResult and returns the containers' information.
Jon Perritt3c166472016-02-25 03:07:41 -060050func ExtractInfo(r pagination.Page) ([]Container, error) {
51 var s []Container
52 err := (r.(ContainerPage)).ExtractInto(&s)
53 return s, err
Jon Perritt8c93a302014-09-28 22:35:57 -050054}
55
56// ExtractNames is a function that takes a ListResult and returns the containers' names.
57func ExtractNames(page pagination.Page) ([]string, error) {
58 casted := page.(ContainerPage)
Ash Wilson72e4d2c2014-10-20 10:27:30 -040059 ct := casted.Header.Get("Content-Type")
Jon Perritt8c93a302014-09-28 22:35:57 -050060
61 switch {
62 case strings.HasPrefix(ct, "application/json"):
63 parsed, err := ExtractInfo(page)
64 if err != nil {
65 return nil, err
66 }
67
68 names := make([]string, 0, len(parsed))
69 for _, container := range parsed {
Jon Perritt8aa40262014-09-29 15:41:32 -050070 names = append(names, container.Name)
Jon Perritt8c93a302014-09-28 22:35:57 -050071 }
72 return names, nil
73 case strings.HasPrefix(ct, "text/plain"):
74 names := make([]string, 0, 50)
75
76 body := string(page.(ContainerPage).Body.([]uint8))
77 for _, name := range strings.Split(body, "\n") {
78 if len(name) > 0 {
79 names = append(names, name)
80 }
81 }
82
83 return names, nil
84 default:
85 return nil, fmt.Errorf("Cannot extract names from response with content-type: [%s]", ct)
86 }
87}
88
Jon Perritt8314f4e2014-12-01 10:58:40 -070089// GetHeader represents the headers returned in the response from a Get request.
90type GetHeader struct {
Jon Perritt3c166472016-02-25 03:07:41 -060091 AcceptRanges string `json:"Accept-Ranges"`
jrperritt655245a2016-08-31 15:30:27 -050092 BytesUsed int64 `json:"-"`
93 ContentLength int64 `json:"-"`
Jon Perritt3c166472016-02-25 03:07:41 -060094 ContentType string `json:"Content-Type"`
95 Date gophercloud.JSONRFC1123 `json:"Date"`
jrperritt655245a2016-08-31 15:30:27 -050096 ObjectCount int64 `json:"-"`
97 Read []string `json:"-"`
Jon Perritt3c166472016-02-25 03:07:41 -060098 TransID string `json:"X-Trans-Id"`
99 VersionsLocation string `json:"X-Versions-Location"`
jrperritt655245a2016-08-31 15:30:27 -0500100 Write []string `json:"-"`
101}
102
103func (h *GetHeader) UnmarshalJSON(b []byte) error {
104 type tmp GetHeader
105 var getHeader *struct {
106 tmp
107 BytesUsed string `json:"X-Container-Bytes-Used"`
108 ContentLength string `json:"Content-Length"`
109 ObjectCount string `json:"X-Container-Object-Count"`
110 Write string `json:"X-Container-Write"`
111 Read string `json:"X-Container-Read"`
112 }
113 err := json.Unmarshal(b, &getHeader)
114 if err != nil {
115 return err
116 }
117
118 *h = GetHeader(getHeader.tmp)
119
120 switch getHeader.BytesUsed {
121 case "":
122 h.BytesUsed = 0
123 default:
124 h.BytesUsed, err = strconv.ParseInt(getHeader.BytesUsed, 10, 64)
125 if err != nil {
126 return err
127 }
128 }
129
130 switch getHeader.ContentLength {
131 case "":
132 h.ContentLength = 0
133 default:
134 h.ContentLength, err = strconv.ParseInt(getHeader.ContentLength, 10, 64)
135 if err != nil {
136 return err
137 }
138 }
139
140 switch getHeader.ObjectCount {
141 case "":
142 h.ObjectCount = 0
143 default:
144 h.ObjectCount, err = strconv.ParseInt(getHeader.ObjectCount, 10, 64)
145 if err != nil {
146 return err
147 }
148 }
149
150 h.Read = strings.Split(getHeader.Read, ",")
151 h.Write = strings.Split(getHeader.Write, ",")
152
153 return nil
Jon Perritt8314f4e2014-12-01 10:58:40 -0700154}
155
Jon Perritt5db08922014-09-30 21:32:48 -0500156// GetResult represents the result of a get operation.
157type GetResult struct {
Jon Perrittd50f93e2014-10-27 14:19:27 -0500158 gophercloud.HeaderResult
Jon Perritt5db08922014-09-30 21:32:48 -0500159}
160
Jon Perritt8314f4e2014-12-01 10:58:40 -0700161// Extract will return a struct of headers returned from a call to Get. To obtain
162// a map of headers, call the ExtractHeader method on the GetResult.
Jon Perritt3c166472016-02-25 03:07:41 -0600163func (r GetResult) Extract() (*GetHeader, error) {
164 var s *GetHeader
165 err := r.ExtractInto(&s)
166 return s, err
Jon Perritt8314f4e2014-12-01 10:58:40 -0700167}
168
Jon Perritt8c93a302014-09-28 22:35:57 -0500169// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
170// and returns the custom metadata associated with the container.
Jon Perritt3c166472016-02-25 03:07:41 -0600171func (r GetResult) ExtractMetadata() (map[string]string, error) {
172 if r.Err != nil {
173 return nil, r.Err
Jon Perritt8c93a302014-09-28 22:35:57 -0500174 }
175 metadata := make(map[string]string)
Jon Perritt3c166472016-02-25 03:07:41 -0600176 for k, v := range r.Header {
Jon Perritt8c93a302014-09-28 22:35:57 -0500177 if strings.HasPrefix(k, "X-Container-Meta-") {
178 key := strings.TrimPrefix(k, "X-Container-Meta-")
179 metadata[key] = v[0]
180 }
181 }
182 return metadata, nil
183}
Jon Perritt5db08922014-09-30 21:32:48 -0500184
Jon Perritt8314f4e2014-12-01 10:58:40 -0700185// CreateHeader represents the headers returned in the response from a Create request.
186type CreateHeader struct {
jrperritt655245a2016-08-31 15:30:27 -0500187 ContentLength int64 `json:"-"`
Jon Perritt3c166472016-02-25 03:07:41 -0600188 ContentType string `json:"Content-Type"`
189 Date gophercloud.JSONRFC1123 `json:"Date"`
190 TransID string `json:"X-Trans-Id"`
Jon Perritt8314f4e2014-12-01 10:58:40 -0700191}
192
jrperritt655245a2016-08-31 15:30:27 -0500193func (h *CreateHeader) UnmarshalJSON(b []byte) error {
194 type tmp CreateHeader
195 var header *struct {
196 tmp
197 ContentLength string `json:"Content-Length"`
198 }
199 err := json.Unmarshal(b, &header)
200 if err != nil {
201 return err
202 }
203
204 *h = CreateHeader(header.tmp)
205
206 switch header.ContentLength {
207 case "":
208 h.ContentLength = 0
209 default:
210 h.ContentLength, err = strconv.ParseInt(header.ContentLength, 10, 64)
211 if err != nil {
212 return err
213 }
214 }
215
216 return nil
217}
218
Jamie Hannaford22ec4792014-10-07 10:07:41 +0200219// CreateResult represents the result of a create operation. To extract the
Jon Perritt9856a342014-10-27 13:44:06 -0500220// the headers from the HTTP response, you can invoke the 'ExtractHeader'
Jamie Hannaford22ec4792014-10-07 10:07:41 +0200221// method on the result struct.
Jon Perritt5db08922014-09-30 21:32:48 -0500222type CreateResult struct {
Jon Perrittd50f93e2014-10-27 14:19:27 -0500223 gophercloud.HeaderResult
Jon Perritt5db08922014-09-30 21:32:48 -0500224}
225
Jon Perritt8314f4e2014-12-01 10:58:40 -0700226// Extract will return a struct of headers returned from a call to Create. To obtain
227// a map of headers, call the ExtractHeader method on the CreateResult.
Jon Perritt3c166472016-02-25 03:07:41 -0600228func (r CreateResult) Extract() (*CreateHeader, error) {
229 var s *CreateHeader
230 err := r.ExtractInto(&s)
231 return s, err
Jon Perritt8314f4e2014-12-01 10:58:40 -0700232}
233
234// UpdateHeader represents the headers returned in the response from a Update request.
235type UpdateHeader struct {
jrperritt655245a2016-08-31 15:30:27 -0500236 ContentLength int64 `json:"-"`
Jon Perritt3c166472016-02-25 03:07:41 -0600237 ContentType string `json:"Content-Type"`
238 Date gophercloud.JSONRFC1123 `json:"Date"`
239 TransID string `json:"X-Trans-Id"`
Jon Perritt8314f4e2014-12-01 10:58:40 -0700240}
241
jrperritt655245a2016-08-31 15:30:27 -0500242func (h *UpdateHeader) UnmarshalJSON(b []byte) error {
243 type tmp UpdateHeader
244 var header *struct {
245 tmp
246 ContentLength string `json:"Content-Length"`
247 }
248 err := json.Unmarshal(b, &header)
249 if err != nil {
250 return err
251 }
252
253 *h = UpdateHeader(header.tmp)
254
255 switch header.ContentLength {
256 case "":
257 h.ContentLength = 0
258 default:
259 h.ContentLength, err = strconv.ParseInt(header.ContentLength, 10, 64)
260 if err != nil {
261 return err
262 }
263 }
264
265 return nil
266}
267
Jamie Hannaford22ec4792014-10-07 10:07:41 +0200268// UpdateResult represents the result of an update operation. To extract the
Jon Perritt9856a342014-10-27 13:44:06 -0500269// the headers from the HTTP response, you can invoke the 'ExtractHeader'
Jamie Hannaford22ec4792014-10-07 10:07:41 +0200270// method on the result struct.
Jon Perritt5db08922014-09-30 21:32:48 -0500271type UpdateResult struct {
Jon Perrittd50f93e2014-10-27 14:19:27 -0500272 gophercloud.HeaderResult
Jon Perritt5db08922014-09-30 21:32:48 -0500273}
274
Jon Perritt8314f4e2014-12-01 10:58:40 -0700275// Extract will return a struct of headers returned from a call to Update. To obtain
276// a map of headers, call the ExtractHeader method on the UpdateResult.
Jon Perritt3c166472016-02-25 03:07:41 -0600277func (r UpdateResult) Extract() (*UpdateHeader, error) {
278 var s *UpdateHeader
279 err := r.ExtractInto(&s)
280 return s, err
Jon Perritt8314f4e2014-12-01 10:58:40 -0700281}
282
283// DeleteHeader represents the headers returned in the response from a Delete request.
284type DeleteHeader struct {
jrperritt655245a2016-08-31 15:30:27 -0500285 ContentLength int64 `json:"-"`
Jon Perritt3c166472016-02-25 03:07:41 -0600286 ContentType string `json:"Content-Type"`
287 Date gophercloud.JSONRFC1123 `json:"Date"`
288 TransID string `json:"X-Trans-Id"`
Jon Perritt8314f4e2014-12-01 10:58:40 -0700289}
290
jrperritt655245a2016-08-31 15:30:27 -0500291func (h *DeleteHeader) UnmarshalJSON(b []byte) error {
292 type tmp DeleteHeader
293 var header *struct {
294 tmp
295 ContentLength string `json:"Content-Length"`
296 }
297 err := json.Unmarshal(b, &header)
298 if err != nil {
299 return err
300 }
301
302 *h = DeleteHeader(header.tmp)
303
304 switch header.ContentLength {
305 case "":
306 h.ContentLength = 0
307 default:
308 h.ContentLength, err = strconv.ParseInt(header.ContentLength, 10, 64)
309 if err != nil {
310 return err
311 }
312 }
313
314 return nil
315}
316
Jamie Hannaford22ec4792014-10-07 10:07:41 +0200317// DeleteResult represents the result of a delete operation. To extract the
Jon Perritt9856a342014-10-27 13:44:06 -0500318// the headers from the HTTP response, you can invoke the 'ExtractHeader'
Jamie Hannaford22ec4792014-10-07 10:07:41 +0200319// method on the result struct.
Jon Perritt5db08922014-09-30 21:32:48 -0500320type DeleteResult struct {
Jon Perrittd50f93e2014-10-27 14:19:27 -0500321 gophercloud.HeaderResult
Jon Perritt5db08922014-09-30 21:32:48 -0500322}
Jon Perritt8314f4e2014-12-01 10:58:40 -0700323
324// Extract will return a struct of headers returned from a call to Delete. To obtain
325// a map of headers, call the ExtractHeader method on the DeleteResult.
Jon Perritt3c166472016-02-25 03:07:41 -0600326func (r DeleteResult) Extract() (*DeleteHeader, error) {
327 var s *DeleteHeader
328 err := r.ExtractInto(&s)
329 return s, err
Jon Perritt8314f4e2014-12-01 10:58:40 -0700330}