You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2017/12/08 12:56:23 UTC

[8/8] jclouds git commit: fix for keystone v3 liveTests (#1)

fix for keystone v3 liveTests (#1)

- some minor renaming for even better clarity

Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/17c11ec9
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/17c11ec9
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/17c11ec9

Branch: refs/heads/keystonev3
Commit: 17c11ec9d7c24bda5845dac77f5b284e7364148f
Parents: 7def816
Author: Andrea Turli <an...@users.noreply.github.com>
Authored: Fri Dec 8 13:55:20 2017 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Fri Dec 8 13:55:20 2017 +0100

----------------------------------------------------------------------
 .../auth/config/AuthenticationModule.java       |   6 +-
 .../auth/domain/ApiAccessKeyCredentials.java    |   2 +-
 .../auth/domain/PasswordCredentials.java        |   2 +-
 .../keystone/auth/domain/TokenCredentials.java  |   2 +-
 .../keystone/catalog/ServiceEndpoint.java       |   4 +-
 .../catalog/config/KeystoneAdminURLModule.java  |   4 +-
 .../catalog/config/ServiceCatalogModule.java    |  14 +-
 ...ationIdToURIFromAccessForTypeAndVersion.java | 129 -------------------
 ...RIFromServiceEndpointsForTypeAndVersion.java | 129 +++++++++++++++++++
 ...IdToAdminURIFromAccessForTypeAndVersion.java |  44 -------
 ...RIFromServiceEndpointsForTypeAndVersion.java |  44 +++++++
 .../suppliers/RegionIdToAdminURISupplier.java   |   2 +-
 ...egionIdToURIFromAccessForTypeAndVersion.java |  46 -------
 ...RIFromServiceEndpointsForTypeAndVersion.java |  46 +++++++
 .../keystone/v3/auth/V3AuthenticationApi.java   |   6 +-
 .../openstack/keystone/v3/domain/Auth.java      |   2 +-
 .../keystone/v3/parsers/ParseToken.java         |  41 ------
 .../v3/parsers/ParseTokenFromHttpResponse.java  |  50 +++++++
 ...nIdToURIFromAccessForTypeAndVersionTest.java |  22 ++--
 ...AdminURIFromAccessForTypeAndVersionTest.java |   6 +-
 ...nIdToURIFromAccessForTypeAndVersionTest.java |   6 +-
 21 files changed, 308 insertions(+), 299 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/config/AuthenticationModule.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/config/AuthenticationModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/config/AuthenticationModule.java
index dbd9743..6731fe8 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/config/AuthenticationModule.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/config/AuthenticationModule.java
@@ -99,7 +99,7 @@ public class AuthenticationModule extends AbstractModule {
    }
 
    protected Map<String, Function<Credentials, AuthInfo>> authenticationMethods(Injector i) {
-      Builder<Function<Credentials, AuthInfo>> fns = ImmutableSet.<Function<Credentials, AuthInfo>> builder();
+      Builder<Function<Credentials, AuthInfo>> fns = ImmutableSet.builder();
       fns.add(i.getInstance(AuthenticatePasswordCredentials.class));
       fns.add(i.getInstance(AuthenticateApiAccessKeyCredentials.class));
       fns.add(i.getInstance(AuthenticateTokenCredentials.class));
@@ -121,7 +121,7 @@ public class AuthenticationModule extends AbstractModule {
    // at 11 hours for now.
    @Provides
    @Singleton
-   public final LoadingCache<Credentials, AuthInfo> provideAccessCache(Function<Credentials, AuthInfo> getAccess) {
+   public final LoadingCache<Credentials, AuthInfo> provideAuthInfoCache(Function<Credentials, AuthInfo> getAccess) {
       return CacheBuilder.newBuilder().expireAfterWrite(11, TimeUnit.HOURS).build(CacheLoader.from(getAccess));
    }
 
@@ -130,7 +130,7 @@ public class AuthenticationModule extends AbstractModule {
    // http://code.google.com/p/guava-libraries/issues/detail?id=872
    @Provides
    @Singleton
-   protected final Supplier<AuthInfo> provideAccessSupplier(final LoadingCache<Credentials, AuthInfo> cache,
+   protected final Supplier<AuthInfo> provideAuthInfoSupplier(final LoadingCache<Credentials, AuthInfo> cache,
          @Provider final Supplier<Credentials> creds) {
       return new Supplier<AuthInfo>() {
          @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/domain/ApiAccessKeyCredentials.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/domain/ApiAccessKeyCredentials.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/domain/ApiAccessKeyCredentials.java
index c2e1e47..75ccf88 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/domain/ApiAccessKeyCredentials.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/domain/ApiAccessKeyCredentials.java
@@ -29,7 +29,7 @@ public abstract class ApiAccessKeyCredentials {
    public abstract String accessKey();
    public abstract String secretKey();
 
-   public static ApiAccessKeyCredentials create(String accessKey, String secretKey, String tenantId, String tenantName) {
+   public static ApiAccessKeyCredentials create(String accessKey, String secretKey) {
       return builder().accessKey(accessKey).secretKey(secretKey).build();
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/domain/PasswordCredentials.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/domain/PasswordCredentials.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/domain/PasswordCredentials.java
index d7a039c..2e1fee9 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/domain/PasswordCredentials.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/domain/PasswordCredentials.java
@@ -30,7 +30,7 @@ public abstract class PasswordCredentials {
    public abstract String username();
    public abstract String password();
 
-   public static PasswordCredentials create(String username, String password, String tenantId, String tenantName) {
+   public static PasswordCredentials create(String username, String password) {
       return builder().username(username).password(password).build();
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/domain/TokenCredentials.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/domain/TokenCredentials.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/domain/TokenCredentials.java
index 7a4e0d3..7f5d0b2 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/domain/TokenCredentials.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/auth/domain/TokenCredentials.java
@@ -28,7 +28,7 @@ public abstract class TokenCredentials {
 
    public abstract String id();
 
-   public static TokenCredentials create(String id, String secretKey, String tenantId, String tenantName) {
+   public static TokenCredentials create(String id) {
       return builder().id(id).build();
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/ServiceEndpoint.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/ServiceEndpoint.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/ServiceEndpoint.java
index 139751e..08477c0 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/ServiceEndpoint.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/ServiceEndpoint.java
@@ -32,11 +32,11 @@ import com.google.common.base.Enums;
 @AutoValue
 public abstract class ServiceEndpoint {
 
-   public static enum Interface {
+   public enum Interface {
       PUBLIC, ADMIN, INTERNAL, UNRECOGNIZED;
 
       public static Interface fromValue(String iface) {
-         return Enums.getIfPresent(Interface.class, iface.toLowerCase()).or(UNRECOGNIZED);
+         return Enums.getIfPresent(Interface.class, iface.toUpperCase()).or(UNRECOGNIZED);
       }
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/KeystoneAdminURLModule.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/KeystoneAdminURLModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/KeystoneAdminURLModule.java
index d670973..6f357c0 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/KeystoneAdminURLModule.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/KeystoneAdminURLModule.java
@@ -24,7 +24,7 @@ import java.util.NoSuchElementException;
 import javax.inject.Singleton;
 
 import org.jclouds.location.Provider;
-import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURIFromAccessForTypeAndVersion;
+import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion;
 import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURISupplier;
 import org.jclouds.openstack.v2_0.ServiceType;
 import org.jclouds.openstack.v2_0.services.Identity;
@@ -41,7 +41,7 @@ public class KeystoneAdminURLModule extends AbstractModule {
    @Override
    protected void configure() {
       install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
-               RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
+               RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
    }
 
    /**

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/ServiceCatalogModule.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/ServiceCatalogModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/ServiceCatalogModule.java
index 9761da0..9019c7c 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/ServiceCatalogModule.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/config/ServiceCatalogModule.java
@@ -34,10 +34,10 @@ import org.jclouds.location.suppliers.all.RegionToProvider;
 import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet;
 import org.jclouds.location.suppliers.implicit.FirstRegion;
 import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
-import org.jclouds.openstack.keystone.catalog.suppliers.LocationIdToURIFromAccessForTypeAndVersion;
-import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURIFromAccessForTypeAndVersion;
+import org.jclouds.openstack.keystone.catalog.suppliers.LocationIdToURIFromServiceEndpointsForTypeAndVersion;
+import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion;
 import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURISupplier;
-import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToURIFromAccessForTypeAndVersion;
+import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToURIFromServiceEndpointsForTypeAndVersion;
 import org.jclouds.openstack.keystone.config.KeystoneProperties;
 import org.jclouds.openstack.keystone.v2_0.catalog.V2ServiceCatalog;
 import org.jclouds.openstack.keystone.v3.catalog.V3ServiceCatalog;
@@ -88,14 +88,14 @@ public class ServiceCatalogModule extends AbstractModule {
    public static class ProviderModule extends AbstractModule {
       @Override
       protected void configure() {
-         install(new FactoryModuleBuilder().build(LocationIdToURIFromAccessForTypeAndVersion.Factory.class));
+         install(new FactoryModuleBuilder().build(LocationIdToURIFromServiceEndpointsForTypeAndVersion.Factory.class));
       }
 
       @Provides
       @Singleton
       protected final Supplier<URI> provideZoneIdToURISupplierForApiVersion(
             @Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
-            LocationIdToURIFromAccessForTypeAndVersion.Factory factory) {
+            LocationIdToURIFromServiceEndpointsForTypeAndVersion.Factory factory) {
          return getLastValueInMap(factory.createForApiTypeAndVersion(serviceType, apiVersion));
       }
 
@@ -115,9 +115,9 @@ public class ServiceCatalogModule extends AbstractModule {
       @Override
       protected void configure() {
          install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
-               RegionIdToURIFromAccessForTypeAndVersion.class).build(RegionIdToURISupplier.Factory.class));
+               RegionIdToURIFromServiceEndpointsForTypeAndVersion.class).build(RegionIdToURISupplier.Factory.class));
          install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
-               RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
+               RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
          // Dynamically build the region list as opposed to from properties
          bind(RegionIdsSupplier.class).to(RegionIdsFromRegionIdToURIKeySet.class);
          bind(ImplicitLocationSupplier.class).to(FirstRegion.class).in(Scopes.SINGLETON);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromAccessForTypeAndVersion.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromAccessForTypeAndVersion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromAccessForTypeAndVersion.java
deleted file mode 100644
index 8adf561..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromAccessForTypeAndVersion.java
+++ /dev/null
@@ -1,129 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.openstack.keystone.catalog.suppliers;
-
-import static com.google.common.collect.Iterables.any;
-import static com.google.common.collect.Iterables.filter;
-import static com.google.common.collect.Iterables.isEmpty;
-import static com.google.common.collect.Maps.transformValues;
-import static com.google.common.collect.Multimaps.asMap;
-import static com.google.common.collect.Multimaps.index;
-
-import java.net.URI;
-import java.util.List;
-import java.util.Map;
-import java.util.NoSuchElementException;
-
-import javax.annotation.Resource;
-
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.logging.Logger;
-import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
-import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointResolutionStrategy;
-import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointToRegion;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Predicates;
-import com.google.common.base.Supplier;
-import com.google.common.collect.Multimap;
-import com.google.inject.Inject;
-import com.google.inject.assistedinject.Assisted;
-
-public class LocationIdToURIFromAccessForTypeAndVersion implements Supplier<Map<String, Supplier<URI>>> {
-
-   public interface Factory {
-      
-      LocationIdToURIFromAccessForTypeAndVersion createForApiTypeAndVersion(@Assisted("apiType") String apiType,
-            @Nullable @Assisted("apiVersion") String apiVersion) throws NoSuchElementException;
-   }
-
-   @Resource
-   protected Logger logger = Logger.NULL;
-
-   protected final Supplier<List<ServiceEndpoint>> serviceEndpoints;
-   protected final ServiceEndpointResolutionStrategy resolveServiceEndpointURI;
-   protected final ServiceEndpointToRegion serviceEndpointToRegion;
-   protected final String apiType;
-   protected final String apiVersion;
-
-   @Inject
-   LocationIdToURIFromAccessForTypeAndVersion(Supplier<List<ServiceEndpoint>> serviceEndpoints,
-         ServiceEndpointResolutionStrategy resolveServiceEndpointURI, ServiceEndpointToRegion serviceEndpointToRegion,
-         @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
-      this.serviceEndpoints = serviceEndpoints;
-      this.resolveServiceEndpointURI = resolveServiceEndpointURI;
-      this.serviceEndpointToRegion = serviceEndpointToRegion;
-      this.apiType = apiType;
-      this.apiVersion = apiVersion;
-   }
-
-   @Override
-   public Map<String, Supplier<URI>> get() {
-      List<ServiceEndpoint> endpoints = serviceEndpoints.get();
-
-      // Filter endpoints by service type
-      Iterable<ServiceEndpoint> endpointsForType = filter(endpoints, apiTypeEquals);
-      if (isEmpty(endpointsForType)) {
-         throw new NoSuchElementException(String.format("no endpoints for apiType %s in service endpoints %s", apiType,
-               endpoints));
-      }
-      
-      // Check if there are endpoints for a particular version, if specified and
-      // there are versioned endpoints
-      boolean checkVersionId = apiVersion != null && any(endpointsForType, versionAware);
-      Predicate<ServiceEndpoint> versionFilter = checkVersionId ? apiVersionEqualsVersionId : Predicates.<ServiceEndpoint> alwaysTrue();
-      Iterable<ServiceEndpoint> endpointsForTypeAndVersion = filter(endpointsForType, versionFilter);
-      if (isEmpty(endpointsForTypeAndVersion)) {
-         throw new NoSuchElementException(String.format(
-               "no service endpoints for apiType %s are of version %s, or version agnostic: %s", apiType, apiVersion,
-               endpointsForType));
-      }
-
-      logger.debug("service endpoints for apiType %s and version %s: %s", apiType, apiVersion,
-            endpointsForTypeAndVersion);
-      
-      Multimap<String, ServiceEndpoint> locationToServiceEndpoints = index(endpointsForTypeAndVersion,
-            serviceEndpointToRegion);
-      return transformValues(asMap(locationToServiceEndpoints), resolveServiceEndpointURI);
-   }
-
-   private final Predicate<ServiceEndpoint> apiVersionEqualsVersionId = new Predicate<ServiceEndpoint>() {
-      @Override
-      public boolean apply(ServiceEndpoint input) {
-         return input.version().equals(apiVersion);
-      }
-   };
-
-   private final Predicate<ServiceEndpoint> versionAware = new Predicate<ServiceEndpoint>() {
-      @Override
-      public boolean apply(ServiceEndpoint input) {
-         return input.version() != null;
-      }
-   };
-
-   private final Predicate<ServiceEndpoint> apiTypeEquals = new Predicate<ServiceEndpoint>() {
-      @Override
-      public boolean apply(ServiceEndpoint input) {
-         return input.type().equals(apiType);
-      }
-   };
-
-   @Override
-   public String toString() {
-      return "locationIdToURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromServiceEndpointsForTypeAndVersion.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromServiceEndpointsForTypeAndVersion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromServiceEndpointsForTypeAndVersion.java
new file mode 100644
index 0000000..a96503d
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/LocationIdToURIFromServiceEndpointsForTypeAndVersion.java
@@ -0,0 +1,129 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.keystone.catalog.suppliers;
+
+import static com.google.common.collect.Iterables.any;
+import static com.google.common.collect.Iterables.filter;
+import static com.google.common.collect.Iterables.isEmpty;
+import static com.google.common.collect.Maps.transformValues;
+import static com.google.common.collect.Multimaps.asMap;
+import static com.google.common.collect.Multimaps.index;
+
+import java.net.URI;
+import java.util.List;
+import java.util.Map;
+import java.util.NoSuchElementException;
+
+import javax.annotation.Resource;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.logging.Logger;
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointResolutionStrategy;
+import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointToRegion;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
+import com.google.common.base.Supplier;
+import com.google.common.collect.Multimap;
+import com.google.inject.Inject;
+import com.google.inject.assistedinject.Assisted;
+
+public class LocationIdToURIFromServiceEndpointsForTypeAndVersion implements Supplier<Map<String, Supplier<URI>>> {
+
+   public interface Factory {
+      
+      LocationIdToURIFromServiceEndpointsForTypeAndVersion createForApiTypeAndVersion(@Assisted("apiType") String apiType,
+                                                                                      @Nullable @Assisted("apiVersion") String apiVersion) throws NoSuchElementException;
+   }
+
+   @Resource
+   protected Logger logger = Logger.NULL;
+
+   protected final Supplier<List<ServiceEndpoint>> serviceEndpoints;
+   protected final ServiceEndpointResolutionStrategy resolveServiceEndpointURI;
+   protected final ServiceEndpointToRegion serviceEndpointToRegion;
+   protected final String apiType;
+   protected final String apiVersion;
+
+   @Inject
+   LocationIdToURIFromServiceEndpointsForTypeAndVersion(Supplier<List<ServiceEndpoint>> serviceEndpoints,
+                                                        ServiceEndpointResolutionStrategy resolveServiceEndpointURI, ServiceEndpointToRegion serviceEndpointToRegion,
+                                                        @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
+      this.serviceEndpoints = serviceEndpoints;
+      this.resolveServiceEndpointURI = resolveServiceEndpointURI;
+      this.serviceEndpointToRegion = serviceEndpointToRegion;
+      this.apiType = apiType;
+      this.apiVersion = apiVersion;
+   }
+
+   @Override
+   public Map<String, Supplier<URI>> get() {
+      List<ServiceEndpoint> endpoints = serviceEndpoints.get();
+
+      // Filter endpoints by service type
+      Iterable<ServiceEndpoint> endpointsForType = filter(endpoints, apiTypeEquals);
+      if (isEmpty(endpointsForType)) {
+         throw new NoSuchElementException(String.format("no endpoints for apiType %s in service endpoints %s", apiType,
+               endpoints));
+      }
+      
+      // Check if there are endpoints for a particular version, if specified and
+      // there are versioned endpoints
+      boolean checkVersionId = apiVersion != null && any(endpointsForType, versionAware);
+      Predicate<ServiceEndpoint> versionFilter = checkVersionId ? apiVersionEqualsVersionId : Predicates.<ServiceEndpoint> alwaysTrue();
+      Iterable<ServiceEndpoint> endpointsForTypeAndVersion = filter(endpointsForType, versionFilter);
+      if (isEmpty(endpointsForTypeAndVersion)) {
+         throw new NoSuchElementException(String.format(
+               "no service endpoints for apiType %s are of version %s, or version agnostic: %s", apiType, apiVersion,
+               endpointsForType));
+      }
+
+      logger.debug("service endpoints for apiType %s and version %s: %s", apiType, apiVersion,
+            endpointsForTypeAndVersion);
+      
+      Multimap<String, ServiceEndpoint> locationToServiceEndpoints = index(endpointsForTypeAndVersion,
+            serviceEndpointToRegion);
+      return transformValues(asMap(locationToServiceEndpoints), resolveServiceEndpointURI);
+   }
+
+   private final Predicate<ServiceEndpoint> apiVersionEqualsVersionId = new Predicate<ServiceEndpoint>() {
+      @Override
+      public boolean apply(ServiceEndpoint input) {
+         return input.version().equals(apiVersion);
+      }
+   };
+
+   private final Predicate<ServiceEndpoint> versionAware = new Predicate<ServiceEndpoint>() {
+      @Override
+      public boolean apply(ServiceEndpoint input) {
+         return input.version() != null;
+      }
+   };
+
+   private final Predicate<ServiceEndpoint> apiTypeEquals = new Predicate<ServiceEndpoint>() {
+      @Override
+      public boolean apply(ServiceEndpoint input) {
+         return input.type().equals(apiType);
+      }
+   };
+
+   @Override
+   public String toString() {
+      return "locationIdToURIFromServiceEndpointsForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java
deleted file mode 100644
index 740b7a3..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.openstack.keystone.catalog.suppliers;
-
-import java.util.List;
-
-import javax.inject.Inject;
-
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
-import org.jclouds.openstack.keystone.catalog.functions.AdminEndpointResolutionStrategy;
-import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointToRegion;
-
-import com.google.common.base.Supplier;
-import com.google.inject.assistedinject.Assisted;
-
-public class RegionIdToAdminURIFromAccessForTypeAndVersion extends LocationIdToURIFromAccessForTypeAndVersion implements
-      RegionIdToAdminURISupplier {
-   @Inject
-   public RegionIdToAdminURIFromAccessForTypeAndVersion(Supplier<List<ServiceEndpoint>> serviceEndpoints,
-         AdminEndpointResolutionStrategy resolveServiceEndpointURI, ServiceEndpointToRegion serviceEndpointToRegion,
-         @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
-      super(serviceEndpoints, resolveServiceEndpointURI, serviceEndpointToRegion, apiType, apiVersion);
-   }
-
-   @Override
-   public String toString() {
-      return "regionIdToAdminURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion.java
new file mode 100644
index 0000000..742d440
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion.java
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.keystone.catalog.suppliers;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+import org.jclouds.openstack.keystone.catalog.functions.AdminEndpointResolutionStrategy;
+import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointToRegion;
+
+import com.google.common.base.Supplier;
+import com.google.inject.assistedinject.Assisted;
+
+public class RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion extends LocationIdToURIFromServiceEndpointsForTypeAndVersion implements
+      RegionIdToAdminURISupplier {
+   @Inject
+   public RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion(Supplier<List<ServiceEndpoint>> serviceEndpoints,
+                                                                  AdminEndpointResolutionStrategy resolveServiceEndpointURI, ServiceEndpointToRegion serviceEndpointToRegion,
+                                                                  @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
+      super(serviceEndpoints, resolveServiceEndpointURI, serviceEndpointToRegion, apiType, apiVersion);
+   }
+
+   @Override
+   public String toString() {
+      return "regionIdToAdminURIFromServiceEndpointsForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURISupplier.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURISupplier.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURISupplier.java
index 0f70205..07f1773 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURISupplier.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToAdminURISupplier.java
@@ -26,7 +26,7 @@ import com.google.common.base.Supplier;
 import com.google.inject.ImplementedBy;
 import com.google.inject.assistedinject.Assisted;
 
-@ImplementedBy(RegionIdToAdminURIFromAccessForTypeAndVersion.class)
+@ImplementedBy(RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion.class)
 public interface RegionIdToAdminURISupplier extends Supplier<Map<String, Supplier<URI>>> {
 
    interface Factory {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromAccessForTypeAndVersion.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromAccessForTypeAndVersion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromAccessForTypeAndVersion.java
deleted file mode 100644
index d40b4af..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromAccessForTypeAndVersion.java
+++ /dev/null
@@ -1,46 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.openstack.keystone.catalog.suppliers;
-
-import java.util.List;
-
-import javax.inject.Inject;
-
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.suppliers.RegionIdToURISupplier;
-import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
-import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointResolutionStrategy;
-import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointToRegion;
-
-import com.google.common.base.Supplier;
-import com.google.inject.assistedinject.Assisted;
-
-public class RegionIdToURIFromAccessForTypeAndVersion extends LocationIdToURIFromAccessForTypeAndVersion implements
-      RegionIdToURISupplier {
-
-   @Inject
-   public RegionIdToURIFromAccessForTypeAndVersion(Supplier<List<ServiceEndpoint>> serviceEndpoints,
-         ServiceEndpointResolutionStrategy resolveServiceEndpointURI, ServiceEndpointToRegion serviceEndpointToRegion,
-         @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
-      super(serviceEndpoints, resolveServiceEndpointURI, serviceEndpointToRegion, apiType, apiVersion);
-   }
-
-   @Override
-   public String toString() {
-      return "regionIdToURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromServiceEndpointsForTypeAndVersion.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromServiceEndpointsForTypeAndVersion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromServiceEndpointsForTypeAndVersion.java
new file mode 100644
index 0000000..7065ee5
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/catalog/suppliers/RegionIdToURIFromServiceEndpointsForTypeAndVersion.java
@@ -0,0 +1,46 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.keystone.catalog.suppliers;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.suppliers.RegionIdToURISupplier;
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointResolutionStrategy;
+import org.jclouds.openstack.keystone.catalog.functions.ServiceEndpointToRegion;
+
+import com.google.common.base.Supplier;
+import com.google.inject.assistedinject.Assisted;
+
+public class RegionIdToURIFromServiceEndpointsForTypeAndVersion extends LocationIdToURIFromServiceEndpointsForTypeAndVersion implements
+      RegionIdToURISupplier {
+
+   @Inject
+   public RegionIdToURIFromServiceEndpointsForTypeAndVersion(Supplier<List<ServiceEndpoint>> serviceEndpoints,
+                                                             ServiceEndpointResolutionStrategy resolveServiceEndpointURI, ServiceEndpointToRegion serviceEndpointToRegion,
+                                                             @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
+      super(serviceEndpoints, resolveServiceEndpointURI, serviceEndpointToRegion, apiType, apiVersion);
+   }
+
+   @Override
+   public String toString() {
+      return "regionIdToURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/auth/V3AuthenticationApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/auth/V3AuthenticationApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/auth/V3AuthenticationApi.java
index 7a84c21..0553c15 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/auth/V3AuthenticationApi.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/auth/V3AuthenticationApi.java
@@ -30,7 +30,7 @@ import org.jclouds.openstack.keystone.auth.domain.TokenCredentials;
 import org.jclouds.openstack.keystone.v3.binders.BindPasswordAuthToJsonPayload;
 import org.jclouds.openstack.keystone.v3.binders.BindTokenAuthToJsonPayload;
 import org.jclouds.openstack.keystone.v3.domain.Token;
-import org.jclouds.openstack.keystone.v3.parsers.ParseToken;
+import org.jclouds.openstack.keystone.v3.parsers.ParseTokenFromHttpResponse;
 import org.jclouds.rest.annotations.MapBinder;
 import org.jclouds.rest.annotations.ResponseParser;
 
@@ -45,14 +45,14 @@ public interface V3AuthenticationApi extends AuthenticationApi, Closeable {
 
    @Named("token:create")
    @POST
-   @ResponseParser(ParseToken.class)
+   @ResponseParser(ParseTokenFromHttpResponse.class) //ParseToken.class)
    @MapBinder(BindPasswordAuthToJsonPayload.class)
    @Override
    Token authenticatePassword(TenantAndCredentials<PasswordCredentials> credentials);
 
    @Named("token:create")
    @POST
-   @ResponseParser(ParseToken.class)
+   @ResponseParser(ParseTokenFromHttpResponse.class) //ParseToken.class)
    @MapBinder(BindTokenAuthToJsonPayload.class)
    @Override
    Token authenticateToken(TenantAndCredentials<TokenCredentials> credentials);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Auth.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Auth.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Auth.java
index 13c3753..fb2caf5 100644
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Auth.java
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Auth.java
@@ -37,7 +37,7 @@ public abstract class Auth {
    public abstract static class Identity {
       
       public abstract List<String> methods();
-      public abstract TokenAuth token();
+      @Nullable public abstract TokenAuth token();
       public abstract PasswordAuth password();
 
       @SerializedNames({ "methods", "token", "password" })

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/parsers/ParseToken.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/parsers/ParseToken.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/parsers/ParseToken.java
deleted file mode 100644
index 1fd633f..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/parsers/ParseToken.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.openstack.keystone.v3.parsers;
-
-import org.jclouds.http.HttpResponse;
-import org.jclouds.http.functions.ParseFirstJsonValueNamed;
-import org.jclouds.json.internal.GsonWrapper;
-import org.jclouds.openstack.keystone.v3.domain.Token;
-
-import com.google.common.collect.Iterables;
-import com.google.inject.Inject;
-import com.google.inject.TypeLiteral;
-
-public class ParseToken extends ParseFirstJsonValueNamed<Token> {
-
-   @Inject
-   ParseToken(GsonWrapper json, TypeLiteral<Token> type, String... nameChoices) {
-      super(json, type, nameChoices);
-   }
-
-   @Override
-   public Token apply(HttpResponse from) {
-      Token token = super.apply(from);
-      String xSubjectToken = Iterables.getOnlyElement(from.getHeaders().get("X-Subject-Token"));
-      return token.toBuilder().id(xSubjectToken).build();
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/parsers/ParseTokenFromHttpResponse.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/parsers/ParseTokenFromHttpResponse.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/parsers/ParseTokenFromHttpResponse.java
new file mode 100644
index 0000000..9a5b799
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/parsers/ParseTokenFromHttpResponse.java
@@ -0,0 +1,50 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.openstack.keystone.v3.parsers;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import javax.inject.Singleton;
+
+import com.google.common.collect.Iterables;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.http.functions.ParseFirstJsonValueNamed;
+import org.jclouds.json.internal.GsonWrapper;
+import org.jclouds.openstack.keystone.v3.domain.Token;
+
+import com.google.common.base.Function;
+import com.google.inject.Inject;
+import com.google.inject.TypeLiteral;
+
+@Singleton
+public class ParseTokenFromHttpResponse implements Function<HttpResponse, Token> {
+   private final ParseFirstJsonValueNamed<Token> parser;
+
+   @Inject
+   public ParseTokenFromHttpResponse(GsonWrapper gsonView) {
+      this.parser = new ParseFirstJsonValueNamed<Token>(gsonView, TypeLiteral.get(Token.class), "token");
+   }
+
+   public Token apply(HttpResponse response) {
+      checkNotNull(response, "response");
+      Token toParse = parser.apply(response);
+      checkNotNull(toParse, "parsed result from %s", response);
+      String xSubjectToken = Iterables.getOnlyElement(response.getHeaders().get("X-Subject-Token"));
+      return toParse.toBuilder().id(xSubjectToken).build();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/LocationIdToURIFromAccessForTypeAndVersionTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/LocationIdToURIFromAccessForTypeAndVersionTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/LocationIdToURIFromAccessForTypeAndVersionTest.java
index 91146b0..0b1c890 100644
--- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/LocationIdToURIFromAccessForTypeAndVersionTest.java
+++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/LocationIdToURIFromAccessForTypeAndVersionTest.java
@@ -28,7 +28,7 @@ import javax.inject.Singleton;
 import org.jclouds.location.Provider;
 import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
 import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
-import org.jclouds.openstack.keystone.catalog.suppliers.LocationIdToURIFromAccessForTypeAndVersion;
+import org.jclouds.openstack.keystone.catalog.suppliers.LocationIdToURIFromServiceEndpointsForTypeAndVersion;
 import org.jclouds.openstack.keystone.v2_0.catalog.V2ServiceCatalog;
 import org.jclouds.openstack.keystone.v2_0.parse.ParseAccessTest;
 import org.jclouds.openstack.keystone.v2_0.parse.ParseRackspaceAccessTest;
@@ -47,7 +47,7 @@ import com.google.inject.assistedinject.FactoryModuleBuilder;
 
 @Test(groups = "unit", testName = "LocationIdToURIFromAccessForTypeAndVersionTest")
 public class LocationIdToURIFromAccessForTypeAndVersionTest {
-   private final LocationIdToURIFromAccessForTypeAndVersion.Factory factory = Guice.createInjector(
+   private final LocationIdToURIFromServiceEndpointsForTypeAndVersion.Factory factory = Guice.createInjector(
          new AbstractModule() {
 
             @Override
@@ -55,9 +55,9 @@ public class LocationIdToURIFromAccessForTypeAndVersionTest {
                bindConstant().annotatedWith(Provider.class).to("openstack-keystone");
                bind(new TypeLiteral<Supplier<URI>>() {
                }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
-               install(new FactoryModuleBuilder().implement(LocationIdToURIFromAccessForTypeAndVersion.class,
-                     LocationIdToURIFromAccessForTypeAndVersion.class).build(
-                     LocationIdToURIFromAccessForTypeAndVersion.Factory.class));
+               install(new FactoryModuleBuilder().implement(LocationIdToURIFromServiceEndpointsForTypeAndVersion.class,
+                     LocationIdToURIFromServiceEndpointsForTypeAndVersion.class).build(
+                     LocationIdToURIFromServiceEndpointsForTypeAndVersion.Factory.class));
                // We test against a 2.0 service catalog but it is OK for the purpose of this test
                bind(new TypeLiteral<Supplier<List<ServiceEndpoint>>>() {
                }).to(V2ServiceCatalog.class).in(Scopes.SINGLETON);
@@ -69,7 +69,7 @@ public class LocationIdToURIFromAccessForTypeAndVersionTest {
                return Suppliers.<AuthInfo> ofInstance(new ParseAccessTest().expected());
             }
 
-         }).getInstance(LocationIdToURIFromAccessForTypeAndVersion.Factory.class);
+         }).getInstance(LocationIdToURIFromServiceEndpointsForTypeAndVersion.Factory.class);
 
    public void testRegionUnmatchesOkWhenNoVersionIdSet() {
       assertEquals(
@@ -91,7 +91,7 @@ public class LocationIdToURIFromAccessForTypeAndVersionTest {
                   URI.create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v2/3456")));
    }
 
-   private final LocationIdToURIFromAccessForTypeAndVersion.Factory raxFactory = Guice.createInjector(
+   private final LocationIdToURIFromServiceEndpointsForTypeAndVersion.Factory raxFactory = Guice.createInjector(
          new AbstractModule() {
 
             @Override
@@ -99,9 +99,9 @@ public class LocationIdToURIFromAccessForTypeAndVersionTest {
                bindConstant().annotatedWith(Provider.class).to("rackspace");
                bind(new TypeLiteral<Supplier<URI>>() {
                }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
-               install(new FactoryModuleBuilder().implement(LocationIdToURIFromAccessForTypeAndVersion.class,
-                     LocationIdToURIFromAccessForTypeAndVersion.class).build(
-                     LocationIdToURIFromAccessForTypeAndVersion.Factory.class));
+               install(new FactoryModuleBuilder().implement(LocationIdToURIFromServiceEndpointsForTypeAndVersion.class,
+                     LocationIdToURIFromServiceEndpointsForTypeAndVersion.class).build(
+                     LocationIdToURIFromServiceEndpointsForTypeAndVersion.Factory.class));
                // We test against a 2.0 service catalog but it is OK for the purpose of this test
                bind(new TypeLiteral<Supplier<List<ServiceEndpoint>>>() {
                }).to(V2ServiceCatalog.class).in(Scopes.SINGLETON);
@@ -112,7 +112,7 @@ public class LocationIdToURIFromAccessForTypeAndVersionTest {
             public Supplier<AuthInfo> provide() {
                return Suppliers.<AuthInfo> ofInstance(new ParseRackspaceAccessTest().expected());
             }
-         }).getInstance(LocationIdToURIFromAccessForTypeAndVersion.Factory.class);
+         }).getInstance(LocationIdToURIFromServiceEndpointsForTypeAndVersion.Factory.class);
 
    @Test(expectedExceptions = NoSuchElementException.class)
    public void testWhenNotInList() {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionTest.java
index 0ed35a4..3a632e2 100644
--- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionTest.java
+++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionTest.java
@@ -28,7 +28,7 @@ import javax.inject.Singleton;
 import org.jclouds.location.Provider;
 import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
 import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
-import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURIFromAccessForTypeAndVersion;
+import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion;
 import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToAdminURISupplier;
 import org.jclouds.openstack.keystone.v2_0.catalog.V2ServiceCatalog;
 import org.jclouds.openstack.keystone.v2_0.parse.ParseAccessTest;
@@ -56,7 +56,7 @@ public class RegionIdToAdminURIFromAccessForTypeAndVersionTest {
          bind(new TypeLiteral<Supplier<URI>>() {
          }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
          install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
-                  RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
+                  RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
          // We test against a 2.0 service catalog but it is OK for the purpose of this test
          bind(new TypeLiteral<Supplier<List<ServiceEndpoint>>>() {
          }).to(V2ServiceCatalog.class).in(Scopes.SINGLETON);
@@ -88,7 +88,7 @@ public class RegionIdToAdminURIFromAccessForTypeAndVersionTest {
          bind(new TypeLiteral<Supplier<URI>>() {
          }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
          install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
-                  RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
+                  RegionIdToAdminURIFromServiceEndpointsForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
          // We test against a 2.0 service catalog but it is OK for the purpose of this test
          bind(new TypeLiteral<Supplier<List<ServiceEndpoint>>>() {
          }).to(V2ServiceCatalog.class).in(Scopes.SINGLETON);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/17c11ec9/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToURIFromAccessForTypeAndVersionTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToURIFromAccessForTypeAndVersionTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToURIFromAccessForTypeAndVersionTest.java
index cbdaf21..65b820d 100644
--- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToURIFromAccessForTypeAndVersionTest.java
+++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/auth/suppliers/RegionIdToURIFromAccessForTypeAndVersionTest.java
@@ -28,7 +28,7 @@ import org.jclouds.location.Provider;
 import org.jclouds.location.suppliers.RegionIdToURISupplier;
 import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
 import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
-import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToURIFromAccessForTypeAndVersion;
+import org.jclouds.openstack.keystone.catalog.suppliers.RegionIdToURIFromServiceEndpointsForTypeAndVersion;
 import org.jclouds.openstack.keystone.v2_0.catalog.V2ServiceCatalog;
 import org.jclouds.openstack.keystone.v2_0.parse.ParseAccessTest;
 import org.jclouds.openstack.keystone.v2_0.parse.ParseRackspaceAccessTest;
@@ -55,7 +55,7 @@ public class RegionIdToURIFromAccessForTypeAndVersionTest {
          bind(new TypeLiteral<Supplier<URI>>() {
          }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
          install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
-                  RegionIdToURIFromAccessForTypeAndVersion.class).build(
+                  RegionIdToURIFromServiceEndpointsForTypeAndVersion.class).build(
                   RegionIdToURISupplier.Factory.class));
          // We test against a 2.0 service catalog but it is OK for the purpose of this test
          bind(new TypeLiteral<Supplier<List<ServiceEndpoint>>>() {
@@ -91,7 +91,7 @@ public class RegionIdToURIFromAccessForTypeAndVersionTest {
          bind(new TypeLiteral<Supplier<URI>>() {
          }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
          install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
-                  RegionIdToURIFromAccessForTypeAndVersion.class).build(
+                  RegionIdToURIFromServiceEndpointsForTypeAndVersion.class).build(
                   RegionIdToURISupplier.Factory.class));
          // We test against a 2.0 service catalog but it is OK for the purpose of this test
          bind(new TypeLiteral<Supplier<List<ServiceEndpoint>>>() {