Shuffle around authentication methods.
I'd like to be able to explicitly authenticated with a certain version.
diff --git a/openstack/client.go b/openstack/client.go
index 7e3850e..98092c8 100644
--- a/openstack/client.go
+++ b/openstack/client.go
@@ -18,46 +18,84 @@
v30 = "v3.0"
)
-// NewClient authenticates to an OpenStack cloud with the provided credentials.
+// AuthenticatedClient logs in to an OpenStack cloud found at the identity endpoint specified by authOptions, acquires a token, and
+// returns a Client instance that's ready to operate.
// 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) {
+func AuthenticatedClient(authOptions gophercloud.AuthOptions) (*Client, error) {
+ client := NewClient(authOptions)
+ err := client.Authenticate()
+ if err != nil {
+ return nil, err
+ }
+ return client, nil
+}
+
+// NewClient prepares an unauthenticated Client instance.
+// Most users will probably prefer using the AuthenticatedClient function instead.
+// This is useful if you wish to explicitly control the version of the identity service that's used for authentication explicitly,
+// for example.
+func NewClient(authOptions gophercloud.AuthOptions) *Client {
+ return &Client{
+ ProviderClient: gophercloud.ProviderClient{
+ Options: authOptions,
+ },
+ }
+}
+
+// Authenticate or re-authenticate against the most recent identity service supported at the provided endpoint.
+func (client *Client) Authenticate() error {
versions := []*utils.Version{
&utils.Version{ID: v20, Priority: 20},
&utils.Version{ID: v30, Priority: 30},
}
- chosen, endpoint, err := utils.ChooseVersion(authOptions.IdentityEndpoint, versions)
+ chosen, endpoint, err := utils.ChooseVersion(client.ProviderClient.Options.IdentityEndpoint, versions)
if err != nil {
- return nil, err
- }
-
- client := Client{
- ProviderClient: gophercloud.ProviderClient{
- IdentityEndpoint: endpoint,
- Options: authOptions,
- },
+ return err
}
switch chosen.ID {
case v20:
+ return client.authenticateV2(endpoint)
case v30:
- identityClient := identity3.NewClient(&client.ProviderClient)
- token, err := identityClient.Authenticate(authOptions)
- if err != nil {
- return nil, err
- }
-
- client.ProviderClient.TokenID = token.ID
+ return client.authenticateV3(endpoint)
default:
- // The switch must be out of sync with "versions".
- return nil, errors.New("Wat")
+ // The switch statement must be out of date from the versions list.
+ return errors.New("Wat")
+ }
+}
+
+// AuthenticateV2 acquires a token explicitly from the v2.0 identity API.
+func (client *Client) AuthenticateV2() error {
+ endpoint := client.ProviderClient.Options.IdentityEndpoint + "/v2.0"
+ return client.authenticateV2(endpoint)
+}
+
+func (client *Client) authenticateV2(endpoint string) error {
+ return errors.New("Not implemented yet.")
+}
+
+// AuthenticateV3 acquires a token explicitly from the v3.0 identity API.
+func (client *Client) AuthenticateV3() error {
+ endpoint := client.ProviderClient.Options.IdentityEndpoint + "/v3"
+ return client.authenticateV3(endpoint)
+}
+
+func (client *Client) authenticateV3(endpoint string) error {
+ identityClient := identity3.NewClient(&client.ProviderClient, endpoint)
+ token, err := identityClient.GetToken(client.ProviderClient.Options)
+ if err != nil {
+ return err
}
- return &client, nil
+ client.ProviderClient.TokenID = token.ID
+
+ return nil
}
// NewIdentityV3 explicitly accesses the v3 identity service.
func (client *Client) NewIdentityV3() (*identity3.Client, error) {
- return identity3.NewClient(&client.ProviderClient), nil
+ endpoint := client.ProviderClient.Options.IdentityEndpoint + "/v3"
+ return identity3.NewClient(&client.ProviderClient, endpoint), nil
}