OpenStack Client: Handle New Identity Endpoints

This commit modifies the openstack client to handle new identity
endpoints in the following ways:

1. Identity endpoints published with a valid URL path
(http://example.com/identity) are now parsed correctly.

If the endpoint has a version suffix (http://example.com/identity/v3),
the client will use /identity as the base and /identity/v3 as the
endpoint.

If the endpoint does not have a version suffix, both the base and the
endpoint will be set to /identity and further version discovery will
be done.

2. Version discovery can now handle version IDs other than v2.0 and v3.
If the Identity Service is publishing an ID of v3.8, Gophercloud will
recognize it as a valid result.

Related-PROD: PROD-24705 (PROD:24705)

Change-Id: I994e159d2bfd4f594eb16308a5a5ca76339206e5
diff --git a/openstack/utils/choose_version.go b/openstack/utils/choose_version.go
index e1e26fb..649c842 100644
--- a/openstack/utils/choose_version.go
+++ b/openstack/utils/choose_version.go
@@ -68,11 +68,6 @@
 		return nil, "", err
 	}
 
-	byID := make(map[string]*Version)
-	for _, version := range recognized {
-		byID[version.ID] = version
-	}
-
 	var highest *Version
 	var endpoint string
 
@@ -84,20 +79,22 @@
 			}
 		}
 
-		if matching, ok := byID[value.ID]; ok {
-			// Prefer a version that exactly matches the provided endpoint.
-			if href == identityEndpoint {
-				if href == "" {
-					return nil, "", fmt.Errorf("Endpoint missing in version %s response from %s", value.ID, client.IdentityBase)
+		for _, version := range recognized {
+			if strings.Contains(value.ID, version.ID) {
+				// Prefer a version that exactly matches the provided endpoint.
+				if href == identityEndpoint {
+					if href == "" {
+						return nil, "", fmt.Errorf("Endpoint missing in version %s response from %s", value.ID, client.IdentityBase)
+					}
+					return version, href, nil
 				}
-				return matching, href, nil
-			}
 
-			// Otherwise, find the highest-priority version with a whitelisted status.
-			if goodStatus[strings.ToLower(value.Status)] {
-				if highest == nil || matching.Priority > highest.Priority {
-					highest = matching
-					endpoint = href
+				// Otherwise, find the highest-priority version with a whitelisted status.
+				if goodStatus[strings.ToLower(value.Status)] {
+					if highest == nil || version.Priority > highest.Priority {
+						highest = version
+						endpoint = href
+					}
 				}
 			}
 		}