Skip to content
This repository has been archived by the owner on Aug 1, 2023. It is now read-only.

Commit

Permalink
Merge 7894900 into e00690e
Browse files Browse the repository at this point in the history
  • Loading branch information
cparratto committed Feb 27, 2017
2 parents e00690e + 7894900 commit 804f568
Show file tree
Hide file tree
Showing 16 changed files with 956 additions and 2 deletions.
52 changes: 52 additions & 0 deletions openstack/identity/v3/domains/requests.go
@@ -0,0 +1,52 @@
package domains

import (
"errors"
"github.com/rackspace/gophercloud"

"github.com/rackspace/gophercloud/pagination"
)

// ListOpts allows you to query the List method.
type ListOpts struct {
Name string `q:"name"`
Enabled string `q:"enabled"`
}

// List enumerates the services available to a specific user.
func List(client *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
u := listURL(client)
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return pagination.Pager{Err: err}
}
u += q.String()
createPage := func(r pagination.PageResult) pagination.Page {
return DomainPage{pagination.LinkedPageBase{PageResult: r}}
}

return pagination.NewPager(client, u, createPage)
}

// PairOpts allows you to pair roles, groups, on a domain
type PairOpts struct {
ID string `json:"id"`
GroupID string `json:"group_id"`
RoleID string `json:"role_id"`
}

// Pair creates a relationship between a role, group, and domain
func Pair(client *gophercloud.ServiceClient, opts PairOpts) error {
if opts.ID == "" || opts.GroupID == "" || opts.RoleID == "" {
return errors.New("Domain, Role, and Group ids are required.")
}

reqOpts := &gophercloud.RequestOpts{
OkCodes: []int{204},
MoreHeaders: map[string]string{"Content-Type": ""},
}

var result PairResult
_, result.Err = client.Put(pairDomainGroupAndRoleURL(client, opts.ID, opts.GroupID, opts.RoleID), nil, nil, reqOpts)
return result.Err
}
113 changes: 113 additions & 0 deletions openstack/identity/v3/domains/requests_test.go
@@ -0,0 +1,113 @@
package domains

import (
"fmt"
"net/http"
"reflect"
"testing"

"github.com/rackspace/gophercloud/pagination"
"github.com/rackspace/gophercloud/testhelper"
"github.com/rackspace/gophercloud/testhelper/client"
)

func TestListSinglePage(t *testing.T) {
testhelper.SetupHTTP()
defer testhelper.TeardownHTTP()

testhelper.Mux.HandleFunc("/domains", func(w http.ResponseWriter, r *http.Request) {
testhelper.TestMethod(t, r, "GET")
testhelper.TestHeader(t, r, "X-Auth-Token", client.TokenID)

w.Header().Add("Content-Type", "application/json")
fmt.Fprintf(w, `
{
"domains": [
{
"description": "Used for swift functional testing",
"enabled": true,
"id": "5a75994a383c449184053ff7270c4e91",
"links": {
"self": "http://example.com/identity/v3/domains/5a75994a383c449184053ff7270c4e91"
},
"name": "swift_test"
},
{
"description": "Owns users and tenants (i.e. projects) available on Identity API v2.",
"enabled": true,
"id": "default",
"links": {
"self": "http://example.com/identity/v3/domains/default"
},
"name": "Default"
}
],
"links": {
"next": null,
"previous": null,
"self": "http://example.com/identity/v3/domains"
}
}
`)
})

count := 0
err := List(client.ServiceClient(), ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
count++
actual, err := ExtractDomains(page)
if err != nil {
return false, err
}

expected := []Domain{
Domain{
Description: "Used for swift functional testing",
ID: "5a75994a383c449184053ff7270c4e91",
Name: "swift_test",
Enabled: true,
Links: Link{Self: "http://example.com/identity/v3/domains/5a75994a383c449184053ff7270c4e91"},
},
Domain{
Description: "Owns users and tenants (i.e. projects) available on Identity API v2.",
ID: "default",
Name: "Default",
Enabled: true,
Links: Link{Self: "http://example.com/identity/v3/domains/default"},
},
}

if !reflect.DeepEqual(expected, actual) {
t.Errorf("Expected %#v, got %#v", expected, actual)
}

return true, nil
})
if err != nil {
t.Errorf("Unexpected error while paging: %v", err)
}
if count != 1 {
t.Errorf("Expected 1 page, got %d", count)
}
}

func TestPairDomainGroupAndRole(t *testing.T) {
testhelper.SetupHTTP()
defer testhelper.TeardownHTTP()

testhelper.Mux.HandleFunc("/domains/5a75994a383c449184053ff7270c4e91/groups/5a75994a383c449184053ff7270c4e92/roles/5a75994a383c449184053ff7270c4e93", func(w http.ResponseWriter, r *http.Request) {
testhelper.TestMethod(t, r, "PUT")
testhelper.TestHeader(t, r, "X-Auth-Token", client.TokenID)
w.WriteHeader(http.StatusNoContent)
})

pair := PairOpts{
ID: "5a75994a383c449184053ff7270c4e91",
GroupID: "5a75994a383c449184053ff7270c4e92",
RoleID: "5a75994a383c449184053ff7270c4e93",
}

err := Pair(client.ServiceClient(), pair)
if err != nil {
t.Fatalf("Unexpected error from Pair: %v", err)
}
}
55 changes: 55 additions & 0 deletions openstack/identity/v3/domains/results.go
@@ -0,0 +1,55 @@
package domains

import (
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"

"github.com/mitchellh/mapstructure"
)

type commonResult struct {
gophercloud.Result
}

// Link the object to hold a project link.
type Link struct {
Self string `json:"self,omitempty"`
}

