Adding quotas operations
diff --git a/openstack/networking/v2/extensions/quotas/requests.go b/openstack/networking/v2/extensions/quotas/requests.go
index d03c081..f16c440 100755
--- a/openstack/networking/v2/extensions/quotas/requests.go
+++ b/openstack/networking/v2/extensions/quotas/requests.go
@@ -1 +1,85 @@
package quotas
+
+import (
+ "github.com/racker/perigee"
+ "github.com/rackspace/gophercloud"
+)
+
+func Get(c *gophercloud.ServiceClient) GetResult {
+ var res GetResult
+ _, err := perigee.Request("GET", rootURL(c), perigee.Options{
+ Results: &res.resp,
+ MoreHeaders: c.Provider.AuthenticatedHeaders(),
+ })
+ res.err = err
+ return res
+}
+
+type UpdateOpts struct {
+ Subnet *int
+ Router *int
+ Network *int
+ FloatingIP *int
+ Port *int
+ HealthMonitor *int
+ SecGroupRule *int
+ SecGroup *int
+ VIP *int
+ Member *int
+ Pool *int
+}
+
+func Update(c *gophercloud.ServiceClient, opts UpdateOpts) UpdateResult {
+ type quota struct {
+ Subnet *int `json:"subnet,omitempty"`
+ Router *int `json:"router,omitempty"`
+ Network *int `json:"network,omitempty"`
+ FloatingIP *int `json:"floatingip,omitempty"`
+ Port *int `json:"port,omitempty"`
+ HealthMonitor *int `json:"health_monitor,omitempty"`
+ SecGroupRule *int `json:"security_group_rule,omitempty"`
+ VIP *int `json:"vip,omitempty"`
+ SecGroup *int `json:"security_group,omitempty"`
+ Member *int `json:"member,omitempty"`
+ Pool *int `json:"pool,omitempty"`
+ }
+
+ type request struct {
+ Quota quota `json:"quota"`
+ }
+
+ reqBody := request{Quota: quota{
+ Subnet: opts.Subnet,
+ Router: opts.Router,
+ Network: opts.Network,
+ FloatingIP: opts.FloatingIP,
+ Port: opts.Port,
+ HealthMonitor: opts.HealthMonitor,
+ SecGroupRule: opts.SecGroupRule,
+ VIP: opts.VIP,
+ SecGroup: opts.SecGroup,
+ Member: opts.Member,
+ Pool: opts.Pool,
+ }}
+
+ var res UpdateResult
+ _, err := perigee.Request("PUT", rootURL(c), perigee.Options{
+ MoreHeaders: c.Provider.AuthenticatedHeaders(),
+ ReqBody: &reqBody,
+ Results: &res.resp,
+ OkCodes: []int{200},
+ })
+ res.err = err
+
+ return res
+}
+
+func Reset(c *gophercloud.ServiceClient) DeleteResult {
+ var res DeleteResult
+ _, err := perigee.Request("DELETE", rootURL(c), perigee.Options{
+ MoreHeaders: c.Provider.AuthenticatedHeaders(),
+ OkCodes: []int{204},
+ })
+ res.err = err
+ return res
+}
diff --git a/openstack/networking/v2/extensions/quotas/requests_test.go b/openstack/networking/v2/extensions/quotas/requests_test.go
index 16c7def..1157c49 100755
--- a/openstack/networking/v2/extensions/quotas/requests_test.go
+++ b/openstack/networking/v2/extensions/quotas/requests_test.go
@@ -1,15 +1,116 @@
package quotas
-import "testing"
+import (
+ "fmt"
+ "net/http"
+ "testing"
+
+ "github.com/rackspace/gophercloud"
+ th "github.com/rackspace/gophercloud/testhelper"
+)
+
+const tokenID = "123"
+
+func serviceClient() *gophercloud.ServiceClient {
+ return &gophercloud.ServiceClient{
+ Provider: &gophercloud.ProviderClient{TokenID: tokenID},
+ Endpoint: th.Endpoint(),
+ }
+}
func TestGet(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+ th.Mux.HandleFunc("/v2.0/quotas", func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "GET")
+ th.TestHeader(t, r, "X-Auth-Token", tokenID)
+
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+
+ fmt.Fprintf(w, `
+{
+ "quota": {
+ "subnet": 10,
+ "router": 10,
+ "port": 50,
+ "network": 10,
+ "floatingip": 50
+ }
+}
+ `)
+ })
+
+ qs, err := Get(serviceClient()).Extract()
+ th.AssertNoErr(t, err)
+
+ th.AssertEquals(t, qs.Subnet, 10)
+ th.AssertEquals(t, qs.Router, 10)
+ th.AssertEquals(t, qs.Port, 50)
+ th.AssertEquals(t, qs.Network, 10)
+ th.AssertEquals(t, qs.FloatingIP, 50)
}
func TestUpdate(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+ th.Mux.HandleFunc("/v2.0/quotas", func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "PUT")
+ th.TestHeader(t, r, "X-Auth-Token", tokenID)
+ th.TestHeader(t, r, "Content-Type", "application/json")
+ th.TestHeader(t, r, "Accept", "application/json")
+ th.TestJSONRequest(t, r, `
+{
+ "quota": {
+ "subnet": 40,
+ "router": 40,
+ "network": 10,
+ "floatingip": 30,
+ "port": 30
+ }
+}
+ `)
+
+ w.Header().Add("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+
+ fmt.Fprintf(w, `
+{
+ "quota": {
+ "subnet": 40,
+ "router": 40,
+ "network": 10,
+ "floatingip": 30,
+ "port": 30
+ }
+}
+ `)
+ })
+
+ i10, i30, i40 := 10, 30, 40
+ opts := UpdateOpts{Subnet: &i40, Router: &i40, Network: &i10, FloatingIP: &i30, Port: &i30}
+ qs, err := Update(serviceClient(), opts).Extract()
+ th.AssertNoErr(t, err)
+
+ th.AssertEquals(t, qs.Subnet, 40)
+ th.AssertEquals(t, qs.Router, 40)
+ th.AssertEquals(t, qs.Port, 30)
+ th.AssertEquals(t, qs.Network, 10)
+ th.AssertEquals(t, qs.FloatingIP, 30)
}
func TestReset(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+ th.Mux.HandleFunc("/v2.0/quotas", func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "DELETE")
+ th.TestHeader(t, r, "X-Auth-Token", tokenID)
+ w.WriteHeader(http.StatusNoContent)
+ })
+
+ res := Reset(serviceClient())
+ th.AssertNoErr(t, res.err)
}
diff --git a/openstack/networking/v2/extensions/quotas/results.go b/openstack/networking/v2/extensions/quotas/results.go
index d03c081..5c73e57 100755
--- a/openstack/networking/v2/extensions/quotas/results.go
+++ b/openstack/networking/v2/extensions/quotas/results.go
@@ -1 +1,62 @@
package quotas
+
+import (
+ "fmt"
+
+ "github.com/mitchellh/mapstructure"
+)
+
+type Quota struct {
+ Subnet int `json:"subnet"`
+ Router int `json:"router"`
+ Port int `json:"port"`
+ Network int `json:"network"`
+ FloatingIP int `json:"floatingip"`
+}
+
+type commonResult struct {
+ resp map[string]interface{}
+ err error
+}
+
+type GetResult commonResult
+
+func (r GetResult) Extract() (*Quota, error) {
+ if r.err != nil {
+ return nil, r.err
+ }
+
+ var res struct {
+ Quota *Quota `json:"quota"`
+ }
+
+ err := mapstructure.Decode(r.resp, &res)
+ if err != nil {
+ return nil, fmt.Errorf("Error decoding Neutron quotas: %v", err)
+ }
+
+ return res.Quota, nil
+}
+
+type UpdateResult struct {
+ commonResult
+}
+
+func (r UpdateResult) Extract() (*Quota, error) {
+ if r.err != nil {
+ return nil, r.err
+ }
+
+ var res struct {
+ Quota *Quota `json:"quota"`
+ }
+
+ err := mapstructure.Decode(r.resp, &res)
+ if err != nil {
+ return nil, fmt.Errorf("Error decoding Neutron quotas: %v", err)
+ }
+
+ return res.Quota, nil
+}
+
+type DeleteResult commonResult
diff --git a/openstack/networking/v2/extensions/quotas/urls.go b/openstack/networking/v2/extensions/quotas/urls.go
index d03c081..a933a7d 100755
--- a/openstack/networking/v2/extensions/quotas/urls.go
+++ b/openstack/networking/v2/extensions/quotas/urls.go
@@ -1 +1,9 @@
package quotas
+
+import "github.com/rackspace/gophercloud"
+
+const version = "v2.0"
+
+func rootURL(c *gophercloud.ServiceClient) string {
+ return c.ServiceURL(version, "quotas")
+}
diff --git a/openstack/networking/v2/extensions/quotas/urls_tests.go b/openstack/networking/v2/extensions/quotas/urls_tests.go
index d03c081..e75ff1b 100755
--- a/openstack/networking/v2/extensions/quotas/urls_tests.go
+++ b/openstack/networking/v2/extensions/quotas/urls_tests.go
@@ -1 +1,20 @@
package quotas
+
+import (
+ "testing"
+
+ "github.com/rackspace/gophercloud"
+ th "github.com/rackspace/gophercloud/testhelper"
+)
+
+const endpoint = "http://localhost:57909/"
+
+func endpointClient() *gophercloud.ServiceClient {
+ return &gophercloud.ServiceClient{Endpoint: endpoint}
+}
+
+func TestRootURL(t *testing.T) {
+ expected := endpoint + "v2.0/quotas"
+ actual := rootURL(endpointClient())
+ th.AssertEquals(t, expected, actual)
+}