github.com/gophercloud/gophercloud@v1.11.0/openstack/identity/v3/services/results.go (about) 1 package services 2 3 import ( 4 "encoding/json" 5 6 "github.com/gophercloud/gophercloud" 7 "github.com/gophercloud/gophercloud/pagination" 8 ) 9 10 type serviceResult struct { 11 gophercloud.Result 12 } 13 14 // Extract interprets a GetResult, CreateResult or UpdateResult as a concrete 15 // Service. An error is returned if the original call or the extraction failed. 16 func (r serviceResult) Extract() (*Service, error) { 17 var s struct { 18 Service *Service `json:"service"` 19 } 20 err := r.ExtractInto(&s) 21 return s.Service, err 22 } 23 24 // CreateResult is the response from a Create request. Call its Extract method 25 // to interpret it as a Service. 26 type CreateResult struct { 27 serviceResult 28 } 29 30 // GetResult is the response from a Get request. Call its Extract method 31 // to interpret it as a Service. 32 type GetResult struct { 33 serviceResult 34 } 35 36 // UpdateResult is the response from an Update request. Call its Extract method 37 // to interpret it as a Service. 38 type UpdateResult struct { 39 serviceResult 40 } 41 42 // DeleteResult is the response from a Delete request. Call its ExtractErr 43 // method to interpret it as a Service. 44 type DeleteResult struct { 45 gophercloud.ErrResult 46 } 47 48 // Service represents an OpenStack Service. 49 type Service struct { 50 // ID is the unique ID of the service. 51 ID string `json:"id"` 52 53 // Type is the type of the service. 54 Type string `json:"type"` 55 56 // Enabled is whether or not the service is enabled. 57 Enabled bool `json:"enabled"` 58 59 // Links contains referencing links to the service. 60 Links map[string]interface{} `json:"links"` 61 62 // Extra is a collection of miscellaneous key/values. 63 Extra map[string]interface{} `json:"-"` 64 } 65 66 func (r *Service) UnmarshalJSON(b []byte) error { 67 type tmp Service 68 var s struct { 69 tmp 70 Extra map[string]interface{} `json:"extra"` 71 } 72 err := json.Unmarshal(b, &s) 73 if err != nil { 74 return err 75 } 76 *r = Service(s.tmp) 77 78 // Collect other fields and bundle them into Extra 79 // but only if a field titled "extra" wasn't sent. 80 if s.Extra != nil { 81 r.Extra = s.Extra 82 } else { 83 var result interface{} 84 err := json.Unmarshal(b, &result) 85 if err != nil { 86 return err 87 } 88 if resultMap, ok := result.(map[string]interface{}); ok { 89 r.Extra = gophercloud.RemainingKeys(Service{}, resultMap) 90 } 91 } 92 93 return err 94 } 95 96 // ServicePage is a single page of Service results. 97 type ServicePage struct { 98 pagination.LinkedPageBase 99 } 100 101 // IsEmpty returns true if the ServicePage contains no results. 102 func (p ServicePage) IsEmpty() (bool, error) { 103 if p.StatusCode == 204 { 104 return true, nil 105 } 106 107 services, err := ExtractServices(p) 108 return len(services) == 0, err 109 } 110 111 // NextPageURL extracts the "next" link from the links section of the result. 112 func (r ServicePage) NextPageURL() (string, error) { 113 var s struct { 114 Links struct { 115 Next string `json:"next"` 116 Previous string `json:"previous"` 117 } `json:"links"` 118 } 119 err := r.ExtractInto(&s) 120 if err != nil { 121 return "", err 122 } 123 return s.Links.Next, err 124 } 125 126 // ExtractServices extracts a slice of Services from a Collection acquired 127 // from List. 128 func ExtractServices(r pagination.Page) ([]Service, error) { 129 var s struct { 130 Services []Service `json:"services"` 131 } 132 err := (r.(ServicePage)).ExtractInto(&s) 133 return s.Services, err 134 }