Use version negotiation in openstack.NewClient().
diff --git a/openstack/client.go b/openstack/client.go
index f1e8258..6e0de06 100644
--- a/openstack/client.go
+++ b/openstack/client.go
@@ -1,18 +1,60 @@
package openstack
import (
+ "errors"
+
"github.com/rackspace/gophercloud"
identity3 "github.com/rackspace/gophercloud/openstack/identity/v3"
+ "github.com/rackspace/gophercloud/openstack/utils"
)
// Client provides access to service clients for this OpenStack cloud.
-type Client gophercloud.ProviderClient
+type Client struct {
+ gophercloud.ProviderClient
+}
+
+const (
+ v20 = "v2.0"
+ v30 = "v3.0"
+)
// 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
// the most recent identity service available to proceed.
func NewClient(authOptions gophercloud.AuthOptions) (*Client, error) {
- return nil, nil
+ versions := []*utils.Version{
+ &utils.Version{ID: v20, Priority: 20},
+ &utils.Version{ID: v30, Priority: 30},
+ }
+
+ chosen, endpoint, err := utils.ChooseVersion(authOptions.IdentityEndpoint, versions)
+ if err != nil {
+ return nil, err
+ }
+
+ client := Client{
+ ProviderClient: gophercloud.ProviderClient{
+ IdentityEndpoint: endpoint,
+ Options: authOptions,
+ },
+ }
+
+ switch chosen.ID {
+ case v20:
+ case v30:
+ identityClient := identity3.NewClient(&client.ProviderClient)
+ token, err := identityClient.Authenticate(authOptions)
+ if err != nil {
+ return nil, err
+ }
+
+ client.ProviderClient.TokenID = token.ID
+ default:
+ // The switch must be out of sync with "versions".
+ return nil, errors.New("Wat")
+ }
+
+ return &client, nil
}
// IdentityV3 explicitly accesses the v3 identity service.
diff --git a/openstack/client_test.go b/openstack/client_test.go
index 8068554..5476271 100644
--- a/openstack/client_test.go
+++ b/openstack/client_test.go
@@ -1,12 +1,64 @@
package openstack
import (
+ "fmt"
+ "net/http"
"testing"
+ "github.com/rackspace/gophercloud"
"github.com/rackspace/gophercloud/testhelper"
)
-func TestAuthenticate(t *testing.T) {
+func TestNewClientV3(t *testing.T) {
testhelper.SetupHTTP()
defer testhelper.TeardownHTTP()
+
+ const ID = "0123456789"
+
+ testhelper.Mux.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
+ fmt.Fprintf(w, `
+ {
+ "versions": {
+ "values": [
+ {
+ "status": "stable",
+ "id": "v3.0",
+ "links": [
+ { "href": "%s", "rel": "self" }
+ ]
+ },
+ {
+ "status": "stable",
+ "id": "v2.0",
+ "links": [
+ { "href": "%s", "rel": "self" }
+ ]
+ }
+ ]
+ }
+ }
+ `, testhelper.Endpoint()+"v3/", testhelper.Endpoint()+"v2.0/")
+ })
+
+ testhelper.Mux.HandleFunc("/v3/auth/tokens", func(w http.ResponseWriter, r *http.Request) {
+ w.Header().Add("X-Subject-Token", ID)
+
+ w.WriteHeader(http.StatusCreated)
+ fmt.Fprintf(w, `{ "token": { "expires_at": "2013-02-02T18:30:59.000000Z" } }`)
+ })
+
+ options := gophercloud.AuthOptions{
+ UserID: "me",
+ Password: "secret",
+ IdentityEndpoint: testhelper.Endpoint(),
+ }
+ client, err := NewClient(options)
+
+ if err != nil {
+ t.Fatalf("Unexpected error from NewClient: %s", err)
+ }
+
+ if client.TokenID != ID {
+ t.Errorf("Expected token ID to be [%s], but was [%s]", ID, client.TokenID)
+ }
}
diff --git a/openstack/identity/v3/client.go b/openstack/identity/v3/client.go
index 5f25ee6..984d03e 100644
--- a/openstack/identity/v3/client.go
+++ b/openstack/identity/v3/client.go
@@ -24,7 +24,7 @@
return &Client{
ServiceClient: gophercloud.ServiceClient{
ProviderClient: *provider,
- Endpoint: provider.IdentityEndpoint + "v3/",
+ Endpoint: provider.IdentityEndpoint,
},
}
}
diff --git a/openstack/identity/v3/client_test.go b/openstack/identity/v3/client_test.go
index 0744e7d..c9cf3c2 100644
--- a/openstack/identity/v3/client_test.go
+++ b/openstack/identity/v3/client_test.go
@@ -16,7 +16,7 @@
defer testhelper.TeardownHTTP()
provider := &gophercloud.ProviderClient{
- IdentityEndpoint: testhelper.Endpoint(),
+ IdentityEndpoint: testhelper.Endpoint() + "v3/",
}
client := NewClient(provider)
@@ -39,7 +39,7 @@
})
provider := &gophercloud.ProviderClient{
- IdentityEndpoint: testhelper.Endpoint(),
+ IdentityEndpoint: testhelper.Endpoint() + "v3/",
}
client := NewClient(provider)