// Domain is main struct for holding domain attributes.
type Domain struct {
Description string `json:"description,omitempty"`
Enabled bool `json:"enabled"`
ID string `json:"id"`
Name string `json:"name"`
Links Link `json:"links"`
}

// PairResult the object to error for failed pairs.
type PairResult struct {
commonResult
}

// DomainPage is a single page of Domain results.
type DomainPage struct {
pagination.LinkedPageBase
}

// IsEmpty returns true if the page contains no results.
func (p DomainPage) IsEmpty() (bool, error) {
domains, err := ExtractDomains(p)
if err != nil {
return true, err
}
return len(domains) == 0, nil
}

// ExtractDomains extracts a slice of Domains from a Collection acquired from List.
func ExtractDomains(page pagination.Page) ([]Domain, error) {
var response struct {
Domains []Domain `mapstructure:"domains"`
}

err := mapstructure.Decode(page.(DomainPage).Body, &response)
return response.Domains, err
}
11 changes: 11 additions & 0 deletions openstack/identity/v3/domains/urls.go
@@ -0,0 +1,11 @@
package domains

import "github.com/rackspace/gophercloud"

func listURL(client *gophercloud.ServiceClient) string {
return client.ServiceURL("domains")
}

func pairDomainGroupAndRoleURL(client *gophercloud.ServiceClient, dID, gID, rID string) string {
return client.ServiceURL("domains/" + dID + "/groups/" + gID + "/roles/" + rID)
}
28 changes: 28 additions & 0 deletions openstack/identity/v3/groups/requests.go
@@ -0,0 +1,28 @@
package groups

import (
"github.com/rackspace/gophercloud"

"github.com/rackspace/gophercloud/pagination"
)

// ListOpts allows you to query the List method.
type ListOpts struct {
Name string `q:"name"`
DomainID string `q:"domain_id"`
}

// List enumerates the services available to a specific user.
func List(client *gophercloud.ServiceClient, opts ListOpts) pagination.Pager {
u := listURL(client)
q, err := gophercloud.BuildQueryString(opts)
if err != nil {
return pagination.Pager{Err: err}
}
u += q.String()
createPage := func(r pagination.PageResult) pagination.Page {
return GroupPage{pagination.LinkedPageBase{PageResult: r}}
}

return pagination.NewPager(client, u, createPage)
}
74 changes: 74 additions & 0 deletions openstack/identity/v3/groups/requests_test.go
@@ -0,0 +1,74 @@
package groups

import (
"fmt"
"net/http"
"reflect"
"testing"

"github.com/rackspace/gophercloud/pagination"
"github.com/rackspace/gophercloud/testhelper"
"github.com/rackspace/gophercloud/testhelper/client"
)

func TestListSinglePage(t *testing.T) {
testhelper.SetupHTTP()
defer testhelper.TeardownHTTP()

testhelper.Mux.HandleFunc("/groups", func(w http.ResponseWriter, r *http.Request) {
testhelper.TestMethod(t, r, "GET")
testhelper.TestHeader(t, r, "X-Auth-Token", client.TokenID)

w.Header().Add("Content-Type", "application/json")
fmt.Fprintf(w, `
{
"links": {
"self": "http://example.com/identity/v3/groups",
"previous": null,
"next": null
},
"groups": [
{
"description": "non-admin group",
"id": "96372bbb152f475aa37e9a76a25a029c",
"links": {
"self": "http://example.com/identity/v3/groups/96372bbb152f475aa37e9a76a25a029c"
},
"name": "nonadmins",
"domain_id": "default"
}
]
}
`)
})

count := 0
err := List(client.ServiceClient(), ListOpts{}).EachPage(func(page pagination.Page) (bool, error) {
count++
actual, err := ExtractGroups(page)
if err != nil {
return false, err
}

expected := []Group{
Group{
Description: "non-admin group",
Name: "nonadmins",
ID: "96372bbb152f475aa37e9a76a25a029c",
Links: Link{Self: "http://example.com/identity/v3/groups/96372bbb152f475aa37e9a76a25a029c"},
},
}

if !reflect.DeepEqual(expected, actual) {
t.Errorf("Expected %#v, got %#v", expected, actual)
}

return true, nil
})
if err != nil {
t.Errorf("Unexpected error while paging: %v", err)
}
if count != 1 {
t.Errorf("Expected 1 page, got %d", count)
}
}
49 changes: 49 additions & 0 deletions openstack/identity/v3/groups/results.go
@@ -0,0 +1,49 @@
package groups

import (
"github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/pagination"

"github.com/mitchellh/mapstructure"
)

type commonResult struct {
gophercloud.Result
}

// Link the object to hold a project link.
type Link struct {
Self string `json:"self,omitempty"`
}

// Group is main struct for holding group attributes.
type Group struct {
Description string `json:"description"`
ID string `json:"id"`
Name string `json:"name"`
Links Link `json:"links"`
}

// GroupPage is a single page of Group results.
type GroupPage struct {
pagination.LinkedPageBase
}

// IsEmpty returns true if the page contains no results.
func (p GroupPage) IsEmpty() (bool, error) {
groups, err := ExtractGroups(p)
if err != nil {
return true, err
}
return len(groups) == 0, nil
}

// ExtractGroups extracts a slice of Groups from a Collection acquired from List.
func ExtractGroups(page pagination.Page) ([]Group, error) {
var response struct {
Groups []Group `mapstructure:"groups"`
}

err := mapstructure.Decode(page.(GroupPage).Body, &response)
return response.Groups, err
}
7 changes: 7 additions & 0 deletions openstack/identity/v3/groups/urls.go
@@ -0,0 +1,7 @@
package groups

import "github.com/rackspace/gophercloud"

func listURL(client *gophercloud.ServiceClient) string {
return client.ServiceURL("groups")
}

0 comments on commit 804f568

Please sign in to comment.