Clarify ServiceClient and ProviderClient.
diff --git a/openstack/client.go b/openstack/client.go
index b4c6589..f1e8258 100644
--- a/openstack/client.go
+++ b/openstack/client.go
@@ -6,7 +6,7 @@
)
// Client provides access to service clients for this OpenStack cloud.
-type Client gophercloud.ServiceClient
+type Client gophercloud.ProviderClient
// NewClient authenticates to an OpenStack cloud with the provided credentials.
// It first queries the root identity endpoint to determine which versions of the identity service are supported, then chooses
diff --git a/openstack/client_test.go b/openstack/client_test.go
new file mode 100644
index 0000000..8068554
--- /dev/null
+++ b/openstack/client_test.go
@@ -0,0 +1,12 @@
+package openstack
+
+import (
+ "testing"
+
+ "github.com/rackspace/gophercloud/testhelper"
+)
+
+func TestAuthenticate(t *testing.T) {
+ testhelper.SetupHTTP()
+ defer testhelper.TeardownHTTP()
+}
diff --git a/openstack/identity/v3/client.go b/openstack/identity/v3/client.go
index 0647471..8c6e3e4 100644
--- a/openstack/identity/v3/client.go
+++ b/openstack/identity/v3/client.go
@@ -1,29 +1,30 @@
package v3
import (
+ "time"
+
"github.com/rackspace/gophercloud"
- "github.com/rackspace/gophercloud/openstack/identity/v3/tokens"
)
-// Client abstracts the connection information necessary to make API calls to Identity v3
-// resources.
+// Client abstracts the connection information necessary to make API calls to Identity v3 resources.
+// It exists mainly to adhere to the IdentityService interface.
type Client gophercloud.ServiceClient
-var (
- nilClient = Client{}
-)
+// Token models a token acquired from the tokens/ API resource.
+type Token struct {
+ ID string
+ ExpiresAt time.Time
+}
-// NewClient attempts to authenticate to the v3 identity endpoint. Returns a populated
-// IdentityV3Client on success or an error on failure.
-func NewClient(authOptions gophercloud.AuthOptions) (*Client, error) {
- client := Client{Options: authOptions}
-
- result, err := tokens.Create(&client, nil)
- if err != nil {
- return nil, err
+// NewClient creates a new client associated with the v3 identity service of a provider.
+func NewClient(provider *gophercloud.ProviderClient) *Client {
+ return &Client{
+ ProviderClient: *provider,
+ Endpoint: provider.IdentityEndpoint + "v3/",
}
+}
- // Assign the token and return.
- client.TokenID = result.TokenID()
- return &client, nil
+// Authenticate provides the supplied credentials to an identity v3 endpoint and attempts to acquire a token.
+func (c *Client) Authenticate(authOptions gophercloud.AuthOptions) (*Token, error) {
+ return nil, nil
}
diff --git a/openstack/identity/v3/client_test.go b/openstack/identity/v3/client_test.go
new file mode 100644
index 0000000..7c57e68
--- /dev/null
+++ b/openstack/identity/v3/client_test.go
@@ -0,0 +1,32 @@
+package v3
+
+import (
+ "fmt"
+ "net/http"
+ "testing"
+
+ "github.com/rackspace/gophercloud"
+ "github.com/rackspace/gophercloud/testhelper"
+)
+
+func TestAuthentication(t *testing.T) {
+ testhelper.SetupHTTP()
+ defer testhelper.TeardownHTTP()
+
+ testhelper.Mux.HandleFunc("/v3/auth/tokens", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Add("X-Subject-Token", "aaaa1111")
+
+ w.WriteHeader(http.StatusCreated)
+ fmt.Fprintf(w, `{ "token": { "expires_at": "2013-02-02T18:30:59.000000Z" } }`)
+ })
+
+ provider := &gophercloud.ProviderClient{
+ IdentityEndpoint: testhelper.Endpoint(),
+ }
+ client := NewClient(provider)
+
+ expected := testhelper.Endpoint() + "v3/"
+ if client.Endpoint != expected {
+ t.Errorf("Expected endpoint to be %s, but was %s", expected, client.Endpoint)
+ }
+}
diff --git a/openstack/identity/v3/tokens/requests.go b/openstack/identity/v3/tokens/requests.go
index 115737e..ab84d81 100644
--- a/openstack/identity/v3/tokens/requests.go
+++ b/openstack/identity/v3/tokens/requests.go
@@ -13,14 +13,14 @@
DomainName string
}
-func subjectTokenHeaders(c *gophercloud.ProviderClient, subjectToken string) map[string]string {
+func subjectTokenHeaders(c *gophercloud.ServiceClient, subjectToken string) map[string]string {
h := c.AuthenticatedHeaders()
h["X-Subject-Token"] = subjectToken
return h
}
// Create authenticates and either generates a new token, or changes the Scope of an existing token.
-func Create(c *gophercloud.ProviderClient, scope *Scope) (gophercloud.AuthResults, error) {
+func Create(c *gophercloud.ServiceClient, scope *Scope) (gophercloud.AuthResults, error) {
type domainReq struct {
ID *string `json:"id,omitempty"`
Name *string `json:"name,omitempty"`
@@ -251,7 +251,7 @@
}
// Info validates and retrieves information about another token.
-func Info(c *gophercloud.ProviderClient, token string) (*TokenCreateResult, error) {
+func Info(c *gophercloud.ServiceClient, token string) (*TokenCreateResult, error) {
var result TokenCreateResult
response, err := perigee.Request("GET", getTokenURL(c), perigee.Options{
@@ -271,7 +271,7 @@
}
// Validate determines if a specified token is valid or not.
-func Validate(c *gophercloud.ProviderClient, token string) (bool, error) {
+func Validate(c *gophercloud.ServiceClient, token string) (bool, error) {
response, err := perigee.Request("HEAD", getTokenURL(c), perigee.Options{
MoreHeaders: subjectTokenHeaders(c, token),
OkCodes: []int{204, 404},
@@ -284,7 +284,7 @@
}
// Revoke immediately makes specified token invalid.
-func Revoke(c *gophercloud.ProviderClient, token string) error {
+func Revoke(c *gophercloud.ServiceClient, token string) error {
_, err := perigee.Request("DELETE", getTokenURL(c), perigee.Options{
MoreHeaders: subjectTokenHeaders(c, token),
OkCodes: []int{204},
diff --git a/openstack/identity/v3/tokens/requests_test.go b/openstack/identity/v3/tokens/requests_test.go
index e1b845f..cfb4ff1 100644
--- a/openstack/identity/v3/tokens/requests_test.go
+++ b/openstack/identity/v3/tokens/requests_test.go
@@ -15,10 +15,13 @@
testhelper.SetupHTTP()
defer testhelper.TeardownHTTP()
- client := gophercloud.ProviderClient{
+ client := gophercloud.ServiceClient{
+ ProviderClient: gophercloud.ProviderClient{
+ IdentityEndpoint: testhelper.Endpoint(),
+ Options: options,
+ TokenID: "12345abcdef",
+ },
Endpoint: testhelper.Endpoint(),
- Options: options,
- TokenID: "12345abcdef",
}
testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) {
@@ -41,9 +44,11 @@
testhelper.SetupHTTP()
defer testhelper.TeardownHTTP()
- client := gophercloud.ProviderClient{
+ client := gophercloud.ServiceClient{
+ ProviderClient: gophercloud.ProviderClient{
+ Options: options,
+ },
Endpoint: testhelper.Endpoint(),
- Options: options,
}
if includeToken {
client.TokenID = "abcdef123456"
@@ -240,9 +245,11 @@
testhelper.SetupHTTP()
defer testhelper.TeardownHTTP()
- client := gophercloud.ProviderClient{
+ client := gophercloud.ServiceClient{
+ ProviderClient: gophercloud.ProviderClient{
+ Options: gophercloud.AuthOptions{UserID: "me", Password: "shhh"},
+ },
Endpoint: testhelper.Endpoint(),
- Options: gophercloud.AuthOptions{UserID: "me", Password: "shhh"},
}
testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) {
@@ -391,9 +398,11 @@
testhelper.SetupHTTP()
defer testhelper.TeardownHTTP()
- client := gophercloud.ProviderClient{
+ client := gophercloud.ServiceClient{
+ ProviderClient: gophercloud.ProviderClient{
+ TokenID: "12345abcdef",
+ },
Endpoint: testhelper.Endpoint(),
- TokenID: "12345abcdef",
}
testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) {
@@ -425,10 +434,12 @@
}
}
-func prepareAuthTokenHandler(t *testing.T, expectedMethod string, status int) gophercloud.ProviderClient {
- client := gophercloud.ProviderClient{
+func prepareAuthTokenHandler(t *testing.T, expectedMethod string, status int) gophercloud.ServiceClient {
+ client := gophercloud.ServiceClient{
+ ProviderClient: gophercloud.ProviderClient{
+ TokenID: "12345abcdef",
+ },
Endpoint: testhelper.Endpoint(),
- TokenID: "12345abcdef",
}
testhelper.Mux.HandleFunc("/auth/tokens", func(w http.ResponseWriter, r *http.Request) {
diff --git a/openstack/identity/v3/tokens/urls.go b/openstack/identity/v3/tokens/urls.go
index ac5a19f..5b47c02 100644
--- a/openstack/identity/v3/tokens/urls.go
+++ b/openstack/identity/v3/tokens/urls.go
@@ -2,6 +2,6 @@
import "github.com/rackspace/gophercloud"
-func getTokenURL(c *gophercloud.ProviderClient) string {
+func getTokenURL(c *gophercloud.ServiceClient) string {
return c.ServiceURL("auth", "tokens")
}
diff --git a/openstack/identity/v3/tokens/urls_test.go b/openstack/identity/v3/tokens/urls_test.go
index 5007b3d..5ff8bc6 100644
--- a/openstack/identity/v3/tokens/urls_test.go
+++ b/openstack/identity/v3/tokens/urls_test.go
@@ -11,7 +11,7 @@
testhelper.SetupHTTP()
defer testhelper.TeardownHTTP()
- client := gophercloud.ProviderClient{Endpoint: testhelper.Endpoint()}
+ client := gophercloud.ServiceClient{Endpoint: testhelper.Endpoint()}
expected := testhelper.Endpoint() + "auth/tokens"
actual := getTokenURL(&client)