github.com/gophercloud/gophercloud@v1.11.0/openstack/networking/v2/extensions/subnetpools/results.go (about) 1 package subnetpools 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strconv" 7 "time" 8 9 "github.com/gophercloud/gophercloud" 10 "github.com/gophercloud/gophercloud/pagination" 11 ) 12 13 type commonResult struct { 14 gophercloud.Result 15 } 16 17 // Extract is a function that accepts a result and extracts a subnetpool resource. 18 func (r commonResult) Extract() (*SubnetPool, error) { 19 var s struct { 20 SubnetPool *SubnetPool `json:"subnetpool"` 21 } 22 err := r.ExtractInto(&s) 23 return s.SubnetPool, err 24 } 25 26 // GetResult represents the result of a get operation. Call its Extract 27 // method to interpret it as a SubnetPool. 28 type GetResult struct { 29 commonResult 30 } 31 32 // CreateResult represents the result of a create operation. Call its Extract 33 // method to interpret it as a SubnetPool. 34 type CreateResult struct { 35 commonResult 36 } 37 38 // UpdateResult represents the result of an update operation. Call its Extract 39 // method to interpret it as a SubnetPool. 40 type UpdateResult struct { 41 commonResult 42 } 43 44 // DeleteResult represents the result of a delete operation. Call its 45 // ExtractErr method to determine if the request succeeded or failed. 46 type DeleteResult struct { 47 gophercloud.ErrResult 48 } 49 50 // SubnetPool represents a Neutron subnetpool. 51 // A subnetpool is a pool of addresses from which subnets can be allocated. 52 type SubnetPool struct { 53 // ID is the id of the subnetpool. 54 ID string `json:"id"` 55 56 // Name is the human-readable name of the subnetpool. 57 Name string `json:"name"` 58 59 // DefaultQuota is the per-project quota on the prefix space 60 // that can be allocated from the subnetpool for project subnets. 61 DefaultQuota int `json:"default_quota"` 62 63 // TenantID is the id of the Identity project. 64 TenantID string `json:"tenant_id"` 65 66 // ProjectID is the id of the Identity project. 67 ProjectID string `json:"project_id"` 68 69 // CreatedAt is the time at which subnetpool has been created. 70 CreatedAt time.Time `json:"-"` 71 72 // UpdatedAt is the time at which subnetpool has been created. 73 UpdatedAt time.Time `json:"-"` 74 75 // Prefixes is the list of subnet prefixes to assign to the subnetpool. 76 // Neutron API merges adjacent prefixes and treats them as a single prefix. 77 // Each subnet prefix must be unique among all subnet prefixes in all subnetpools 78 // that are associated with the address scope. 79 Prefixes []string `json:"prefixes"` 80 81 // DefaultPrefixLen is yhe size of the prefix to allocate when the cidr 82 // or prefixlen attributes are omitted when you create the subnet. 83 // Defaults to the MinPrefixLen. 84 DefaultPrefixLen int `json:"-"` 85 86 // MinPrefixLen is the smallest prefix that can be allocated from a subnetpool. 87 // For IPv4 subnetpools, default is 8. 88 // For IPv6 subnetpools, default is 64. 89 MinPrefixLen int `json:"-"` 90 91 // MaxPrefixLen is the maximum prefix size that can be allocated from the subnetpool. 92 // For IPv4 subnetpools, default is 32. 93 // For IPv6 subnetpools, default is 128. 94 MaxPrefixLen int `json:"-"` 95 96 // AddressScopeID is the Neutron address scope to assign to the subnetpool. 97 AddressScopeID string `json:"address_scope_id"` 98 99 // IPversion is the IP protocol version. 100 // Valid value is 4 or 6. Default is 4. 101 IPversion int `json:"ip_version"` 102 103 // Shared indicates whether this network is shared across all projects. 104 Shared bool `json:"shared"` 105 106 // Description is thehuman-readable description for the resource. 107 Description string `json:"description"` 108 109 // IsDefault indicates if the subnetpool is default pool or not. 110 IsDefault bool `json:"is_default"` 111 112 // RevisionNumber is the revision number of the subnetpool. 113 RevisionNumber int `json:"revision_number"` 114 115 // Tags optionally set via extensions/attributestags 116 Tags []string `json:"tags"` 117 } 118 119 func (r *SubnetPool) UnmarshalJSON(b []byte) error { 120 type tmp SubnetPool 121 122 // Support for older neutron time format 123 var s1 struct { 124 tmp 125 DefaultPrefixLen interface{} `json:"default_prefixlen"` 126 MinPrefixLen interface{} `json:"min_prefixlen"` 127 MaxPrefixLen interface{} `json:"max_prefixlen"` 128 129 CreatedAt gophercloud.JSONRFC3339NoZ `json:"created_at"` 130 UpdatedAt gophercloud.JSONRFC3339NoZ `json:"updated_at"` 131 } 132 133 err := json.Unmarshal(b, &s1) 134 if err == nil { 135 *r = SubnetPool(s1.tmp) 136 137 r.CreatedAt = time.Time(s1.CreatedAt) 138 r.UpdatedAt = time.Time(s1.UpdatedAt) 139 140 switch t := s1.DefaultPrefixLen.(type) { 141 case string: 142 if r.DefaultPrefixLen, err = strconv.Atoi(t); err != nil { 143 return err 144 } 145 case float64: 146 r.DefaultPrefixLen = int(t) 147 default: 148 return fmt.Errorf("DefaultPrefixLen has unexpected type: %T", t) 149 } 150 151 switch t := s1.MinPrefixLen.(type) { 152 case string: 153 if r.MinPrefixLen, err = strconv.Atoi(t); err != nil { 154 return err 155 } 156 case float64: 157 r.MinPrefixLen = int(t) 158 default: 159 return fmt.Errorf("MinPrefixLen has unexpected type: %T", t) 160 } 161 162 switch t := s1.MaxPrefixLen.(type) { 163 case string: 164 if r.MaxPrefixLen, err = strconv.Atoi(t); err != nil { 165 return err 166 } 167 case float64: 168 r.MaxPrefixLen = int(t) 169 default: 170 return fmt.Errorf("MaxPrefixLen has unexpected type: %T", t) 171 } 172 173 return nil 174 } 175 176 // Support for newer neutron time format 177 var s2 struct { 178 tmp 179 DefaultPrefixLen interface{} `json:"default_prefixlen"` 180 MinPrefixLen interface{} `json:"min_prefixlen"` 181 MaxPrefixLen interface{} `json:"max_prefixlen"` 182 183 CreatedAt time.Time `json:"created_at"` 184 UpdatedAt time.Time `json:"updated_at"` 185 } 186 187 err = json.Unmarshal(b, &s2) 188 if err != nil { 189 return err 190 } 191 192 *r = SubnetPool(s2.tmp) 193 194 r.CreatedAt = time.Time(s2.CreatedAt) 195 r.UpdatedAt = time.Time(s2.UpdatedAt) 196 197 switch t := s2.DefaultPrefixLen.(type) { 198 case string: 199 if r.DefaultPrefixLen, err = strconv.Atoi(t); err != nil { 200 return err 201 } 202 case float64: 203 r.DefaultPrefixLen = int(t) 204 default: 205 return fmt.Errorf("DefaultPrefixLen has unexpected type: %T", t) 206 } 207 208 switch t := s2.MinPrefixLen.(type) { 209 case string: 210 if r.MinPrefixLen, err = strconv.Atoi(t); err != nil { 211 return err 212 } 213 case float64: 214 r.MinPrefixLen = int(t) 215 default: 216 return fmt.Errorf("MinPrefixLen has unexpected type: %T", t) 217 } 218 219 switch t := s2.MaxPrefixLen.(type) { 220 case string: 221 if r.MaxPrefixLen, err = strconv.Atoi(t); err != nil { 222 return err 223 } 224 case float64: 225 r.MaxPrefixLen = int(t) 226 default: 227 return fmt.Errorf("MaxPrefixLen has unexpected type: %T", t) 228 } 229 230 return nil 231 } 232 233 // SubnetPoolPage stores a single page of SubnetPools from a List() API call. 234 type SubnetPoolPage struct { 235 pagination.LinkedPageBase 236 } 237 238 // NextPageURL is invoked when a paginated collection of subnetpools has reached 239 // the end of a page and the pager seeks to traverse over a new one. 240 // In order to do this, it needs to construct the next page's URL. 241 func (r SubnetPoolPage) NextPageURL() (string, error) { 242 var s struct { 243 Links []gophercloud.Link `json:"subnetpools_links"` 244 } 245 err := r.ExtractInto(&s) 246 if err != nil { 247 return "", err 248 } 249 return gophercloud.ExtractNextURL(s.Links) 250 } 251 252 // IsEmpty determines whether or not a SubnetPoolPage is empty. 253 func (r SubnetPoolPage) IsEmpty() (bool, error) { 254 if r.StatusCode == 204 { 255 return true, nil 256 } 257 258 subnetpools, err := ExtractSubnetPools(r) 259 return len(subnetpools) == 0, err 260 } 261 262 // ExtractSubnetPools interprets the results of a single page from a List() API call, 263 // producing a slice of SubnetPools structs. 264 func ExtractSubnetPools(r pagination.Page) ([]SubnetPool, error) { 265 var s struct { 266 SubnetPools []SubnetPool `json:"subnetpools"` 267 } 268 err := (r.(SubnetPoolPage)).ExtractInto(&s) 269 return s.SubnetPools, err 270 }