blob: 6a93b4d0d2d5a12b3469b951f77ab4d3c580ca61 [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
12type Container map[string]interface{}
13
14type commonResult struct {
15 gophercloud.CommonResult
16}
17
18func (r GetResult) Extract() (*Container, error) {
19 if r.Err != nil {
20 return nil, r.Err
21 }
22
23 var res struct {
24 Container *Container
25 }
26
27 err := mapstructure.Decode(r.Resp, &res)
28 if err != nil {
29 return nil, fmt.Errorf("Error decoding Object Storage Container: %v", err)
30 }
31
32 return res.Container, nil
33}
34
35type CreateResult struct {
36 commonResult
37}
38
39// GetResult represents the result of a get operation.
40type GetResult struct {
41 Resp *http.Response
42 Err error
43}
44
45// UpdateResult represents the result of an update operation.
46type UpdateResult commonResult
47
48// DeleteResult represents the result of a delete operation.
49type DeleteResult commonResult
50
51// ListResult is a *http.Response that is returned from a call to the List function.
52type ContainerPage struct {
53 pagination.MarkerPageBase
54}
55
56// IsEmpty returns true if a ListResult contains no container names.
57func (r ContainerPage) IsEmpty() (bool, error) {
58 names, err := ExtractNames(r)
59 if err != nil {
60 return true, err
61 }
62 return len(names) == 0, nil
63}
64
65// LastMarker returns the last container name in a ListResult.
66func (r ContainerPage) LastMarker() (string, error) {
67 names, err := ExtractNames(r)
68 if err != nil {
69 return "", err
70 }
71 if len(names) == 0 {
72 return "", nil
73 }
74 return names[len(names)-1], nil
75}
76
77// ExtractInfo is a function that takes a ListResult and returns the containers' information.
78func ExtractInfo(page pagination.Page) ([]Container, error) {
79 untyped := page.(ContainerPage).Body.([]interface{})
80 results := make([]Container, len(untyped))
81 for index, each := range untyped {
82 results[index] = Container(each.(map[string]interface{}))
83 }
84 return results, nil
85}
86
87// ExtractNames is a function that takes a ListResult and returns the containers' names.
88func ExtractNames(page pagination.Page) ([]string, error) {
89 casted := page.(ContainerPage)
90 ct := casted.Header.Get("Content-Type")
91
92 switch {
93 case strings.HasPrefix(ct, "application/json"):
94 parsed, err := ExtractInfo(page)
95 if err != nil {
96 return nil, err
97 }
98
99 names := make([]string, 0, len(parsed))
100 for _, container := range parsed {
101 names = append(names, container["name"].(string))
102 }
103 return names, nil
104 case strings.HasPrefix(ct, "text/plain"):
105 names := make([]string, 0, 50)
106
107 body := string(page.(ContainerPage).Body.([]uint8))
108 for _, name := range strings.Split(body, "\n") {
109 if len(name) > 0 {
110 names = append(names, name)
111 }
112 }
113
114 return names, nil
115 default:
116 return nil, fmt.Errorf("Cannot extract names from response with content-type: [%s]", ct)
117 }
118}
119
120// ExtractMetadata is a function that takes a GetResult (of type *http.Response)
121// and returns the custom metadata associated with the container.
122func (gr GetResult) ExtractMetadata() (map[string]string, error) {
123 if gr.Err != nil {
124 return nil, gr.Err
125 }
126 metadata := make(map[string]string)
127 for k, v := range gr.Resp.Header {
128 if strings.HasPrefix(k, "X-Container-Meta-") {
129 key := strings.TrimPrefix(k, "X-Container-Meta-")
130 metadata[key] = v[0]
131 }
132 }
133 return metadata, nil
134}