github.com/gophercloud/gophercloud@v1.11.0/openstack/objectstorage/v1/containers/results.go (about) 1 package containers 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strconv" 7 "strings" 8 "time" 9 10 "github.com/gophercloud/gophercloud" 11 "github.com/gophercloud/gophercloud/pagination" 12 ) 13 14 // Container represents a container resource. 15 type Container struct { 16 // The total number of bytes stored in the container. 17 Bytes int64 `json:"bytes"` 18 19 // The total number of objects stored in the container. 20 Count int64 `json:"count"` 21 22 // The name of the container. 23 Name string `json:"name"` 24 } 25 26 // ContainerPage is the page returned by a pager when traversing over a 27 // collection of containers. 28 type ContainerPage struct { 29 pagination.MarkerPageBase 30 } 31 32 // IsEmpty returns true if a ListResult contains no container names. 33 func (r ContainerPage) IsEmpty() (bool, error) { 34 if r.StatusCode == 204 { 35 return true, nil 36 } 37 38 names, err := ExtractNames(r) 39 return len(names) == 0, err 40 } 41 42 // LastMarker returns the last container name in a ListResult. 43 func (r ContainerPage) LastMarker() (string, error) { 44 names, err := ExtractNames(r) 45 if err != nil { 46 return "", err 47 } 48 if len(names) == 0 { 49 return "", nil 50 } 51 return names[len(names)-1], nil 52 } 53 54 // ExtractInfo is a function that takes a ListResult and returns the 55 // containers' information. 56 func ExtractInfo(r pagination.Page) ([]Container, error) { 57 var s []Container 58 err := (r.(ContainerPage)).ExtractInto(&s) 59 return s, err 60 } 61 62 // ExtractNames is a function that takes a ListResult and returns the 63 // containers' names. 64 func ExtractNames(page pagination.Page) ([]string, error) { 65 casted := page.(ContainerPage) 66 ct := casted.Header.Get("Content-Type") 67 68 switch { 69 case strings.HasPrefix(ct, "application/json"): 70 parsed, err := ExtractInfo(page) 71 if err != nil { 72 return nil, err 73 } 74 75 names := make([]string, 0, len(parsed)) 76 for _, container := range parsed { 77 names = append(names, container.Name) 78 } 79 return names, nil 80 case strings.HasPrefix(ct, "text/plain") || ct == "": 81 names := make([]string, 0, 50) 82 83 body := string(page.(ContainerPage).Body.([]uint8)) 84 for _, name := range strings.Split(body, "\n") { 85 if len(name) > 0 { 86 names = append(names, name) 87 } 88 } 89 90 return names, nil 91 default: 92 return nil, fmt.Errorf("Cannot extract names from response with content-type: [%s]", ct) 93 } 94 } 95 96 // GetHeader represents the headers returned in the response from a Get request. 97 type GetHeader struct { 98 AcceptRanges string `json:"Accept-Ranges"` 99 BytesUsed int64 `json:"X-Container-Bytes-Used,string"` 100 ContentLength int64 `json:"Content-Length,string"` 101 ContentType string `json:"Content-Type"` 102 Date time.Time `json:"-"` 103 ObjectCount int64 `json:"X-Container-Object-Count,string"` 104 Read []string `json:"-"` 105 TransID string `json:"X-Trans-Id"` 106 VersionsLocation string `json:"X-Versions-Location"` 107 HistoryLocation string `json:"X-History-Location"` 108 Write []string `json:"-"` 109 StoragePolicy string `json:"X-Storage-Policy"` 110 TempURLKey string `json:"X-Container-Meta-Temp-URL-Key"` 111 TempURLKey2 string `json:"X-Container-Meta-Temp-URL-Key-2"` 112 Timestamp float64 `json:"X-Timestamp,string"` 113 VersionsEnabled bool `json:"-"` 114 } 115 116 func (r *GetHeader) UnmarshalJSON(b []byte) error { 117 type tmp GetHeader 118 var s struct { 119 tmp 120 Write string `json:"X-Container-Write"` 121 Read string `json:"X-Container-Read"` 122 Date gophercloud.JSONRFC1123 `json:"Date"` 123 VersionsEnabled string `json:"X-Versions-Enabled"` 124 } 125 126 err := json.Unmarshal(b, &s) 127 if err != nil { 128 return err 129 } 130 131 *r = GetHeader(s.tmp) 132 133 r.Read = strings.Split(s.Read, ",") 134 r.Write = strings.Split(s.Write, ",") 135 136 r.Date = time.Time(s.Date) 137 138 if s.VersionsEnabled != "" { 139 // custom unmarshaller here is required to handle boolean value 140 // that starts with a capital letter 141 r.VersionsEnabled, err = strconv.ParseBool(s.VersionsEnabled) 142 } 143 144 return err 145 } 146 147 // GetResult represents the result of a get operation. 148 type GetResult struct { 149 gophercloud.HeaderResult 150 } 151 152 // Extract will return a struct of headers returned from a call to Get. 153 func (r GetResult) Extract() (*GetHeader, error) { 154 var s GetHeader 155 err := r.ExtractInto(&s) 156 return &s, err 157 } 158 159 // ExtractMetadata is a function that takes a GetResult (of type *http.Response) 160 // and returns the custom metadata associated with the container. 161 func (r GetResult) ExtractMetadata() (map[string]string, error) { 162 if r.Err != nil { 163 return nil, r.Err 164 } 165 metadata := make(map[string]string) 166 for k, v := range r.Header { 167 if strings.HasPrefix(k, "X-Container-Meta-") { 168 key := strings.TrimPrefix(k, "X-Container-Meta-") 169 metadata[key] = v[0] 170 } 171 } 172 return metadata, nil 173 } 174 175 // CreateHeader represents the headers returned in the response from a Create 176 // request. 177 type CreateHeader struct { 178 ContentLength int64 `json:"Content-Length,string"` 179 ContentType string `json:"Content-Type"` 180 Date time.Time `json:"-"` 181 TransID string `json:"X-Trans-Id"` 182 } 183 184 func (r *CreateHeader) UnmarshalJSON(b []byte) error { 185 type tmp CreateHeader 186 var s struct { 187 tmp 188 Date gophercloud.JSONRFC1123 `json:"Date"` 189 } 190 err := json.Unmarshal(b, &s) 191 if err != nil { 192 return err 193 } 194 195 *r = CreateHeader(s.tmp) 196 197 r.Date = time.Time(s.Date) 198 199 return err 200 } 201 202 // CreateResult represents the result of a create operation. To extract the 203 // the headers from the HTTP response, call its Extract method. 204 type CreateResult struct { 205 gophercloud.HeaderResult 206 } 207 208 // Extract will return a struct of headers returned from a call to Create. 209 // To extract the headers from the HTTP response, call its Extract method. 210 func (r CreateResult) Extract() (*CreateHeader, error) { 211 var s CreateHeader 212 err := r.ExtractInto(&s) 213 return &s, err 214 } 215 216 // UpdateHeader represents the headers returned in the response from a Update 217 // request. 218 type UpdateHeader struct { 219 ContentLength int64 `json:"Content-Length,string"` 220 ContentType string `json:"Content-Type"` 221 Date time.Time `json:"-"` 222 TransID string `json:"X-Trans-Id"` 223 } 224 225 func (r *UpdateHeader) UnmarshalJSON(b []byte) error { 226 type tmp UpdateHeader 227 var s struct { 228 tmp 229 Date gophercloud.JSONRFC1123 `json:"Date"` 230 } 231 err := json.Unmarshal(b, &s) 232 if err != nil { 233 return err 234 } 235 236 *r = UpdateHeader(s.tmp) 237 238 r.Date = time.Time(s.Date) 239 240 return err 241 } 242 243 // UpdateResult represents the result of an update operation. To extract the 244 // the headers from the HTTP response, call its Extract method. 245 type UpdateResult struct { 246 gophercloud.HeaderResult 247 } 248 249 // Extract will return a struct of headers returned from a call to Update. 250 func (r UpdateResult) Extract() (*UpdateHeader, error) { 251 var s UpdateHeader 252 err := r.ExtractInto(&s) 253 return &s, err 254 } 255 256 // DeleteHeader represents the headers returned in the response from a Delete 257 // request. 258 type DeleteHeader struct { 259 ContentLength int64 `json:"Content-Length,string"` 260 ContentType string `json:"Content-Type"` 261 Date time.Time `json:"-"` 262 TransID string `json:"X-Trans-Id"` 263 } 264 265 func (r *DeleteHeader) UnmarshalJSON(b []byte) error { 266 type tmp DeleteHeader 267 var s struct { 268 tmp 269 Date gophercloud.JSONRFC1123 `json:"Date"` 270 } 271 err := json.Unmarshal(b, &s) 272 if err != nil { 273 return err 274 } 275 276 *r = DeleteHeader(s.tmp) 277 278 r.Date = time.Time(s.Date) 279 280 return err 281 } 282 283 // DeleteResult represents the result of a delete operation. To extract the 284 // headers from the HTTP response, call its Extract method. 285 type DeleteResult struct { 286 gophercloud.HeaderResult 287 } 288 289 // Extract will return a struct of headers returned from a call to Delete. 290 func (r DeleteResult) Extract() (*DeleteHeader, error) { 291 var s DeleteHeader 292 err := r.ExtractInto(&s) 293 return &s, err 294 } 295 296 type BulkDeleteResponse struct { 297 ResponseStatus string `json:"Response Status"` 298 ResponseBody string `json:"Response Body"` 299 Errors [][]string `json:"Errors"` 300 NumberDeleted int `json:"Number Deleted"` 301 NumberNotFound int `json:"Number Not Found"` 302 } 303 304 // BulkDeleteResult represents the result of a bulk delete operation. To extract 305 // the response object from the HTTP response, call its Extract method. 306 type BulkDeleteResult struct { 307 gophercloud.Result 308 } 309 310 // Extract will return a BulkDeleteResponse struct returned from a BulkDelete 311 // call. 312 func (r BulkDeleteResult) Extract() (*BulkDeleteResponse, error) { 313 var s BulkDeleteResponse 314 err := r.ExtractInto(&s) 315 return &s, err 316 }