Moving calls to client helper while I'm at it
diff --git a/_site/openstack/identity/v2/tenants/doc.go b/_site/openstack/identity/v2/tenants/doc.go
new file mode 100644
index 0000000..473a302
--- /dev/null
+++ b/_site/openstack/identity/v2/tenants/doc.go
@@ -0,0 +1,7 @@
+/*
+Package tenants contains API calls that query for information about tenants on an OpenStack deployment.
+
+See: http://developer.openstack.org/api-ref-identity-v2.html#identity-auth-v2
+And: http://developer.openstack.org/api-ref-identity-v2.html#admin-tenants
+*/
+package tenants
diff --git a/_site/openstack/identity/v2/tenants/fixtures.go b/_site/openstack/identity/v2/tenants/fixtures.go
new file mode 100644
index 0000000..7f044ac
--- /dev/null
+++ b/_site/openstack/identity/v2/tenants/fixtures.go
@@ -0,0 +1,65 @@
+// +build fixtures
+
+package tenants
+
+import (
+ "fmt"
+ "net/http"
+ "testing"
+
+ th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/rackspace/gophercloud/testhelper/client"
+)
+
+// ListOutput provides a single page of Tenant results.
+const ListOutput = `
+{
+ "tenants": [
+ {
+ "id": "1234",
+ "name": "Red Team",
+ "description": "The team that is red",
+ "enabled": true
+ },
+ {
+ "id": "9876",
+ "name": "Blue Team",
+ "description": "The team that is blue",
+ "enabled": false
+ }
+ ]
+}
+`
+
+// RedTeam is a Tenant fixture.
+var RedTeam = Tenant{
+ ID: "1234",
+ Name: "Red Team",
+ Description: "The team that is red",
+ Enabled: true,
+}
+
+// BlueTeam is a Tenant fixture.
+var BlueTeam = Tenant{
+ ID: "9876",
+ Name: "Blue Team",
+ Description: "The team that is blue",
+ Enabled: false,
+}
+
+// ExpectedTenantSlice is the slice of tenants expected to be returned from ListOutput.
+var ExpectedTenantSlice = []Tenant{RedTeam, BlueTeam}
+
+// HandleListTenantsSuccessfully creates an HTTP handler at `/tenants` on the test handler mux that
+// responds with a list of two tenants.
+func HandleListTenantsSuccessfully(t *testing.T) {
+ th.Mux.HandleFunc("/tenants", func(w http.ResponseWriter, r *http.Request) {
+ th.TestMethod(t, r, "GET")
+ th.TestHeader(t, r, "Accept", "application/json")
+ th.TestHeader(t, r, "X-Auth-Token", client.TokenID)
+
+ w.Header().Set("Content-Type", "application/json")
+ w.WriteHeader(http.StatusOK)
+ fmt.Fprintf(w, ListOutput)
+ })
+}
diff --git a/_site/openstack/identity/v2/tenants/requests.go b/_site/openstack/identity/v2/tenants/requests.go
new file mode 100644
index 0000000..5ffeaa7
--- /dev/null
+++ b/_site/openstack/identity/v2/tenants/requests.go
@@ -0,0 +1,33 @@
+package tenants
+
+import (
+ "github.com/rackspace/gophercloud"
+ "github.com/rackspace/gophercloud/pagination"
+)
+
+// ListOpts filters the Tenants that are returned by the List call.
+type ListOpts struct {
+ // Marker is the ID of the last Tenant on the previous page.
+ Marker string `q:"marker"`
+
+ // Limit specifies the page size.
+ Limit int `q:"limit"`
+}
+
+// List enumerates the Tenants to which the current token has access.
+func List(client *gophercloud.ServiceClient, opts *ListOpts) pagination.Pager {
+ createPage := func(r pagination.LastHTTPResponse) pagination.Page {
+ return TenantPage{pagination.LinkedPageBase{LastHTTPResponse: r}}
+ }
+
+ url := listURL(client)
+ if opts != nil {
+ q, err := gophercloud.BuildQueryString(opts)
+ if err != nil {
+ return pagination.Pager{Err: err}
+ }
+ url += q.String()
+ }
+
+ return pagination.NewPager(client, url, createPage)
+}
diff --git a/_site/openstack/identity/v2/tenants/requests_test.go b/_site/openstack/identity/v2/tenants/requests_test.go
new file mode 100644
index 0000000..e8f172d
--- /dev/null
+++ b/_site/openstack/identity/v2/tenants/requests_test.go
@@ -0,0 +1,29 @@
+package tenants
+
+import (
+ "testing"
+
+ "github.com/rackspace/gophercloud/pagination"
+ th "github.com/rackspace/gophercloud/testhelper"
+ "github.com/rackspace/gophercloud/testhelper/client"
+)
+
+func TestListTenants(t *testing.T) {
+ th.SetupHTTP()
+ defer th.TeardownHTTP()
+ HandleListTenantsSuccessfully(t)
+
+ count := 0
+ err := List(client.ServiceClient(), nil).EachPage(func(page pagination.Page) (bool, error) {
+ count++
+
+ actual, err := ExtractTenants(page)
+ th.AssertNoErr(t, err)
+
+ th.CheckDeepEquals(t, ExpectedTenantSlice, actual)
+
+ return true, nil
+ })
+ th.AssertNoErr(t, err)
+ th.CheckEquals(t, count, 1)
+}
diff --git a/_site/openstack/identity/v2/tenants/results.go b/_site/openstack/identity/v2/tenants/results.go
new file mode 100644
index 0000000..c1220c3
--- /dev/null
+++ b/_site/openstack/identity/v2/tenants/results.go
@@ -0,0 +1,62 @@
+package tenants
+
+import (
+ "github.com/mitchellh/mapstructure"
+ "github.com/rackspace/gophercloud"
+ "github.com/rackspace/gophercloud/pagination"
+)
+
+// Tenant is a grouping of users in the identity service.
+type Tenant struct {
+ // ID is a unique identifier for this tenant.
+ ID string `mapstructure:"id"`
+
+ // Name is a friendlier user-facing name for this tenant.
+ Name string `mapstructure:"name"`
+
+ // Description is a human-readable explanation of this Tenant's purpose.
+ Description string `mapstructure:"description"`
+
+ // Enabled indicates whether or not a tenant is active.
+ Enabled bool `mapstructure:"enabled"`
+}
+
+// TenantPage is a single page of Tenant results.
+type TenantPage struct {
+ pagination.LinkedPageBase
+}
+
+// IsEmpty determines whether or not a page of Tenants contains any results.
+func (page TenantPage) IsEmpty() (bool, error) {
+ tenants, err := ExtractTenants(page)
+ if err != nil {
+ return false, err
+ }
+ return len(tenants) == 0, nil
+}
+
+// NextPageURL extracts the "next" link from the tenants_links section of the result.
+func (page TenantPage) NextPageURL() (string, error) {
+ type resp struct {
+ Links []gophercloud.Link `mapstructure:"tenants_links"`
+ }
+
+ var r resp
+ err := mapstructure.Decode(page.Body, &r)
+ if err != nil {
+ return "", err
+ }
+
+ return gophercloud.ExtractNextURL(r.Links)
+}
+
+// ExtractTenants returns a slice of Tenants contained in a single page of results.
+func ExtractTenants(page pagination.Page) ([]Tenant, error) {
+ casted := page.(TenantPage).Body
+ var response struct {
+ Tenants []Tenant `mapstructure:"tenants"`
+ }
+
+ err := mapstructure.Decode(casted, &response)
+ return response.Tenants, err
+}
diff --git a/_site/openstack/identity/v2/tenants/urls.go b/_site/openstack/identity/v2/tenants/urls.go
new file mode 100644
index 0000000..1dd6ce0
--- /dev/null
+++ b/_site/openstack/identity/v2/tenants/urls.go
@@ -0,0 +1,7 @@
+package tenants
+
+import "github.com/rackspace/gophercloud"
+
+func listURL(client *gophercloud.ServiceClient) string {
+ return client.ServiceURL("tenants")
+}