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 2018/01/16 08:12:44 UTC

[6/9] jclouds git commit: Add support for OpenStack Keystone V3

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java
deleted file mode 100644
index bd794d2..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java
+++ /dev/null
@@ -1,42 +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.v2_0.suppliers;
-
-import javax.inject.Inject;
-
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.openstack.keystone.v2_0.domain.Access;
-import org.jclouds.openstack.keystone.v2_0.functions.EndpointToRegion;
-import org.jclouds.openstack.keystone.v2_0.functions.EndpointToSupplierAdminURI;
-
-import com.google.common.base.Supplier;
-import com.google.inject.assistedinject.Assisted;
-
-public class RegionIdToAdminURIFromAccessForTypeAndVersion extends LocationIdToURIFromAccessForTypeAndVersion implements
-         RegionIdToAdminURISupplier {
-   @Inject
-   public RegionIdToAdminURIFromAccessForTypeAndVersion(Supplier<Access> access,
-            EndpointToSupplierAdminURI endpointToSupplierURI, EndpointToRegion endpointToRegion,
-            @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
-      super(access, endpointToSupplierURI, endpointToRegion, apiType, apiVersion);
-   }
-
-   @Override
-   public String toString() {
-      return "regionIdToAdminURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURISupplier.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURISupplier.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURISupplier.java
deleted file mode 100644
index 759c2b9..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURISupplier.java
+++ /dev/null
@@ -1,45 +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.v2_0.suppliers;
-
-import java.net.URI;
-import java.util.Map;
-import java.util.NoSuchElementException;
-
-import org.jclouds.javax.annotation.Nullable;
-
-import com.google.common.base.Supplier;
-import com.google.inject.ImplementedBy;
-import com.google.inject.assistedinject.Assisted;
-
-@ImplementedBy(RegionIdToAdminURIFromAccessForTypeAndVersion.class)
-public interface RegionIdToAdminURISupplier extends Supplier<Map<String, Supplier<URI>>> {
-   interface Factory {
-      /**
-       * 
-       * @param apiType
-       *           type of the api, according to the provider. ex. {@code compute}
-       *           {@code object-store}
-       * @param apiVersion
-       *           version of the api, or null
-       * @return regions mapped to default uri
-       * @throws NoSuchElementException if the {@code apiType} is not present in the catalog
-       */
-      RegionIdToAdminURISupplier createForApiTypeAndVersion(@Assisted("apiType") String apiType,
-               @Nullable @Assisted("apiVersion") String apiVersion) throws NoSuchElementException;
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToURIFromAccessForTypeAndVersion.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToURIFromAccessForTypeAndVersion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToURIFromAccessForTypeAndVersion.java
deleted file mode 100644
index aff2814..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToURIFromAccessForTypeAndVersion.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.v2_0.suppliers;
-
-import javax.inject.Inject;
-
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.suppliers.RegionIdToURISupplier;
-import org.jclouds.openstack.keystone.v2_0.domain.Access;
-import org.jclouds.openstack.keystone.v2_0.functions.EndpointToRegion;
-import org.jclouds.openstack.keystone.v2_0.functions.EndpointToSupplierURI;
-
-import com.google.common.base.Supplier;
-import com.google.inject.assistedinject.Assisted;
-
-public class RegionIdToURIFromAccessForTypeAndVersion extends LocationIdToURIFromAccessForTypeAndVersion implements
-         RegionIdToURISupplier {
-
-   @Inject
-   public RegionIdToURIFromAccessForTypeAndVersion(Supplier<Access> access,
-            EndpointToSupplierURI endpointToSupplierURI, EndpointToRegion endpointToRegion,
-            @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
-      super(access, endpointToSupplierURI, endpointToRegion, apiType, apiVersion);
-   }
-
-   @Override
-   public String toString() {
-      return "regionIdToURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersion.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersion.java
deleted file mode 100644
index 41f936b..0000000
--- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersion.java
+++ /dev/null
@@ -1,47 +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.v2_0.suppliers;
-
-import javax.inject.Inject;
-
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.suppliers.ZoneIdToURISupplier;
-import org.jclouds.openstack.keystone.v2_0.domain.Access;
-import org.jclouds.openstack.keystone.v2_0.functions.EndpointToRegion;
-import org.jclouds.openstack.keystone.v2_0.functions.EndpointToSupplierURI;
-
-import com.google.common.base.Supplier;
-import com.google.inject.assistedinject.Assisted;
-
-public class ZoneIdToURIFromAccessForTypeAndVersion extends LocationIdToURIFromAccessForTypeAndVersion implements
-         ZoneIdToURISupplier {
-
-   @Inject
-   public ZoneIdToURIFromAccessForTypeAndVersion(
-            Supplier<Access> access,
-            // NOTE that in some services, the region is in fact the zone. temporarily, we need
-            // to use the region field, in this case.
-            EndpointToSupplierURI endpointToSupplierURI, EndpointToRegion endpointToZone,
-            @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
-      super(access, endpointToSupplierURI, endpointToZone, apiType, apiVersion);
-   }
-
-   @Override
-   public String toString() {
-      return "zoneIdToURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/KeystoneApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/KeystoneApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/KeystoneApi.java
new file mode 100644
index 0000000..05cd91d
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/KeystoneApi.java
@@ -0,0 +1,62 @@
+/*
+ * 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;
+
+import java.io.Closeable;
+
+import org.jclouds.openstack.keystone.v3.features.AuthApi;
+import org.jclouds.openstack.keystone.v3.features.CatalogApi;
+import org.jclouds.openstack.keystone.v3.features.ProjectApi;
+import org.jclouds.openstack.keystone.v3.features.RegionApi;
+import org.jclouds.openstack.keystone.v3.features.UserApi;
+import org.jclouds.rest.annotations.Delegate;
+
+/**
+ * Provides access to the OpenStack Identity (Keystone) REST API.
+ */
+public interface KeystoneApi extends Closeable {
+
+   /**
+    * Provides access to authentication and token management features.
+    */
+   @Delegate
+   AuthApi getAuthApi();
+
+   /**
+    * Provides access to service catalog features.
+    */
+   @Delegate
+   CatalogApi getCatalogApi();
+   
+   /**
+    * Provides access to region features.
+    */
+   @Delegate
+   RegionApi getRegionApi();
+   
+   /**
+    * Provides access to project features.
+    */
+   @Delegate
+   ProjectApi getProjectApi();
+   
+   /**
+    * Provides access to user features.
+    */
+   @Delegate
+   UserApi getUserApi();
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/KeystoneApiMetadata.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/KeystoneApiMetadata.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/KeystoneApiMetadata.java
new file mode 100644
index 0000000..14fe19a
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/KeystoneApiMetadata.java
@@ -0,0 +1,97 @@
+/*
+ * 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;
+
+import static org.jclouds.openstack.keystone.config.KeystoneProperties.CREDENTIAL_TYPE;
+import static org.jclouds.openstack.keystone.config.KeystoneProperties.KEYSTONE_VERSION;
+import static org.jclouds.openstack.keystone.config.KeystoneProperties.SERVICE_TYPE;
+
+import java.net.URI;
+import java.util.Properties;
+
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.openstack.keystone.auth.config.AuthenticationModule;
+import org.jclouds.openstack.keystone.catalog.config.KeystoneAdminURLModule;
+import org.jclouds.openstack.keystone.catalog.config.ServiceCatalogModule;
+import org.jclouds.openstack.keystone.v3.config.KeystoneHttpApiModule;
+import org.jclouds.openstack.v2_0.ServiceType;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
+
+import com.google.auto.service.AutoService;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+/**
+ * Implementation of {@link ApiMetadata} for Keystone 3.0 API
+ */
+@AutoService(ApiMetadata.class)
+public class KeystoneApiMetadata extends BaseHttpApiMetadata<KeystoneApi> {
+
+   @Override
+   public Builder<?> toBuilder() {
+      return new ConcreteBuilder().fromApiMetadata(this);
+   }
+
+   public KeystoneApiMetadata() {
+      this(new ConcreteBuilder());
+   }
+
+   protected KeystoneApiMetadata(Builder<?> builder) {
+      super(builder);
+   }
+
+   public static Properties defaultProperties() {
+      Properties properties = BaseHttpApiMetadata.defaultProperties();
+      properties.setProperty(CREDENTIAL_TYPE, org.jclouds.openstack.keystone.auth.config.CredentialTypes.PASSWORD_CREDENTIALS);
+      properties.setProperty(SERVICE_TYPE, ServiceType.IDENTITY);
+      properties.setProperty(KEYSTONE_VERSION, "3");
+      return properties;
+   }
+
+   public abstract static class Builder<T extends Builder<T>> extends BaseHttpApiMetadata.Builder<KeystoneApi, T> {
+
+      protected Builder() {
+          id("openstack-keystone-3")
+         .name("OpenStack Keystone 3.x API")
+         .identityName("${domain}:${userName} or ${userName}, if your keystone supports a default project")
+         .credentialName("${password}")
+         .endpointName("Keystone V3 base URL")
+         .documentation(URI.create("http://api.openstack.org/"))
+         .version("3")
+         .defaultEndpoint("http://localhost/identity/v3")
+         .defaultProperties(KeystoneApiMetadata.defaultProperties())
+         .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
+                                     .add(AuthenticationModule.class)
+                                     .add(ServiceCatalogModule.class)
+                                     .add(KeystoneAdminURLModule.class)
+                                     .add(KeystoneHttpApiModule.class)
+                                     .build());
+      }
+
+      @Override
+      public KeystoneApiMetadata build() {
+         return new KeystoneApiMetadata(this);
+      }
+   }
+
+   private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
+      @Override
+      protected ConcreteBuilder self() {
+         return this;
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/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
new file mode 100644
index 0000000..0902f65
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/auth/V3AuthenticationApi.java
@@ -0,0 +1,60 @@
+/*
+ * 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.auth;
+
+import java.io.Closeable;
+
+import javax.ws.rs.Consumes;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.openstack.keystone.auth.AuthenticationApi;
+import org.jclouds.openstack.keystone.auth.domain.PasswordCredentials;
+import org.jclouds.openstack.keystone.auth.domain.TenantOrDomainAndCredentials;
+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.ParseTokenFromHttpResponse;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.ResponseParser;
+
+import com.google.inject.name.Named;
+
+/**
+ * Provides access to the OpenStack Keystone Authentication API.
+ */
+@Consumes(MediaType.APPLICATION_JSON)
+@Path("/auth/tokens")
+public interface V3AuthenticationApi extends AuthenticationApi, Closeable {
+
+   @Named("token:create")
+   @POST
+   @ResponseParser(ParseTokenFromHttpResponse.class)
+   @MapBinder(BindPasswordAuthToJsonPayload.class)
+   @Override
+   Token authenticatePassword(TenantOrDomainAndCredentials<PasswordCredentials> credentials);
+
+   @Named("token:create")
+   @POST
+   @ResponseParser(ParseTokenFromHttpResponse.class)
+   @MapBinder(BindTokenAuthToJsonPayload.class)
+   @Override
+   Token authenticateToken(TenantOrDomainAndCredentials<TokenCredentials> credentials);
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindAuthToJsonPayload.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindAuthToJsonPayload.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindAuthToJsonPayload.java
new file mode 100644
index 0000000..a27ae12
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindAuthToJsonPayload.java
@@ -0,0 +1,107 @@
+/*
+ * 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.binders;
+
+import static com.google.common.base.Preconditions.checkArgument;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.base.Predicates.instanceOf;
+import static com.google.common.collect.Iterables.tryFind;
+import static org.jclouds.openstack.keystone.v3.domain.Auth.Scope.DOMAIN;
+import static org.jclouds.openstack.keystone.v3.domain.Auth.Scope.DOMAIN_ID;
+import static org.jclouds.openstack.keystone.v3.domain.Auth.Scope.PROJECT;
+import static org.jclouds.openstack.keystone.v3.domain.Auth.Scope.PROJECT_ID;
+import static org.jclouds.openstack.keystone.v3.domain.Auth.Scope.UNSCOPED;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.json.Json;
+import org.jclouds.openstack.keystone.auth.domain.TenantOrDomainAndCredentials;
+import org.jclouds.openstack.keystone.v3.domain.Auth;
+import org.jclouds.openstack.keystone.v3.domain.Auth.DomainIdScope;
+import org.jclouds.openstack.keystone.v3.domain.Auth.DomainScope;
+import org.jclouds.openstack.keystone.v3.domain.Auth.Id;
+import org.jclouds.openstack.keystone.v3.domain.Auth.Name;
+import org.jclouds.openstack.keystone.v3.domain.Auth.ProjectIdScope;
+import org.jclouds.openstack.keystone.v3.domain.Auth.ProjectScope;
+import org.jclouds.openstack.keystone.v3.domain.Auth.ProjectScope.ProjectName;
+import org.jclouds.rest.MapBinder;
+import org.jclouds.rest.binders.BindToJsonPayload;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+public abstract class BindAuthToJsonPayload<T> extends BindToJsonPayload implements MapBinder {
+
+   private static final Set<String> SCOPE_PREFIXES = ImmutableSet
+         .of(PROJECT, PROJECT_ID, DOMAIN, DOMAIN_ID);
+
+   protected BindAuthToJsonPayload(Json jsonBinder) {
+      super(jsonBinder);
+   }
+
+   protected abstract Auth buildAuth(TenantOrDomainAndCredentials<T> credentials, Object scope);
+
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
+      checkArgument(checkNotNull(request, "request") instanceof GeneratedHttpRequest,
+            "this binder is only valid for GeneratedHttpRequests!");
+      GeneratedHttpRequest gRequest = (GeneratedHttpRequest) request;
+
+      Optional<Object> authentication = tryFind(gRequest.getInvocation().getArgs(),
+            instanceOf(TenantOrDomainAndCredentials.class));
+      checkArgument(authentication.isPresent(), "no credentials found in the api call arguments");
+
+      @SuppressWarnings("unchecked")
+      TenantOrDomainAndCredentials<T> credentials = (TenantOrDomainAndCredentials<T>) authentication.get();
+      Object scope = parseScope(credentials);
+      Auth auth = buildAuth(credentials, scope);
+
+      R authRequest = super.bindToRequest(request, ImmutableMap.of("auth", auth));
+      authRequest.getPayload().setSensitive(true);
+
+      return authRequest;
+   }
+
+   private Object parseScope(TenantOrDomainAndCredentials<T> credentials) {
+      String scope = credentials.scope();
+      // If there is no prefix, assume an unscoped authentication
+      if (!scope.contains(":")) {
+         checkArgument(scope.equals(UNSCOPED), "Invalid scope: %s", scope);
+         return UNSCOPED;
+      }
+      // Otherwise, parse if it is a project or domain scope
+      String[] parts = scope.split(":");
+      checkArgument(parts.length == 2, "Invalid scope: %s", scope);
+      checkArgument(SCOPE_PREFIXES.contains(parts[0]), "Scope prefix should be: %s", SCOPE_PREFIXES);
+
+      if (PROJECT.equals(parts[0])) {
+         Object domainScope = credentials.tenantOrDomainId() != null ? Id.create(credentials.tenantOrDomainId()) : Name
+               .create(credentials.tenantOrDomainName());
+         return ProjectScope.create(ProjectName.create(parts[1], domainScope));
+      } else if (PROJECT_ID.equals(parts[0])) {
+         return ProjectIdScope.create(Id.create(parts[1]));
+      } else if (DOMAIN.equals(parts[0])) {
+         return DomainScope.create(Name.create(parts[1]));
+      } else {
+         return DomainIdScope.create(Id.create(parts[1]));
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindPasswordAuthToJsonPayload.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindPasswordAuthToJsonPayload.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindPasswordAuthToJsonPayload.java
new file mode 100644
index 0000000..40c94f8
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindPasswordAuthToJsonPayload.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.binders;
+
+import static java.util.Collections.singletonList;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.json.Json;
+import org.jclouds.openstack.keystone.auth.domain.PasswordCredentials;
+import org.jclouds.openstack.keystone.auth.domain.TenantOrDomainAndCredentials;
+import org.jclouds.openstack.keystone.v3.domain.Auth;
+import org.jclouds.openstack.keystone.v3.domain.Auth.Identity;
+import org.jclouds.openstack.keystone.v3.domain.Auth.Identity.PasswordAuth;
+import org.jclouds.openstack.keystone.v3.domain.Auth.Identity.PasswordAuth.UserAuth;
+import org.jclouds.openstack.keystone.v3.domain.Auth.Identity.PasswordAuth.UserAuth.DomainAuth;
+
+@Singleton
+public class BindPasswordAuthToJsonPayload extends BindAuthToJsonPayload<PasswordCredentials> {
+
+   @Inject
+   BindPasswordAuthToJsonPayload(Json jsonBinder) {
+      super(jsonBinder);
+   }
+
+   @Override
+   protected Auth buildAuth(TenantOrDomainAndCredentials<PasswordCredentials> credentials, Object scope) {
+      PasswordCredentials creds = credentials.credentials();
+      DomainAuth domain = DomainAuth.create(credentials.tenantOrDomainName());
+      UserAuth user = UserAuth.create(creds.username(), domain, creds.password());
+
+      return Auth.create(Identity.create(singletonList("password"), null, PasswordAuth.create(user)), scope);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindTokenAuthToJsonPayload.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindTokenAuthToJsonPayload.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindTokenAuthToJsonPayload.java
new file mode 100644
index 0000000..439baa2
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/binders/BindTokenAuthToJsonPayload.java
@@ -0,0 +1,45 @@
+/*
+ * 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.binders;
+
+import static java.util.Collections.singletonList;
+
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.json.Json;
+import org.jclouds.openstack.keystone.auth.domain.TenantOrDomainAndCredentials;
+import org.jclouds.openstack.keystone.auth.domain.TokenCredentials;
+import org.jclouds.openstack.keystone.v3.domain.Auth;
+import org.jclouds.openstack.keystone.v3.domain.Auth.Id;
+import org.jclouds.openstack.keystone.v3.domain.Auth.Identity;
+
+@Singleton
+public class BindTokenAuthToJsonPayload extends BindAuthToJsonPayload<TokenCredentials> {
+
+   @Inject
+   BindTokenAuthToJsonPayload(Json jsonBinder) {
+      super(jsonBinder);
+   }
+
+   @Override
+   protected Auth buildAuth(TenantOrDomainAndCredentials<TokenCredentials> credentials, Object scope) {
+      Id token = Id.create(credentials.credentials().id());
+      return Auth.create(Identity.create(singletonList("token"), token, null), scope);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/catalog/V3ServiceCatalog.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/catalog/V3ServiceCatalog.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/catalog/V3ServiceCatalog.java
new file mode 100644
index 0000000..0e86f2b
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/catalog/V3ServiceCatalog.java
@@ -0,0 +1,63 @@
+/*
+ * 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.catalog;
+
+import java.util.List;
+
+import javax.annotation.Resource;
+import javax.inject.Inject;
+import javax.inject.Singleton;
+
+import org.jclouds.logging.Logger;
+import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
+import org.jclouds.openstack.keystone.catalog.ServiceEndpoint;
+import org.jclouds.openstack.keystone.v3.domain.Catalog;
+import org.jclouds.openstack.keystone.v3.domain.Endpoint;
+import org.jclouds.openstack.keystone.v3.domain.Token;
+
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableList;
+
+@Singleton
+public class V3ServiceCatalog implements Supplier<List<ServiceEndpoint>> {
+
+   @Resource
+   private Logger logger = Logger.NULL;
+
+   private final Supplier<AuthInfo> authInfo;
+
+   @Inject
+   V3ServiceCatalog(Supplier<AuthInfo> authInfo) {
+      this.authInfo = authInfo;
+   }
+
+   @Override
+   public List<ServiceEndpoint> get() {
+      Token token = (Token) authInfo.get();
+
+      ImmutableList.Builder<ServiceEndpoint> serviceEndpoints = ImmutableList.builder();
+      for (Catalog catalog : token.catalog()) {
+         for (Endpoint endpoint : catalog.endpoints()) {
+            serviceEndpoints.add(ServiceEndpoint.builder().id(endpoint.id()).iface(endpoint.iface())
+                  .regionId(endpoint.regionId()).type(catalog.type()).url(endpoint.url()).build());
+         }
+      }
+
+      return serviceEndpoints.build();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/config/KeystoneHttpApiModule.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/config/KeystoneHttpApiModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/config/KeystoneHttpApiModule.java
new file mode 100644
index 0000000..1212680
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/config/KeystoneHttpApiModule.java
@@ -0,0 +1,37 @@
+/*
+ * 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.config;
+
+import org.jclouds.json.config.GsonModule;
+import org.jclouds.json.config.GsonModule.DateAdapter;
+import org.jclouds.openstack.keystone.v3.KeystoneApi;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.config.HttpApiModule;
+
+/**
+ * Configures the Keystone API.
+ */
+@ConfiguresHttpApi
+public class KeystoneHttpApiModule extends HttpApiModule<KeystoneApi> {
+
+   @Override
+   protected void configure() {
+      super.configure();
+      bind(DateAdapter.class).to(GsonModule.Iso8601DateAdapter.class);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/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
new file mode 100644
index 0000000..58c9ee6
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Auth.java
@@ -0,0 +1,166 @@
+/*
+ * 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.domain;
+
+import java.util.List;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Auth {
+   public abstract Identity identity();
+   @Nullable public abstract Object scope();
+
+   @SerializedNames({ "identity", "scope" })
+   public static Auth create(Identity identity, Object scope) {
+      return new AutoValue_Auth(identity, scope);
+   }
+   
+   @AutoValue
+   public abstract static class Identity {
+      public abstract List<String> methods();
+      @Nullable public abstract Id token();
+      @Nullable public abstract PasswordAuth password();
+
+      @SerializedNames({ "methods", "token", "password" })
+      public static Identity create(List<String> methods, Id token, PasswordAuth password) {
+         return new AutoValue_Auth_Identity(methods, token, password);
+      }
+
+      @AutoValue
+      public abstract static class PasswordAuth {
+         public abstract UserAuth user();
+
+         @SerializedNames({ "user" })
+         public static PasswordAuth create(UserAuth user) {
+            return new AutoValue_Auth_Identity_PasswordAuth(user);
+         }
+
+         @AutoValue
+         public abstract static class UserAuth {
+            public abstract String name();
+            public abstract DomainAuth domain();
+            public abstract String password();
+
+            @SerializedNames({ "name", "domain", "password" })
+            public static UserAuth create(String name, DomainAuth domain, String password) {
+               return new AutoValue_Auth_Identity_PasswordAuth_UserAuth(name, domain, password);
+            }
+
+            @AutoValue
+            public abstract static class DomainAuth {
+               @Nullable public abstract String name();
+
+               @SerializedNames({ "name" })
+               public static DomainAuth create(String name) {
+                  return new AutoValue_Auth_Identity_PasswordAuth_UserAuth_DomainAuth(name);
+               }
+            }
+         }
+      }
+   }
+   
+   @AutoValue
+   public abstract static class Id {
+      public abstract String id();
+
+      @SerializedNames({ "id" })
+      public static Id create(String id) {
+         return new AutoValue_Auth_Id(id);
+      }
+   }
+   
+   @AutoValue
+   public abstract static class Name {
+      @Nullable public abstract String name();
+
+      @SerializedNames({ "name" })
+      public static Name create(String name) {
+         return new AutoValue_Auth_Name(name);
+      }
+   }
+   
+   public static class Scope {
+      public static final String PROJECT = "project";
+      public static final String PROJECT_ID = "projectId";
+      public static final String DOMAIN = "domain";
+      public static final String DOMAIN_ID = "domainId";
+      public static final String UNSCOPED = "unscoped";
+   }
+
+   @AutoValue
+   public abstract static class ProjectScope {
+      public abstract ProjectName project();
+      
+      @SerializedNames({ Scope.PROJECT })
+      public static ProjectScope create(ProjectName project) {
+         return new AutoValue_Auth_ProjectScope(project);
+      }
+      
+      @AutoValue
+      public abstract static class ProjectName {
+         public abstract String name();
+         @Nullable public abstract Object domain();
+         
+         @SerializedNames({ "name", Scope.DOMAIN })
+         public static ProjectName create(String name, Object domain) {
+            return new AutoValue_Auth_ProjectScope_ProjectName(name, domain);
+         }
+         
+         public static ProjectName create(String name, Name domain) {
+            return new AutoValue_Auth_ProjectScope_ProjectName(name, domain);
+         }
+
+         public static ProjectName create(String name, Id domain) {
+            return new AutoValue_Auth_ProjectScope_ProjectName(name, domain);
+         }
+      }
+   }
+   
+   @AutoValue
+   public abstract static class ProjectIdScope {
+      public abstract Id project();
+
+      @SerializedNames({ Scope.PROJECT })
+      public static ProjectIdScope create(Id id) {
+         return new AutoValue_Auth_ProjectIdScope(id);
+      }
+   }
+   
+   @AutoValue
+   public abstract static class DomainIdScope {
+      public abstract Id domain();
+
+      @SerializedNames({ Scope.DOMAIN })
+      public static DomainIdScope create(Id id) {
+         return new AutoValue_Auth_DomainIdScope(id);
+      }
+   }
+   
+   @AutoValue
+   public abstract static class DomainScope {
+      public abstract Name domain();
+
+      @SerializedNames({ Scope.DOMAIN })
+      public static DomainScope create(Name name) {
+         return new AutoValue_Auth_DomainScope(name);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Catalog.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Catalog.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Catalog.java
new file mode 100644
index 0000000..8fa6b7d
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Catalog.java
@@ -0,0 +1,64 @@
+/*
+ * 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.domain;
+
+import java.util.List;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+
+@AutoValue
+public abstract class Catalog {
+
+   public abstract String id();
+   @Nullable public abstract String name();
+   public abstract String type();
+   public abstract List<Endpoint> endpoints();
+
+   @SerializedNames({ "id", "name", "type", "endpoints" })
+   public static Catalog create(String id, String name, String type, List<Endpoint> endpoints) {
+      return builder().id(id).name(name).type(type).endpoints(endpoints).build();
+   }
+
+   Catalog() {
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_Catalog.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder id(String id);
+      public abstract Builder name(String name);
+      public abstract Builder type(String type);
+      public abstract Builder endpoints(List<Endpoint> endpoints);
+
+      abstract List<Endpoint> endpoints();
+      abstract Catalog autoBuild();
+
+      public Catalog build() {
+         endpoints(endpoints() == null ? ImmutableList.<Endpoint> of() : ImmutableList.copyOf(endpoints()));
+         return autoBuild();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Endpoint.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Endpoint.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Endpoint.java
new file mode 100644
index 0000000..0c6b919
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Endpoint.java
@@ -0,0 +1,64 @@
+/*
+ * 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.domain;
+
+import java.net.URI;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Endpoint {
+
+   @Nullable public abstract String id();
+   @Nullable public abstract String region();
+   @Nullable public abstract String regionId();
+   @Nullable public abstract String serviceId();
+   public abstract URI url();
+   @Nullable public abstract Boolean enabled();
+   public abstract String iface();
+
+   @SerializedNames({ "id", "region", "region_id", "service_id", "url", "enabled", "interface" })
+   public static Endpoint create(String id, String region, String regionId, String serviceId, URI url, Boolean enabled,
+         String iface) {
+      return builder().id(serviceId).region(region).regionId(regionId).serviceId(serviceId).url(url).enabled(enabled)
+            .iface(iface).build();
+   }
+
+   Endpoint() {
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_Endpoint.Builder();
+   }
+   
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder id(String id);
+      public abstract Builder region(String region);
+      public abstract Builder regionId(String regionId);
+      public abstract Builder serviceId(String serviceId);
+      public abstract Builder url(URI url);
+      public abstract Builder enabled(Boolean enabled);
+      public abstract Builder iface(String iface);
+      public abstract Endpoint build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Group.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Group.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Group.java
new file mode 100644
index 0000000..ee2738a
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Group.java
@@ -0,0 +1,56 @@
+/*
+ * 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.domain;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Group {
+
+   public abstract String id();
+   public abstract String name();
+   @Nullable public abstract String description();
+   @Nullable public abstract String domainId();
+   @Nullable public abstract Link link();
+
+   @SerializedNames({ "id", "name", "description", "domain_id", "links" })
+   public static Group create(String id, String name, String description, String domainId, Link link) {
+      return builder().id(id).name(name).description(description).domainId(domainId).link(link).build();
+   }
+
+   Group() {
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_Group.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder id(String id);
+      public abstract Builder name(String String);
+      public abstract Builder description(String description);
+      public abstract Builder domainId(String domainId);
+      public abstract Builder link(Link link);
+      public abstract Group build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Link.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Link.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Link.java
new file mode 100644
index 0000000..0d86069
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Link.java
@@ -0,0 +1,36 @@
+/*
+ * 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.domain;
+
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Link {
+
+   public abstract String self();
+
+   @SerializedNames({"self"})
+   public static Link create(String self) {
+      return new AutoValue_Link(self);
+   }
+
+   Link() {
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Project.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Project.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Project.java
new file mode 100644
index 0000000..00ae34a
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Project.java
@@ -0,0 +1,79 @@
+/*
+ * 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.domain;
+
+import java.util.List;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+
+@AutoValue
+public abstract class Project {
+
+   public abstract boolean isDomain();
+   @Nullable public abstract String description();
+   @Nullable public abstract String domainId();
+   @Nullable public abstract String domainName();
+   public abstract boolean enabled();
+   @Nullable public abstract String id();
+   public abstract String name();
+   @Nullable public abstract String parentId();
+   @Nullable public abstract List<String> tags();
+   @Nullable public abstract Link link();
+
+   @SerializedNames({ "is_domain", "description", "domain_id", "domain_name", "enabled", "id", "name", "parent_id",
+         "tags", "links" })
+   public static Project create(boolean isDomain, String description, String domainId, String domainName,
+         boolean enabled, String id, String name, String parentId, List<String> tags, Link link) {
+      return builder().isDomain(isDomain).description(description).domainId(domainId).domainName(domainName)
+            .enabled(enabled).id(id).name(name).parentId(parentId).tags(tags).link(link).build();
+   }
+
+   Project() {
+   }
+   
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_Project.Builder().isDomain(false).enabled(true);
+   }
+   
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder isDomain(boolean isDomain);
+      public abstract Builder description(String description);
+      public abstract Builder domainId(String domainId);
+      public abstract Builder domainName(String domainName);
+      public abstract Builder enabled(boolean enabled);
+      public abstract Builder id(String id);
+      public abstract Builder name(String name);
+      public abstract Builder parentId(String parentId);
+      public abstract Builder tags(List<String> tags);
+      public abstract Builder link(Link link);
+      
+      abstract List<String> tags();
+      abstract Project autoBuild();
+      
+      public Project build() {
+         tags(tags() == null ? null : ImmutableList.copyOf(tags()));
+         return autoBuild();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Region.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Region.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Region.java
new file mode 100644
index 0000000..70598fe
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Region.java
@@ -0,0 +1,54 @@
+/*
+ * 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.domain;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class Region {
+
+   public abstract String id();
+   public abstract String description();
+   @Nullable public abstract Link link();
+   @Nullable public abstract String parentRegionId();
+
+   @SerializedNames({ "id", "description", "links", "parent_region_id" })
+   public static Region create(String id, String description, Link link, String parentRegionId) {
+      return builder().id(id).description(description).link(link).parentRegionId(parentRegionId).build();
+   }
+
+   Region() {
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_Region.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder id(String id);
+      public abstract Builder description(String name);
+      public abstract Builder link(Link link);
+      public abstract Builder parentRegionId(String parentRegionId);
+      public abstract Region build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Token.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Token.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Token.java
new file mode 100644
index 0000000..8fc20a8
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/Token.java
@@ -0,0 +1,87 @@
+/*
+ * 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.domain;
+
+import java.util.Date;
+import java.util.List;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+import org.jclouds.openstack.keystone.auth.domain.AuthInfo;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+
+@AutoValue
+public abstract class Token implements AuthInfo {
+
+   @Nullable public abstract String id();
+   public abstract List<String> methods();
+   @Nullable public abstract Date expiresAt();
+   @Nullable public abstract Object extras();
+   @Nullable public abstract List<Catalog> catalog();
+   @Nullable public abstract List<String> auditIds();
+   public abstract User user();
+   public abstract Date issuedAt();
+   
+   @Override
+   public String getAuthToken() {
+      return id();
+   }
+   
+   @SerializedNames({ "id", "methods", "expires_at", "extras", "catalog", "audit_ids", "user", "issued_at" })
+   private static Token create(String id, List<String> methods, Date expiresAt, Object extras, List<Catalog> catalog,
+         List<String> auditIds, User user, Date issuedAt) {
+      return builder().id(id).methods(methods).expiresAt(expiresAt).extras(extras).catalog(catalog).auditIds(auditIds)
+            .user(user).issuedAt(issuedAt).build();
+   }
+
+   Token() {
+   }
+
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_Token.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+
+      public abstract Builder id(String id);
+      public abstract Builder methods(List<String> methods);
+      public abstract Builder expiresAt(Date expiresAt);
+      public abstract Builder extras(Object extras);
+      public abstract Builder catalog(List<Catalog> catalog);
+      public abstract Builder auditIds(List<String> auditIds);
+      public abstract Builder user(User user);
+      public abstract Builder issuedAt(Date issuedAt);
+
+      abstract List<Catalog> catalog();
+      abstract List<String> methods();
+      abstract List<String> auditIds();
+
+      abstract Token autoBuild();
+
+      public Token build() {
+         return catalog(catalog() != null ? ImmutableList.copyOf(catalog()) : ImmutableList.<Catalog>of())
+                 .methods(methods() != null ? ImmutableList.copyOf(methods()) : ImmutableList.<String>of())
+                 .auditIds(auditIds() != null ? ImmutableList.copyOf(auditIds()) : ImmutableList.<String>of())
+                 .autoBuild();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/User.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/User.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/User.java
new file mode 100644
index 0000000..bda6411
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/domain/User.java
@@ -0,0 +1,77 @@
+/*
+ * 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.domain;
+
+import java.util.Date;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+@AutoValue
+public abstract class User {
+
+   @AutoValue
+   public abstract static class Domain {
+      public abstract String id();
+      public abstract String name();
+
+      @SerializedNames({ "id", "name" })
+      public static Domain create(String id, String name) {
+         return new AutoValue_User_Domain(id, name);
+      }
+   }
+
+   public abstract String id();
+   public abstract String name();
+   @Nullable public abstract Date passwordExpiresAt();
+   @Nullable public abstract Domain domain();
+   @Nullable public abstract String domainId();
+   @Nullable public abstract String defaultProjectId();
+   @Nullable public abstract Boolean enabled();
+   @Nullable public abstract Link link();
+
+   @SerializedNames({ "id", "name", "password_expires_at", "domain", "domain_id", "default_project_id", "enabled", "links" })
+   public static User create(String id, String name, Date passwordExpiresAt, Domain domain, String domainId,
+         String defaultProjectId, Boolean enabled, Link link) {
+      return builder().id(id).name(name).passwordExpiresAt(passwordExpiresAt).domain(domain).domainId(domainId)
+            .defaultProjectId(defaultProjectId).enabled(enabled).link(link).build();
+   }
+
+   User() {
+   }
+   
+   public abstract Builder toBuilder();
+
+   public static Builder builder() {
+      return new AutoValue_User.Builder();
+   }
+   
+   @AutoValue.Builder
+   public abstract static class Builder {
+      public abstract Builder id(String id);
+      public abstract Builder name(String name);
+      public abstract Builder passwordExpiresAt(Date passwordExpiresAt);
+      public abstract Builder domain(Domain domain);
+      public abstract Builder domainId(String domainId);
+      public abstract Builder defaultProjectId(String defaultProjectId);
+      public abstract Builder enabled(Boolean enabled);
+      public abstract Builder link(Link link);
+      public abstract User build();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/AuthApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/AuthApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/AuthApi.java
new file mode 100644
index 0000000..845c738
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/AuthApi.java
@@ -0,0 +1,84 @@
+/*
+ * 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.features;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
+import org.jclouds.openstack.keystone.v3.domain.Token;
+import org.jclouds.openstack.keystone.v3.domain.User;
+import org.jclouds.openstack.v2_0.services.Identity;
+import org.jclouds.rest.annotations.Endpoint;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.Headers;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+
+/**
+ * Provides access to the Keystone Authentication API.
+ */
+@Consumes(MediaType.APPLICATION_JSON)
+@RequestFilters(AuthenticateRequest.class)
+@Endpoint(Identity.class)
+@Path("/auth")
+public interface AuthApi {
+
+   /**
+    * Validate a token and, if it is valid, return access information regarding the tenant (though not the service catalog).
+    */
+   @Named("token:get")
+   @GET
+   @SelectJson("token")
+   @Path("/tokens")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   @Headers(keys = "X-Subject-Token", values = "{token}")
+   Token get(@PathParam("token") String token);
+
+   /**
+    * Validate a token and, if it is valid, return access information regarding the tenant (though not the service catalog).
+    */
+   @Named("token:getuser")
+   @GET
+   @SelectJson("user")
+   @Path("/tokens")
+   @Fallback(NullOnNotFoundOr404.class)
+   @Nullable
+   @Headers(keys = "X-Subject-Token", values = "{token}")
+   User getUserOfToken(@PathParam("token") String token);
+
+   /**
+    * Validate a token. This is a high-performance variant of the #getToken() call that does not return any further
+    * information.
+    */
+   @Named("token:check")
+   @HEAD
+   @Path("/tokens")
+   @Headers(keys = "X-Subject-Token", values = "{token}")
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean isValid(@PathParam("token") String token);
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/CatalogApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/CatalogApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/CatalogApi.java
new file mode 100644
index 0000000..c29f299
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/CatalogApi.java
@@ -0,0 +1,54 @@
+/*
+ * 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.features;
+
+import java.util.List;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.GET;
+import javax.ws.rs.Path;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
+import org.jclouds.openstack.keystone.v3.domain.Endpoint;
+import org.jclouds.openstack.v2_0.services.Identity;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+
+/**
+ * Provides access to the Keystone Admin API.
+ */
+@Consumes(MediaType.APPLICATION_JSON)
+@RequestFilters(AuthenticateRequest.class)
+@org.jclouds.rest.annotations.Endpoint(Identity.class)
+public interface CatalogApi {
+
+   /**
+    * List all endpoints for a token.
+    * <p>
+    * NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/988672 )
+    */
+   @Named("endpoints:list")
+   @GET
+   @SelectJson("endpoints")
+   @Path("/endpoints")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<Endpoint> endpoints();
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/ProjectApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/ProjectApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/ProjectApi.java
new file mode 100644
index 0000000..494e851
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/ProjectApi.java
@@ -0,0 +1,124 @@
+/*
+ * 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.features;
+
+import java.util.List;
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.HEAD;
+import javax.ws.rs.POST;
+import javax.ws.rs.PUT;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
+import org.jclouds.openstack.keystone.v3.domain.Project;
+import org.jclouds.openstack.v2_0.services.Identity;
+import org.jclouds.rest.annotations.Endpoint;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.MapBinder;
+import org.jclouds.rest.annotations.PATCH;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.WrapWith;
+import org.jclouds.rest.binders.BindToJsonPayload;
+
+/**
+ * Provides access to the Keystone Projects API.
+ */
+@Consumes(MediaType.APPLICATION_JSON)
+@RequestFilters(AuthenticateRequest.class)
+@Endpoint(Identity.class)
+@Path("/projects")
+public interface ProjectApi {
+
+   @Named("projects:list")
+   @GET
+   @SelectJson("projects")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<Project> list();
+   
+   @Named("projects:get")
+   @GET
+   @Path("/{id}")
+   @SelectJson("project")
+   @Fallback(NullOnNotFoundOr404.class)
+   Project get(@PathParam("id") String id);
+   
+   @Named("projects:create")
+   @POST
+   @SelectJson("project")
+   @WrapWith("project") 
+   Project create(@PayloadParam("name") String name, @Nullable @PayloadParam("description") String description,
+         @PayloadParam("enabled") boolean enabled, @PayloadParam("is_domain") boolean isDomain,
+         @Nullable @PayloadParam("domain_id") String domainId, @Nullable @PayloadParam("parent_id") String parentId);
+   
+   @Named("projects:update")
+   @PATCH
+   @Path("/{id}")
+   @SelectJson("project")
+   Project update(@PathParam("id") String id, @WrapWith("project") Project project);
+   
+   @Named("projects:delete")
+   @DELETE
+   @Path("/{id}")
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean delete(@PathParam("id") String id);
+   
+   @Named("projects:listTags")
+   @GET
+   @Path("/{projectId}/tags")
+   @SelectJson("tags")
+   Set<String> listTags(@PathParam("projectId") String projectId);
+   
+   @Named("projects:hasTag")
+   @HEAD
+   @Path("/{projectId}/tags/{tag}")
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean hasTag(@PathParam("projectId") String projectId, @PathParam("tag") String tag);
+   
+   @Named("projects:addTag")
+   @PUT
+   @Path("/{projectId}/tags/{tag}")
+   void addTag(@PathParam("projectId") String projectId, @PathParam("tag") String tag);
+   
+   @Named("projects:removeTag")
+   @DELETE
+   @Path("/{projectId}/tags/{tag}")
+   void removeTag(@PathParam("projectId") String projectId, @PathParam("tag") String tag);
+   
+   @Named("projects:setTags")
+   @PUT
+   @Path("/{projectId}/tags")
+   @MapBinder(BindToJsonPayload.class)
+   void setTags(@PathParam("projectId") String projectId, @PayloadParam("tags") Set<String> tags);
+   
+   @Named("projects:removeTags")
+   @DELETE
+   @Path("/{projectId}/tags")
+   void removeAllTags(@PathParam("projectId") String projectId);
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/RegionApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/RegionApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/RegionApi.java
new file mode 100644
index 0000000..c21716f
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/RegionApi.java
@@ -0,0 +1,87 @@
+/*
+ * 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.features;
+
+import java.util.List;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
+import org.jclouds.openstack.keystone.v3.domain.Region;
+import org.jclouds.openstack.v2_0.services.Identity;
+import org.jclouds.rest.annotations.Endpoint;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.PATCH;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.WrapWith;
+
+/**
+ * Provides access to the Keystone Region API.
+ */
+@Consumes(MediaType.APPLICATION_JSON)
+@RequestFilters(AuthenticateRequest.class)
+@Endpoint(Identity.class)
+@Path("/regions")
+public interface RegionApi {
+
+   @Named("regions:list")
+   @GET
+   @SelectJson("regions")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<Region> list();
+
+   @Named("regions:get")
+   @GET
+   @Path("/{id}")
+   @SelectJson("region")
+   @Fallback(NullOnNotFoundOr404.class)
+   Region get(@PathParam("id") String id);
+
+   @Named("regions:create")
+   @POST
+   @SelectJson("region")
+   @WrapWith("region")
+   Region create(@PayloadParam("id") String id, @Nullable @PayloadParam("description") String description,
+         @Nullable @PayloadParam("parent_region_id") String parentId);
+
+   @Named("regions:update")
+   @PATCH
+   @Path("/{id}")
+   @SelectJson("region")
+   @WrapWith("region")
+   Region update(@PathParam("id") String id, @Nullable @PayloadParam("description") String description,
+         @Nullable @PayloadParam("parent_region_id") String parentId);
+
+   @Named("regions:delete")
+   @DELETE
+   @Path("/{id}")
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean delete(@PathParam("id") String id);
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/dd73410d/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/UserApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/UserApi.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/UserApi.java
new file mode 100644
index 0000000..1617b51
--- /dev/null
+++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v3/features/UserApi.java
@@ -0,0 +1,111 @@
+/*
+ * 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.features;
+
+import java.util.List;
+
+import javax.inject.Named;
+import javax.ws.rs.Consumes;
+import javax.ws.rs.DELETE;
+import javax.ws.rs.GET;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+import javax.ws.rs.PathParam;
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.Fallbacks.EmptyListOnNotFoundOr404;
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.openstack.keystone.auth.filters.AuthenticateRequest;
+import org.jclouds.openstack.keystone.v3.domain.Group;
+import org.jclouds.openstack.keystone.v3.domain.Project;
+import org.jclouds.openstack.keystone.v3.domain.User;
+import org.jclouds.openstack.v2_0.services.Identity;
+import org.jclouds.rest.annotations.Endpoint;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.PATCH;
+import org.jclouds.rest.annotations.PayloadParam;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SelectJson;
+import org.jclouds.rest.annotations.WrapWith;
+
+/**
+ * Provides access to the Keystone User API.
+ */
+@Consumes(MediaType.APPLICATION_JSON)
+@RequestFilters(AuthenticateRequest.class)
+@Endpoint(Identity.class)
+@Path("/users")
+public interface UserApi {
+
+   @Named("users:list")
+   @GET
+   @SelectJson("users")
+   @Fallback(EmptyListOnNotFoundOr404.class)
+   List<User> list();
+
+   @Named("users:get")
+   @GET
+   @Path("/{id}")
+   @SelectJson("user")
+   @Fallback(NullOnNotFoundOr404.class)
+   User get(@PathParam("id") String id);
+
+   @Named("users:create")
+   @POST
+   @SelectJson("user")
+   @WrapWith("user")
+   User create(@PayloadParam("name") String name, @Nullable @PayloadParam("password") String password,
+         @Nullable @PayloadParam("enabled") Boolean enabled, @Nullable @PayloadParam("domain_id") String domainId,
+         @Nullable @PayloadParam("default_project_id") String defaultProjectId);
+
+   @Named("users:update")
+   @PATCH
+   @Path("/{id}")
+   @SelectJson("user")
+   @WrapWith("user")
+   User update(@PathParam("id") String id, @PayloadParam("name") String name,
+         @Nullable @PayloadParam("password") String password, @Nullable @PayloadParam("enabled") Boolean enabled,
+         @Nullable @PayloadParam("domain_id") String domainId,
+         @Nullable @PayloadParam("default_project_id") String defaultProjectId);
+
+   @Named("users:delete")
+   @DELETE
+   @Path("/{id}")
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean delete(@PathParam("id") String id);
+
+   @Named("users:groups")
+   @GET
+   @Path("/{id}/groups")
+   @SelectJson("groups")
+   List<Group> listGroups(@PathParam("id") String id);
+
+   @Named("users:projects")
+   @GET
+   @Path("/{id}/projects")
+   @SelectJson("projects")
+   List<Project> listProjects(@PathParam("id") String id);
+
+   @Named("users:password")
+   @POST
+   @Path("/{id}/password")
+   @WrapWith("user")
+   void changePassword(@PathParam("id") String id, @PayloadParam("original_password") String originalPassword,
+         @PayloadParam("password") String newPassword);
+}