github.com/gophercloud/gophercloud@v1.11.0/openstack/container/v1/capsules/results.go (about) 1 package capsules 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "time" 7 8 "github.com/gophercloud/gophercloud" 9 "github.com/gophercloud/gophercloud/pagination" 10 ) 11 12 type commonResult struct { 13 gophercloud.Result 14 } 15 16 // ExtractBase is a function that accepts a result and extracts 17 // a base a capsule resource. 18 func (r commonResult) ExtractBase() (*Capsule, error) { 19 var s *Capsule 20 err := r.ExtractInto(&s) 21 return s, err 22 } 23 24 // Extract is a function that accepts a result and extracts a capsule result. 25 // The result will be returned as an interface{} where it should be able to 26 // be casted as either a Capsule or CapsuleV132. 27 func (r commonResult) Extract() (interface{}, error) { 28 s, err := r.ExtractBase() 29 if err == nil { 30 return s, nil 31 } 32 33 if _, ok := err.(*json.UnmarshalTypeError); !ok { 34 return s, err 35 } 36 37 return r.ExtractV132() 38 } 39 40 // GetResult represents the result of a get operation. 41 type GetResult struct { 42 commonResult 43 } 44 45 // CreateResult is the response from a Create operation. Call its Extract 46 // method to interpret it as a Capsule. 47 type CreateResult struct { 48 commonResult 49 } 50 51 // DeleteResult represents the result of a delete operation. 52 type DeleteResult struct { 53 gophercloud.ErrResult 54 } 55 56 type CapsulePage struct { 57 pagination.LinkedPageBase 58 } 59 60 // Represents a Capsule 61 type Capsule struct { 62 // UUID for the capsule 63 UUID string `json:"uuid"` 64 65 // User ID for the capsule 66 UserID string `json:"user_id"` 67 68 // Project ID for the capsule 69 ProjectID string `json:"project_id"` 70 71 // cpu for the capsule 72 CPU float64 `json:"cpu"` 73 74 // Memory for the capsule 75 Memory string `json:"memory"` 76 77 // The name of the capsule 78 MetaName string `json:"meta_name"` 79 80 // Indicates whether capsule is currently operational. 81 Status string `json:"status"` 82 83 // Indicates whether capsule is currently operational. 84 StatusReason string `json:"status_reason"` 85 86 // The created time of the capsule. 87 CreatedAt time.Time `json:"-"` 88 89 // The updated time of the capsule. 90 UpdatedAt time.Time `json:"-"` 91 92 // Links includes HTTP references to the itself, useful for passing along to 93 // other APIs that might want a capsule reference. 94 Links []interface{} `json:"links"` 95 96 // The capsule version 97 CapsuleVersion string `json:"capsule_version"` 98 99 // The capsule restart policy 100 RestartPolicy string `json:"restart_policy"` 101 102 // The capsule metadata labels 103 MetaLabels map[string]string `json:"meta_labels"` 104 105 // The list of containers uuids inside capsule. 106 ContainersUUIDs []string `json:"containers_uuids"` 107 108 // The capsule IP addresses 109 Addresses map[string][]Address `json:"addresses"` 110 111 // The capsule volume attached information 112 VolumesInfo map[string][]string `json:"volumes_info"` 113 114 // The container object inside capsule 115 Containers []Container `json:"containers"` 116 117 // The capsule host 118 Host string `json:"host"` 119 } 120 121 type Container struct { 122 // The Container IP addresses 123 Addresses map[string][]Address `json:"addresses"` 124 125 // UUID for the container 126 UUID string `json:"uuid"` 127 128 // User ID for the container 129 UserID string `json:"user_id"` 130 131 // Project ID for the container 132 ProjectID string `json:"project_id"` 133 134 // cpu for the container 135 CPU float64 `json:"cpu"` 136 137 // Memory for the container 138 Memory string `json:"memory"` 139 140 // Image for the container 141 Image string `json:"image"` 142 143 // The container container 144 Labels map[string]string `json:"labels"` 145 146 // The created time of the container 147 CreatedAt time.Time `json:"-"` 148 149 // The updated time of the container 150 UpdatedAt time.Time `json:"-"` 151 152 // The started time of the container 153 StartedAt time.Time `json:"-"` 154 155 // Name for the container 156 Name string `json:"name"` 157 158 // Links includes HTTP references to the itself, useful for passing along to 159 // other APIs that might want a capsule reference. 160 Links []interface{} `json:"links"` 161 162 // auto remove flag token for the container 163 AutoRemove bool `json:"auto_remove"` 164 165 // Host for the container 166 Host string `json:"host"` 167 168 // Work directory for the container 169 WorkDir string `json:"workdir"` 170 171 // Disk for the container 172 Disk int `json:"disk"` 173 174 // Image pull policy for the container 175 ImagePullPolicy string `json:"image_pull_policy"` 176 177 // Task state for the container 178 TaskState string `json:"task_state"` 179 180 // Host name for the container 181 HostName string `json:"hostname"` 182 183 // Environment for the container 184 Environment map[string]string `json:"environment"` 185 186 // Status for the container 187 Status string `json:"status"` 188 189 // Auto Heal flag for the container 190 AutoHeal bool `json:"auto_heal"` 191 192 // Status details for the container 193 StatusDetail string `json:"status_detail"` 194 195 // Status reason for the container 196 StatusReason string `json:"status_reason"` 197 198 // Image driver for the container 199 ImageDriver string `json:"image_driver"` 200 201 // Command for the container 202 Command []string `json:"command"` 203 204 // Image for the container 205 Runtime string `json:"runtime"` 206 207 // Interactive flag for the container 208 Interactive bool `json:"interactive"` 209 210 // Restart Policy for the container 211 RestartPolicy map[string]string `json:"restart_policy"` 212 213 // Ports information for the container 214 Ports []int `json:"ports"` 215 216 // Security groups for the container 217 SecurityGroups []string `json:"security_groups"` 218 } 219 220 type Address struct { 221 PreserveOnDelete bool `json:"preserve_on_delete"` 222 Addr string `json:"addr"` 223 Port string `json:"port"` 224 Version float64 `json:"version"` 225 SubnetID string `json:"subnet_id"` 226 } 227 228 // NextPageURL is invoked when a paginated collection of capsules has reached 229 // the end of a page and the pager seeks to traverse over a new one. In order 230 // to do this, it needs to construct the next page's URL. 231 func (r CapsulePage) NextPageURL() (string, error) { 232 var s struct { 233 Next string `json:"next"` 234 } 235 err := r.ExtractInto(&s) 236 if err != nil { 237 return "", err 238 } 239 return s.Next, nil 240 } 241 242 // IsEmpty checks whether a CapsulePage struct is empty. 243 func (r CapsulePage) IsEmpty() (bool, error) { 244 if r.StatusCode == 204 { 245 return true, nil 246 } 247 248 is, err := ExtractCapsules(r) 249 if err != nil { 250 return false, err 251 } 252 253 if v, ok := is.([]Capsule); ok { 254 return len(v) == 0, nil 255 } 256 257 if v, ok := is.([]CapsuleV132); ok { 258 return len(v) == 0, nil 259 } 260 261 return false, fmt.Errorf("Unable to determine Capsule type") 262 } 263 264 // ExtractCapsulesBase accepts a Page struct, specifically a CapsulePage struct, 265 // and extracts the elements into a slice of Capsule structs. In other words, 266 // a generic collection is mapped into the relevant slice. 267 func ExtractCapsulesBase(r pagination.Page) ([]Capsule, error) { 268 var s struct { 269 Capsules []Capsule `json:"capsules"` 270 } 271 272 err := (r.(CapsulePage)).ExtractInto(&s) 273 return s.Capsules, err 274 } 275 276 // ExtractCapsules accepts a Page struct, specifically a CapsulePage struct, 277 // and extracts the elements into an interface. 278 // This interface should be able to be casted as either a Capsule or 279 // CapsuleV132 struct 280 func ExtractCapsules(r pagination.Page) (interface{}, error) { 281 s, err := ExtractCapsulesBase(r) 282 if err == nil { 283 return s, nil 284 } 285 286 if _, ok := err.(*json.UnmarshalTypeError); !ok { 287 return nil, err 288 } 289 290 return ExtractCapsulesV132(r) 291 } 292 293 func (r *Capsule) UnmarshalJSON(b []byte) error { 294 type tmp Capsule 295 296 // Support for "older" zun time formats. 297 var s1 struct { 298 tmp 299 CreatedAt gophercloud.JSONRFC3339ZNoT `json:"created_at"` 300 UpdatedAt gophercloud.JSONRFC3339ZNoT `json:"updated_at"` 301 } 302 303 err := json.Unmarshal(b, &s1) 304 if err == nil { 305 *r = Capsule(s1.tmp) 306 307 r.CreatedAt = time.Time(s1.CreatedAt) 308 r.UpdatedAt = time.Time(s1.UpdatedAt) 309 310 return nil 311 } 312 313 // Support for "new" zun time formats. 314 var s2 struct { 315 tmp 316 CreatedAt gophercloud.JSONRFC3339ZNoTNoZ `json:"created_at"` 317 UpdatedAt gophercloud.JSONRFC3339ZNoTNoZ `json:"updated_at"` 318 } 319 320 err = json.Unmarshal(b, &s2) 321 if err != nil { 322 return err 323 } 324 325 *r = Capsule(s2.tmp) 326 327 r.CreatedAt = time.Time(s2.CreatedAt) 328 r.UpdatedAt = time.Time(s2.UpdatedAt) 329 330 return nil 331 } 332 333 func (r *Container) UnmarshalJSON(b []byte) error { 334 type tmp Container 335 336 // Support for "older" zun time formats. 337 var s1 struct { 338 tmp 339 CreatedAt gophercloud.JSONRFC3339ZNoT `json:"created_at"` 340 UpdatedAt gophercloud.JSONRFC3339ZNoT `json:"updated_at"` 341 StartedAt gophercloud.JSONRFC3339ZNoT `json:"started_at"` 342 } 343 344 err := json.Unmarshal(b, &s1) 345 if err == nil { 346 *r = Container(s1.tmp) 347 348 r.CreatedAt = time.Time(s1.CreatedAt) 349 r.UpdatedAt = time.Time(s1.UpdatedAt) 350 r.StartedAt = time.Time(s1.StartedAt) 351 352 return nil 353 } 354 355 // Support for "new" zun time formats. 356 var s2 struct { 357 tmp 358 CreatedAt gophercloud.JSONRFC3339ZNoTNoZ `json:"created_at"` 359 UpdatedAt gophercloud.JSONRFC3339ZNoTNoZ `json:"updated_at"` 360 StartedAt gophercloud.JSONRFC3339ZNoTNoZ `json:"started_at"` 361 } 362 363 err = json.Unmarshal(b, &s2) 364 if err != nil { 365 return err 366 } 367 368 *r = Container(s2.tmp) 369 370 r.CreatedAt = time.Time(s2.CreatedAt) 371 r.UpdatedAt = time.Time(s2.UpdatedAt) 372 r.StartedAt = time.Time(s2.StartedAt) 373 374 return nil 375 }