diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncClient.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncClient.java index c8b515235b..170f4c19c3 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncClient.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationAsyncClient.java @@ -23,6 +23,7 @@ import javax.ws.rs.POST; import javax.ws.rs.Path; import javax.ws.rs.core.MediaType; +import org.jclouds.javax.annotation.Nullable; import org.jclouds.openstack.keystone.v2_0.binders.BindAuthToJsonPayload; import org.jclouds.openstack.keystone.v2_0.domain.Access; import org.jclouds.openstack.keystone.v2_0.domain.ApiAccessKeyCredentials; @@ -53,7 +54,7 @@ public interface AuthenticationAsyncClient { @Consumes(MediaType.APPLICATION_JSON) @Path("/tokens") @MapBinder(BindAuthToJsonPayload.class) - ListenableFuture authenticateWithTenantNameAndCredentials(@PayloadParam("tenantName") String tenantName, + ListenableFuture authenticateWithTenantNameAndCredentials(@Nullable @PayloadParam("tenantName") String tenantName, PasswordCredentials passwordCredentials); /** @@ -64,7 +65,7 @@ public interface AuthenticationAsyncClient { @Consumes(MediaType.APPLICATION_JSON) @Path("/tokens") @MapBinder(BindAuthToJsonPayload.class) - ListenableFuture authenticateWithTenantIdAndCredentials(@PayloadParam("tenantId") String tenantId, + ListenableFuture authenticateWithTenantIdAndCredentials(@Nullable @PayloadParam("tenantId") String tenantId, PasswordCredentials passwordCredentials); /** @@ -77,7 +78,7 @@ public interface AuthenticationAsyncClient { @MapBinder(BindAuthToJsonPayload.class) // TODO: is tenantName permanent? or should we switch to tenantId at some point. seems most tools // still use tenantName - ListenableFuture authenticateWithTenantNameAndCredentials(@PayloadParam("tenantName") String tenantName, + ListenableFuture authenticateWithTenantNameAndCredentials(@Nullable @PayloadParam("tenantName") String tenantName, ApiAccessKeyCredentials apiAccessKeyCredentials); /** @@ -88,6 +89,6 @@ public interface AuthenticationAsyncClient { @Consumes(MediaType.APPLICATION_JSON) @Path("/tokens") @MapBinder(BindAuthToJsonPayload.class) - ListenableFuture authenticateWithTenantIdAndCredentials(@PayloadParam("tenantId") String tenantId, + ListenableFuture authenticateWithTenantIdAndCredentials(@Nullable @PayloadParam("tenantId") String tenantId, ApiAccessKeyCredentials apiAccessKeyCredentials); } diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationClient.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationClient.java index 167f6bb99f..fc701f50b1 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationClient.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/AuthenticationClient.java @@ -21,6 +21,7 @@ package org.jclouds.openstack.keystone.v2_0; import java.util.concurrent.TimeUnit; import org.jclouds.concurrent.Timeout; +import org.jclouds.javax.annotation.Nullable; import org.jclouds.openstack.keystone.v2_0.domain.Access; import org.jclouds.openstack.keystone.v2_0.domain.ApiAccessKeyCredentials; import org.jclouds.openstack.keystone.v2_0.domain.PasswordCredentials; @@ -42,26 +43,26 @@ public interface AuthenticationClient { * * @return access with token */ - Access authenticateWithTenantNameAndCredentials(String tenantId, PasswordCredentials passwordCredentials); + Access authenticateWithTenantNameAndCredentials(@Nullable String tenantId, PasswordCredentials passwordCredentials); /** * Authenticate to generate a token. * * @return access with token */ - Access authenticateWithTenantIdAndCredentials(String tenantId, PasswordCredentials passwordCredentials); + Access authenticateWithTenantIdAndCredentials(@Nullable String tenantId, PasswordCredentials passwordCredentials); /** * Authenticate to generate a token. * * @return access with token */ - Access authenticateWithTenantNameAndCredentials(String tenantId, ApiAccessKeyCredentials passwordCredentials); + Access authenticateWithTenantNameAndCredentials(@Nullable String tenantId, ApiAccessKeyCredentials passwordCredentials); /** * Authenticate to generate a token. * * @return access with token */ - Access authenticateWithTenantIdAndCredentials(String tenantId, ApiAccessKeyCredentials passwordCredentials); + Access authenticateWithTenantIdAndCredentials(@Nullable String tenantId, ApiAccessKeyCredentials passwordCredentials); } \ No newline at end of file diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java index a9c8f69310..c15f193b99 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneApiMetadata.java @@ -18,12 +18,14 @@ */ package org.jclouds.openstack.keystone.v2_0; +import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE; import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE; import java.net.URI; import java.util.Properties; import org.jclouds.apis.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes; import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties; import org.jclouds.openstack.keystone.v2_0.config.KeystoneRestClientModule; import org.jclouds.openstack.v2_0.ServiceType; @@ -44,19 +46,18 @@ public class KeystoneApiMetadata extends BaseRestApiMetadata { /** The serialVersionUID */ private static final long serialVersionUID = 6725672099385580694L; - public static final TypeToken> CONTEXT_TOKEN = new TypeToken>() { - - /** The serialVersionUID */ - private static final long serialVersionUID = 3030344682235783904L; + + public static final TypeToken> CONTEXT_TOKEN = new TypeToken>() { + private static final long serialVersionUID = -5070937833892503232L; }; @Override public Builder toBuilder() { - return new Builder().fromApiMetadata(this); + return (Builder) new Builder(getApi(), getAsyncApi()).fromApiMetadata(this); } public KeystoneApiMetadata() { - this(new Builder()); + this(new Builder(KeystoneClient.class, KeystoneAsyncClient.class)); } protected KeystoneApiMetadata(Builder builder) { @@ -67,14 +68,15 @@ public class KeystoneApiMetadata extends BaseRestApiMetadata { Properties properties = BaseRestApiMetadata.defaultProperties(); // TODO: this doesn't actually do anything yet. properties.setProperty(KeystoneProperties.VERSION, "2.0"); + properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS); properties.put(SERVICE_TYPE, ServiceType.IDENTITY); return properties; } public static class Builder extends BaseRestApiMetadata.Builder { - protected Builder() { - super(KeystoneClient.class, KeystoneAsyncClient.class); + protected Builder(Class api, Class asyncApi) { + super(api, asyncApi); id("openstack-keystone") .name("OpenStack Keystone Essex+ API") .identityName("tenantId:user") diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneAsyncClient.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneAsyncClient.java index 1d23d251f4..c05af31d49 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneAsyncClient.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneAsyncClient.java @@ -18,21 +18,22 @@ */ package org.jclouds.openstack.keystone.v2_0; -import java.util.Set; - +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; import javax.ws.rs.Path; +import javax.ws.rs.core.MediaType; import org.jclouds.Constants; -import org.jclouds.javax.annotation.Nullable; -import org.jclouds.location.Region; -import org.jclouds.location.functions.RegionToEndpoint; -import org.jclouds.openstack.keystone.v2_0.features.AdminAsyncClient; -import org.jclouds.openstack.keystone.v2_0.features.ServiceAsyncClient; -import org.jclouds.openstack.keystone.v2_0.functions.RegionToAdminEndpointURI; +import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.features.TenantAsyncClient; +import org.jclouds.openstack.keystone.v2_0.features.TokenAsyncClient; +import org.jclouds.openstack.keystone.v2_0.features.UserAsyncClient; import org.jclouds.rest.annotations.Delegate; -import org.jclouds.rest.annotations.EndpointParam; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; -import com.google.inject.Provides; +import com.google.common.util.concurrent.ListenableFuture; /** * Provides access to Openstack keystone resources via their REST API. @@ -42,20 +43,34 @@ import com.google.inject.Provides; * @see * @see KeystoneClient */ -@Path("/v{" + Constants.PROPERTY_API_VERSION + "}") public interface KeystoneAsyncClient { + /** - * @return the Region codes configured + * @see KeystoneClient#getApiMetadata() */ - @Provides - @Region - Set getConfiguredRegions(); + @GET + @SelectJson("version") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/v{" + Constants.PROPERTY_API_VERSION + "}/") + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getApiMetadata(); - /** Provides asynchronous access to Identity user-accessible features */ + /** + * @see KeystoneClient#getTokenClient() + */ @Delegate - ServiceAsyncClient getServiceClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region); + TokenAsyncClient getTokenClient(); - /** Provides asynchronous access to the KeyStone Admin API */ + /** + * @see KeystoneClient#getUserClient() + */ @Delegate - AdminAsyncClient getAdminClientForRegion(@EndpointParam(parser = RegionToAdminEndpointURI.class) @Nullable String region); + UserAsyncClient getUserClient(); + + + /** + * @see KeystoneClient#getTenantClient() + */ + @Delegate + TenantAsyncClient getTenantClient(); } diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneClient.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneClient.java index ae23238227..a73f75859b 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneClient.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/KeystoneClient.java @@ -18,20 +18,14 @@ */ package org.jclouds.openstack.keystone.v2_0; -import java.util.Set; import java.util.concurrent.TimeUnit; import org.jclouds.concurrent.Timeout; -import org.jclouds.javax.annotation.Nullable; -import org.jclouds.location.Region; -import org.jclouds.location.functions.RegionToEndpoint; -import org.jclouds.openstack.keystone.v2_0.features.AdminClient; -import org.jclouds.openstack.keystone.v2_0.features.ServiceClient; -import org.jclouds.openstack.keystone.v2_0.functions.RegionToAdminEndpointURI; +import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.features.TenantClient; +import org.jclouds.openstack.keystone.v2_0.features.TokenClient; +import org.jclouds.openstack.keystone.v2_0.features.UserClient; import org.jclouds.rest.annotations.Delegate; -import org.jclouds.rest.annotations.EndpointParam; - -import com.google.inject.Provides; /** * Provides access to Openstack keystone resources via their REST API. @@ -39,22 +33,34 @@ import com.google.inject.Provides; * * @author Adam Lowe * @see + * @see KeystoneAsyncClient */ @Timeout(duration = 10, timeUnit = TimeUnit.SECONDS) public interface KeystoneClient { + /** - * @return the Region codes configured + * Discover API version information, links to documentation (PDF, HTML, WADL), and supported media types + * + * @return the requested information */ - @Provides - @Region - Set getConfiguredRegions(); + ApiMetadata getApiMetadata(); - /** Provides synchronous access to Identity user-accessible features */ + /** + * Provides synchronous access to Token features + */ @Delegate - ServiceClient getServiceClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region); + TokenClient getTokenClient(); - /** Provides synchronous access to the KeyStone Admin API */ + /** + * Provides synchronous access to User features + */ @Delegate - AdminClient getAdminClientForRegion(@EndpointParam(parser = RegionToAdminEndpointURI.class) @Nullable String region); + UserClient getUserClient(); + + /** + * Provides synchronous access to Tenant features + */ + @Delegate + TenantClient getTenantClient(); } \ No newline at end of file diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/binders/BindAuthToJsonPayload.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/binders/BindAuthToJsonPayload.java index 87f583db2c..77f37fb4dd 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/binders/BindAuthToJsonPayload.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/binders/BindAuthToJsonPayload.java @@ -29,14 +29,15 @@ import javax.inject.Singleton; import org.jclouds.http.HttpRequest; import org.jclouds.json.Json; -import org.jclouds.openstack.keystone.v2_0.domain.ApiAccessKeyCredentials; -import org.jclouds.openstack.keystone.v2_0.domain.PasswordCredentials; +import org.jclouds.openstack.keystone.v2_0.config.CredentialType; import org.jclouds.rest.MapBinder; import org.jclouds.rest.binders.BindToJsonPayload; import org.jclouds.rest.internal.GeneratedHttpRequest; +import com.google.common.base.Predicates; import com.google.common.base.Strings; import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Iterables; import com.google.common.collect.ImmutableMap.Builder; /** @@ -57,11 +58,9 @@ public class BindAuthToJsonPayload extends BindToJsonPayload implements MapBinde } protected void addCredentialsInArgsOrNull(GeneratedHttpRequest gRequest, Builder builder) { - for (Object arg : gRequest.getArgs()) { - if (arg instanceof PasswordCredentials) { - builder.put("passwordCredentials", PasswordCredentials.class.cast(arg)); - } else if (arg instanceof ApiAccessKeyCredentials) { - builder.put("apiAccessKeyCredentials", ApiAccessKeyCredentials.class.cast(arg)); + for (Object arg : Iterables.filter(gRequest.getArgs(), Predicates.notNull())) { + if (arg.getClass().isAnnotationPresent(CredentialType.class)) { + builder.put(arg.getClass().getAnnotation(CredentialType.class).value(), arg); } } } diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialType.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialType.java index c168ccc666..4509b40198 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialType.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialType.java @@ -18,29 +18,25 @@ */ package org.jclouds.openstack.keystone.v2_0.config; -import static com.google.common.base.Preconditions.checkNotNull; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; -import com.google.common.base.CaseFormat; +import javax.inject.Qualifier; /** - * Configuration properties and constants used in Keystone connections. - * + * @see CredentialTypes * @author Adrian Cole + * */ -public enum CredentialType { - - API_ACCESS_KEY_CREDENTIALS, - - PASSWORD_CREDENTIALS; - - @Override - public String toString() { - return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name()); - } - - public static CredentialType fromValue(String credentialType) { - return valueOf(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(credentialType, - "credentialType"))); - } - -} +@Retention(value = RetentionPolicy.RUNTIME) +@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD }) +@Qualifier +public @interface CredentialType { + /** + * @see CredentialTypes + * + */ + String value(); +} \ No newline at end of file diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialTypes.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialTypes.java new file mode 100644 index 0000000000..42035496f2 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/CredentialTypes.java @@ -0,0 +1,56 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.config; + +import static com.google.common.base.Preconditions.checkArgument; + +import java.util.Map; + +import com.google.common.base.Function; +import com.google.common.collect.Maps; + +/** + * Configuration properties and constants used in Keystone connections. + * + * @author Adrian Cole + */ +public class CredentialTypes { + + public static final String API_ACCESS_KEY_CREDENTIALS = "apiAccessKeyCredentials"; + + public static final String PASSWORD_CREDENTIALS = "passwordCredentials"; + + public static String credentialTypeOf(T input) { + Class authenticationType = input.getClass(); + checkArgument(authenticationType.isAnnotationPresent(CredentialType.class), + "programming error: %s should have annotation %s", authenticationType, CredentialType.class.getName()); + return authenticationType.getAnnotation(CredentialType.class).value(); + } + + public static Map indexByCredentialType(Iterable iterable) { + return Maps.uniqueIndex(iterable, new Function() { + + @Override + public String apply(T input) { + return credentialTypeOf(input); + } + + }); + } +} diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java index 5379e3f4f1..c556487086 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java @@ -18,9 +18,11 @@ */ package org.jclouds.openstack.keystone.v2_0.config; +import static com.google.common.base.Preconditions.checkArgument; import static com.google.common.base.Throwables.propagate; import static org.jclouds.rest.config.BinderUtils.bindClientAndAsyncClient; +import java.util.Map; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -45,10 +47,10 @@ import org.jclouds.openstack.keystone.v2_0.domain.Access; import org.jclouds.openstack.keystone.v2_0.functions.AuthenticateApiAccessKeyCredentials; import org.jclouds.openstack.keystone.v2_0.functions.AuthenticatePasswordCredentials; import org.jclouds.openstack.keystone.v2_0.handlers.RetryOnRenew; -import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURIFromAccessForTypeAndVersionSupplier; +import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURIFromAccessForTypeAndVersion; import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURISupplier; -import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToURIFromAccessForTypeAndVersionSupplier; -import org.jclouds.openstack.keystone.v2_0.suppliers.ZoneIdToURIFromAccessForTypeAndVersionSupplier; +import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToURIFromAccessForTypeAndVersion; +import org.jclouds.openstack.keystone.v2_0.suppliers.ZoneIdToURIFromAccessForTypeAndVersion; import org.jclouds.rest.annotations.ApiVersion; import com.google.common.base.Function; @@ -56,8 +58,10 @@ import com.google.common.base.Supplier; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; +import com.google.common.collect.ImmutableSet; +import com.google.common.collect.ImmutableSet.Builder; import com.google.inject.AbstractModule; -import com.google.inject.Inject; +import com.google.inject.Injector; import com.google.inject.Module; import com.google.inject.Provides; import com.google.inject.assistedinject.FactoryModuleBuilder; @@ -76,18 +80,24 @@ public class KeystoneAuthenticationModule extends AbstractModule { protected KeystoneAuthenticationModule(Module locationModule) { this.locationModule = locationModule; } - - public static Module forRegions() { - return new KeystoneAuthenticationModule(new RegionModule()); + + public static class KeystoneAuthenticationModuleForRegions extends KeystoneAuthenticationModule { + public KeystoneAuthenticationModuleForRegions() { + super(new RegionModule()); + } } + public static Module forRegions() { + return new KeystoneAuthenticationModuleForRegions(); + } + public static class RegionModule extends AbstractModule { @Override protected void configure() { install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class, - RegionIdToURIFromAccessForTypeAndVersionSupplier.class).build(RegionIdToURISupplier.Factory.class)); + RegionIdToURIFromAccessForTypeAndVersion.class).build(RegionIdToURISupplier.Factory.class)); install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class, - RegionIdToAdminURIFromAccessForTypeAndVersionSupplier.class).build(RegionIdToAdminURISupplier.Factory.class)); + RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class)); // dynamically build the region list as opposed to from properties bind(RegionIdsSupplier.class).to(RegionIdsFromRegionIdToURIKeySet.class); } @@ -101,14 +111,15 @@ public class KeystoneAuthenticationModule extends AbstractModule { RegionIdToURISupplier.Factory factory) { return factory.createForApiTypeAndVersion(serviceType, apiVersion); } - - // supply the region to id to AdminURL map from keystone, based on the servicetype and api version in + + // supply the region to id to AdminURL map from keystone, based on the servicetype and api + // version in // config @Provides @Singleton protected RegionIdToAdminURISupplier provideRegionIdToAdminURISupplierForApiVersion( - @Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion, - RegionIdToAdminURISupplier.Factory factory) { + @Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion, + RegionIdToAdminURISupplier.Factory factory) { return factory.createForApiTypeAndVersion(serviceType, apiVersion); } @@ -118,7 +129,7 @@ public class KeystoneAuthenticationModule extends AbstractModule { @Override protected void configure() { install(new FactoryModuleBuilder().implement(ZoneIdToURISupplier.class, - ZoneIdToURIFromAccessForTypeAndVersionSupplier.class).build(ZoneIdToURISupplier.Factory.class)); + ZoneIdToURIFromAccessForTypeAndVersion.class).build(ZoneIdToURISupplier.Factory.class)); // dynamically build the zone list as opposed to from properties bind(ZoneIdsSupplier.class).to(ZoneIdsFromZoneIdToURIKeySet.class); } @@ -135,18 +146,27 @@ public class KeystoneAuthenticationModule extends AbstractModule { } + public static class KeystoneAuthenticationModuleForZones extends KeystoneAuthenticationModule { + public KeystoneAuthenticationModuleForZones() { + super(new ZoneModule()); + } + } + public static Module forZones() { - return new KeystoneAuthenticationModule(new ZoneModule()); + return new KeystoneAuthenticationModuleForZones(); } @Override protected void configure() { bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class); - bind(CredentialType.class).toProvider(CredentialTypeFromPropertyOrDefault.class); - // ServiceClient is used directly for filters and retry handlers, so let's bind it + bindAuthenticationClient(); + install(locationModule); + } + + protected void bindAuthenticationClient() { + // AuthenticationClient is used directly for filters and retry handlers, so let's bind it // explicitly bindClientAndAsyncClient(binder(), AuthenticationClient.class, AuthenticationAsyncClient.class); - install(locationModule); } /** @@ -164,41 +184,25 @@ public class KeystoneAuthenticationModule extends AbstractModule { }; } + @Provides @Singleton - static class CredentialTypeFromPropertyOrDefault implements javax.inject.Provider { - /** - * use optional injection to supply a default value for credential type. so that we don't have - * to set a default property. - */ - @Inject(optional = true) - @Named(KeystoneProperties.CREDENTIAL_TYPE) - String credentialType = CredentialType.PASSWORD_CREDENTIALS.toString(); - - @Override - public CredentialType get() { - return CredentialType.fromValue(credentialType); - } + protected Map> authenticationMethods(Injector i) { + Builder> fns = ImmutableSet.> builder(); + fns.add(i.getInstance(AuthenticatePasswordCredentials.class)); + fns.add(i.getInstance(AuthenticateApiAccessKeyCredentials.class)); + return CredentialTypes.indexByCredentialType(fns.build()); } @Provides @Singleton - protected Function authenticationMethodForCredentialType(CredentialType credentialType, - AuthenticatePasswordCredentials authenticatePasswordCredentials, - AuthenticateApiAccessKeyCredentials authenticateApiAccessKeyCredentials) { - Function authMethod; - switch (credentialType) { - case PASSWORD_CREDENTIALS: - authMethod = authenticatePasswordCredentials; - break; - case API_ACCESS_KEY_CREDENTIALS: - authMethod = authenticateApiAccessKeyCredentials; - break; - default: - throw new IllegalArgumentException("credential type not supported: " + credentialType); - } + protected Function authenticationMethodForCredentialType( + @Named(KeystoneProperties.CREDENTIAL_TYPE) String credentialType, + Map> authenticationMethods) { + checkArgument(authenticationMethods.containsKey(credentialType), "credential type %s not in supported list: %s", + credentialType, authenticationMethods.keySet()); // regardless of how we authenticate, we should retry if there is a timeout exception logging // in. - return new RetryOnTimeOutExceptionFunction(authMethod); + return new RetryOnTimeOutExceptionFunction(authenticationMethods.get(credentialType)); } // TODO: what is the timeout of the session token? modify default accordingly diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneProperties.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneProperties.java index a180e101d6..1865c23373 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneProperties.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneProperties.java @@ -36,7 +36,7 @@ public interface KeystoneProperties { *
  • passwordCredentials
  • * * - * @see CredentialType + * @see CredentialTypes * @see
    */ diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneRestClientModule.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneRestClientModule.java index 7a07dd6444..4e6c9c10e3 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneRestClientModule.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneRestClientModule.java @@ -26,15 +26,19 @@ import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.ServerError; import org.jclouds.openstack.keystone.v2_0.KeystoneAsyncClient; import org.jclouds.openstack.keystone.v2_0.KeystoneClient; -import org.jclouds.openstack.keystone.v2_0.features.AdminAsyncClient; -import org.jclouds.openstack.keystone.v2_0.features.AdminClient; -import org.jclouds.openstack.keystone.v2_0.features.ServiceAsyncClient; -import org.jclouds.openstack.keystone.v2_0.features.ServiceClient; +import org.jclouds.openstack.keystone.v2_0.features.TenantAsyncClient; +import org.jclouds.openstack.keystone.v2_0.features.TenantClient; +import org.jclouds.openstack.keystone.v2_0.features.TokenAsyncClient; +import org.jclouds.openstack.keystone.v2_0.features.TokenClient; +import org.jclouds.openstack.keystone.v2_0.features.UserAsyncClient; +import org.jclouds.openstack.keystone.v2_0.features.UserClient; import org.jclouds.openstack.keystone.v2_0.handlers.KeystoneErrorHandler; import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.config.RestClientModule; import com.google.common.collect.ImmutableMap; +import com.google.common.reflect.TypeToken; +import com.google.inject.util.Modules; /** * Configures the Keystone connection. @@ -42,15 +46,22 @@ import com.google.common.collect.ImmutableMap; * @author Adam Lowe */ @ConfiguresRestClient -public class KeystoneRestClientModule extends RestClientModule { +public class KeystoneRestClientModule extends RestClientModule { public static final Map, Class> DELEGATE_MAP = ImmutableMap., Class> builder() - .put(ServiceClient.class, ServiceAsyncClient.class) - .put(AdminClient.class, AdminAsyncClient.class) + .put(TokenClient.class, TokenAsyncClient.class) + .put(UserClient.class, UserAsyncClient.class) + .put(TenantClient.class, TenantAsyncClient.class) .build(); - + + @SuppressWarnings("unchecked") public KeystoneRestClientModule() { - super(DELEGATE_MAP); + super((TypeToken) TypeToken.of(KeystoneClient.class), (TypeToken) TypeToken.of(KeystoneAsyncClient.class), DELEGATE_MAP); + } + + protected KeystoneRestClientModule(TypeToken syncClientType, TypeToken asyncClientType, + Map, Class> sync2Async) { + super(syncClientType, asyncClientType, sync2Async); } @Override @@ -61,13 +72,10 @@ public class KeystoneRestClientModule extends RestClientModule * @author Adrian Cole */ +@CredentialType(CredentialTypes.API_ACCESS_KEY_CREDENTIALS) public class ApiAccessKeyCredentials { public static Builder builder() { return new Builder(); diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/ApiMetadata.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/ApiMetadata.java index 5b78d101c3..14e5552c67 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/ApiMetadata.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/ApiMetadata.java @@ -105,15 +105,31 @@ public class ApiMetadata extends Resource { private String status; @Nullable private Date updated; + + + // dealing with the goofy structure with "values" holder noted here + // http://docs.openstack.org/api/openstack-identity-service/2.0/content/Versions-d1e472.html + // if they change this to not be a value holder, we'll probably need to write a custom + // deserializer. + private static class MediaTypesHolder { + private Set values = ImmutableSet.of(); + + private MediaTypesHolder() { + } + + private MediaTypesHolder(Set mediaTypes) { + this.values = ImmutableSet.copyOf(checkNotNull(mediaTypes, "mediaTypes")); + } + } + @SerializedName(value="media-types") - @Nullable - private Set mediaTypes = ImmutableSet.of(); + private MediaTypesHolder mediaTypes = new MediaTypesHolder(); protected ApiMetadata(Builder builder) { super(builder); this.status = checkNotNull(builder.status, "status"); this.updated = checkNotNull(builder.updated, "updated"); - this.mediaTypes = ImmutableSet.copyOf(checkNotNull(builder.mediaTypes, "mediaTypes")); + this.mediaTypes = new MediaTypesHolder(builder.mediaTypes); } /** @@ -131,12 +147,12 @@ public class ApiMetadata extends Resource { /** */ public Set getMediaTypes() { - return Collections.unmodifiableSet(this.mediaTypes); + return Collections.unmodifiableSet(this.mediaTypes.values); } @Override public int hashCode() { - return Objects.hashCode(status, updated, mediaTypes); + return Objects.hashCode(status, updated, mediaTypes.values); } @Override @@ -146,14 +162,14 @@ public class ApiMetadata extends Resource { ApiMetadata that = ApiMetadata.class.cast(obj); return super.equals(that) && Objects.equal(this.status, that.status) && Objects.equal(this.updated, that.updated) - && Objects.equal(this.mediaTypes, that.mediaTypes); + && Objects.equal(this.mediaTypes.values, that.mediaTypes.values); } protected ToStringHelper string() { return super.string() .add("status", status) .add("updated", updated) - .add("mediaTypes", mediaTypes); + .add("mediaTypes", mediaTypes.values); } } \ No newline at end of file diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Endpoint.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Endpoint.java index fc3c58e440..5574ed5ef3 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Endpoint.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Endpoint.java @@ -57,6 +57,8 @@ public class Endpoint implements Comparable { protected URI internalURL; protected URI adminURL; protected String tenantId; + protected URI versionInfo; + protected URI versionList; /** * @see Endpoint#getVersionId() @@ -105,14 +107,31 @@ public class Endpoint implements Comparable { this.tenantId = tenantId; return this; } - + + /** + * @see Endpoint#getVersionInfo() + */ + public Builder versionInfo(URI versionInfo) { + this.versionInfo = checkNotNull(versionInfo, "versionInfo"); + return this; + } + + /** + * @see Endpoint#getVersionList() + */ + public Builder versionList(URI versionList) { + this.versionList = checkNotNull(versionList, "versionList"); + return this; + } + public Endpoint build() { - return new Endpoint(versionId, region, publicURL, internalURL, adminURL, tenantId); + return new Endpoint(versionId, region, publicURL, internalURL, adminURL, tenantId, versionInfo, versionList); } public Builder fromEndpoint(Endpoint from) { return versionId(from.getVersionId()).region(from.getRegion()).publicURL(from.getPublicURL()).internalURL( - from.getInternalURL()).tenantId(from.getTenantId()); + from.getInternalURL()).tenantId(from.getTenantId()).versionInfo(from.getVersionInfo()).versionList( + from.getVersionList()); } } @@ -130,35 +149,41 @@ public class Endpoint implements Comparable { protected URI publicURL; protected URI internalURL; protected URI adminURL; + protected URI versionInfo; + protected URI versionList; // renamed half-way through @Deprecated protected String tenantName; protected String tenantId; - protected Endpoint(String versionId, String region, @Nullable URI publicURL, @Nullable URI internalURL, - @Nullable URI adminURL, @Nullable String tenantId) { - this.versionId = checkNotNull(versionId, "versionId"); - this.region = checkNotNull(region, "region"); + protected Endpoint(@Nullable String versionId, @Nullable String region, @Nullable URI publicURL, @Nullable URI internalURL, + @Nullable URI adminURL, @Nullable String tenantId, @Nullable URI versionInfo, @Nullable URI versionList) { + this.versionId = versionId; + this.region = region; this.publicURL = publicURL; this.internalURL = internalURL; this.adminURL = adminURL; this.tenantId = tenantId; + this.versionInfo = versionInfo; + this.versionList = versionList; } /** - * When provversionIding an ID, it is assumed that the endpoint exists in the current OpenStack + * When providing an ID, it is assumed that the endpoint exists in the current OpenStack * deployment * - * @return the versionId of the endpoint in the current OpenStack deployment + * @return the versionId of the endpoint in the current OpenStack deployment, or null if not specified */ + @Nullable public String getVersionId() { return versionId != null ? versionId : id; } /** - * @return the region of the endpoint + * @return the region of the endpoint, or null if not specified */ + @Nullable public String getRegion() { return region; } @@ -195,6 +220,20 @@ public class Endpoint implements Comparable { return tenantId != null ? tenantId : tenantName; } + /** + */ + @Nullable + public URI getVersionInfo() { + return versionInfo; + } + + /** + */ + @Nullable + public URI getVersionList() { + return versionList; + } + @Override public boolean equals(Object object) { if (this == object) { @@ -216,8 +255,9 @@ public class Endpoint implements Comparable { @Override public String toString() { - return toStringHelper("").add("versionId", getVersionId()).add("region", region).add("publicURL", publicURL).add("internalURL", - internalURL).add("adminURL", adminURL).add("tenantId", getTenantId()).toString(); + return toStringHelper("").add("versionId", getVersionId()).add("region", region).add("publicURL", publicURL).add( + "internalURL", internalURL).add("adminURL", adminURL).add("tenantId", getTenantId()).add("versionInfo", + versionInfo).add("versionList", versionList).toString(); } @Override diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/PasswordCredentials.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/PasswordCredentials.java index 8fef3d18b2..72fec16ea2 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/PasswordCredentials.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/PasswordCredentials.java @@ -23,6 +23,9 @@ import static com.google.common.base.Objects.equal; import static com.google.common.base.Objects.toStringHelper; import static com.google.common.base.Preconditions.checkNotNull; +import org.jclouds.openstack.keystone.v2_0.config.CredentialType; +import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes; + import com.google.common.base.Objects; /** @@ -32,6 +35,7 @@ import com.google.common.base.Objects; * /> * @author Adrian Cole */ +@CredentialType(CredentialTypes.PASSWORD_CREDENTIALS) public class PasswordCredentials { public static Builder builder() { return new Builder(); diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Role.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Role.java index 3e7342ee31..51e8ec4eb5 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Role.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/domain/Role.java @@ -53,6 +53,7 @@ public class Role implements Comparable { public static class Builder { protected String id; protected String name; + protected String description; protected String serviceId; protected String tenantId; @@ -71,7 +72,15 @@ public class Role implements Comparable { this.name = checkNotNull(name, "name"); return this; } - + + /** + * @see Role#getDescription() + */ + public Builder description(String description) { + this.description = checkNotNull(description, "description"); + return this; + } + /** * @see Role#getServiceId() */ @@ -89,11 +98,11 @@ public class Role implements Comparable { } public Role build() { - return new Role(id, name, serviceId, tenantId); + return new Role(id, name, description, serviceId, tenantId); } public Builder fromRole(Role from) { - return id(from.getId()).name(from.getName()).serviceId(from.getServiceId()).tenantId(from.getTenantId()); + return id(from.getId()).name(from.getName()).description(from.getName()).serviceId(from.getServiceId()).tenantId(from.getTenantId()); } } @@ -105,15 +114,17 @@ public class Role implements Comparable { protected String id; protected String name; + protected String description; protected String serviceId; // renamed half-way through @Deprecated protected String tenantName; protected String tenantId; - protected Role(String id, String name, @Nullable String serviceId, @Nullable String tenantId) { + protected Role(String id, String name, @Nullable String description, @Nullable String serviceId, @Nullable String tenantId) { this.id = checkNotNull(id, "id"); this.name = checkNotNull(name, "name"); + this.description = description; this.serviceId = serviceId; this.tenantId = tenantId; } @@ -133,6 +144,14 @@ public class Role implements Comparable { public String getName() { return name; } + + /** + * @return the description of the role + */ + @Nullable + public String getDescription() { + return description; + } /** * @return the service id of the role or null, if not present @@ -171,7 +190,7 @@ public class Role implements Comparable { @Override public String toString() { - return toStringHelper("").add("id", id).add("name", name).add("serviceId", serviceId).add("tenantId", getTenantId()) + return toStringHelper("").add("id", id).add("name", name).add("description", description).add("serviceId", serviceId).add("tenantId", getTenantId()) .toString(); } diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/AdminAsyncClient.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/AdminAsyncClient.java deleted file mode 100644 index 2c259af154..0000000000 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/AdminAsyncClient.java +++ /dev/null @@ -1,177 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds 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.features; - -import java.util.Set; - -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.QueryParam; -import javax.ws.rs.core.MediaType; - -import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; -import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; -import org.jclouds.openstack.keystone.v2_0.domain.Role; -import org.jclouds.openstack.keystone.v2_0.domain.Tenant; -import org.jclouds.openstack.keystone.v2_0.domain.Token; -import org.jclouds.openstack.keystone.v2_0.domain.User; -import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; -import org.jclouds.rest.annotations.ExceptionParser; -import org.jclouds.rest.annotations.RequestFilters; -import org.jclouds.rest.annotations.SelectJson; -import org.jclouds.rest.annotations.SkipEncoding; -import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; -import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; -import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; - -import com.google.common.util.concurrent.ListenableFuture; - -/** - * Provides asynchronous access to Admin via their REST API. - *

    - * - * @see AdminClient - * @see - * @author Adam Lowe - */ -@SkipEncoding({ '/', '=' }) -public interface AdminAsyncClient { - /** - * @see AdminClient#getApiMetadata() - */ - @GET - @SelectJson("version") - @Consumes(MediaType.APPLICATION_JSON) - @Path("/") - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getApiMetadata(); - - /** - * @see AdminClient#listTenants() - */ - @GET - @SelectJson("tenants") - @Consumes(MediaType.APPLICATION_JSON) - @Path("/tenants") - @RequestFilters(AuthenticateRequest.class) - @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) - ListenableFuture> listTenants(); - - /** @see AdminClient#getToken(String) */ - @GET - @SelectJson("token") - @Consumes(MediaType.APPLICATION_JSON) - @Path("/tokens/{token}") - @RequestFilters(AuthenticateRequest.class) - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getToken(@PathParam("token") String token); - - /** @see AdminClient#getUserOfToken(String) */ - @GET - @SelectJson("user") - @Consumes(MediaType.APPLICATION_JSON) - @Path("/tokens/{token}") - @RequestFilters(AuthenticateRequest.class) - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getUserOfToken(@PathParam("token") String token); - - /** @see AdminClient#checkTokenIsValid(String) */ - @HEAD - @Path("/tokens/{token}") - @RequestFilters(AuthenticateRequest.class) - @ExceptionParser(ReturnFalseOnNotFoundOr404.class) - ListenableFuture checkTokenIsValid(@PathParam("token") String token); - - /** @see AdminClient#getEndpointsForToken(String) */ - @GET - @SelectJson("endpoints") - @Consumes(MediaType.APPLICATION_JSON) - @Path("/tokens/{token}/endpoints") - @RequestFilters(AuthenticateRequest.class) - @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) - ListenableFuture> getEndpointsForToken(@PathParam("token") String token); - - /** @see AdminClient#getTenant(String) */ - @GET - @SelectJson("tenant") - @Consumes(MediaType.APPLICATION_JSON) - @Path("/tenants/{tenantId}") - @RequestFilters(AuthenticateRequest.class) - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getTenant(@PathParam("tenantId") String tenantId); - - /** @see AdminClient#getTenantByName(String) */ - @GET - @SelectJson("tenant") - @Consumes(MediaType.APPLICATION_JSON) - @Path("/tenants") - @RequestFilters(AuthenticateRequest.class) - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getTenantByName(@QueryParam("name") String tenantName); - - /** @see AdminClient#listUsers() */ - @GET - @SelectJson("users") - @Consumes(MediaType.APPLICATION_JSON) - @Path("/users") - @RequestFilters(AuthenticateRequest.class) - @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) - ListenableFuture> listUsers(); - - /** @see AdminClient#getUser(String) */ - @GET - @SelectJson("user") - @Consumes(MediaType.APPLICATION_JSON) - @Path("/users/{userId}") - @RequestFilters(AuthenticateRequest.class) - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getUser(@PathParam("userId") String userId); - - /** @see AdminClient#getUserByName(String) */ - @GET - @SelectJson("user") - @Consumes(MediaType.APPLICATION_JSON) - @Path("/users") - @RequestFilters(AuthenticateRequest.class) - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getUserByName(@QueryParam("name") String userName); - - /** @see AdminClient#listRolesOfUser(String) */ - @GET - @SelectJson("roles") - @Consumes(MediaType.APPLICATION_JSON) - @Path("/users/{userId}/roles") - @RequestFilters(AuthenticateRequest.class) - @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) - ListenableFuture> listRolesOfUser(@PathParam("userId") String userId); - - /** @see AdminClient#listRolesOfUserOnTenant(String, String) */ - @GET - @SelectJson("roles") - @Consumes(MediaType.APPLICATION_JSON) - @Path("/tenants/{tenantId}/users/{userId}/roles") - @RequestFilters(AuthenticateRequest.class) - @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) - ListenableFuture> listRolesOfUserOnTenant(@PathParam("userId") String userId, @PathParam("tenantId") String tenantId); -} diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/AdminClient.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/AdminClient.java deleted file mode 100644 index bbaa922aba..0000000000 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/AdminClient.java +++ /dev/null @@ -1,145 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds 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.features; - -import java.util.Set; -import java.util.concurrent.TimeUnit; - -import org.jclouds.concurrent.Timeout; -import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; -import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; -import org.jclouds.openstack.keystone.v2_0.domain.Role; -import org.jclouds.openstack.keystone.v2_0.domain.Tenant; -import org.jclouds.openstack.keystone.v2_0.domain.Token; -import org.jclouds.openstack.keystone.v2_0.domain.User; - -/** - * Provides synchronous access to the KeyStone Admin API. - *

    - * - * @author Adam Lowe - * @see AdminAsyncClient - * @see - */ -@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) -public interface AdminClient { - - /** - * Discover API version information, links to documentation (PDF, HTML, WADL), and supported media types - * - * @return the requested information - */ - ApiMetadata getApiMetadata(); - - /** - * The operation returns a list of tenants which the current token provides access to. - */ - Set listTenants(); - - /** - * Retrieve information about a tenant, by tenant ID - * - * @return the information about the tenant - */ - Tenant getTenant(String tenantId); - - /** - * Retrieve information about a tenant, by tenant name - *

    - * NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/956687 ) - * - * @return the information about the tenant - */ - Tenant getTenantByName(String tenantName); - - /** - * Validate a token and, if it is valid, return access information regarding the tenant (though not the service catalog)/ - * - * @return the requested information - */ - Token getToken(String token); - - /** - * Validate a token and, if it is valid, return access information regarding the tenant (though not the service catalog)/ - * - * @return the requested information - */ - User getUserOfToken(String token); - - /** - * Validate a token. This is a high-performance variant of the #getToken() call that does not return any further - * information. - * - * @return true if the token is valid - */ - Boolean checkTokenIsValid(String token); - - /** - * List all endpoints for a token - *

    - * NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/988672 ) - * - * @return the set of endpoints - */ - Set getEndpointsForToken(String token); - - /** - * Retrieve the list of users - *

    - * NOTE: this method is not in API documentation for keystone, but does work - * - * @return the list of users - */ - Set listUsers(); - - /** - * Retrieve information about a user, by user ID - * - * @return the information about the user - */ - User getUser(String userId); - - /** - * Retrieve information about a user, by user name - *

    - * NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/956687 ) - * - * @return the information about the user - */ - User getUserByName(String userName); - - /** - * Retrieves the list of global roles associated with a specific user (excludes tenant roles). - *

    - * NOTE: Broken in openstack ( https://bugs.launchpad.net/keystone/+bug/933565 ) - * - * @return the set of Roles granted to the user - */ - Set listRolesOfUser(String userId); - - /** - * List the roles a user has been granted on a specific tenant - * - * @return the set of roles - */ - Set listRolesOfUserOnTenant(String userId, String tenantId); - -} \ No newline at end of file diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/ServiceAsyncClient.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantAsyncClient.java similarity index 64% rename from apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/ServiceAsyncClient.java rename to apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantAsyncClient.java index 7a7f10d209..20955ecb66 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/ServiceAsyncClient.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantAsyncClient.java @@ -23,9 +23,11 @@ import java.util.Set; import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; import javax.ws.rs.core.MediaType; -import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; +import org.jclouds.Constants; import org.jclouds.openstack.keystone.v2_0.domain.Tenant; import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; import org.jclouds.rest.annotations.ExceptionParser; @@ -38,28 +40,21 @@ import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; import com.google.common.util.concurrent.ListenableFuture; /** - * Provides asynchronous access to Service via their REST API. + * Provides asynchronous access to Tenant via their REST API. *

    * - * @see ServiceClient - * @see * @author Adam Lowe */ -@SkipEncoding({ '/', '=' }) -public interface ServiceAsyncClient { - /** - * @see ServiceClient#getApiMetadata() - */ - @GET - @SelectJson("version") - @Consumes(MediaType.APPLICATION_JSON) - @Path("/") - @ExceptionParser(ReturnNullOnNotFoundOr404.class) - ListenableFuture getApiMetadata(); +@Path("/v{" + Constants.PROPERTY_API_VERSION + "}") +@SkipEncoding( { '/', '=' }) +public interface TenantAsyncClient { /** - * @see ServiceClient#listTenants() + * @see TenantClient#list() */ @GET @SelectJson("tenants") @@ -67,5 +62,24 @@ public interface ServiceAsyncClient { @Path("/tenants") @RequestFilters(AuthenticateRequest.class) @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) - ListenableFuture> listTenants(); + ListenableFuture> list(); + + /** @see TenantClient#get(String) */ + @GET + @SelectJson("tenant") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tenants/{tenantId}") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture get(@PathParam("tenantId") String tenantId); + + /** @see TenantClient#getByName(String) */ + @GET + @SelectJson("tenant") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tenants") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getByName(@QueryParam("name") String tenantName); + } diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/ServiceClient.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantClient.java similarity index 64% rename from apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/ServiceClient.java rename to apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantClient.java index 604f8d3705..8253b912a4 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/ServiceClient.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TenantClient.java @@ -22,30 +22,39 @@ import java.util.Set; import java.util.concurrent.TimeUnit; import org.jclouds.concurrent.Timeout; -import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; import org.jclouds.openstack.keystone.v2_0.domain.Tenant; /** - * Provides synchronous access to the KeyStone Service API. + * Provides synchronous access to the KeyStone Tenant API. *

    - * + * * @author Adam Lowe - * @see ServiceAsyncClient - * @see */ @Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) -public interface ServiceClient { - - /** - * Discover API version information, links to documentation (PDF, HTML, WADL), and supported media types - * - * @return the requested information - */ - ApiMetadata getApiMetadata(); +public interface TenantClient { /** * The operation returns a list of tenants which the current token provides access to. */ - Set listTenants(); + Set list(); + + /** + * Retrieve information about a tenant, by tenant ID + * + * @return the information about the tenant + */ + Tenant get(String tenantId); + + /** + * Retrieve information about a tenant, by tenant name + *

    + * NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/956687 ) + * + * @return the information about the tenant + */ + Tenant getByName(String tenantName); } \ No newline at end of file diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TokenAsyncClient.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TokenAsyncClient.java new file mode 100644 index 0000000000..7975954954 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TokenAsyncClient.java @@ -0,0 +1,94 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.features; + +import java.util.Set; + +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.Constants; +import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; +import org.jclouds.openstack.keystone.v2_0.domain.Token; +import org.jclouds.openstack.keystone.v2_0.domain.User; +import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnFalseOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to Token via their REST API. + *

    + * + * @see TokenClient + * @see + * @author Adam Lowe + */ +@Path("/v{" + Constants.PROPERTY_API_VERSION + "}") +@SkipEncoding({ '/', '=' }) +public interface TokenAsyncClient { + + + /** @see TokenClient#get(String) */ + @GET + @SelectJson("token") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tokens/{token}") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture get(@PathParam("token") String token); + + /** @see TokenClient#getUserOfToken(String) */ + @GET + @SelectJson("user") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tokens/{token}") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getUserOfToken(@PathParam("token") String token); + + /** @see TokenClient#isValid(String) */ + @HEAD + @Path("/tokens/{token}") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnFalseOnNotFoundOr404.class) + ListenableFuture isValid(@PathParam("token") String token); + + /** @see TokenClient#listEndpointsForToken(String) */ + @GET + @SelectJson("endpoints") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tokens/{token}/endpoints") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listEndpointsForToken(@PathParam("token") String token); + +} diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TokenClient.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TokenClient.java new file mode 100644 index 0000000000..3a1078370d --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/TokenClient.java @@ -0,0 +1,77 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.features; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; +import org.jclouds.openstack.keystone.v2_0.domain.Token; +import org.jclouds.openstack.keystone.v2_0.domain.User; + +import com.google.common.annotations.Beta; + +/** + * Provides synchronous access to the KeyStone Admin API. + *

    + * + * @author Adam Lowe + * @see TokenAsyncClient + * @see + */ +@Beta +@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) +public interface TokenClient { + + + /** + * Validate a token and, if it is valid, return access information regarding the tenant (though not the service catalog)/ + * + * @return the requested information + */ + Token get(String token); + + /** + * Validate a token and, if it is valid, return access information regarding the tenant (though not the service catalog)/ + * + * @return the requested information + */ + User getUserOfToken(String token); + + /** + * Validate a token. This is a high-performance variant of the #getToken() call that does not return any further + * information. + * + * @return true if the token is valid + */ + boolean isValid(String token); + + /** + * List all endpoints for a token + *

    + * NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/988672 ) + * + * @return the set of endpoints + */ + Set listEndpointsForToken(String token); + +} \ No newline at end of file diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserAsyncClient.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserAsyncClient.java new file mode 100644 index 0000000000..d56f0d1b02 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserAsyncClient.java @@ -0,0 +1,101 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.features; + +import java.util.Set; + +import javax.ws.rs.Consumes; +import javax.ws.rs.GET; +import javax.ws.rs.Path; +import javax.ws.rs.PathParam; +import javax.ws.rs.QueryParam; +import javax.ws.rs.core.MediaType; + +import org.jclouds.Constants; +import org.jclouds.openstack.keystone.v2_0.domain.Role; +import org.jclouds.openstack.keystone.v2_0.domain.User; +import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; +import org.jclouds.rest.annotations.ExceptionParser; +import org.jclouds.rest.annotations.RequestFilters; +import org.jclouds.rest.annotations.SelectJson; +import org.jclouds.rest.annotations.SkipEncoding; +import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404; +import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404; + +import com.google.common.util.concurrent.ListenableFuture; + +/** + * Provides asynchronous access to User via their REST API. + *

    + * + * @see UserClient + * @see + * @author Adam Lowe + */ +@Path("/v{" + Constants.PROPERTY_API_VERSION + "}") +@SkipEncoding({ '/', '=' }) +public interface UserAsyncClient { + + /** @see UserClient#list() */ + @GET + @SelectJson("users") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/users") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> list(); + + /** @see UserClient#get(String) */ + @GET + @SelectJson("user") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/users/{userId}") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture get(@PathParam("userId") String userId); + + /** @see UserClient#getByName(String) */ + @GET + @SelectJson("user") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/users") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnNullOnNotFoundOr404.class) + ListenableFuture getByName(@QueryParam("name") String userName); + + /** @see UserClient#listRolesOfUser(String) */ + @GET + @SelectJson("roles") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/users/{userId}/roles") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listRolesOfUser(@PathParam("userId") String userId); + + /** @see UserClient#listRolesOfUserOnTenant(String, String) */ + @GET + @SelectJson("roles") + @Consumes(MediaType.APPLICATION_JSON) + @Path("/tenants/{tenantId}/users/{userId}/roles") + @RequestFilters(AuthenticateRequest.class) + @ExceptionParser(ReturnEmptySetOnNotFoundOr404.class) + ListenableFuture> listRolesOfUserOnTenant(@PathParam("userId") String userId, @PathParam("tenantId") String tenantId); +} diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserClient.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserClient.java new file mode 100644 index 0000000000..8a811ba242 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/features/UserClient.java @@ -0,0 +1,85 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.features; + +import java.util.Set; +import java.util.concurrent.TimeUnit; + +import org.jclouds.concurrent.Timeout; +import org.jclouds.openstack.keystone.v2_0.domain.Role; +import org.jclouds.openstack.keystone.v2_0.domain.User; + +import com.google.common.annotations.Beta; + +/** + * Provides synchronous access to the KeyStone User API. + *

    + * + * @author Adam Lowe + * @see UserAsyncClient + * @see + */ +@Beta +@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS) +public interface UserClient { + + /** + * Retrieve the list of users + *

    + * NOTE: this method is not in API documentation for keystone, but does work + * + * @return the list of users + */ + Set list(); + + /** + * Retrieve information about a user, by user ID + * + * @return the information about the user + */ + User get(String userId); + + /** + * Retrieve information about a user, by user name + *

    + * NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/956687 ) + * + * @return the information about the user + */ + User getByName(String userName); + + /** + * Retrieves the list of global roles associated with a specific user (excludes tenant roles). + *

    + * NOTE: Broken in openstack ( https://bugs.launchpad.net/keystone/+bug/933565 ) + * + * @return the set of Roles granted to the user + */ + Set listRolesOfUser(String userId); + + /** + * List the roles a user has been granted on a specific tenant + * + * @return the set of roles + */ + Set listRolesOfUserOnTenant(String userId, String tenantId); + +} \ No newline at end of file diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java index d1aa97f24e..b6915e8e1d 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java @@ -21,17 +21,17 @@ package org.jclouds.openstack.keystone.v2_0.functions; import javax.inject.Inject; import javax.inject.Singleton; -import org.jclouds.domain.Credentials; import org.jclouds.openstack.keystone.v2_0.AuthenticationClient; +import org.jclouds.openstack.keystone.v2_0.config.CredentialType; +import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes; import org.jclouds.openstack.keystone.v2_0.domain.Access; import org.jclouds.openstack.keystone.v2_0.domain.ApiAccessKeyCredentials; -import org.jclouds.rest.AuthorizationException; - -import com.google.common.base.Function; +import org.jclouds.openstack.keystone.v2_0.functions.internal.BaseAuthenticator; +@CredentialType(CredentialTypes.API_ACCESS_KEY_CREDENTIALS) @Singleton -public class AuthenticateApiAccessKeyCredentials implements Function { - private final AuthenticationClient client; +public class AuthenticateApiAccessKeyCredentials extends BaseAuthenticator { + protected final AuthenticationClient client; @Inject public AuthenticateApiAccessKeyCredentials(AuthenticationClient client) { @@ -39,25 +39,18 @@ public class AuthenticateApiAccessKeyCredentials implements Function { - private final AuthenticationClient client; +@CredentialType(CredentialTypes.PASSWORD_CREDENTIALS) +@Singleton +public class AuthenticatePasswordCredentials extends BaseAuthenticator { + protected final AuthenticationClient client; @Inject public AuthenticatePasswordCredentials(AuthenticationClient client) { @@ -37,25 +39,18 @@ public class AuthenticatePasswordCredentials implements Function { } \ No newline at end of file diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/ReturnRegion.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/ReturnRegionOrProvider.java similarity index 75% rename from apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/ReturnRegion.java rename to apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/ReturnRegionOrProvider.java index 37ec7d8ce0..2a2a3dff46 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/ReturnRegion.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/ReturnRegionOrProvider.java @@ -20,15 +20,23 @@ package org.jclouds.openstack.keystone.v2_0.functions; import static com.google.common.base.Preconditions.checkNotNull; +import javax.inject.Inject; import javax.inject.Singleton; +import org.jclouds.location.Provider; import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; @Singleton -public class ReturnRegion implements EndpointToRegion { +public class ReturnRegionOrProvider implements EndpointToRegion { + private String provider; + + @Inject + ReturnRegionOrProvider(@Provider String provider) { + this.provider = checkNotNull(provider, "provider"); + } @Override public String apply(Endpoint input) { - return checkNotNull(input.getRegion(), "no region for endpoint %s", input); + return input.getRegion() != null ? input.getRegion() : provider; } } \ No newline at end of file diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/internal/BaseAuthenticator.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/internal/BaseAuthenticator.java new file mode 100644 index 0000000000..35704b4225 --- /dev/null +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/internal/BaseAuthenticator.java @@ -0,0 +1,62 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.functions.internal; + +import javax.annotation.Resource; + +import org.jclouds.domain.Credentials; +import org.jclouds.logging.Logger; +import org.jclouds.openstack.keystone.v2_0.domain.Access; + +import com.google.common.base.Function; + +public abstract class BaseAuthenticator implements Function { + + @Resource + protected Logger logger = Logger.NULL; + + @Override + public Access apply(Credentials input) { + String tenantId = null; + String usernameOrAccessKey = input.identity; + if (input.identity.indexOf(':') == -1) { + logger.debug("Identity %s does not match format tenantName:accessKey", input.identity); + } else { + tenantId = input.identity.substring(0, input.identity.indexOf(':')); + usernameOrAccessKey = input.identity.substring(input.identity.indexOf(':') + 1); + } + String passwordOrSecretKey = input.credential; + + C creds = createCredentials(usernameOrAccessKey, passwordOrSecretKey); + Access access; + if (tenantId != null && tenantId.matches("^[0-9]+$")) { + access = authenticateWithTenantId(tenantId, creds); + } else { + access = authenticateWithTenantNameOrNull(tenantId, creds); + } + return access; + } + + public abstract C createCredentials(String identity, String credential); + + protected abstract Access authenticateWithTenantId(String tenantId, C apiAccessKeyCredentials); + + protected abstract Access authenticateWithTenantNameOrNull(String tenantId, C apiAccessKeyCredentials); + +} \ No newline at end of file diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/LocationIdToURIFromAccessForTypeAndVersionSupplier.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/LocationIdToURIFromAccessForTypeAndVersion.java similarity index 92% rename from apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/LocationIdToURIFromAccessForTypeAndVersionSupplier.java rename to apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/LocationIdToURIFromAccessForTypeAndVersion.java index 0b73cb8c46..4206cf673c 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/LocationIdToURIFromAccessForTypeAndVersionSupplier.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/LocationIdToURIFromAccessForTypeAndVersion.java @@ -38,7 +38,7 @@ import com.google.common.collect.Maps; import com.google.inject.assistedinject.Assisted; @Singleton -public class LocationIdToURIFromAccessForTypeAndVersionSupplier implements Supplier>> { +public class LocationIdToURIFromAccessForTypeAndVersion implements Supplier>> { protected final Supplier access; protected final EndpointToSupplierURI endpointToSupplierURI; protected final Function endpointToLocationId; @@ -46,7 +46,7 @@ public class LocationIdToURIFromAccessForTypeAndVersionSupplier implements Suppl protected final String apiVersion; @Inject - public LocationIdToURIFromAccessForTypeAndVersionSupplier(Supplier access, + public LocationIdToURIFromAccessForTypeAndVersion(Supplier access, EndpointToSupplierURI endpointToSupplierURI, Function endpointToLocationId, @Assisted("apiType") String apiType, @Assisted("apiVersion") String apiVersion) { this.access = access; @@ -70,8 +70,8 @@ public class LocationIdToURIFromAccessForTypeAndVersionSupplier implements Suppl }); } catch (NoSuchElementException e) { - throw new NoSuchElementException(String.format("apiType %s not found in catalog %s", apiType, - accessResponse.getServiceCatalog())); + throw new NoSuchElementException(String.format("apiType %s not found in catalog %s", apiType, accessResponse + .getServiceCatalog())); } Map locationIdToEndpoint = Maps.uniqueIndex(Iterables.filter(service.getEndpoints(), new Predicate() { diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionSupplier.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java similarity index 72% rename from apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionSupplier.java rename to apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java index 74d15f5be0..36496586e7 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionSupplier.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersion.java @@ -21,6 +21,7 @@ package org.jclouds.openstack.keystone.v2_0.suppliers; import javax.inject.Inject; import javax.inject.Singleton; +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; @@ -29,12 +30,12 @@ import com.google.common.base.Supplier; import com.google.inject.assistedinject.Assisted; @Singleton -public class RegionIdToAdminURIFromAccessForTypeAndVersionSupplier extends - LocationIdToURIFromAccessForTypeAndVersionSupplier implements RegionIdToAdminURISupplier { +public class RegionIdToAdminURIFromAccessForTypeAndVersion extends LocationIdToURIFromAccessForTypeAndVersion implements + RegionIdToAdminURISupplier { @Inject - public RegionIdToAdminURIFromAccessForTypeAndVersionSupplier(Supplier access, - EndpointToSupplierAdminURI endpointToSupplierURI, EndpointToRegion endpointToRegion, - @Assisted("apiType") String apiType, @Assisted("apiVersion") String apiVersion) { + public RegionIdToAdminURIFromAccessForTypeAndVersion(Supplier access, + EndpointToSupplierAdminURI endpointToSupplierURI, EndpointToRegion endpointToRegion, + @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) { super(access, endpointToSupplierURI, endpointToRegion, apiType, apiVersion); } 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 index 9f2b1c15b7..d39e101da2 100644 --- 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 @@ -3,6 +3,8 @@ package org.jclouds.openstack.keystone.v2_0.suppliers; import java.net.URI; import java.util.Map; +import org.jclouds.javax.annotation.Nullable; + import com.google.common.base.Supplier; import com.google.inject.ImplementedBy; import com.google.inject.assistedinject.Assisted; @@ -10,7 +12,7 @@ import com.google.inject.assistedinject.Assisted; /** * @author Adam Lowe */ -@ImplementedBy(RegionIdToAdminURIFromAccessForTypeAndVersionSupplier.class) +@ImplementedBy(RegionIdToAdminURIFromAccessForTypeAndVersion.class) public interface RegionIdToAdminURISupplier extends Supplier>> { static interface Factory { /** @@ -19,10 +21,10 @@ public interface RegionIdToAdminURISupplier extends Supplier access, + public RegionIdToURIFromAccessForTypeAndVersion(Supplier access, EndpointToSupplierURI endpointToSupplierURI, EndpointToRegion endpointToRegion, - @Assisted("apiType") String apiType, @Assisted("apiVersion") String apiVersion) { + @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) { super(access, endpointToSupplierURI, endpointToRegion, apiType, apiVersion); } diff --git a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersionSupplier.java b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersion.java similarity index 83% rename from apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersionSupplier.java rename to apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersion.java index 36ceb3c82d..350a9f8b8f 100644 --- a/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersionSupplier.java +++ b/apis/openstack-keystone/src/main/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersion.java @@ -21,6 +21,7 @@ package org.jclouds.openstack.keystone.v2_0.suppliers; import javax.inject.Inject; import javax.inject.Singleton; +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; @@ -30,16 +31,16 @@ import com.google.common.base.Supplier; import com.google.inject.assistedinject.Assisted; @Singleton -public class ZoneIdToURIFromAccessForTypeAndVersionSupplier extends LocationIdToURIFromAccessForTypeAndVersionSupplier - implements ZoneIdToURISupplier { +public class ZoneIdToURIFromAccessForTypeAndVersion extends LocationIdToURIFromAccessForTypeAndVersion implements + ZoneIdToURISupplier { @Inject - public ZoneIdToURIFromAccessForTypeAndVersionSupplier( + public ZoneIdToURIFromAccessForTypeAndVersion( Supplier 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, @Assisted("apiVersion") String apiVersion) { + @Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) { super(access, endpointToSupplierURI, endpointToZone, apiType, apiVersion); } diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/KeystoneClientExpectTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/KeystoneClientExpectTest.java new file mode 100644 index 0000000000..eddcb33090 --- /dev/null +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/KeystoneClientExpectTest.java @@ -0,0 +1,64 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 1.1 (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-1.1 + * + * 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; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertNull; + +import java.net.URI; + +import org.jclouds.http.HttpRequest; +import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestClientExpectTest; +import org.jclouds.openstack.keystone.v2_0.parse.ParseRackspaceApiMetadataTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; + +/** + * + * @author Adrian Cole + */ +@Test(testName = "KeystoneClientExpectTest") +public class KeystoneClientExpectTest extends BaseKeystoneRestClientExpectTest { + + public void testGetApiMetaData() { + KeystoneClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + HttpRequest.builder().method("GET").endpoint(URI.create(endpoint + "/v2.0/")). + headers(ImmutableMultimap.of("Accept", APPLICATION_JSON)).build(), + HttpResponse.builder().statusCode(200). + payload(payloadFromResourceWithContentType("/raxVersion.json", APPLICATION_JSON)).build()); + ApiMetadata metadata = client.getApiMetadata(); + + assertEquals(metadata, new ParseRackspaceApiMetadataTest().expected()); + } + + public void testGetApiMetaDataFailNotFound() { + KeystoneClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/").headers(ImmutableMultimap.of("Accept", APPLICATION_JSON)).build(), + standardResponseBuilder(404).build()); + assertNull(client.getApiMetadata()); + } + +} + diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/KeystoneClientLiveTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/KeystoneClientLiveTest.java new file mode 100644 index 0000000000..3d0cddb328 --- /dev/null +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/KeystoneClientLiveTest.java @@ -0,0 +1,43 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 1.1 (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-1.1 + * + * 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; + +import static org.testng.Assert.assertNotNull; + +import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneClientLiveTest; +import org.testng.annotations.Test; + +/** + * Tests KeystoneClient + * + * @author Adam Lowe + */ +@Test(groups = "live", testName = "KeystoneClientLiveTest") +public class KeystoneClientLiveTest extends BaseKeystoneClientLiveTest { + + public void testGetApiMetaData() { + ApiMetadata result = keystoneContext.getApi().getApiMetadata(); + assertNotNull(result); + assertNotNull(result.getId()); + assertNotNull(result.getStatus()); + assertNotNull(result.getUpdated()); + } + +} diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/config/CredentialTypesTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/config/CredentialTypesTest.java new file mode 100644 index 0000000000..d8d8b2b786 --- /dev/null +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/config/CredentialTypesTest.java @@ -0,0 +1,54 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.config; + +import static org.testng.Assert.assertEquals; + +import org.jclouds.openstack.keystone.v2_0.domain.PasswordCredentials; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "CredentialTypesTest") +public class CredentialTypesTest { + + public void testCredentialTypeOfWhenValid() { + assertEquals(CredentialTypes.credentialTypeOf(PasswordCredentials.createWithUsernameAndPassword("username", + "password")), CredentialTypes.PASSWORD_CREDENTIALS); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testCredentialTypeOfWithoutAnnotation() { + CredentialTypes.credentialTypeOf(""); + } + + public void testIndexByCredentialTypeWhenValid() { + assertEquals(CredentialTypes.indexByCredentialType( + ImmutableSet.of(PasswordCredentials.createWithUsernameAndPassword("username", "password"))).keySet(), + ImmutableSet.of(CredentialTypes.PASSWORD_CREDENTIALS)); + } + + @Test(expectedExceptions = IllegalArgumentException.class) + public void testIndexByCredentialTypeWithoutAnnotation() { + CredentialTypes.indexByCredentialType(ImmutableSet.of("")); + } +} diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/AdminClientExpectTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/AdminClientExpectTest.java deleted file mode 100644 index 9ca48068c4..0000000000 --- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/AdminClientExpectTest.java +++ /dev/null @@ -1,381 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds licenses this file - * to you under the Apache License, Version 1.1 (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-1.1 - * - * 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.features; - -import static javax.ws.rs.core.MediaType.APPLICATION_JSON; -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; -import static org.testng.Assert.assertTrue; - -import java.net.URI; -import java.util.Set; - -import org.jclouds.date.DateService; -import org.jclouds.date.internal.SimpleDateFormatDateService; -import org.jclouds.http.HttpResponseException; -import org.jclouds.openstack.keystone.v2_0.KeystoneClient; -import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; -import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; -import org.jclouds.openstack.keystone.v2_0.domain.MediaType; -import org.jclouds.openstack.keystone.v2_0.domain.Role; -import org.jclouds.openstack.keystone.v2_0.domain.Tenant; -import org.jclouds.openstack.keystone.v2_0.domain.Token; -import org.jclouds.openstack.keystone.v2_0.domain.User; -import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestClientExpectTest; -import org.jclouds.openstack.v2_0.domain.Link; -import org.jclouds.rest.AuthorizationException; -import org.testng.annotations.Test; - -import com.google.common.collect.ImmutableMultimap; -import com.google.common.collect.ImmutableSet; - -/** - * Tests parsing and Guice wiring of UserClient - * - * @author Adam Lowe - */ -@Test(testName = "AdminClientExpectTest") -public class AdminClientExpectTest extends BaseKeystoneRestClientExpectTest { - private DateService dateService = new SimpleDateFormatDateService(); - - public AdminClientExpectTest() { - endpoint = "https://csnode.jclouds.org:35357"; - } - - public void testGetApiMetaData() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/"). - headers(ImmutableMultimap.of("Accept", APPLICATION_JSON)).build(), - standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/api_metadata.json", APPLICATION_JSON)).build()) - .getAdminClientForRegion("region-a.geo-1"); - ApiMetadata metadata = client.getApiMetadata(); - assertNotNull(metadata); - assertEquals(metadata.getId(), "v2.0"); - - ApiMetadata expected = ApiMetadata.builder().id("v2.0") - .links(ImmutableSet.of(Link.builder().relation(Link.Relation.SELF).href(URI.create("http://172.16.89.140:5000/v2.0/")).build(), - Link.builder().relation(Link.Relation.DESCRIBEDBY).type("text/html").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/content/")).build(), - Link.builder().relation(Link.Relation.DESCRIBEDBY).type("application/pdf").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf")).build() - )) - .status("beta") - .updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-11-19T00:00:00Z")) - .mediaTypes(ImmutableSet.of( - MediaType.builder().base("application/json").type("application/vnd.openstack.identity-v2.0+json").build(), - MediaType.builder().base("application/xml").type("application/vnd.openstack.identity-v2.0+xml").build() - )) - .build(); - - assertEquals(metadata, expected); - } - - public void testGetApiMetaDataFailNotFound() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/").headers(ImmutableMultimap.of("Accept", APPLICATION_JSON)).build(), - standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); - assertNull(client.getApiMetadata()); - } - - public void testListTenants() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/tenants").build(), - standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/tenant_list.json", APPLICATION_JSON)).build()) - .getAdminClientForRegion("region-a.geo-1"); - Set tenants = client.listTenants(); - assertNotNull(tenants); - assertFalse(tenants.isEmpty()); - - Set expected = ImmutableSet.of( - Tenant.builder().name("demo").id("05d1dc7af71646deba64cfc17b81bec0").build(), - Tenant.builder().name("admin").id("7aa2e17ec29f44d193c48feaba0852cc").build() - ); - - assertEquals(tenants, expected); - } - - public void testListTenantsFailNotFound() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/tenants").build(), - standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); - assertTrue(client.listTenants().isEmpty()); - } - - public void testGetTenant() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/tenants/013ba41150a14830bec85ffe93353bcc").build(), - standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/tenant_details.json", APPLICATION_JSON)).build()) - .getAdminClientForRegion("region-a.geo-1"); - Tenant tenant = client.getTenant("013ba41150a14830bec85ffe93353bcc"); - assertNotNull(tenant); - assertEquals(tenant, Tenant.builder().id("013ba41150a14830bec85ffe93353bcc").name("admin").build()); - } - - @Test(expectedExceptions = AuthorizationException.class) - public void testListTenantsFailNotAuthorized() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/tenants/013ba41150a14830bec85ffe93353bcc").build(), - standardResponseBuilder(401).build()).getAdminClientForRegion("region-a.geo-1"); - client.getTenant("013ba41150a14830bec85ffe93353bcc"); - } - - public void testGetTenantByName() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/tenants?name=admin").build(), - standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/tenant_details.json", APPLICATION_JSON)).build()) - .getAdminClientForRegion("region-a.geo-1"); - Tenant tenant = client.getTenantByName("admin"); - assertNotNull(tenant); - assertEquals(tenant, Tenant.builder().id("013ba41150a14830bec85ffe93353bcc").name("admin").build()); - } - - public void testGetTenantByNameFailNotFound() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/tenants?name=admin").build(), - standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); - assertNull(client.getTenantByName("admin")); - } - - public void testGetToken() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(), - standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/token_details.json", APPLICATION_JSON)).build()) - .getAdminClientForRegion("region-a.geo-1"); - Token token = client.getToken("sometokenorother"); - assertNotNull(token); - assertEquals(token, - Token.builder().id("167eccdc790946969ced473732e8109b").expires(dateService.iso8601SecondsDateParse("2012-04-28T12:42:50Z")) - .tenant(Tenant.builder().id("4cea93f5464b4f1c921fb3e0461d72b5").name("demo").build()).build()); - } - - public void testGetTokenFailNotFound() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(), - standardResponseBuilder(404).build()) - .getAdminClientForRegion("region-a.geo-1"); - assertNull(client.getToken("sometokenorother")); - } - - @Test(expectedExceptions = HttpResponseException.class) - public void testGetTokenFail500() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(), - standardResponseBuilder(500).build()).getAdminClientForRegion("region-a.geo-1"); - client.getToken("sometokenorother"); - } - - public void testGetUserOfToken() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(), - standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/token_details.json", APPLICATION_JSON)).build()) - .getAdminClientForRegion("region-a.geo-1"); - User user = client.getUserOfToken("sometokenorother"); - assertNotNull(user); - assertEquals(user, User.builder().id("2b9b606181634ae9ac86fd95a8bc2cde").name("admin") - .roles(ImmutableSet.of(Role.builder().id("79cada5c02814b57a52e0eed4dd388cb").name("admin").build())) - .build()); - } - - public void testGetUserOfTokenFailNotFound() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(), - standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); - assertNull(client.getUserOfToken("sometokenorother")); - } - - public void testCheckTokenIsValid() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").method("HEAD") - .headers(ImmutableMultimap.of("X-Auth-Token", authToken)).build(), - standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/token_details.json", APPLICATION_JSON)).build()) - .getAdminClientForRegion("region-a.geo-1"); - assertTrue(client.checkTokenIsValid("sometokenorother")); - } - - public void testCheckTokenIsValidFailNotValid() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").method("HEAD") - .headers(ImmutableMultimap.of("X-Auth-Token", authToken)).build(), - standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); - assertFalse(client.checkTokenIsValid("sometokenorother")); - } - - @Test - public void testGetEndpointsForToken() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/tokens/XXXXXX/endpoints").build(), - standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_endpoints.json", APPLICATION_JSON)).build()) - .getAdminClientForRegion("region-a.geo-1"); - Set endpoints = client.getEndpointsForToken("XXXXXX"); - - assertEquals(endpoints, ImmutableSet.of( - Endpoint.builder().publicURL(URI.create("https://csnode.jclouds.org/v2.0/")) - .adminURL(URI.create("https://csnode.jclouds.org:35357/v2.0/")) - .region("region-a.geo-1").versionId("2.0").build() - )); - } - - @Test - public void testGetEndpointsForTokenFailNotFound() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/tokens/XXXXXX/endpoints").build(), - standardResponseBuilder(404).build()) - .getAdminClientForRegion("region-a.geo-1"); - assertTrue(client.getEndpointsForToken("XXXXXX").isEmpty()); - } - - public void testListUsers() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/users").build(), - standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_list.json", APPLICATION_JSON)).build()) - .getAdminClientForRegion("region-a.geo-1"); - Set users = client.listUsers(); - assertNotNull(users); - assertFalse(users.isEmpty()); - - Set expected = ImmutableSet.of( - User.builder().name("nova").id("e021dfd758eb44a89f1c57c8ef3be8e2").build(), - User.builder().name("glance").id("3f6c1c9ba993495ead7d2eb2192e284f").build(), - User.builder().name("demo").id("667b2e1420604df8b67cd8ea57d4ee64").build(), - User.builder().name("admin").id("2b9b606181634ae9ac86fd95a8bc2cde").build() - ); - - assertEquals(users, expected); - } - - @Test(expectedExceptions = AuthorizationException.class) - public void testListUsersFailNotAuth() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/users").build(), - standardResponseBuilder(401).build()).getAdminClientForRegion("region-a.geo-1"); - client.listUsers(); - } - - public void testGetUser() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/users/e021dfd758eb44a89f1c57c8ef3be8e2").build(), - standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_details.json", APPLICATION_JSON)).build()) - .getAdminClientForRegion("region-a.geo-1"); - User user = client.getUser("e021dfd758eb44a89f1c57c8ef3be8e2"); - assertNotNull(user); - assertEquals(user, User.builder().name("nova").id("e021dfd758eb44a89f1c57c8ef3be8e2").build()); - } - - public void testGetUserFailNotFound() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/users/f021dfd758eb44a89f1c57c8ef3be8e2").build(), - standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); - assertNull(client.getUser("f021dfd758eb44a89f1c57c8ef3be8e2")); - } - - public void testGetUserByName() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/users?name=nova").build(), - standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_details.json", APPLICATION_JSON)).build()) - .getAdminClientForRegion("region-a.geo-1"); - User user = client.getUserByName("nova"); - assertNotNull(user); - assertEquals(user, User.builder().name("nova").id("e021dfd758eb44a89f1c57c8ef3be8e2").build()); - } - - public void testGetUserByNameFailNotFound() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/users?name=fred").build(), - standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); - assertNull(client.getUserByName("fred")); - } - - public void testListRolesOfUser() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/users/3f6c1c9ba993495ead7d2eb2192e284f/roles").build(), - standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_role_list.json", APPLICATION_JSON)).build()) - .getAdminClientForRegion("region-a.geo-1"); - Set roles = client.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f"); - assertNotNull(roles); - assertFalse(roles.isEmpty()); - assertEquals(roles, ImmutableSet.of( - Role.builder().id("79cada5c02814b57a52e0eed4dd388cb").name("admin").build() - )); - } - - public void testListRolesOfUserFailNotFound() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/users/4f6c1c9ba993495ead7d2eb2192e284f/roles").build(), - standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); - assertTrue(client.listRolesOfUser("4f6c1c9ba993495ead7d2eb2192e284f").isEmpty()); - } - - @Test(expectedExceptions = HttpResponseException.class) - public void testListRolesOfUserFailNotImplemented() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/users/5f6c1c9ba993495ead7d2eb2192e284f/roles").build(), - standardResponseBuilder(501).build()).getAdminClientForRegion("region-a.geo-1"); - assertTrue(client.listRolesOfUser("5f6c1c9ba993495ead7d2eb2192e284f").isEmpty()); - } - - public void testListRolesOfUserInTenant() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/users/3f6c1c9ba993495ead7d2eb2192e284f/roles").build(), - standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_tenant_role_list.json", APPLICATION_JSON)).build()) - .getAdminClientForRegion("region-a.geo-1"); - Set roles = client.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f"); - assertNotNull(roles); - assertFalse(roles.isEmpty()); - assertEquals(roles, ImmutableSet.of( - Role.builder().id("31c451195aac49b386039341e2c92a16").name("KeystoneServiceAdmin").build(), - Role.builder().id("79cada5c02814b57a52e0eed4dd388cb").name("admin").build(), - Role.builder().id("6ea17ddd37a6447794cb0e164d4db894").name("KeystoneAdmin").build())); - } - - public void testListRolesOfUserInTenantFailNotFound() { - AdminClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - standardRequestBuilder(endpoint + "/v2.0/users/3f6c1c9ba993495ead7d2eb2192e284f/roles").build(), - standardResponseBuilder(404).build()).getAdminClientForRegion("region-a.geo-1"); - assertTrue(client.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f").isEmpty()); - } - -} diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/AdminClientLiveTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/AdminClientLiveTest.java deleted file mode 100644 index 62db6cd514..0000000000 --- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/AdminClientLiveTest.java +++ /dev/null @@ -1,192 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds licenses this file - * to you under the Apache License, Version 1.1 (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-1.1 - * - * 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.features; - -import static org.testng.Assert.assertEquals; -import static org.testng.Assert.assertFalse; -import static org.testng.Assert.assertNotNull; -import static org.testng.Assert.assertNull; -import static org.testng.AssertJUnit.assertTrue; - -import java.net.URI; -import java.util.Set; - -import org.jclouds.http.HttpRequest; -import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; -import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; -import org.jclouds.openstack.keystone.v2_0.domain.Role; -import org.jclouds.openstack.keystone.v2_0.domain.Tenant; -import org.jclouds.openstack.keystone.v2_0.domain.Token; -import org.jclouds.openstack.keystone.v2_0.domain.User; -import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; -import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneClientLiveTest; -import org.testng.annotations.BeforeMethod; -import org.testng.annotations.Test; - -import com.google.common.collect.Iterables; - -/** - * Tests AdminClient - * - * @author Adam Lowe - */ -@Test(groups = "live", testName = "AdminClientLiveTest", singleThreaded = true) -public class AdminClientLiveTest extends BaseKeystoneClientLiveTest { - - protected String token; - - // Get the token currently in use (there's currently no listTokens()) - @BeforeMethod - public void grabToken() { - AuthenticateRequest ar = keystoneContext.getUtils().getInjector().getInstance(AuthenticateRequest.class); - HttpRequest test = ar.filter(HttpRequest.builder().method("GET").endpoint(URI.create(endpoint)).build()); - token = Iterables.getOnlyElement(test.getHeaders().get("X-Auth-Token")); - } - - public void testGetApiMetaData() { - for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { - ApiMetadata result = keystoneContext.getApi().getAdminClientForRegion(regionId).getApiMetadata(); - assertNotNull(result); - assertNotNull(result.getId()); - assertNotNull(result.getStatus()); - assertNotNull(result.getUpdated()); - } - } - - public void testTenants() { - for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { - AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); - Set result = client.listTenants(); - assertNotNull(result); - assertFalse(result.isEmpty()); - - for (Tenant tenant : result) { - assertNotNull(tenant.getId()); - - Tenant aTenant = client.getTenant(tenant.getId()); - assertEquals(aTenant, tenant); - } - } - } - - public void testToken() { - for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { - AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); - assertTrue(client.checkTokenIsValid(token)); - Token result = client.getToken(token); - assertNotNull(result); - assertEquals(result.getId(), token); - assertNotNull(result.getTenant()); - - User user = client.getUserOfToken(token); - assertNotNull(user); - assertNotNull(user.getId()); - assertNotNull(user.getName()); - } - } - - public void testInvalidToken() { - for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { - AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); - assertFalse(client.checkTokenIsValid("thisisnotarealtoken!")); - assertNull(client.getToken("thisisnotarealtoken!")); - } - } - - // TODO this threw 501 not implemented - @Test(enabled = false) - public void testTokenEndpoints() { - for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { - AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); - Set endpoints = client.getEndpointsForToken(token); - assertNotNull(endpoints); - assertFalse(endpoints.isEmpty()); - } - } - - // TODO this threw 501 not implemented - @Test(enabled = false) - public void testInvalidTokenEndpoints() { - for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { - AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); - assertTrue(client.getEndpointsForToken("thisisnotarealtoken!").isEmpty()); - } - } - - public void testUsers() { - for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { - AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); - Set users = client.listUsers(); - assertNotNull(users); - assertFalse(users.isEmpty()); - for (User user : users) { - User aUser = client.getUser(user.getId()); - assertEquals(aUser, user); - } - } - } - - @Test(dependsOnMethods = {"testUsers", "testTenants"}) - public void testUserRolesOnTenant() { - for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { - AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); - Set users = client.listUsers(); - Set tenants = client.listTenants(); - - for (User user : users) { - for (Tenant tenant : tenants) { - Set roles = client.listRolesOfUserOnTenant(user.getId(), tenant.getId()); - for (Role role : roles) { - assertNotNull(role.getId()); - } - } - } - } - } - - // TODO this functionality is currently broken in openstack - @Test(enabled = false, dependsOnMethods = "testUsers") - public void testListRolesOfUser() { - for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { - AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); - for (User user : client.listUsers()) { - Set roles = client.listRolesOfUser(user.getId()); - for (Role role : roles) { - assertNotNull(role.getId()); - } - } - } - } - - // TODO this functionality is currently broken in openstack (possibly deprecated?) - @Test(enabled=false, dependsOnMethods = {"testUsers", "testTenants"}) - public void testUsersAndTenantsByName() { - for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { - AdminClient client = keystoneContext.getApi().getAdminClientForRegion(regionId); - for (User user : client.listUsers()) { - User aUser = client.getUserByName(user.getName()); - assertEquals(aUser, user); - } - for (Tenant tenant : client.listTenants()) { - Tenant aTenant = client.getTenantByName(tenant.getName()); - assertEquals(aTenant, tenant); - } - } - } -} \ No newline at end of file diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/TenantClientExpectTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/TenantClientExpectTest.java new file mode 100644 index 0000000000..afe2bcb2cd --- /dev/null +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/TenantClientExpectTest.java @@ -0,0 +1,112 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 1.1 (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-1.1 + * + * 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.features; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +import java.util.Set; + +import org.jclouds.openstack.keystone.v2_0.KeystoneClient; +import org.jclouds.openstack.keystone.v2_0.domain.Tenant; +import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestClientExpectTest; +import org.jclouds.rest.AuthorizationException; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableSet; + +/** + * Tests parsing and Guice wiring of TenantClient + * + * @author Adam Lowe + */ +@Test(testName = "TenantClientExpectTest") +public class TenantClientExpectTest extends BaseKeystoneRestClientExpectTest { + + public void testListTenants() { + TenantClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tenants").build(), + standardResponseBuilder(200).payload( + payloadFromResourceWithContentType("/tenant_list.json", APPLICATION_JSON)).build()) + .getTenantClient(); + Set tenants = client.list(); + assertNotNull(tenants); + assertFalse(tenants.isEmpty()); + + Set expected = ImmutableSet.of(Tenant.builder().name("demo").id("05d1dc7af71646deba64cfc17b81bec0") + .build(), Tenant.builder().name("admin").id("7aa2e17ec29f44d193c48feaba0852cc").build()); + + assertEquals(tenants, expected); + } + + public void testListTenantsFailNotFound() { + TenantClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tenants").build(), standardResponseBuilder(404).build()) + .getTenantClient(); + assertTrue(client.list().isEmpty()); + } + + public void testGetTenant() { + TenantClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tenants/013ba41150a14830bec85ffe93353bcc").build(), + standardResponseBuilder(200).payload( + payloadFromResourceWithContentType("/tenant_details.json", APPLICATION_JSON)).build()) + .getTenantClient(); + Tenant tenant = client.get("013ba41150a14830bec85ffe93353bcc"); + assertNotNull(tenant); + assertEquals(tenant, Tenant.builder().id("013ba41150a14830bec85ffe93353bcc").name("admin").build()); + } + + @Test(expectedExceptions = AuthorizationException.class) + public void testListTenantsFailNotAuthorized() { + TenantClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tenants/013ba41150a14830bec85ffe93353bcc").build(), + standardResponseBuilder(401).build()).getTenantClient(); + client.get("013ba41150a14830bec85ffe93353bcc"); + } + + public void testGetTenantByName() { + TenantClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, + responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tenants?name=admin").build(), + standardResponseBuilder(200).payload( + payloadFromResourceWithContentType("/tenant_details.json", APPLICATION_JSON)).build()) + .getTenantClient(); + Tenant tenant = client.getByName("admin"); + assertNotNull(tenant); + assertEquals(tenant, Tenant.builder().id("013ba41150a14830bec85ffe93353bcc").name("admin").build()); + } + + public void testGetTenantByNameFailNotFound() { + TenantClient client = requestsSendResponses(keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tenants?name=admin").build(), + standardResponseBuilder(404).build()).getTenantClient(); + assertNull(client.getByName("admin")); + } + +} diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/TenantClientLiveTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/TenantClientLiveTest.java new file mode 100644 index 0000000000..09f9f2069b --- /dev/null +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/TenantClientLiveTest.java @@ -0,0 +1,67 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 1.1 (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-1.1 + * + * 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.features; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; + +import java.util.Set; + +import org.jclouds.openstack.keystone.v2_0.domain.Tenant; +import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneClientLiveTest; +import org.testng.annotations.Test; + +/** + * Tests TenantClient + * + * @author Adam Lowe + */ +@Test(groups = "live", testName = "TenantClientLiveTest") +public class TenantClientLiveTest extends BaseKeystoneClientLiveTest { + + public void testTenants() { + TenantClient client = keystoneContext.getApi().getTenantClient(); + Set result = client.list(); + assertNotNull(result); + assertFalse(result.isEmpty()); + + for (Tenant tenant : result) { + assertNotNull(tenant.getId()); + + Tenant aTenant = client.get(tenant.getId()); + assertNotNull(aTenant, "get returned null for tenant: " + tenant); + + assertEquals(aTenant, tenant); + } + } + + public void testTenantsByName() { + + TenantClient client = keystoneContext.getApi().getTenantClient(); + + for (Tenant tenant : client.list()) { + Tenant aTenant = client.getByName(tenant.getName()); + assertNotNull(aTenant, "get returned null for tenant: " + tenant); + + assertEquals(aTenant, tenant); + } + + } +} diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/TokenClientExpectTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/TokenClientExpectTest.java new file mode 100644 index 0000000000..bb77b3a4e9 --- /dev/null +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/TokenClientExpectTest.java @@ -0,0 +1,153 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 1.1 (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-1.1 + * + * 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.features; + +import static javax.ws.rs.core.MediaType.APPLICATION_JSON; +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; + +import java.net.URI; +import java.util.Set; + +import org.jclouds.date.DateService; +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.http.HttpResponseException; +import org.jclouds.openstack.keystone.v2_0.KeystoneClient; +import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; +import org.jclouds.openstack.keystone.v2_0.domain.Role; +import org.jclouds.openstack.keystone.v2_0.domain.Tenant; +import org.jclouds.openstack.keystone.v2_0.domain.Token; +import org.jclouds.openstack.keystone.v2_0.domain.User; +import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestClientExpectTest; +import org.testng.annotations.Test; + +import com.google.common.collect.ImmutableMultimap; +import com.google.common.collect.ImmutableSet; + +/** + * Tests parsing and Guice wiring of TokenClient + * + * @author Adam Lowe + */ +@Test(testName = "TokenClientExpectTest") +public class TokenClientExpectTest extends BaseKeystoneRestClientExpectTest { + private DateService dateService = new SimpleDateFormatDateService(); + + public void testGetToken() { + TokenClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/token_details.json", APPLICATION_JSON)).build()) + .getTokenClient(); + Token token = client.get("sometokenorother"); + assertNotNull(token); + assertEquals(token, + Token.builder().id("167eccdc790946969ced473732e8109b").expires(dateService.iso8601SecondsDateParse("2012-04-28T12:42:50Z")) + .tenant(Tenant.builder().id("4cea93f5464b4f1c921fb3e0461d72b5").name("demo").build()).build()); + } + + public void testGetTokenFailNotFound() { + TokenClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(), + standardResponseBuilder(404).build()) + .getTokenClient(); + assertNull(client.get("sometokenorother")); + } + + @Test(expectedExceptions = HttpResponseException.class) + public void testGetTokenFail500() { + TokenClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(), + standardResponseBuilder(500).build()).getTokenClient(); + client.get("sometokenorother"); + } + + public void testGetUserOfToken() { + TokenClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/token_details.json", APPLICATION_JSON)).build()) + .getTokenClient(); + User user = client.getUserOfToken("sometokenorother"); + assertNotNull(user); + assertEquals(user, User.builder().id("2b9b606181634ae9ac86fd95a8bc2cde").name("admin") + .roles(ImmutableSet.of(Role.builder().id("79cada5c02814b57a52e0eed4dd388cb").name("admin").build())) + .build()); + } + + public void testGetUserOfTokenFailNotFound() { + TokenClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").build(), + standardResponseBuilder(404).build()).getTokenClient(); + assertNull(client.getUserOfToken("sometokenorother")); + } + + public void testCheckTokenIsValid() { + TokenClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").method("HEAD") + .headers(ImmutableMultimap.of("X-Auth-Token", authToken)).build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/token_details.json", APPLICATION_JSON)).build()) + .getTokenClient(); + assertTrue(client.isValid("sometokenorother")); + } + + public void testCheckTokenIsValidFailNotValid() { + TokenClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/sometokenorother").method("HEAD") + .headers(ImmutableMultimap.of("X-Auth-Token", authToken)).build(), + standardResponseBuilder(404).build()).getTokenClient(); + assertFalse(client.isValid("sometokenorother")); + } + + @Test + public void testGetEndpointsForToken() { + TokenClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/XXXXXX/endpoints").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_endpoints.json", APPLICATION_JSON)).build()) + .getTokenClient(); + Set endpoints = client.listEndpointsForToken("XXXXXX"); + + assertEquals(endpoints, ImmutableSet.of( + Endpoint.builder().publicURL(URI.create("https://csnode.jclouds.org/v2.0/")) + .adminURL(URI.create("https://csnode.jclouds.org:35357/v2.0/")) + .region("region-a.geo-1").versionId("2.0").build() + )); + } + + @Test + public void testGetEndpointsForTokenFailNotFound() { + TokenClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/tokens/XXXXXX/endpoints").build(), + standardResponseBuilder(404).build()) + .getTokenClient(); + assertTrue(client.listEndpointsForToken("XXXXXX").isEmpty()); + } + + +} diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/TokenClientLiveTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/TokenClientLiveTest.java new file mode 100644 index 0000000000..6dfbb92624 --- /dev/null +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/TokenClientLiveTest.java @@ -0,0 +1,98 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 1.1 (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-1.1 + * + * 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.features; + +import static org.testng.Assert.assertEquals; +import static org.testng.Assert.assertFalse; +import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.AssertJUnit.assertTrue; + +import java.net.URI; +import java.util.Set; + +import org.jclouds.http.HttpRequest; +import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; +import org.jclouds.openstack.keystone.v2_0.domain.Token; +import org.jclouds.openstack.keystone.v2_0.domain.User; +import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest; +import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneClientLiveTest; +import org.testng.annotations.BeforeMethod; +import org.testng.annotations.Test; + +import com.google.common.collect.Iterables; + +/** + * Tests TokenClient + * + * @author Adam Lowe + */ +@Test(groups = "live", testName = "TokenClientLiveTest", singleThreaded = true) +public class TokenClientLiveTest extends BaseKeystoneClientLiveTest { + + protected String token; + + // Get the token currently in use (there's currently no listTokens()) + @BeforeMethod + public void grabToken() { + AuthenticateRequest ar = keystoneContext.getUtils().getInjector().getInstance(AuthenticateRequest.class); + HttpRequest test = ar.filter(HttpRequest.builder().method("GET").endpoint(URI.create(endpoint)).build()); + token = Iterables.getOnlyElement(test.getHeaders().get("X-Auth-Token")); + } + + public void testToken() { + + TokenClient client = keystoneContext.getApi().getTokenClient(); + assertTrue(client.isValid(token)); + Token result = client.get(token); + assertNotNull(result); + assertEquals(result.getId(), token); + assertNotNull(result.getTenant()); + + User user = client.getUserOfToken(token); + assertNotNull(user); + assertNotNull(user.getId()); + assertNotNull(user.getName()); + + } + + public void testInvalidToken() { + + TokenClient client = keystoneContext.getApi().getTokenClient(); + assertFalse(client.isValid("thisisnotarealtoken!")); + assertNull(client.get("thisisnotarealtoken!")); + + } + + public void testTokenEndpoints() { + + TokenClient client = keystoneContext.getApi().getTokenClient(); + Set endpoints = client.listEndpointsForToken(token); + assertNotNull(endpoints); + assertFalse(endpoints.isEmpty()); + + } + + public void testInvalidTokenEndpoints() { + + TokenClient client = keystoneContext.getApi().getTokenClient(); + assertTrue(client.listEndpointsForToken("thisisnotarealtoken!").isEmpty()); + + } +} \ No newline at end of file diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/UserClientExpectTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/UserClientExpectTest.java index d6e8504ecc..71b83dca17 100644 --- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/UserClientExpectTest.java +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/UserClientExpectTest.java @@ -22,21 +22,19 @@ import static javax.ws.rs.core.MediaType.APPLICATION_JSON; import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; +import static org.testng.Assert.assertNull; +import static org.testng.Assert.assertTrue; -import java.net.URI; import java.util.Set; -import org.jclouds.date.internal.SimpleDateFormatDateService; -import org.jclouds.http.HttpRequest; -import org.jclouds.http.HttpResponse; +import org.jclouds.http.HttpResponseException; import org.jclouds.openstack.keystone.v2_0.KeystoneClient; -import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; -import org.jclouds.openstack.keystone.v2_0.domain.MediaType; -import org.jclouds.openstack.keystone.v2_0.domain.Tenant; +import org.jclouds.openstack.keystone.v2_0.domain.Role; +import org.jclouds.openstack.keystone.v2_0.domain.User; import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestClientExpectTest; -import org.jclouds.openstack.v2_0.domain.Link; +import org.jclouds.rest.AuthorizationException; +import org.testng.annotations.Test; -import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableSet; /** @@ -44,53 +42,128 @@ import com.google.common.collect.ImmutableSet; * * @author Adam Lowe */ +@Test(testName = "UserClientExpectTest") public class UserClientExpectTest extends BaseKeystoneRestClientExpectTest { - public void testGetApiMetaData() { - ServiceClient client = requestsSendResponses( + public void testListUsers() { + UserClient client = requestsSendResponses( keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - HttpRequest.builder().method("GET").endpoint(URI.create(endpoint + "/v2.0/")). - headers(ImmutableMultimap.of("Accept", APPLICATION_JSON)).build(), - HttpResponse.builder().statusCode(200). - payload(payloadFromResourceWithContentType("/api_metadata.json", APPLICATION_JSON)).build()) - .getServiceClientForRegion("region-a.geo-1"); - ApiMetadata metadata = client.getApiMetadata(); - assertNotNull(metadata); - assertEquals(metadata.getId(), "v2.0"); + standardRequestBuilder(endpoint + "/v2.0/users").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_list.json", APPLICATION_JSON)).build()) + .getUserClient(); + Set users = client.list(); + assertNotNull(users); + assertFalse(users.isEmpty()); - ApiMetadata expected = ApiMetadata.builder().id("v2.0") - .links(ImmutableSet.of(Link.builder().relation(Link.Relation.SELF).href(URI.create("http://172.16.89.140:5000/v2.0/")).build(), - Link.builder().relation(Link.Relation.DESCRIBEDBY).type("text/html").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/content/")).build(), - Link.builder().relation(Link.Relation.DESCRIBEDBY).type("application/pdf").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf")).build() - )) - .status("beta") - .updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-11-19T00:00:00Z")) - .mediaTypes(ImmutableSet.of( - MediaType.builder().base("application/json").type("application/vnd.openstack.identity-v2.0+json").build(), - MediaType.builder().base("application/xml").type("application/vnd.openstack.identity-v2.0+xml").build() - )) - .build(); - - assertEquals(metadata, expected); - } - - public void testListTenants() { - ServiceClient client = requestsSendResponses( - keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, - HttpRequest.builder().method("GET").endpoint(URI.create(endpoint + "/v2.0/tenants")). - headers(ImmutableMultimap.of("Accept", APPLICATION_JSON, "X-Auth-Token", authToken)).build(), - HttpResponse.builder().statusCode(200). - payload(payloadFromResourceWithContentType("/tenant_list.json", APPLICATION_JSON)).build()) - .getServiceClientForRegion("region-a.geo-1"); - Set tenants = client.listTenants(); - assertNotNull(tenants); - assertFalse(tenants.isEmpty()); - - Set expected = ImmutableSet.of( - Tenant.builder().name("demo").id("05d1dc7af71646deba64cfc17b81bec0").build(), - Tenant.builder().name("admin").id("7aa2e17ec29f44d193c48feaba0852cc").build() + Set expected = ImmutableSet.of( + User.builder().name("nova").id("e021dfd758eb44a89f1c57c8ef3be8e2").build(), + User.builder().name("glance").id("3f6c1c9ba993495ead7d2eb2192e284f").build(), + User.builder().name("demo").id("667b2e1420604df8b67cd8ea57d4ee64").build(), + User.builder().name("admin").id("2b9b606181634ae9ac86fd95a8bc2cde").build() ); - assertEquals(tenants, expected); + assertEquals(users, expected); } + + @Test(expectedExceptions = AuthorizationException.class) + public void testListUsersFailNotAuth() { + UserClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users").build(), + standardResponseBuilder(401).build()).getUserClient(); + client.list(); + } + + public void testGetUser() { + UserClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users/e021dfd758eb44a89f1c57c8ef3be8e2").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_details.json", APPLICATION_JSON)).build()) + .getUserClient(); + User user = client.get("e021dfd758eb44a89f1c57c8ef3be8e2"); + assertNotNull(user); + assertEquals(user, User.builder().name("nova").id("e021dfd758eb44a89f1c57c8ef3be8e2").build()); + } + + public void testGetUserFailNotFound() { + UserClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users/f021dfd758eb44a89f1c57c8ef3be8e2").build(), + standardResponseBuilder(404).build()).getUserClient(); + assertNull(client.get("f021dfd758eb44a89f1c57c8ef3be8e2")); + } + + public void testGetUserByName() { + UserClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users?name=nova").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_details.json", APPLICATION_JSON)).build()) + .getUserClient(); + User user = client.getByName("nova"); + assertNotNull(user); + assertEquals(user, User.builder().name("nova").id("e021dfd758eb44a89f1c57c8ef3be8e2").build()); + } + + public void testGetUserByNameFailNotFound() { + UserClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users?name=fred").build(), + standardResponseBuilder(404).build()).getUserClient(); + assertNull(client.getByName("fred")); + } + + public void testListRolesOfUser() { + UserClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users/3f6c1c9ba993495ead7d2eb2192e284f/roles").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_role_list.json", APPLICATION_JSON)).build()) + .getUserClient(); + Set roles = client.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f"); + assertNotNull(roles); + assertFalse(roles.isEmpty()); + assertEquals(roles, ImmutableSet.of( + Role.builder().id("79cada5c02814b57a52e0eed4dd388cb").name("admin").build() + )); + } + + public void testListRolesOfUserFailNotFound() { + UserClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users/4f6c1c9ba993495ead7d2eb2192e284f/roles").build(), + standardResponseBuilder(404).build()).getUserClient(); + assertTrue(client.listRolesOfUser("4f6c1c9ba993495ead7d2eb2192e284f").isEmpty()); + } + + @Test(expectedExceptions = HttpResponseException.class) + public void testListRolesOfUserFailNotImplemented() { + UserClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users/5f6c1c9ba993495ead7d2eb2192e284f/roles").build(), + standardResponseBuilder(501).build()).getUserClient(); + assertTrue(client.listRolesOfUser("5f6c1c9ba993495ead7d2eb2192e284f").isEmpty()); + } + + public void testListRolesOfUserInTenant() { + UserClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users/3f6c1c9ba993495ead7d2eb2192e284f/roles").build(), + standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_tenant_role_list.json", APPLICATION_JSON)).build()) + .getUserClient(); + Set roles = client.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f"); + assertNotNull(roles); + assertFalse(roles.isEmpty()); + assertEquals(roles, ImmutableSet.of( + Role.builder().id("31c451195aac49b386039341e2c92a16").name("KeystoneServiceAdmin").build(), + Role.builder().id("79cada5c02814b57a52e0eed4dd388cb").name("admin").build(), + Role.builder().id("6ea17ddd37a6447794cb0e164d4db894").name("KeystoneAdmin").build())); + } + + public void testListRolesOfUserInTenantFailNotFound() { + UserClient client = requestsSendResponses( + keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess, + standardRequestBuilder(endpoint + "/v2.0/users/3f6c1c9ba993495ead7d2eb2192e284f/roles").build(), + standardResponseBuilder(404).build()).getUserClient(); + assertTrue(client.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f").isEmpty()); + } + } diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/UserClientLiveTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/UserClientLiveTest.java index c1cf75acee..3e1aaacefc 100644 --- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/UserClientLiveTest.java +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/features/UserClientLiveTest.java @@ -18,43 +18,75 @@ */ package org.jclouds.openstack.keystone.v2_0.features; +import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertFalse; import static org.testng.Assert.assertNotNull; import java.util.Set; -import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata; +import org.jclouds.openstack.keystone.v2_0.domain.Role; import org.jclouds.openstack.keystone.v2_0.domain.Tenant; +import org.jclouds.openstack.keystone.v2_0.domain.User; import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneClientLiveTest; import org.testng.annotations.Test; /** * Tests UserClient - * + * * @author Adam Lowe */ -@Test(groups = "live", testName = "UserClientLiveTest") +@Test(groups = "live", testName = "UserClientLiveTest", singleThreaded = true) public class UserClientLiveTest extends BaseKeystoneClientLiveTest { - public void testGetApiMetaData() { - for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { - ApiMetadata result = keystoneContext.getApi().getServiceClientForRegion(regionId).getApiMetadata(); - assertNotNull(result); - assertNotNull(result.getId()); - assertNotNull(result.getStatus()); - assertNotNull(result.getUpdated()); + public void testUsers() { + + UserClient client = keystoneContext.getApi().getUserClient(); + Set users = client.list(); + assertNotNull(users); + assertFalse(users.isEmpty()); + for (User user : users) { + User aUser = client.get(user.getId()); + assertEquals(aUser, user); } + } - public void testListTenants() { - for (String regionId : keystoneContext.getApi().getConfiguredRegions()) { - Set result = keystoneContext.getApi().getServiceClientForRegion(regionId).listTenants(); - assertNotNull(result); - assertFalse(result.isEmpty()); + public void testUserRolesOnTenant() { - for (Tenant tenant : result) { - assertNotNull(tenant.getId()); + UserClient client = keystoneContext.getApi().getUserClient(); + Set users = client.list(); + Set tenants = keystoneContext.getApi().getTenantClient().list(); + + for (User user : users) { + for (Tenant tenant : tenants) { + Set roles = client.listRolesOfUserOnTenant(user.getId(), tenant.getId()); + for (Role role : roles) { + assertNotNull(role.getId()); + } } } + } -} + + public void testListRolesOfUser() { + + UserClient client = keystoneContext.getApi().getUserClient(); + for (User user : client.list()) { + Set roles = client.listRolesOfUser(user.getId()); + for (Role role : roles) { + assertNotNull(role.getId()); + } + } + + } + + public void testUsersByName() { + + UserClient client = keystoneContext.getApi().getUserClient(); + for (User user : client.list()) { + User aUser = client.getByName(user.getName()); + assertEquals(aUser, user); + } + + } +} \ No newline at end of file diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/functions/ReturnRegionTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/functions/ReturnRegionOrProviderTest.java similarity index 72% rename from apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/functions/ReturnRegionTest.java rename to apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/functions/ReturnRegionOrProviderTest.java index 4a8cfe5976..595ed260a1 100644 --- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/functions/ReturnRegionTest.java +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/functions/ReturnRegionOrProviderTest.java @@ -28,9 +28,9 @@ import org.testng.annotations.Test; /** * @author Adrian Cole */ -@Test(groups = "unit", testName = "ReturnRegionTest") -public class ReturnRegionTest { - private final ReturnRegion fn = new ReturnRegion(); +@Test(groups = "unit", testName = "ReturnRegionOrProviderTest") +public class ReturnRegionOrProviderTest { + private final ReturnRegionOrProvider fn = new ReturnRegionOrProvider("openstack-keystone"); public void testRegionNotNullReturnsRegion() { assertEquals( @@ -39,15 +39,11 @@ public class ReturnRegionTest { .build()), "LON"); } - public void testRegionNullNiceNPE() { - try { - fn.apply(Endpoint.builder().versionId("1.0").publicURL( - URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953")) - .build()); - assert false; - } catch (NullPointerException e) { - assertEquals(e.getMessage(), "region"); - } + public void testRegionNullReturnsProvider() { + assertEquals( + fn.apply(Endpoint.builder().versionId("1.0").publicURL( + URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953")) + .build()), "openstack-keystone"); } } diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/internal/BaseKeystoneClientLiveTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/internal/BaseKeystoneClientLiveTest.java index 3f7be6f320..217108c702 100644 --- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/internal/BaseKeystoneClientLiveTest.java +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/internal/BaseKeystoneClientLiveTest.java @@ -38,13 +38,13 @@ import com.google.common.reflect.TypeToken; * @author Adam Lowe */ @Test(groups = "live") -public class BaseKeystoneClientLiveTest extends BaseContextLiveTest> { +public class BaseKeystoneClientLiveTest extends BaseContextLiveTest> { public BaseKeystoneClientLiveTest() { provider = "openstack-keystone"; } - protected RestContext keystoneContext; + protected RestContext keystoneContext; @BeforeGroups(groups = { "integration", "live" }) @Override @@ -67,7 +67,7 @@ public class BaseKeystoneClientLiveTest extends BaseContextLiveTest> contextType() { + protected TypeToken> contextType() { return KeystoneApiMetadata.CONTEXT_TOKEN; } diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/internal/BaseKeystoneRestClientExpectTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/internal/BaseKeystoneRestClientExpectTest.java index 102090a500..e48a7f43c9 100644 --- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/internal/BaseKeystoneRestClientExpectTest.java +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/internal/BaseKeystoneRestClientExpectTest.java @@ -25,8 +25,10 @@ import java.util.Properties; import javax.ws.rs.core.MediaType; +import org.jclouds.apis.ApiMetadata; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; +import org.jclouds.openstack.keystone.v2_0.KeystoneApiMetadata; import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.rest.internal.BaseRestClientExpectTest; @@ -43,14 +45,14 @@ public class BaseKeystoneRestClientExpectTest extends BaseRestClientExpectTes protected HttpRequest keystoneAuthWithAccessKeyAndSecretKey; protected String authToken; protected HttpResponse responseWithKeystoneAccess; - protected String endpoint = "https://csnode.jclouds.org"; + protected String endpoint = "http://localhost:5000"; public BaseKeystoneRestClientExpectTest() { provider = "openstack-keystone"; keystoneAuthWithUsernameAndPassword = KeystoneFixture.INSTANCE.initialAuthWithUsernameAndPassword(identity, - credential); + credential); keystoneAuthWithAccessKeyAndSecretKey = KeystoneFixture.INSTANCE.initialAuthWithAccessKeyAndSecretKey(identity, - credential); + credential); authToken = KeystoneFixture.INSTANCE.getAuthToken(); responseWithKeystoneAccess = KeystoneFixture.INSTANCE.responseWithAccess(); @@ -59,15 +61,15 @@ public class BaseKeystoneRestClientExpectTest extends BaseRestClientExpectTes } protected HttpRequest.Builder standardRequestBuilder(String endpoint) { - return HttpRequest.builder().method("GET") - .headers(ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken)) - .endpoint(URI.create(endpoint)); + return HttpRequest.builder().method("GET").headers( + ImmutableMultimap.of("Accept", MediaType.APPLICATION_JSON, "X-Auth-Token", authToken)).endpoint( + URI.create(endpoint)); } protected HttpResponse.Builder standardResponseBuilder(int status) { return HttpResponse.builder().statusCode(status); } - + @Override protected Properties setupProperties() { Properties props = super.setupProperties(); @@ -77,7 +79,13 @@ public class BaseKeystoneRestClientExpectTest extends BaseRestClientExpectTes @Override protected HttpRequestComparisonType compareHttpRequestAsType(HttpRequest input) { - return Objects.equal("HEAD", input.getMethod()) ? HttpRequestComparisonType.DEFAULT : HttpRequestComparisonType.JSON; + return Objects.equal("HEAD", input.getMethod()) ? HttpRequestComparisonType.DEFAULT + : HttpRequestComparisonType.JSON; + } + + @Override + protected ApiMetadata createApiMetadata() { + return new KeystoneApiMetadata(); } } diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseAccessTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseAccessTest.java index b4dd8e8277..ba381dd055 100644 --- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseAccessTest.java +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseAccessTest.java @@ -85,17 +85,23 @@ public class ParseAccessTest extends BaseItemParserTest { .tenantId("3456") .publicURL(URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456")) .region("az-1.region-a.geo-1") - .versionId("1.1").build(), + .versionId("1.1") + .versionInfo(URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/")) + .versionList(URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com")).build(), Endpoint.builder() .tenantId("3456") .publicURL(URI.create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456")) .region("az-2.region-a.geo-1") - .versionId("1.1").build(), + .versionId("1.1") + .versionInfo(URI.create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v1.1/")) + .versionList(URI.create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com")).build(), Endpoint.builder() .tenantId("3456") .publicURL(URI.create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456")) .region("az-3.region-a.geo-1") - .versionId("1.1").build()).build(), + .versionId("1.1") + .versionInfo(URI.create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v1.1/")) + .versionList(URI.create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com")).build()).build(), Service.builder().name("Quantum Service").type("network").endpoints( Endpoint.builder() diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseRackspaceAccessTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseRackspaceAccessTest.java new file mode 100644 index 0000000000..670b1c5ab7 --- /dev/null +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseRackspaceAccessTest.java @@ -0,0 +1,113 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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.parse; + +import java.net.URI; + +import javax.ws.rs.Consumes; +import javax.ws.rs.core.MediaType; + +import org.jclouds.date.internal.SimpleDateFormatDateService; +import org.jclouds.json.BaseItemParserTest; +import org.jclouds.openstack.keystone.v2_0.domain.Access; +import org.jclouds.openstack.keystone.v2_0.domain.Endpoint; +import org.jclouds.openstack.keystone.v2_0.domain.Role; +import org.jclouds.openstack.keystone.v2_0.domain.Service; +import org.jclouds.openstack.keystone.v2_0.domain.Tenant; +import org.jclouds.openstack.keystone.v2_0.domain.Token; +import org.jclouds.openstack.keystone.v2_0.domain.User; +import org.jclouds.rest.annotations.SelectJson; +import org.testng.annotations.Test; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "ParseAccessTest") +public class ParseRackspaceAccessTest extends BaseItemParserTest { + + @Override + public String resource() { + return "/raxAuth.json"; + } + + @Override + @SelectJson("access") + @Consumes(MediaType.APPLICATION_JSON) + public Access expected() { + return Access.builder().token( + Token.builder().expires(new SimpleDateFormatDateService().iso8601DateParse("2012-06-06T20:56:47.000-05:00")) + .id("Auth_4f173437e4b013bee56d1007").tenant( + Tenant.builder().id("40806637803162").name("40806637803162").build()) + .build()).user( + User.builder().id("54321").name("joe").roles( + Role.builder().id("3").name("identity:user-admin").description("User Admin Role.") + .build()).build()).serviceCatalog( + + Service.builder().name("cloudDatabases").type("rax:database").endpoints( + Endpoint.builder().tenantId("40806637803162").publicURL( + URI.create("https://dfw.databases.api.rackspacecloud.com/v1.0/40806637803162")) + .region("DFW").build(), + Endpoint.builder().tenantId("40806637803162").publicURL( + URI.create("https://ord.databases.api.rackspacecloud.com/v1.0/40806637803162")) + .region("ORD").build()).build(), + + Service.builder().name("cloudServers").type("compute").endpoints( + Endpoint.builder().tenantId("40806637803162").publicURL( + URI.create("https://servers.api.rackspacecloud.com/v1.0/40806637803162")) + .versionId("1.0").versionInfo(URI.create("https://servers.api.rackspacecloud.com/v1.0")) + .versionList(URI.create("https://servers.api.rackspacecloud.com/")).build()).build(), + + Service.builder().name("cloudFiles").type("object-store").endpoints( + Endpoint.builder().tenantId("MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22").publicURL( + URI.create("https://storage101.dfw1.clouddrive.com/v1/MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22")) + .internalURL( + URI.create("https://snet-storage101.dfw1.clouddrive.com/v1/MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22")) + .region("DFW").build()).build(), + + Service.builder().name("cloudServersOpenStack").type("compute").endpoints( + Endpoint.builder().tenantId("40806637803162").publicURL( + URI.create("https://dfw.servers.api.rackspacecloud.com/v2/40806637803162")) + .versionInfo(URI.create("https://dfw.servers.api.rackspacecloud.com/v2")) + .versionList(URI.create("https://dfw.servers.api.rackspacecloud.com/")) + .versionId("2") + .region("DFW").build()).build(), + + Service.builder().name("cloudLoadBalancers").type("rax:load-balancer").endpoints( + Endpoint.builder().tenantId("40806637803162").publicURL( + URI.create("https://ord.loadbalancers.api.rackspacecloud.com/v1.0/40806637803162")) + .region("ORD").build(), + Endpoint.builder().tenantId("40806637803162").publicURL( + URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/40806637803162")) + .region("DFW").build()).build(), + + Service.builder().name("cloudMonitoring").type("rax:monitor").endpoints( + Endpoint.builder().tenantId("40806637803162").publicURL( + URI.create("https://monitoring.api.rackspacecloud.com/v1.0/40806637803162")).build()).build(), + + Service.builder().name("cloudDNS").type("dnsextension:dns").endpoints( + Endpoint.builder().tenantId("40806637803162").publicURL( + URI.create("https://dns.api.rackspacecloud.com/v1.0/40806637803162")).build()).build(), + + Service.builder().name("cloudFilesCDN").type("rax:object-cdn").endpoints( + Endpoint.builder().tenantId("MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22").publicURL( + URI.create("https://cdn1.clouddrive.com/v1/MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22")) + .region("DFW").build()).build() + ).build(); + } +} diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseApiMetadataTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseRackspaceApiMetadataTest.java similarity index 72% rename from apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseApiMetadataTest.java rename to apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseRackspaceApiMetadataTest.java index df44b6d504..23647aee2b 100644 --- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseApiMetadataTest.java +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/parse/ParseRackspaceApiMetadataTest.java @@ -7,7 +7,7 @@ * "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 + * https://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 @@ -33,30 +33,31 @@ import org.testng.annotations.Test; import com.google.common.collect.ImmutableSet; /** - * @author Adam Lowe + * @author Adrian Cole */ @Test(groups = "unit", testName = "ParseApiMetadataTest") -public class ParseApiMetadataTest extends BaseItemParserTest { +public class ParseRackspaceApiMetadataTest extends BaseItemParserTest { @Override public String resource() { - return "/apiMetadataResponse.json"; + return "/raxVersion.json"; } + // http://docs.openstack.org/api/openstack-identity-service/2.0/content/Versions-d1e472.html @Override @SelectJson("version") @Consumes(MediaType.APPLICATION_JSON) public ApiMetadata expected() { return ApiMetadata.builder().id("v2.0") - .links(ImmutableSet.of(Link.builder().relation(Link.Relation.SELF).href(URI.create("http://172.16.89.140:5000/v2.0/")).build(), - Link.builder().relation(Link.Relation.DESCRIBEDBY).type("text/html").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/content/")).build(), - Link.builder().relation(Link.Relation.DESCRIBEDBY).type("application/pdf").href(URI.create("http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf")).build() + .links(ImmutableSet.of(Link.builder().relation(Link.Relation.SELF).href(URI.create("https://identity.api.rackspacecloud.com/v2.0")).build(), + Link.builder().relation(Link.Relation.DESCRIBEDBY).type("application/pdf").href(URI.create("http://docs.rackspacecloud.com/auth/api/v2.0/auth-client-devguide-latest.pdf")).build(), + Link.builder().relation(Link.Relation.DESCRIBEDBY).type("application/vnd.sun.wadl+xml").href(URI.create("http://docs.rackspacecloud.com/auth/api/v2.0/auth.wadl")).build() )) - .status("beta") - .updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-11-19T00:00:00Z")) + .status("BETA") + .updated(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-01-21T11:33:21-06:00")) .mediaTypes(ImmutableSet.of( - org.jclouds.openstack.keystone.v2_0.domain.MediaType.builder().base("application/json").type("application/vnd.openstack.identity-v2.0+json").build(), - org.jclouds.openstack.keystone.v2_0.domain.MediaType.builder().base("application/xml").type("application/vnd.openstack.identity-v2.0+xml").build() + org.jclouds.openstack.keystone.v2_0.domain.MediaType.builder().base("application/xml").type("application/vnd.openstack.identity+xml;version=2.0").build(), + org.jclouds.openstack.keystone.v2_0.domain.MediaType.builder().base("application/json").type("application/vnd.openstack.identity+json;version=2.0").build() )) .build(); } diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionSupplierTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionTest.java similarity index 51% rename from apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionSupplierTest.java rename to apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionTest.java index fffde689c6..09f266708e 100644 --- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionSupplierTest.java +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToAdminURIFromAccessForTypeAndVersionTest.java @@ -22,11 +22,14 @@ import static org.testng.Assert.assertEquals; import java.net.URI; import java.util.Map; +import java.util.NoSuchElementException; import javax.inject.Singleton; +import org.jclouds.location.Provider; import org.jclouds.openstack.keystone.v2_0.domain.Access; import org.jclouds.openstack.keystone.v2_0.parse.ParseAccessTest; +import org.jclouds.openstack.keystone.v2_0.parse.ParseRackspaceAccessTest; import org.testng.annotations.Test; import com.google.common.base.Supplier; @@ -36,19 +39,23 @@ import com.google.common.collect.Maps; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Provides; +import com.google.inject.TypeLiteral; import com.google.inject.assistedinject.FactoryModuleBuilder; /** * @author Adam Lowe */ -@Test(groups = "unit", testName = "RegionIdToAdminURIFromAccessForTypeAndVersionSupplierTest") -public class RegionIdToAdminURIFromAccessForTypeAndVersionSupplierTest { +@Test(groups = "unit", testName = "RegionIdToAdminURIFromAccessForTypeAndVersionTest") +public class RegionIdToAdminURIFromAccessForTypeAndVersionTest { private final RegionIdToAdminURISupplier.Factory factory = Guice.createInjector(new AbstractModule() { @Override protected void configure() { + bindConstant().annotatedWith(Provider.class).to("openstack-keystone"); + bind(new TypeLiteral>() { + }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity"))); install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class, - RegionIdToAdminURIFromAccessForTypeAndVersionSupplier.class).build(RegionIdToAdminURISupplier.Factory.class)); + RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class)); } @SuppressWarnings("unused") @@ -69,5 +76,45 @@ public class RegionIdToAdminURIFromAccessForTypeAndVersionSupplierTest { assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.1").get(), Suppliers . supplierFunction()), map); } + + private final RegionIdToAdminURISupplier.Factory raxFactory = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(Provider.class).to("rackspace"); + bind(new TypeLiteral>() { + }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity"))); + install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class, + RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class)); + } + + @SuppressWarnings("unused") + @Provides + @Singleton + public Supplier provide() { + return Suppliers.ofInstance(new ParseRackspaceAccessTest().expected()); + } + }).getInstance(RegionIdToAdminURISupplier.Factory.class); + + @Test(expectedExceptions = NoSuchElementException.class) + public void testWhenNotInList() { + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("goo", "1.0").get(), Suppliers + . supplierFunction()), ImmutableMap.of("rackspace", URI + .create("https://servers.api.rackspacecloud.com/v1.0/40806637803162"))); + } + + public void testProviderWhenNoRegions() { + Map map = Maps.newLinkedHashMap(); + map.put("rackspace", null); + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("compute", "1.0").get(), Suppliers + . supplierFunction()), map); + } + + public void testOkWithNoVersions() { + Map map = Maps.newLinkedHashMap(); + map.put("DFW", null); + map.put("ORD", null); + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("rax:database", null).get(), Suppliers + . supplierFunction()), map); + } } diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToURIFromAccessForTypeAndVersionSupplierTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToURIFromAccessForTypeAndVersionSupplierTest.java deleted file mode 100644 index ef993f1211..0000000000 --- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToURIFromAccessForTypeAndVersionSupplierTest.java +++ /dev/null @@ -1,71 +0,0 @@ -/** - * Licensed to jclouds, Inc. (jclouds) under one or more - * contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. jclouds 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 static org.testng.Assert.assertEquals; - -import java.net.URI; - -import javax.inject.Singleton; - -import org.jclouds.location.suppliers.RegionIdToURISupplier; -import org.jclouds.openstack.keystone.v2_0.domain.Access; -import org.jclouds.openstack.keystone.v2_0.parse.ParseAccessTest; -import org.testng.annotations.Test; - -import com.google.common.base.Supplier; -import com.google.common.base.Suppliers; -import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Maps; -import com.google.inject.AbstractModule; -import com.google.inject.Guice; -import com.google.inject.Provides; -import com.google.inject.assistedinject.FactoryModuleBuilder; - -/** - * @author Adrian Cole - */ -@Test(groups = "unit", testName = "RegionIdToURIFromAccessForTypeAndVersionSupplierTest") -public class RegionIdToURIFromAccessForTypeAndVersionSupplierTest { - private final RegionIdToURISupplier.Factory factory = Guice.createInjector(new AbstractModule() { - - @Override - protected void configure() { - install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class, - RegionIdToURIFromAccessForTypeAndVersionSupplier.class).build(RegionIdToURISupplier.Factory.class)); - } - - @SuppressWarnings("unused") - @Provides - @Singleton - public Supplier provide() { - return Suppliers.ofInstance(new ParseAccessTest().expected()); - } - }).getInstance(RegionIdToURISupplier.Factory.class); - - public void testRegionMatches() { - assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.0").get(), Suppliers - . supplierFunction()), ImmutableMap.of()); - assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.1").get(), Suppliers - . supplierFunction()), ImmutableMap.of("az-1.region-a.geo-1", URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"), - "az-2.region-a.geo-1", URI.create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"), - "az-3.region-a.geo-1", URI.create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"))); - } - -} diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToURIFromAccessForTypeAndVersionTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToURIFromAccessForTypeAndVersionTest.java new file mode 100644 index 0000000000..650fcd5c82 --- /dev/null +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/RegionIdToURIFromAccessForTypeAndVersionTest.java @@ -0,0 +1,120 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds 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 static org.testng.Assert.assertEquals; + +import java.net.URI; +import java.util.NoSuchElementException; + +import javax.inject.Singleton; + +import org.jclouds.location.Provider; +import org.jclouds.location.suppliers.RegionIdToURISupplier; +import org.jclouds.openstack.keystone.v2_0.domain.Access; +import org.jclouds.openstack.keystone.v2_0.parse.ParseAccessTest; +import org.jclouds.openstack.keystone.v2_0.parse.ParseRackspaceAccessTest; +import org.testng.annotations.Test; + +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; +import com.google.common.collect.ImmutableMap; +import com.google.common.collect.Maps; +import com.google.inject.AbstractModule; +import com.google.inject.Guice; +import com.google.inject.Provides; +import com.google.inject.TypeLiteral; +import com.google.inject.assistedinject.FactoryModuleBuilder; + +/** + * @author Adrian Cole + */ +@Test(groups = "unit", testName = "RegionIdToURIFromAccessForTypeAndVersionTest") +public class RegionIdToURIFromAccessForTypeAndVersionTest { + private final RegionIdToURISupplier.Factory factory = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bindConstant().annotatedWith(Provider.class).to("openstack-keystone"); + bind(new TypeLiteral>(){ + }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity"))); + install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class, + RegionIdToURIFromAccessForTypeAndVersion.class).build( + RegionIdToURISupplier.Factory.class)); + } + + @SuppressWarnings("unused") + @Provides + @Singleton + public Supplier provide() { + return Suppliers.ofInstance(new ParseAccessTest().expected()); + } + }).getInstance(RegionIdToURISupplier.Factory.class); + + public void testRegionMatches() { + assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.0").get(), Suppliers + . supplierFunction()), ImmutableMap.of()); + assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.1").get(), Suppliers + . supplierFunction()), ImmutableMap.of("az-1.region-a.geo-1", URI + .create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"), "az-2.region-a.geo-1", URI + .create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"), "az-3.region-a.geo-1", URI + .create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"))); + } + + private final RegionIdToURISupplier.Factory raxFactory = Guice.createInjector(new AbstractModule() { + + @Override + protected void configure() { + bindConstant().annotatedWith(Provider.class).to("rackspace"); + bind(new TypeLiteral>() { + }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity"))); + install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class, + RegionIdToURIFromAccessForTypeAndVersion.class).build( + RegionIdToURISupplier.Factory.class)); + } + + @SuppressWarnings("unused") + @Provides + @Singleton + public Supplier provide() { + return Suppliers.ofInstance(new ParseRackspaceAccessTest().expected()); + } + }).getInstance(RegionIdToURISupplier.Factory.class); + + @Test(expectedExceptions = NoSuchElementException.class) + public void testWhenNotInList() { + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("goo", "1.0").get(), Suppliers + . supplierFunction()), ImmutableMap.of("rackspace", URI + .create("https://servers.api.rackspacecloud.com/v1.0/40806637803162"))); + } + + public void testProviderWhenNoRegions() { + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("compute", "1.0").get(), Suppliers + . supplierFunction()), ImmutableMap.of("rackspace", URI + .create("https://servers.api.rackspacecloud.com/v1.0/40806637803162"))); + } + + public void testOkWithNoVersions() { + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("rax:database", null).get(), Suppliers + . supplierFunction()), ImmutableMap.of("DFW", URI + .create("https://dfw.databases.api.rackspacecloud.com/v1.0/40806637803162"), "ORD", URI + .create("https://ord.databases.api.rackspacecloud.com/v1.0/40806637803162"))); + } + +} diff --git a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersionSupplierTest.java b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersionTest.java similarity index 52% rename from apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersionSupplierTest.java rename to apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersionTest.java index b8c72edd78..3805196400 100644 --- a/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersionSupplierTest.java +++ b/apis/openstack-keystone/src/test/java/org/jclouds/openstack/keystone/v2_0/suppliers/ZoneIdToURIFromAccessForTypeAndVersionTest.java @@ -21,12 +21,15 @@ package org.jclouds.openstack.keystone.v2_0.suppliers; import static org.testng.Assert.assertEquals; import java.net.URI; +import java.util.NoSuchElementException; import javax.inject.Singleton; +import org.jclouds.location.Provider; import org.jclouds.location.suppliers.ZoneIdToURISupplier; import org.jclouds.openstack.keystone.v2_0.domain.Access; import org.jclouds.openstack.keystone.v2_0.parse.ParseAccessTest; +import org.jclouds.openstack.keystone.v2_0.parse.ParseRackspaceAccessTest; import org.testng.annotations.Test; import com.google.common.base.Supplier; @@ -36,19 +39,23 @@ import com.google.common.collect.Maps; import com.google.inject.AbstractModule; import com.google.inject.Guice; import com.google.inject.Provides; +import com.google.inject.TypeLiteral; import com.google.inject.assistedinject.FactoryModuleBuilder; /** * @author Adrian Cole */ @Test(groups = "unit", testName = "ZoneIdToURIFromAccessForTypeAndVersionSupplierTest") -public class ZoneIdToURIFromAccessForTypeAndVersionSupplierTest { +public class ZoneIdToURIFromAccessForTypeAndVersionTest { private final ZoneIdToURISupplier.Factory factory = Guice.createInjector(new AbstractModule() { @Override protected void configure() { + bindConstant().annotatedWith(Provider.class).to("rackspace"); + bind(new TypeLiteral>() { + }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity"))); install(new FactoryModuleBuilder().implement(ZoneIdToURISupplier.class, - ZoneIdToURIFromAccessForTypeAndVersionSupplier.class).build(ZoneIdToURISupplier.Factory.class)); + ZoneIdToURIFromAccessForTypeAndVersion.class).build(ZoneIdToURISupplier.Factory.class)); } @SuppressWarnings("unused") @@ -67,5 +74,41 @@ public class ZoneIdToURIFromAccessForTypeAndVersionSupplierTest { "az-2.region-a.geo-1", URI.create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"), "az-3.region-a.geo-1", URI.create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"))); } + + private final ZoneIdToURISupplier.Factory raxFactory = Guice.createInjector(new AbstractModule() { + @Override + protected void configure() { + bindConstant().annotatedWith(Provider.class).to("rackspace"); + bind(new TypeLiteral>() { + }).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity"))); + install(new FactoryModuleBuilder().implement(ZoneIdToURISupplier.class, + ZoneIdToURIFromAccessForTypeAndVersion.class).build(ZoneIdToURISupplier.Factory.class)); + } + + @SuppressWarnings("unused") + @Provides + @Singleton + public Supplier provide() { + return Suppliers.ofInstance(new ParseRackspaceAccessTest().expected()); + } + }).getInstance(ZoneIdToURISupplier.Factory.class); + + @Test(expectedExceptions = NoSuchElementException.class) + public void testWhenNotInList() { + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("goo", "1.0").get(), Suppliers + . supplierFunction()), ImmutableMap.of("rackspace", URI + .create("https://servers.api.rackspacecloud.com/v1.0/40806637803162"))); + } + + public void testProviderWhenNoZones() { + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("compute", "1.0").get(), Suppliers + . supplierFunction()), ImmutableMap.of("rackspace", URI.create("https://servers.api.rackspacecloud.com/v1.0/40806637803162"))); + } + + public void testOkWithNoVersions() { + assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("rax:database", null).get(), Suppliers + . supplierFunction()), ImmutableMap.of("DFW", URI.create("https://dfw.databases.api.rackspacecloud.com/v1.0/40806637803162"), + "ORD", URI.create("https://ord.databases.api.rackspacecloud.com/v1.0/40806637803162"))); + } } diff --git a/apis/openstack-keystone/src/test/resources/apiMetadataResponse.json b/apis/openstack-keystone/src/test/resources/apiMetadataResponse.json deleted file mode 100644 index 09934299c9..0000000000 --- a/apis/openstack-keystone/src/test/resources/apiMetadataResponse.json +++ /dev/null @@ -1 +0,0 @@ -{"version": {"status": "beta", "updated": "2011-11-19T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}, {"base": "application/xml", "type": "application/vnd.openstack.identity-v2.0+xml"}], "id": "v2.0", "links": [{"href": "http://172.16.89.140:5000/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/content/", "type": "text/html", "rel": "describedby"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf", "type": "application/pdf", "rel": "describedby"}]}} \ No newline at end of file diff --git a/apis/openstack-keystone/src/test/resources/api_metadata.json b/apis/openstack-keystone/src/test/resources/api_metadata.json deleted file mode 100644 index 09934299c9..0000000000 --- a/apis/openstack-keystone/src/test/resources/api_metadata.json +++ /dev/null @@ -1 +0,0 @@ -{"version": {"status": "beta", "updated": "2011-11-19T00:00:00Z", "media-types": [{"base": "application/json", "type": "application/vnd.openstack.identity-v2.0+json"}, {"base": "application/xml", "type": "application/vnd.openstack.identity-v2.0+xml"}], "id": "v2.0", "links": [{"href": "http://172.16.89.140:5000/v2.0/", "rel": "self"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/content/", "type": "text/html", "rel": "describedby"}, {"href": "http://docs.openstack.org/api/openstack-identity-service/2.0/identity-dev-guide-2.0.pdf", "type": "application/pdf", "rel": "describedby"}]}} \ No newline at end of file diff --git a/apis/openstack-keystone/src/test/resources/raxAuth.json b/apis/openstack-keystone/src/test/resources/raxAuth.json new file mode 100644 index 0000000000..fbf29eff1f --- /dev/null +++ b/apis/openstack-keystone/src/test/resources/raxAuth.json @@ -0,0 +1,98 @@ +{ + "access": { + "token": { + "id": "Auth_4f173437e4b013bee56d1007", + "expires": "2012-06-06T20:56:47.000-05:00", + "tenant": { + "id": "40806637803162", + "name": "40806637803162" + } + }, + "serviceCatalog": [{ + "endpoints": [{ + "region": "DFW", + "tenantId": "40806637803162", + "publicURL": "https:\/\/dfw.databases.api.rackspacecloud.com\/v1.0\/40806637803162" + }, { + "region": "ORD", + "tenantId": "40806637803162", + "publicURL": "https:\/\/ord.databases.api.rackspacecloud.com\/v1.0\/40806637803162" + }], + "name": "cloudDatabases", + "type": "rax:database" + }, { + "endpoints": [{ + "tenantId": "40806637803162", + "publicURL": "https:\/\/servers.api.rackspacecloud.com\/v1.0\/40806637803162", + "versionInfo": "https:\/\/servers.api.rackspacecloud.com\/v1.0", + "versionList": "https:\/\/servers.api.rackspacecloud.com\/", + "versionId": "1.0" + }], + "name": "cloudServers", + "type": "compute" + }, { + "endpoints": [{ + "region": "DFW", + "tenantId": "MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22", + "publicURL": "https:\/\/storage101.dfw1.clouddrive.com\/v1\/MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22", + "internalURL": "https:\/\/snet-storage101.dfw1.clouddrive.com\/v1\/MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22" + }], + "name": "cloudFiles", + "type": "object-store" + }, { + "endpoints": [{ + "region": "DFW", + "tenantId": "40806637803162", + "publicURL": "https:\/\/dfw.servers.api.rackspacecloud.com\/v2\/40806637803162", + "versionInfo": "https:\/\/dfw.servers.api.rackspacecloud.com\/v2", + "versionList": "https:\/\/dfw.servers.api.rackspacecloud.com\/", + "versionId": "2" + }], + "name": "cloudServersOpenStack", + "type": "compute" + }, { + "endpoints": [{ + "region": "ORD", + "tenantId": "40806637803162", + "publicURL": "https:\/\/ord.loadbalancers.api.rackspacecloud.com\/v1.0\/40806637803162" + }, { + "region": "DFW", + "tenantId": "40806637803162", + "publicURL": "https:\/\/dfw.loadbalancers.api.rackspacecloud.com\/v1.0\/40806637803162" + }], + "name": "cloudLoadBalancers", + "type": "rax:load-balancer" + }, { + "endpoints": [{ + "tenantId": "40806637803162", + "publicURL": "https:\/\/monitoring.api.rackspacecloud.com\/v1.0\/40806637803162" + }], + "name": "cloudMonitoring", + "type": "rax:monitor" + }, { + "endpoints": [{ + "tenantId": "40806637803162", + "publicURL": "https:\/\/dns.api.rackspacecloud.com\/v1.0\/40806637803162" + }], + "name": "cloudDNS", + "type": "dnsextension:dns" + }, { + "endpoints": [{ + "region": "DFW", + "tenantId": "MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22", + "publicURL": "https:\/\/cdn1.clouddrive.com\/v1\/MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22" + }], + "name": "cloudFilesCDN", + "type": "rax:object-cdn" + }], + "user": { + "id": "54321", + "roles": [{ + "id": "3", + "description": "User Admin Role.", + "name": "identity:user-admin" + }], + "name": "joe" + } + } +} \ No newline at end of file diff --git a/apis/openstack-keystone/src/test/resources/raxVersion.json b/apis/openstack-keystone/src/test/resources/raxVersion.json new file mode 100644 index 0000000000..13d99de05a --- /dev/null +++ b/apis/openstack-keystone/src/test/resources/raxVersion.json @@ -0,0 +1,28 @@ +{ + "version": { + "id": "v2.0", + "updated": "2012-01-21T11:33:21-06:00", + "status": "BETA", + "links": [{ + "rel": "self", + "href": "https:\/\/identity.api.rackspacecloud.com\/v2.0" + }, { + "rel": "describedby", + "type": "application\/pdf", + "href": "http:\/\/docs.rackspacecloud.com\/auth\/api\/v2.0\/auth-client-devguide-latest.pdf" + }, { + "rel": "describedby", + "type": "application\/vnd.sun.wadl+xml", + "href": "http:\/\/docs.rackspacecloud.com\/auth\/api\/v2.0\/auth.wadl" + }], + "media-types": { + "values": [{ + "base": "application\/xml", + "type": "application\/vnd.openstack.identity+xml;version=2.0" + }, { + "base": "application\/json", + "type": "application\/vnd.openstack.identity+json;version=2.0" + }] + } + } +} \ No newline at end of file diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaApiMetadata.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaApiMetadata.java index 870db664d8..a48920a8db 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaApiMetadata.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/NovaApiMetadata.java @@ -18,6 +18,7 @@ */ package org.jclouds.openstack.nova.v1_1; +import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE; import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE; import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.VERSION; import static org.jclouds.openstack.nova.v1_1.config.NovaProperties.AUTO_ALLOCATE_FLOATING_IPS; @@ -29,6 +30,8 @@ import java.util.Properties; import org.jclouds.apis.ApiMetadata; import org.jclouds.compute.ComputeServiceContext; +import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes; +import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.KeystoneAuthenticationModuleForZones; import org.jclouds.openstack.nova.v1_1.compute.config.NovaComputeServiceContextModule; import org.jclouds.openstack.nova.v1_1.config.NovaRestClientModule; import org.jclouds.openstack.v2_0.ServiceType; @@ -73,6 +76,8 @@ public class NovaApiMetadata extends BaseRestApiMetadata { properties.setProperty("jclouds.ssh.retry-auth", "true"); properties.setProperty(SERVICE_TYPE, ServiceType.COMPUTE); + properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS); + // TODO: this doesn't actually do anything yet. properties.setProperty(VERSION, "2.0"); @@ -95,7 +100,7 @@ public class NovaApiMetadata extends BaseRestApiMetadata { .defaultEndpoint("http://localhost:5000") .defaultProperties(NovaApiMetadata.defaultProperties()) .view(TypeToken.of(ComputeServiceContext.class)) - .defaultModules(ImmutableSet.>of(NovaRestClientModule.class, NovaComputeServiceContextModule.class)); + .defaultModules(ImmutableSet.>of(KeystoneAuthenticationModuleForZones.class, NovaRestClientModule.class, NovaComputeServiceContextModule.class)); } @Override diff --git a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java index b9bfa0ac86..5eccc0759f 100644 --- a/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java +++ b/apis/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java @@ -31,7 +31,6 @@ import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.ServerError; import org.jclouds.location.suppliers.ImplicitLocationSupplier; import org.jclouds.location.suppliers.implicit.OnlyLocationOrFirstZone; -import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule; import org.jclouds.openstack.nova.v1_1.NovaAsyncClient; import org.jclouds.openstack.nova.v1_1.NovaClient; import org.jclouds.openstack.nova.v1_1.domain.Extension; @@ -126,12 +125,6 @@ public class NovaRestClientModule extends RestClientModule> * type of the api, according to the provider. ex. {@code compute} {@code * object-store} * @param apiVersion - * version of the api + * version of the api, or null if not present * @return regions mapped to default uri */ ZoneIdToURISupplier createForApiTypeAndVersion(@Assisted("apiType") String apiType, - @Assisted("apiVersion") String apiVersion); + @Nullable @Assisted("apiVersion") String apiVersion); } } \ No newline at end of file diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/GlanceApiMetadata.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/GlanceApiMetadata.java index 5d52819197..a3c1adbbfe 100644 --- a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/GlanceApiMetadata.java +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/GlanceApiMetadata.java @@ -18,6 +18,7 @@ */ package org.jclouds.openstack.glance.v1_0; +import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE; import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE; import java.net.URI; @@ -25,7 +26,9 @@ import java.util.Properties; import org.jclouds.apis.ApiMetadata; import org.jclouds.openstack.glance.v1_0.config.GlanceRestClientModule; +import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes; import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties; +import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule.KeystoneAuthenticationModuleForRegions; import org.jclouds.openstack.v2_0.ServiceType; import org.jclouds.rest.RestContext; import org.jclouds.rest.internal.BaseRestApiMetadata; @@ -64,6 +67,8 @@ public class GlanceApiMetadata extends BaseRestApiMetadata { public static Properties defaultProperties() { Properties properties = BaseRestApiMetadata.defaultProperties(); properties.setProperty(SERVICE_TYPE, ServiceType.IMAGE); + properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS); + // TODO: this doesn't actually do anything yet. properties.setProperty(KeystoneProperties.VERSION, "2.0"); return properties; @@ -81,7 +86,7 @@ public class GlanceApiMetadata extends BaseRestApiMetadata { .version("1.0") .defaultEndpoint("http://localhost:5000") .defaultProperties(GlanceApiMetadata.defaultProperties()) - .defaultModules(ImmutableSet.>of(GlanceRestClientModule.class)); + .defaultModules(ImmutableSet.>of(KeystoneAuthenticationModuleForRegions.class, GlanceRestClientModule.class)); } @Override diff --git a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/config/GlanceRestClientModule.java b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/config/GlanceRestClientModule.java index 2e6c7b2918..9dbe6f5234 100644 --- a/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/config/GlanceRestClientModule.java +++ b/labs/openstack-glance/src/main/java/org/jclouds/openstack/glance/v1_0/config/GlanceRestClientModule.java @@ -31,7 +31,6 @@ import org.jclouds.openstack.glance.v1_0.GlanceClient; import org.jclouds.openstack.glance.v1_0.features.ImageAsyncClient; import org.jclouds.openstack.glance.v1_0.features.ImageClient; import org.jclouds.openstack.glance.v1_0.handlers.GlanceErrorHandler; -import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule; import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.config.RestClientModule; @@ -59,17 +58,6 @@ public class GlanceRestClientModule extends RestClientModule>of(QuantumRestClientModule.class)); + .defaultModules(ImmutableSet.>of(KeystoneAuthenticationModuleForRegions.class, QuantumRestClientModule.class)); } @Override diff --git a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/config/QuantumRestClientModule.java b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/config/QuantumRestClientModule.java index 4017df5257..8850d989f9 100644 --- a/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/config/QuantumRestClientModule.java +++ b/labs/openstack-quantum/src/main/java/org/jclouds/openstack/quantum/v1_0/config/QuantumRestClientModule.java @@ -26,7 +26,6 @@ import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.ServerError; import org.jclouds.json.config.GsonModule.DateAdapter; import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; -import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule; import org.jclouds.openstack.quantum.v1_0.QuantumAsyncClient; import org.jclouds.openstack.quantum.v1_0.QuantumClient; import org.jclouds.openstack.quantum.v1_0.features.NetworkAsyncClient; @@ -62,17 +61,6 @@ public class QuantumRestClientModule extends RestClientModule>of(SwiftRestClientModule.class)); + .defaultModules(ImmutableSet.>of(KeystoneAuthenticationModuleForRegions.class, SwiftRestClientModule.class)); } @Override diff --git a/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/config/SwiftRestClientModule.java b/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/config/SwiftRestClientModule.java index 54dfd01498..daa5c2eb10 100644 --- a/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/config/SwiftRestClientModule.java +++ b/labs/openstack-swift/src/main/java/org/jclouds/openstack/swift/v1/config/SwiftRestClientModule.java @@ -26,7 +26,6 @@ import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.ServerError; import org.jclouds.json.config.GsonModule.DateAdapter; import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; -import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule; import org.jclouds.openstack.swift.v1.SwiftAsyncClient; import org.jclouds.openstack.swift.v1.SwiftClient; import org.jclouds.openstack.swift.v1.features.AccountAsyncClient; @@ -65,17 +64,6 @@ public class SwiftRestClientModule extends RestClientModule>of(HPCloudObjectStorageRestClientModule.class, HPCloudObjectStorageBlobStoreContextModule.class)); + .defaultModules(ImmutableSet.>of(KeystoneAuthenticationModuleForRegions.class, HPCloudObjectStorageRestClientModule.class, HPCloudObjectStorageBlobStoreContextModule.class)); } @Override diff --git a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/config/HPCloudObjectStorageRestClientModule.java b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/config/HPCloudObjectStorageRestClientModule.java index a165856a0b..a2ec6948e2 100644 --- a/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/config/HPCloudObjectStorageRestClientModule.java +++ b/providers/hpcloud-objectstorage/src/main/java/org/jclouds/hpcloud/objectstorage/config/HPCloudObjectStorageRestClientModule.java @@ -38,7 +38,6 @@ import org.jclouds.http.annotation.ServerError; import org.jclouds.json.config.GsonModule.DateAdapter; import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; import org.jclouds.location.suppliers.RegionIdToURISupplier; -import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule; import org.jclouds.openstack.services.ServiceType; import org.jclouds.openstack.swift.CommonSwiftAsyncClient; import org.jclouds.openstack.swift.CommonSwiftClient; @@ -73,13 +72,6 @@ public class HPCloudObjectStorageRestClientModule extends super.configure(); } - @Override - protected void installLocations() { - super.installLocations(); - // TODO: select this from KeystoneProperties.VERSION; - install(KeystoneAuthenticationModule.forRegions()); - } - @Override protected void bindErrorHandlers() { bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(ParseSwiftErrorFromHttpResponse.class);