Merge branch 'master' of github.com:jclouds/jclouds into cloudstack-qa

This commit is contained in:
Andrei Savu 2012-06-07 11:25:44 +03:00
commit a83aa71087
258 changed files with 5477 additions and 1828 deletions

View File

@ -28,7 +28,6 @@ import org.jclouds.apis.ApiMetadata;
import org.jclouds.blobstore.BlobStoreContext;
import org.jclouds.cloudfiles.blobstore.config.CloudFilesBlobStoreContextModule;
import org.jclouds.cloudfiles.config.CloudFilesRestClientModule;
import org.jclouds.openstack.OpenStackAuthAsyncClient;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
@ -81,7 +80,7 @@ public class CloudFilesApiMetadata extends BaseRestApiMetadata {
.identityName("Username")
.credentialName("API Key")
.documentation(URI.create("http://docs.rackspacecloud.com/files/api/v1/cfdevguide_d5/content/ch01.html"))
.version(OpenStackAuthAsyncClient.VERSION)
.version("1.0")
.defaultProperties(CloudFilesApiMetadata.defaultProperties())
.view(TypeToken.of(BlobStoreContext.class))
.defaultModules(ImmutableSet.<Class<? extends Module>>of(CloudFilesRestClientModule.class, CloudFilesBlobStoreContextModule.class));

View File

@ -25,7 +25,6 @@ import org.jclouds.apis.ApiMetadata;
import org.jclouds.cloudloadbalancers.config.CloudLoadBalancersRestClientModule;
import org.jclouds.cloudloadbalancers.loadbalancer.config.CloudLoadBalancersLoadBalancerContextModule;
import org.jclouds.loadbalancer.LoadBalancerServiceContext;
import org.jclouds.openstack.OpenStackAuthAsyncClient;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
@ -75,7 +74,7 @@ public class CloudLoadBalancersApiMetadata extends BaseRestApiMetadata {
.identityName("Username")
.credentialName("API Key")
.documentation(URI.create("http://docs.rackspacecloud.com/loadbalancers/api/v1.0/clb-devguide/content/ch01.html"))
.version(OpenStackAuthAsyncClient.VERSION)
.version("1.0")
.defaultEndpoint("https://auth.api.rackspacecloud.com")
.defaultProperties(CloudLoadBalancersApiMetadata.defaultProperties())
.view(TypeToken.of(LoadBalancerServiceContext.class))

View File

@ -25,7 +25,6 @@ import org.jclouds.apis.ApiMetadata;
import org.jclouds.cloudservers.compute.config.CloudServersComputeServiceContextModule;
import org.jclouds.cloudservers.config.CloudServersRestClientModule;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.openstack.OpenStackAuthAsyncClient;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
@ -74,7 +73,7 @@ public class CloudServersApiMetadata extends BaseRestApiMetadata {
.identityName("Username")
.credentialName("API Key")
.documentation(URI.create("http://docs.rackspacecloud.com/servers/api/v1.0/cs-devguide/content/ch01.html"))
.version(OpenStackAuthAsyncClient.VERSION)
.version("1.0")
.defaultEndpoint("https://auth.api.rackspacecloud.com")
.defaultProperties(CloudServersApiMetadata.defaultProperties())
.view(TypeToken.of(ComputeServiceContext.class))

View File

@ -35,9 +35,9 @@ import org.jclouds.http.HttpRequest;
import org.jclouds.http.functions.ReleasePayloadAndReturn;
import org.jclouds.http.functions.ReturnTrueIf2xx;
import org.jclouds.http.functions.UnwrapOnlyJsonValue;
import org.jclouds.openstack.TestOpenStackAuthenticationModule;
import org.jclouds.openstack.filters.AddTimestampQuery;
import org.jclouds.openstack.filters.AuthenticateRequest;
import org.jclouds.openstack.internal.TestOpenStackAuthenticationModule;
import org.jclouds.openstack.nova.config.NovaRestClientModule;
import org.jclouds.openstack.nova.domain.RebootType;
import org.jclouds.openstack.nova.options.CreateServerOptions;

View File

@ -27,7 +27,7 @@
<version>1.5.0-SNAPSHOT</version>
<relativePath>../../project/pom.xml</relativePath>
</parent>
<groupId>org.jclouds.labs</groupId>
<groupId>org.jclouds.api</groupId>
<artifactId>openstack-keystone</artifactId>
<name>jcloud openstack-keystone api</name>
<description>jclouds components to access an implementation of OpenStack Keystone</description>
@ -43,7 +43,9 @@
<test.openstack-keystone.credential>FIXME_CREDENTIALS</test.openstack-keystone.credential>
<test.jclouds.keystone.credential-type>passwordCredentials</test.jclouds.keystone.credential-type>
<jclouds.osgi.export>org.jclouds.openstack.keystone.v2_0*;version="${project.version}"</jclouds.osgi.export>
<jclouds.osgi.export>org.jclouds.openstack.v2_0*;version="${project.version}",
org.jclouds.openstack.keystone.v2_0*;version="${project.version}"
</jclouds.osgi.export>
<jclouds.osgi.import>
org.jclouds.rest.internal;version="${project.version}",
org.jclouds*;version="${project.version}",
@ -53,8 +55,8 @@
<dependencies>
<dependency>
<groupId>org.jclouds.common</groupId>
<artifactId>openstack-common</artifactId>
<groupId>org.jclouds</groupId>
<artifactId>jclouds-core</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
@ -64,13 +66,6 @@
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.common</groupId>
<artifactId>openstack-common</artifactId>
<version>${project.version}</version>
<type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jclouds.driver</groupId>
<artifactId>jclouds-slf4j</artifactId>

View File

@ -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<Access> authenticateWithTenantNameAndCredentials(@PayloadParam("tenantName") String tenantName,
ListenableFuture<Access> 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<Access> authenticateWithTenantIdAndCredentials(@PayloadParam("tenantId") String tenantId,
ListenableFuture<Access> 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<Access> authenticateWithTenantNameAndCredentials(@PayloadParam("tenantName") String tenantName,
ListenableFuture<Access> 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<Access> authenticateWithTenantIdAndCredentials(@PayloadParam("tenantId") String tenantId,
ListenableFuture<Access> authenticateWithTenantIdAndCredentials(@Nullable @PayloadParam("tenantId") String tenantId,
ApiAccessKeyCredentials apiAccessKeyCredentials);
}

View File

@ -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);
}

View File

@ -18,15 +18,17 @@
*/
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.services.ServiceType;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.rest.RestContext;
import org.jclouds.rest.internal.BaseRestApiMetadata;
@ -44,16 +46,18 @@ public class KeystoneApiMetadata extends BaseRestApiMetadata {
/** The serialVersionUID */
private static final long serialVersionUID = 6725672099385580694L;
public static final TypeToken<RestContext<KeystoneClient, KeystoneAsyncClient>> CONTEXT_TOKEN = new TypeToken<RestContext<KeystoneClient, KeystoneAsyncClient>>() {
public static final TypeToken<RestContext<? extends KeystoneClient,? extends KeystoneAsyncClient>> CONTEXT_TOKEN = new TypeToken<RestContext<? extends KeystoneClient,? extends KeystoneAsyncClient>>() {
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) {
@ -62,19 +66,17 @@ public class KeystoneApiMetadata extends BaseRestApiMetadata {
public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
// auth fail can happen while cloud-init applies keypair updates
properties.setProperty("jclouds.ssh.max-retries", "7");
properties.setProperty("jclouds.ssh.retry-auth", "true");
// 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")

View File

@ -18,54 +18,59 @@
*/
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.openstack.filters.AuthenticateRequest;
import org.jclouds.Constants;
import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata;
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
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.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 Service via their REST API.
* Provides access to Openstack keystone resources via their REST API.
* <p/>
*
* @see ServiceClient
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Service_API_Client_Operations.html"
* />
*
* @author Adam Lowe
* @see <a href="http://keystone.openstack.org/" />
* @see KeystoneClient
*/
@SkipEncoding({ '/', '=' })
public interface ServiceAsyncClient {
public interface KeystoneAsyncClient {
/**
* @see ServiceClient#getApiMetadata()
* @see KeystoneClient#getApiMetadata()
*/
@GET
@SelectJson("version")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/")
@Path("/v{" + Constants.PROPERTY_API_VERSION + "}/")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<ApiMetadata> getApiMetadata();
/**
* @see ServiceClient#listTenants()
* @see KeystoneClient#getTokenClient()
*/
@GET
@SelectJson("tenants")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/tenants")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Tenant>> listTenants();
@Delegate
TokenAsyncClient getTokenClient();
/**
* @see KeystoneClient#getUserClient()
*/
@Delegate
UserAsyncClient getUserClient();
/**
* @see KeystoneClient#getTenantClient()
*/
@Delegate
TenantAsyncClient getTenantClient();
}

View File

@ -18,18 +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.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.
@ -37,22 +33,34 @@ import com.google.inject.Provides;
*
* @author Adam Lowe
* @see <a href="http://keystone.openstack.org/" />
* @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<String> 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();
}

View File

@ -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<String, Object> 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);
}
}
}

View File

@ -18,29 +18,21 @@
*/
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.
*
* @author Adrian Cole
*
*/
public enum CredentialType {
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface Authentication {
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")));
}
}
}

View File

@ -0,0 +1,42 @@
/**
* 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 java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
/**
* @see CredentialTypes
* @author Adrian Cole
*
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface CredentialType {
/**
* @see CredentialTypes
*
*/
String value();
}

View File

@ -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 <T> 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 <T> Map<String, T> indexByCredentialType(Iterable<T> iterable) {
return Maps.uniqueIndex(iterable, new Function<T, String>() {
@Override
public String apply(T input) {
return credentialTypeOf(input);
}
});
}
}

View File

@ -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;
@ -39,17 +41,16 @@ import org.jclouds.location.suppliers.ZoneIdToURISupplier;
import org.jclouds.location.suppliers.ZoneIdsSupplier;
import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet;
import org.jclouds.location.suppliers.derived.ZoneIdsFromZoneIdToURIKeySet;
import org.jclouds.openstack.Authentication;
import org.jclouds.openstack.keystone.v2_0.AuthenticationAsyncClient;
import org.jclouds.openstack.keystone.v2_0.AuthenticationClient;
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;
@ -57,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;
@ -77,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);
}
@ -102,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);
}
@ -119,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);
}
@ -136,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);
}
/**
@ -165,41 +184,25 @@ public class KeystoneAuthenticationModule extends AbstractModule {
};
}
@Provides
@Singleton
static class CredentialTypeFromPropertyOrDefault implements javax.inject.Provider<CredentialType> {
/**
* 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<String, Function<Credentials, Access>> authenticationMethods(Injector i) {
Builder<Function<Credentials, Access>> fns = ImmutableSet.<Function<Credentials, Access>> builder();
fns.add(i.getInstance(AuthenticatePasswordCredentials.class));
fns.add(i.getInstance(AuthenticateApiAccessKeyCredentials.class));
return CredentialTypes.indexByCredentialType(fns.build());
}
@Provides
@Singleton
protected Function<Credentials, Access> authenticationMethodForCredentialType(CredentialType credentialType,
AuthenticatePasswordCredentials authenticatePasswordCredentials,
AuthenticateApiAccessKeyCredentials authenticateApiAccessKeyCredentials) {
Function<Credentials, Access> 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<Credentials, Access> authenticationMethodForCredentialType(
@Named(KeystoneProperties.CREDENTIAL_TYPE) String credentialType,
Map<String, Function<Credentials, Access>> 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<Credentials, Access>(authMethod);
return new RetryOnTimeOutExceptionFunction<Credentials, Access>(authenticationMethods.get(credentialType));
}
// TODO: what is the timeout of the session token? modify default accordingly

View File

@ -18,7 +18,7 @@
*/
package org.jclouds.openstack.keystone.v2_0.config;
import org.jclouds.openstack.services.ServiceType;
import org.jclouds.openstack.v2_0.ServiceType;
/**
* Configuration properties and constants used in Keystone connections.
@ -36,7 +36,7 @@ public interface KeystoneProperties {
* <li>passwordCredentials</li>
* </ul>
*
* @see CredentialType
* @see CredentialTypes
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_authenticate_v2.0_tokens_Service_API_Client_Operations.html"
* />
*/

View File

@ -24,17 +24,21 @@ import org.jclouds.http.HttpErrorHandler;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.http.annotation.Redirection;
import org.jclouds.http.annotation.ServerError;
import org.jclouds.openstack.keystone.v2_0.AdminAsyncClient;
import org.jclouds.openstack.keystone.v2_0.AdminClient;
import org.jclouds.openstack.keystone.v2_0.KeystoneAsyncClient;
import org.jclouds.openstack.keystone.v2_0.KeystoneClient;
import org.jclouds.openstack.keystone.v2_0.ServiceAsyncClient;
import org.jclouds.openstack.keystone.v2_0.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,14 +46,22 @@ import com.google.common.collect.ImmutableMap;
* @author Adam Lowe
*/
@ConfiguresRestClient
public class KeystoneRestClientModule extends RestClientModule<KeystoneClient, KeystoneAsyncClient> {
public class KeystoneRestClientModule<S extends KeystoneClient, A extends KeystoneAsyncClient> extends RestClientModule<S, A> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, 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<S> syncClientType, TypeToken<A> asyncClientType,
Map<Class<?>, Class<?>> sync2Async) {
super(syncClientType, asyncClientType, sync2Async);
}
@Override
@ -60,13 +72,10 @@ public class KeystoneRestClientModule extends RestClientModule<KeystoneClient, K
@Override
protected void installLocations() {
// TODO: select this from KeystoneProperties.VERSION; note you select from
// a guice provided property, so it will have to come from somewhere else, maybe we move
// this to the the ContextBuilder
install(KeystoneAuthenticationModule.forRegions());
install(new KeystoneAuthenticationModule(Modules.EMPTY_MODULE));
super.installLocations();
}
@Override
protected void bindErrorHandlers() {
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(KeystoneErrorHandler.class);

View File

@ -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.API_ACCESS_KEY_CREDENTIALS)
public class ApiAccessKeyCredentials {
public static Builder builder() {
return new Builder();

View File

@ -25,7 +25,7 @@ import java.util.Date;
import java.util.Set;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.openstack.domain.Resource;
import org.jclouds.openstack.v2_0.domain.Resource;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
@ -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<MediaType> values = ImmutableSet.of();
private MediaTypesHolder() {
}
private MediaTypesHolder(Set<MediaType> mediaTypes) {
this.values = ImmutableSet.copyOf(checkNotNull(mediaTypes, "mediaTypes"));
}
}
@SerializedName(value="media-types")
@Nullable
private Set<MediaType> 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<MediaType> 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);
}
}

View File

@ -57,6 +57,8 @@ public class Endpoint implements Comparable<Endpoint> {
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<Endpoint> {
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<Endpoint> {
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<Endpoint> {
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<Endpoint> {
@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

View File

@ -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();

View File

@ -53,6 +53,7 @@ public class Role implements Comparable<Role> {
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<Role> {
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<Role> {
}
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<Role> {
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<Role> {
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<Role> {
@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();
}

View File

@ -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 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.Tenant;
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 Tenant via their REST API.
* <p/>
*
* @see TenantClient
* @see <a href=
* "http://docs.openstack.org/api/openstack-identity-service/2.0/content/Tenant_Operations.html"
* />
* @author Adam Lowe
*/
@Path("/v{" + Constants.PROPERTY_API_VERSION + "}")
@SkipEncoding( { '/', '=' })
public interface TenantAsyncClient {
/**
* @see TenantClient#list()
*/
@GET
@SelectJson("tenants")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/tenants")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Tenant>> list();
/** @see TenantClient#get(String) */
@GET
@SelectJson("tenant")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/tenants/{tenantId}")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Tenant> 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<Tenant> getByName(@QueryParam("name") String tenantName);
}

View File

@ -16,36 +16,45 @@
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.keystone.v2_0;
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.Tenant;
/**
* Provides synchronous access to the KeyStone Service API.
* Provides synchronous access to the KeyStone Tenant API.
* <p/>
*
*
* @author Adam Lowe
* @see ServiceAsyncClient
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Service_API_Client_Operations.html"
* @see TenantAsyncClient
* @see <a href=
* "http://docs.openstack.org/api/openstack-identity-service/2.0/content/Tenant_Operations.html"
* />
*/
@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<Tenant> listTenants();
Set<Tenant> 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
* <p/>
* NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/956687 )
*
* @return the information about the tenant
*/
Tenant getByName(String tenantName);
}

View File

@ -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.
* <p/>
*
* @see TokenClient
* @see <a href=
* "http://docs.openstack.org/api/openstack-identity-service/2.0/content/Token_Operations.html"
* />
* @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<Token> 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<User> getUserOfToken(@PathParam("token") String token);
/** @see TokenClient#isValid(String) */
@HEAD
@Path("/tokens/{token}")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnFalseOnNotFoundOr404.class)
ListenableFuture<Boolean> 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<Set<Endpoint>> listEndpointsForToken(@PathParam("token") String token);
}

View File

@ -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.
* <p/>
*
* @author Adam Lowe
* @see TokenAsyncClient
* @see <a href=
* "http://docs.openstack.org/api/openstack-identity-service/2.0/content/Token_Operations.html"
* />
*/
@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
* <p/>
* NOTE: currently not working in openstack ( https://bugs.launchpad.net/keystone/+bug/988672 )
*
* @return the set of endpoints
*/
Set<Endpoint> listEndpointsForToken(String token);
}

View File

@ -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.
* <p/>
*
* @see UserClient
* @see <a href=
* "http://docs.openstack.org/api/openstack-identity-service/2.0/content/User_Operations.html"
* />
* @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<Set<User>> list();
/** @see UserClient#get(String) */
@GET
@SelectJson("user")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/users/{userId}")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<User> 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<User> 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<Set<Role>> 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<Set<Role>> listRolesOfUserOnTenant(@PathParam("userId") String userId, @PathParam("tenantId") String tenantId);
}

View File

@ -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.
* <p/>
*
* @author Adam Lowe
* @see UserAsyncClient
* @see <a href=
* "http://docs.openstack.org/api/openstack-identity-service/2.0/content/User_Operations.html"
* />
*/
@Beta
@Timeout(duration = 30, timeUnit = TimeUnit.SECONDS)
public interface UserClient {
/**
* Retrieve the list of users
* <p/>
* NOTE: this method is not in API documentation for keystone, but does work
*
* @return the list of users
*/
Set<User> 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
* <p/>
* 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).
* <p/>
* NOTE: Broken in openstack ( https://bugs.launchpad.net/keystone/+bug/933565 )
*
* @return the set of Roles granted to the user
*/
Set<Role> listRolesOfUser(String userId);
/**
* List the roles a user has been granted on a specific tenant
*
* @return the set of roles
*/
Set<Role> listRolesOfUserOnTenant(String userId, String tenantId);
}

View File

@ -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.filters;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.http.HttpException;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpRequestFilter;
import org.jclouds.http.utils.ModifyRequest;
import org.jclouds.openstack.keystone.v2_0.config.Authentication;
import org.jclouds.openstack.v2_0.reference.AuthHeaders;
import com.google.common.base.Supplier;
/**
* Signs the Keystone-based request. This will update the Authentication Token before 24 hours is up.
*
* @author Adrian Cole
*
*/
@Singleton
public class AuthenticateRequest implements HttpRequestFilter {
private final Supplier<String> authTokenProvider;
@Inject
public AuthenticateRequest(@Authentication Supplier<String> authTokenProvider) {
this.authTokenProvider = authTokenProvider;
}
@Override
public HttpRequest filter(HttpRequest request) throws HttpException {
return ModifyRequest.replaceHeader(request, AuthHeaders.AUTH_TOKEN, authTokenProvider.get());
}
}

View File

@ -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<Credentials, Access> {
private final AuthenticationClient client;
public class AuthenticateApiAccessKeyCredentials extends BaseAuthenticator<ApiAccessKeyCredentials> {
protected final AuthenticationClient client;
@Inject
public AuthenticateApiAccessKeyCredentials(AuthenticationClient client) {
@ -39,25 +39,18 @@ public class AuthenticateApiAccessKeyCredentials implements Function<Credentials
}
@Override
public Access apply(Credentials input) {
if (input.identity.indexOf(':') == -1) {
throw new AuthorizationException(String.format("Identity %s does not match format tenantName:accessKey",
input.identity), null);
}
protected Access authenticateWithTenantNameOrNull(String tenantId, ApiAccessKeyCredentials apiAccessKeyCredentials) {
return client.authenticateWithTenantNameAndCredentials(tenantId, apiAccessKeyCredentials);
}
String tenantId = input.identity.substring(0, input.identity.indexOf(':'));
String usernameOrAccessKey = input.identity.substring(input.identity.indexOf(':') + 1);
String passwordOrSecretKey = input.credential;
@Override
protected Access authenticateWithTenantId(String tenantId, ApiAccessKeyCredentials apiAccessKeyCredentials) {
return client.authenticateWithTenantIdAndCredentials(tenantId, apiAccessKeyCredentials);
}
ApiAccessKeyCredentials apiAccessKeyCredentials = ApiAccessKeyCredentials.createWithAccessKeyAndSecretKey(
usernameOrAccessKey, passwordOrSecretKey);
Access access;
if (tenantId.matches("^[0-9]+$")) {
access = client.authenticateWithTenantIdAndCredentials(tenantId, apiAccessKeyCredentials);
} else {
access = client.authenticateWithTenantNameAndCredentials(tenantId, apiAccessKeyCredentials);
}
return access;
@Override
public ApiAccessKeyCredentials createCredentials(String identity, String credential) {
return ApiAccessKeyCredentials.createWithAccessKeyAndSecretKey(identity, credential);
}
@Override

View File

@ -19,17 +19,19 @@
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.PasswordCredentials;
import org.jclouds.rest.AuthorizationException;
import org.jclouds.openstack.keystone.v2_0.functions.internal.BaseAuthenticator;
import com.google.common.base.Function;
public class AuthenticatePasswordCredentials implements Function<Credentials, Access> {
private final AuthenticationClient client;
@CredentialType(CredentialTypes.PASSWORD_CREDENTIALS)
@Singleton
public class AuthenticatePasswordCredentials extends BaseAuthenticator<PasswordCredentials> {
protected final AuthenticationClient client;
@Inject
public AuthenticatePasswordCredentials(AuthenticationClient client) {
@ -37,25 +39,18 @@ public class AuthenticatePasswordCredentials implements Function<Credentials, Ac
}
@Override
public Access apply(Credentials input) {
if (input.identity.indexOf(':') == -1) {
throw new AuthorizationException(String.format("Identity %s does not match format tenantId:username",
input.identity), null);
}
protected Access authenticateWithTenantNameOrNull(String tenantId, PasswordCredentials apiAccessKeyCredentials) {
return client.authenticateWithTenantNameAndCredentials(tenantId, apiAccessKeyCredentials);
}
String tenantId = input.identity.substring(0, input.identity.indexOf(':'));
String usernameOrAccessKey = input.identity.substring(input.identity.indexOf(':') + 1);
String passwordOrSecretKey = input.credential;
@Override
protected Access authenticateWithTenantId(String tenantId, PasswordCredentials apiAccessKeyCredentials) {
return client.authenticateWithTenantIdAndCredentials(tenantId, apiAccessKeyCredentials);
}
PasswordCredentials passwordCredentials = PasswordCredentials.createWithUsernameAndPassword(usernameOrAccessKey,
passwordOrSecretKey);
Access access;
if (tenantId.matches("^[0-9]+$")) {
access = client.authenticateWithTenantIdAndCredentials(tenantId, passwordCredentials);
} else {
access = client.authenticateWithTenantNameAndCredentials(tenantId, passwordCredentials);
}
return access;
@Override
public PasswordCredentials createCredentials(String identity, String credential) {
return PasswordCredentials.createWithUsernameAndPassword(identity, credential);
}
@Override

View File

@ -23,7 +23,7 @@ import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
import com.google.common.base.Function;
import com.google.inject.ImplementedBy;
@ImplementedBy(ReturnRegion.class)
@ImplementedBy(ReturnRegionOrProvider.class)
public interface EndpointToRegion extends Function<Endpoint, String> {
}

View File

@ -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;
}
}

View File

@ -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<C> implements Function<Credentials, Access> {
@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);
}

View File

@ -29,7 +29,6 @@ import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.logging.Logger;
import org.jclouds.openstack.keystone.v2_0.domain.Access;
import org.jclouds.openstack.reference.AuthHeaders;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Multimap;
@ -62,8 +61,8 @@ public class RetryOnRenew implements HttpRetryHandler {
case 401:
// Do not retry on 401 from authentication request
Multimap<String, String> headers = command.getCurrentRequest().getHeaders();
if (headers != null && headers.containsKey(AuthHeaders.AUTH_USER)
&& headers.containsKey(AuthHeaders.AUTH_KEY) && !headers.containsKey(AuthHeaders.AUTH_TOKEN)) {
if (headers != null && headers.containsKey("X-Auth-User")
&& headers.containsKey("X-Auth-Key") && !headers.containsKey("X-Auth-Token")) {
retry = false;
} else {
byte[] content = closeClientButKeepContentStream(response);

View File

@ -38,7 +38,7 @@ import com.google.common.collect.Maps;
import com.google.inject.assistedinject.Assisted;
@Singleton
public class LocationIdToURIFromAccessForTypeAndVersionSupplier implements Supplier<Map<String, Supplier<URI>>> {
public class LocationIdToURIFromAccessForTypeAndVersion implements Supplier<Map<String, Supplier<URI>>> {
protected final Supplier<Access> access;
protected final EndpointToSupplierURI endpointToSupplierURI;
protected final Function<Endpoint, String> endpointToLocationId;
@ -46,7 +46,7 @@ public class LocationIdToURIFromAccessForTypeAndVersionSupplier implements Suppl
protected final String apiVersion;
@Inject
public LocationIdToURIFromAccessForTypeAndVersionSupplier(Supplier<Access> access,
public LocationIdToURIFromAccessForTypeAndVersion(Supplier<Access> access,
EndpointToSupplierURI endpointToSupplierURI, Function<Endpoint, String> 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<String, Endpoint> locationIdToEndpoint = Maps.uniqueIndex(Iterables.filter(service.getEndpoints(),
new Predicate<Endpoint>() {

View File

@ -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> access,
EndpointToSupplierAdminURI endpointToSupplierURI, EndpointToRegion endpointToRegion,
@Assisted("apiType") String apiType, @Assisted("apiVersion") String apiVersion) {
public RegionIdToAdminURIFromAccessForTypeAndVersion(Supplier<Access> access,
EndpointToSupplierAdminURI endpointToSupplierURI, EndpointToRegion endpointToRegion,
@Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
super(access, endpointToSupplierURI, endpointToRegion, apiType, apiVersion);
}

View File

@ -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<Map<String, Supplier<URI>>> {
static interface Factory {
/**
@ -19,10 +21,10 @@ public interface RegionIdToAdminURISupplier extends Supplier<Map<String, Supplie
* 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
* @return regions mapped to default uri
*/
RegionIdToAdminURISupplier createForApiTypeAndVersion(@Assisted("apiType") String apiType,
@Assisted("apiVersion") String apiVersion);
@Nullable @Assisted("apiVersion") String apiVersion);
}
}

View File

@ -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.RegionIdToURISupplier;
import org.jclouds.openstack.keystone.v2_0.domain.Access;
import org.jclouds.openstack.keystone.v2_0.functions.EndpointToRegion;
@ -30,13 +31,13 @@ import com.google.common.base.Supplier;
import com.google.inject.assistedinject.Assisted;
@Singleton
public class RegionIdToURIFromAccessForTypeAndVersionSupplier extends
LocationIdToURIFromAccessForTypeAndVersionSupplier implements RegionIdToURISupplier {
public class RegionIdToURIFromAccessForTypeAndVersion extends LocationIdToURIFromAccessForTypeAndVersion implements
RegionIdToURISupplier {
@Inject
public RegionIdToURIFromAccessForTypeAndVersionSupplier(Supplier<Access> access,
public RegionIdToURIFromAccessForTypeAndVersion(Supplier<Access> 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);
}

View File

@ -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> 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);
}

View File

@ -0,0 +1,52 @@
/**
* 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, Name 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.v2_0;
/**
* An OpenStack service, such as Compute (Nova), Object Storage (Swift), or Image Service (Glance).
* A service provides one or more endpoints through which users can access resources and perform
* (presumably useful) operations.
*
* @author Adrian Cole
* @see <a href="http://docs.openstack.org/api/openstack-typeentity-service/2.0/content/Identity-Service-Concepts-e1362.html"
* />
*/
public interface ServiceType {
/**
* Object Storage (Swift)
*/
public static final String OBJECT_STORE = "object-store";
/**
* Compute (Nova)
*/
public static final String COMPUTE = "compute";
/**
* Image Service (Glance)
*/
public static final String IMAGE = "image";
/**
* Identity Service (Keystone)
*/
public static final String IDENTITY = "identity";
/**
* Network Service (Quantum)
*/
public static final String NETWORK = "network";
}

View File

@ -0,0 +1,207 @@
/**
* 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, Href 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.v2_0.domain;
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 java.net.URI;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
import com.google.gson.annotations.SerializedName;
/**
* For convenience, resources contain links to themselves. This allows a client to easily obtain a
* resource URIs rather than to construct them.
*
* @author AdrianCole
* @see <a href= "http://docs.openstack.org/api/openstack-compute/1.1/content/LinksReferences.html"
* />
*/
public class Link {
/**
* Relations associated with resources.
*/
public static enum Relation {
/**
* a versioned link to the resource. These links should be used in cases where the link will
* be followed immediately.
*/
SELF,
/**
* a permanent link to a resource that is appropriate for long term storage.
*/
BOOKMARK,
/**
*
*/
DESCRIBEDBY,
/**
* an alternate representation of the resource. For example, an OpenStack Compute image may
* have an alternate representation in the OpenStack Image service.
*/
ALTERNATE,
/**
* the value returned by the OpenStack service was not recognized.
*/
UNRECOGNIZED;
public String value() {
return name().toLowerCase();
}
public static Relation fromValue(String v) {
try {
return valueOf(v.toUpperCase());
} catch (IllegalArgumentException e) {
return UNRECOGNIZED;
}
}
}
public static Link create(Relation relation, URI href) {
return new Link(relation, null, href);
}
public static Link create(Relation relation,String type, URI href) {
return new Link(relation, type, href);
}
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromLink(this);
}
public static class Builder {
protected Relation relation;
protected String type;
protected URI href;
/**
* @see Link#getRelation()
*/
public Builder relation(Relation relation) {
this.relation = checkNotNull(relation, "relation");
return this;
}
/**
* @see Link#getType()
*/
public Builder type(String type) {
this.type = type;
return this;
}
/**
* @see Link#getHref()
*/
public Builder href(URI href) {
this.href = checkNotNull(href, "href");
return this;
}
public Link build(){
return new Link(relation, type, href);
}
public Builder fromLink(Link from) {
return relation(from.getRelation()).type(from.getType()).href(from.getHref());
}
}
protected Link() {
// we want serializers like Gson to work w/o using sun.misc.Unsafe,
// prohibited in GAE. This also implies fields are not final.
// see http://code.google.com/p/jclouds/issues/detail?id=925
}
@SerializedName("rel")
protected Relation relation;
protected String type;
protected URI href;
protected Link(Relation relation, @Nullable String type, URI href) {
this.relation = checkNotNull(relation, "relation");
this.type = type;
this.href = checkNotNull(href, "href");
}
/**
* There are three kinds of link relations associated with resources. A self link contains a
* versioned link to the resource. These links should be used in cases where the link will be
* followed immediately. A bookmark link provides a permanent link to a resource that is
* appropriate for long term storage. An alternate link can contain an alternate representation
* of the resource. For example, an OpenStack Compute image may have an alternate representation
* in the OpenStack Image service. Note that the type attribute here is used to provide a hint as
* to the type of representation to expect when following the link.
*
* @return the relation of the resource in the current OpenStack deployment
*/
public Relation getRelation() {
return relation;
}
/**
* @return the type of the resource or null if not specified
*/
@Nullable
public String getType() {
return type;
}
/**
* @return the href of the resource
*/
public URI getHref() {
return href;
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof Link) {
final Link other = Link.class.cast(object);
return equal(relation, other.relation) && equal(type, other.type) && equal(href, other.href);
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hashCode(relation, type, href);
}
@Override
public String toString() {
return toStringHelper("").add("relation", relation).add("type", type).add("href", href).toString();
}
}

View File

@ -0,0 +1,185 @@
/**
* 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, Name 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.v2_0.domain;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Collections;
import java.util.Set;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ImmutableSet;
/**
* Resource found in a paginated collection
*
* @author AdrianCole
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/1.1/content/Paginated_Collections-d1e664.html"
* />
*/
public class Resource implements Comparable<Resource> {
public static Builder<?> builder() {
return new ConcreteBuilder();
}
public Builder<?> toBuilder() {
return new ConcreteBuilder().fromResource(this);
}
public static abstract class Builder<T extends Builder<T>> {
protected abstract T self();
private String id;
private String name;
private Set<Link> links = ImmutableSet.of();
/**
* @see Resource#getId()
*/
public T id(String id) {
this.id = id;
return self();
}
/**
* @see Resource#getName()
*/
public T name(String name) {
this.name = name;
return self();
}
/**
* @see Resource#getLinks()
*/
public T links(Link... links) {
return links(ImmutableSet.copyOf(checkNotNull(links, "links")));
}
/**
* @see Resource#getLinks()
*/
public T links(Set<Link> links) {
this.links = links;
return self();
}
public Resource build() {
return new Resource(this);
}
public T fromResource(Resource in) {
return this
.id(in.getId())
.name(in.getName())
.links(in.getLinks())
;
}
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
@Override
protected ConcreteBuilder self() {
return this;
}
}
protected Resource() {
// we want serializers like Gson to work w/o using sun.misc.Unsafe,
// prohibited in GAE. This also implies fields are not final.
// see http://code.google.com/p/jclouds/issues/detail?id=925
}
private String id;
private String name;
private Set<Link> links = ImmutableSet.of();
protected Resource(Builder<?> builder) {
this.id = checkNotNull(builder.id, "id");
this.name = builder.name;
this.links = ImmutableSet.copyOf(checkNotNull(builder.links, "links"));
}
/**
* When providing an ID, it is assumed that the resource exists in the current OpenStack
* deployment
*
* @return the id of the resource in the current OpenStack deployment
*/
public String getId() {
return id;
}
/**
* @return the name of the resource
*/
@Nullable
public String getName() {
return name;
}
/**
* @return the links of the id address allocated to the new server
*/
public Set<Link> getLinks() {
return Collections.unmodifiableSet(this.links);
}
@Override
public int hashCode() {
return Objects.hashCode(id, name, links);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
Resource that = Resource.class.cast(obj);
return Objects.equal(this.getId(), that.getId())
&& Objects.equal(this.name, that.name)
&& Objects.equal(this.links, that.links);
}
protected ToStringHelper string() {
return Objects.toStringHelper("")
.add("id", getId())
.add("name", name)
.add("links", links);
}
@Override
public String toString() {
return string().toString();
}
@Override
public int compareTo(Resource that) {
if (that == null)
return 1;
if (this == that)
return 0;
return this.getId().compareTo(that.getId());
}
}

View File

@ -0,0 +1,100 @@
/**
* 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.v2_0.options;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.base.Preconditions.checkState;
import java.util.Date;
import org.jclouds.http.options.BaseHttpRequestOptions;
/**
* Options used to control paginated results (aka list commands).
*
* @see <a href="http://docs.rackspacecloud.com/servers/api/cs-devguide-latest.pdf" />
* @author Adrian Cole
*/
public class BaseListOptions extends BaseHttpRequestOptions {
public static final BaseListOptions NONE = new BaseListOptions();
/**
* Only return objects changed since this time.
*/
public BaseListOptions changesSince(Date ifModifiedSince) {
this.queryParameters.put("changes-since", checkNotNull(ifModifiedSince, "ifModifiedSince")
.getTime()
/ 1000 + "");
return this;
}
/**
* Indicates where to begin listing. The list will only include objects that occur after the
* offset. This is convenient for pagination: To get the next page of results use the last result
* number of the current page + current page offset as the offset.
*/
public BaseListOptions startAt(long offset) {
checkState(offset >= 0, "offset must be >= 0");
queryParameters.put("offset", Long.toString(checkNotNull(offset, "offset")));
return this;
}
/**
* To reduce load on the service, list operations will return a maximum of 1,000 items at a time.
* To navigate the collection, the parameters limit and offset can be set in the URI
* (e.g.?limit=0&offset=0). If an offset is given beyond the end of a list an empty list will be
* returned.
* <p/>
* Note that list operations never return itemNotFound (404) faults.
*/
public BaseListOptions maxResults(int limit) {
checkState(limit >= 0, "limit must be >= 0");
checkState(limit <= 10000, "limit must be <= 10000");
queryParameters.put("limit", Integer.toString(limit));
return this;
}
public static class Builder {
/**
* @see BaseListOptions#startAt(long)
*/
public static BaseListOptions startAt(long prefix) {
BaseListOptions options = new BaseListOptions();
return options.startAt(prefix);
}
/**
* @see BaseListOptions#maxResults
*/
public static BaseListOptions maxResults(int maxKeys) {
BaseListOptions options = new BaseListOptions();
return options.maxResults(maxKeys);
}
/**
* @see BaseListOptions#changesSince(Date)
*/
public static BaseListOptions changesSince(Date since) {
BaseListOptions options = new BaseListOptions();
return options.changesSince(since);
}
}
}

View File

@ -0,0 +1,103 @@
/*
* 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.v2_0.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import org.jclouds.openstack.v2_0.domain.Link;
import org.jclouds.openstack.v2_0.domain.Link.Relation;
import com.google.common.base.Predicate;
/**
* Predicates handy when working with Link Types
*
* @author Adrian Cole
*/
public class LinkPredicates {
/**
* matches links of the given relation
*
* @param rel relation of the link
* @return predicate that will match links of the given rel
*/
public static Predicate<Link> relationEquals(final Relation rel) {
checkNotNull(rel, "rel must be defined");
return new Predicate<Link>() {
@Override
public boolean apply(Link link) {
return rel.equals(link.getRelation());
}
@Override
public String toString() {
return "relEquals(" + rel + ")";
}
};
}
/**
* matches links of the given href
*
* @param href
* @return predicate that will match links of the given href
*/
public static Predicate<Link> hrefEquals(final URI href) {
checkNotNull(href, "href must be defined");
return new Predicate<Link>() {
@Override
public boolean apply(Link link) {
return href.equals(link.getHref());
}
@Override
public String toString() {
return "hrefEquals(" + href + ")";
}
};
}
/**
* matches links of the given type
*
* @param type
* ex. application/pdf
* @return predicate that will match links of the given type
*/
public static Predicate<Link> typeEquals(final String type) {
checkNotNull(type, "type must be defined");
return new Predicate<Link>() {
@Override
public boolean apply(Link link) {
return type.equals(link.getType());
}
@Override
public String toString() {
return "typeEquals(" + type + ")";
}
};
}
}

View File

@ -0,0 +1,31 @@
/**
* 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.v2_0.reference;
/**
* @author Adrian Cole
*
*/
public interface AuthHeaders {
public static final String AUTH_USER = "X-Auth-User";
public static final String AUTH_KEY = "X-Auth-Key";
public static final String AUTH_TOKEN = "X-Auth-Token";
}

View File

@ -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 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.v2_0.services;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
import org.jclouds.openstack.v2_0.ServiceType;
/**
* Compute (Nova)
*
* @author Adrian Cole
* @see <a href="http://docs.openstack.org/api/openstack-typeentity-service/2.0/content/Identity-Service-Concepts-e1362.html"
* />
* @see ServiceType#COMPUTE
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface Compute {
}

View File

@ -0,0 +1,79 @@
/**
* 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.v2_0.services;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
import org.jclouds.openstack.v2_0.ServiceType;
/**
* An extension of a {@link ServiceType service}. In order for us to understand
* the context of the extension, we must consider the <a href=
* "http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html"
* >extensions call</a>.
*
* <br/>
* For our purposes, the minimal context of an extension is the type of the
* service it extends ex. {@link ServiceType#COMPUTE}, and its namespace ex. <a
* href
* ="http://docs.openstack.org/ext/keypairs/api/v1.1">http://docs.openstack.org
* /ext/keypairs/api/v1.1</a>.
*
* @author Adrian Cole
*
* @see ServiceType
* @see <a href=
* "http://docs.openstack.org/api/openstack-compute/2/content/Extensions-d1e1444.html"
* />
* @see <a href="http://nova.openstack.org/api_ext" />
* @see <a href="http://nova.openstack.org/api_ext/ext_keypairs.html" />
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface Extension {
/**
* the service type this is an extension of.
*
* <h3>note</h3>
*
* This isn't necessarily one of the built-in {@link ServiceType services},
* it could be an extension of a custom service.
*
* @return the service type this is an extension of.
*
*/
String of();
/**
* namespace ex. <a href
* ="http://docs.openstack.org/ext/keypairs/api/v1.1">http
* ://docs.openstack.org /ext/keypairs/api/v1.1</a>.
*
* @return the namespace of the extension
*/
String namespace();
}

View File

@ -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 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.v2_0.services;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
import org.jclouds.openstack.v2_0.ServiceType;
/**
* Image Service (Glance)
*
* @author Adrian Cole
* @see <a href="http://docs.openstack.org/api/openstack-typeentity-service/2.0/content/Identity-Service-Concepts-e1362.html"
* />
* @see ServiceType#IMAGE
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface Image {
}

View File

@ -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 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.v2_0.services;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
import org.jclouds.openstack.v2_0.ServiceType;
/**
* Object Storage (Swift)
*
* @author Adrian Cole
* @see <a href="http://docs.openstack.org/api/openstack-typeentity-service/2.0/content/Identity-Service-Concepts-e1362.html"
* />
* @see ServiceType#OBJECT_STORE
*/
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface ObjectStore {
}

View File

@ -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<KeystoneClient> {
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());
}
}

View File

@ -18,43 +18,26 @@
*/
package org.jclouds.openstack.keystone.v2_0;
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.Tenant;
import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneClientLiveTest;
import org.testng.annotations.Test;
/**
* Tests UserClient
*
* Tests KeystoneClient
*
* @author Adam Lowe
*/
@Test(groups = "live", testName = "UserClientLiveTest")
public class UserClientLiveTest extends BaseKeystoneClientLiveTest {
@Test(groups = "live", testName = "KeystoneClientLiveTest")
public class KeystoneClientLiveTest 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());
}
ApiMetadata result = keystoneContext.getApi().getApiMetadata();
assertNotNull(result);
assertNotNull(result.getId());
assertNotNull(result.getStatus());
assertNotNull(result.getUpdated());
}
public void testListTenants() {
for (String regionId : keystoneContext.getApi().getConfiguredRegions()) {
Set<Tenant> result = keystoneContext.getApi().getServiceClientForRegion(regionId).listTenants();
assertNotNull(result);
assertFalse(result.isEmpty());
for (Tenant tenant : result) {
assertNotNull(tenant.getId());
}
}
}
}

View File

@ -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(""));
}
}

View File

@ -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<KeystoneClient> {
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<Tenant> tenants = client.list();
assertNotNull(tenants);
assertFalse(tenants.isEmpty());
Set<Tenant> 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"));
}
}

View File

@ -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<Tenant> 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);
}
}
}

View File

@ -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<KeystoneClient> {
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<Endpoint> 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());
}
}

View File

@ -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<Endpoint> endpoints = client.listEndpointsForToken(token);
assertNotNull(endpoints);
assertFalse(endpoints.isEmpty());
}
public void testInvalidTokenEndpoints() {
TokenClient client = keystoneContext.getApi().getTokenClient();
assertTrue(client.listEndpointsForToken("thisisnotarealtoken!").isEmpty());
}
}

View File

@ -0,0 +1,169 @@
/**
* 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.http.HttpResponseException;
import org.jclouds.openstack.keystone.v2_0.KeystoneClient;
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.rest.AuthorizationException;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* Tests parsing and Guice wiring of UserClient
*
* @author Adam Lowe
*/
@Test(testName = "UserClientExpectTest")
public class UserClientExpectTest extends BaseKeystoneRestClientExpectTest<KeystoneClient> {
public void testListUsers() {
UserClient client = requestsSendResponses(
keystoneAuthWithUsernameAndPassword, responseWithKeystoneAccess,
standardRequestBuilder(endpoint + "/v2.0/users").build(),
standardResponseBuilder(200).payload(payloadFromResourceWithContentType("/user_list.json", APPLICATION_JSON)).build())
.getUserClient();
Set<User> users = client.list();
assertNotNull(users);
assertFalse(users.isEmpty());
Set<User> 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() {
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<Role> 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<Role> 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());
}
}

View File

@ -0,0 +1,92 @@
/**
* 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.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", singleThreaded = true)
public class UserClientLiveTest extends BaseKeystoneClientLiveTest {
public void testUsers() {
UserClient client = keystoneContext.getApi().getUserClient();
Set<User> users = client.list();
assertNotNull(users);
assertFalse(users.isEmpty());
for (User user : users) {
User aUser = client.get(user.getId());
assertEquals(aUser, user);
}
}
public void testUserRolesOnTenant() {
UserClient client = keystoneContext.getApi().getUserClient();
Set<User> users = client.list();
Set<Tenant> tenants = keystoneContext.getApi().getTenantClient().list();
for (User user : users) {
for (Tenant tenant : tenants) {
Set<Role> 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<Role> 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);
}
}
}

View File

@ -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");
}
}

View File

@ -38,13 +38,13 @@ import com.google.common.reflect.TypeToken;
* @author Adam Lowe
*/
@Test(groups = "live")
public class BaseKeystoneClientLiveTest extends BaseContextLiveTest<RestContext<KeystoneClient, KeystoneAsyncClient>> {
public class BaseKeystoneClientLiveTest extends BaseContextLiveTest<RestContext<? extends KeystoneClient,? extends KeystoneAsyncClient>> {
public BaseKeystoneClientLiveTest() {
provider = "openstack-keystone";
}
protected RestContext<KeystoneClient, KeystoneAsyncClient> keystoneContext;
protected RestContext<? extends KeystoneClient,? extends KeystoneAsyncClient> keystoneContext;
@BeforeGroups(groups = { "integration", "live" })
@Override
@ -67,7 +67,7 @@ public class BaseKeystoneClientLiveTest extends BaseContextLiveTest<RestContext<
}
@Override
protected TypeToken<RestContext<KeystoneClient, KeystoneAsyncClient>> contextType() {
protected TypeToken<RestContext<? extends KeystoneClient,? extends KeystoneAsyncClient>> contextType() {
return KeystoneApiMetadata.CONTEXT_TOKEN;
}

View File

@ -25,9 +25,11 @@ 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.services.ServiceType;
import org.jclouds.openstack.keystone.v2_0.KeystoneApiMetadata;
import org.jclouds.openstack.v2_0.ServiceType;
import org.jclouds.rest.internal.BaseRestClientExpectTest;
import com.google.common.base.Objects;
@ -43,14 +45,14 @@ public class BaseKeystoneRestClientExpectTest<S> 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<S> 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<S> 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();
}
}

View File

@ -85,17 +85,23 @@ public class ParseAccessTest extends BaseItemParserTest<Access> {
.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()

View File

@ -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<Access> {
@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();
}
}

View File

@ -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
@ -25,38 +25,39 @@ import javax.ws.rs.core.MediaType;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.json.BaseItemParserTest;
import org.jclouds.openstack.domain.Link;
import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata;
import org.jclouds.openstack.v2_0.domain.Link;
import org.jclouds.rest.annotations.SelectJson;
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<ApiMetadata> {
public class ParseRackspaceApiMetadataTest extends BaseItemParserTest<ApiMetadata> {
@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();
}

View File

@ -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<Supplier<URI>>() {
}).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
.<URI> supplierFunction()), map);
}
private final RegionIdToAdminURISupplier.Factory raxFactory = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Provider.class).to("rackspace");
bind(new TypeLiteral<Supplier<URI>>() {
}).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
}
@SuppressWarnings("unused")
@Provides
@Singleton
public Supplier<Access> 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
.<URI> supplierFunction()), ImmutableMap.of("rackspace", URI
.create("https://servers.api.rackspacecloud.com/v1.0/40806637803162")));
}
public void testProviderWhenNoRegions() {
Map<String, URI> map = Maps.newLinkedHashMap();
map.put("rackspace", null);
assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("compute", "1.0").get(), Suppliers
.<URI> supplierFunction()), map);
}
public void testOkWithNoVersions() {
Map<String, URI> map = Maps.newLinkedHashMap();
map.put("DFW", null);
map.put("ORD", null);
assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("rax:database", null).get(), Suppliers
.<URI> supplierFunction()), map);
}
}

View File

@ -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<Supplier<URI>>(){
}).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<Access> provide() {
return Suppliers.ofInstance(new ParseAccessTest().expected());
}
}).getInstance(RegionIdToURISupplier.Factory.class);
public void testRegionMatches() {
assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.0").get(), Suppliers
.<URI> supplierFunction()), ImmutableMap.of());
assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.1").get(), Suppliers
.<URI> 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<Supplier<URI>>() {
}).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<Access> 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
.<URI> 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
.<URI> 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
.<URI> 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")));
}
}

View File

@ -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<Supplier<URI>>() {
}).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<Supplier<URI>>() {
}).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<Access> 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
.<URI> 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
.<URI> 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
.<URI> 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")));
}
}

View File

@ -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.v2_0.options;
import static org.jclouds.openstack.v2_0.options.BaseListOptions.Builder.changesSince;
import static org.jclouds.openstack.v2_0.options.BaseListOptions.Builder.maxResults;
import static org.jclouds.openstack.v2_0.options.BaseListOptions.Builder.startAt;
import static org.testng.Assert.assertEquals;
import java.util.Date;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableList;
/**
* Tests behavior of {@code ListOptions}
*
* @author Adrian Cole
*/
@Test(groups = "unit")
public class BaseListOptionsTest {
public void testChangesSince() {
Date ifModifiedSince = new Date();
BaseListOptions options = new BaseListOptions().changesSince(ifModifiedSince);
assertEquals(ImmutableList.of(ifModifiedSince.getTime() / 1000 + ""), options
.buildQueryParameters().get("changes-since"));
}
public void testStartAt() {
long offset = 1;
BaseListOptions options = new BaseListOptions().startAt(offset);
assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("offset"));
}
public void testMaxResults() {
int limit = 1;
BaseListOptions options = new BaseListOptions().maxResults(limit);
assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("limit"));
}
public void testChangesSinceStatic() {
Date ifModifiedSince = new Date();
BaseListOptions options = changesSince(ifModifiedSince);
assertEquals(ImmutableList.of(ifModifiedSince.getTime() / 1000 + ""), options
.buildQueryParameters().get("changes-since"));
}
public void testStartAtStatic() {
long offset = 1;
BaseListOptions options = startAt(offset);
assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("offset"));
}
public void testMaxResultsStatic() {
int limit = 1;
BaseListOptions options = maxResults(limit);
assertEquals(ImmutableList.of("1"), options.buildQueryParameters().get("limit"));
}
}

View File

@ -0,0 +1,51 @@
package org.jclouds.openstack.v2_0.predicates;
import static org.jclouds.openstack.v2_0.predicates.LinkPredicates.hrefEquals;
import static org.jclouds.openstack.v2_0.predicates.LinkPredicates.relationEquals;
import static org.jclouds.openstack.v2_0.predicates.LinkPredicates.typeEquals;
import java.net.URI;
import org.jclouds.openstack.v2_0.domain.Link;
import org.jclouds.openstack.v2_0.domain.Link.Relation;
import org.testng.annotations.Test;
/**
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "LinkPredicatesTest")
public class LinkPredicatesTest {
Link ref = Link.builder().type("application/pdf").relation(Relation.DESCRIBEDBY).href(
URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1")).build();
@Test
public void testRelationEqualsWhenEqual() {
assert relationEquals(Relation.DESCRIBEDBY).apply(ref);
}
@Test
public void testRelationEqualsWhenNotEqual() {
assert !relationEquals(Relation.UNRECOGNIZED).apply(ref);
}
@Test
public void testTypeEqualsWhenEqual() {
assert typeEquals("application/pdf").apply(ref);
}
@Test
public void testTypeEqualsWhenNotEqual() {
assert !typeEquals("foo").apply(ref);
}
@Test
public void testHrefEqualsWhenEqual() {
assert hrefEquals(URI.create("http://docs.openstack.org/ext/keypairs/api/v1.1")).apply(ref);
}
@Test
public void testHrefEqualsWhenNotEqual() {
assert !hrefEquals(URI.create("foo")).apply(ref);
}
}

View File

@ -1,51 +1,64 @@
<?xml version="1.0"?>
<configuration scan="false">
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds-wire.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<appender name="BLOBSTOREFILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds-blobstore.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<root>
<level value="warn" />
</root>
<logger name="org.jclouds">
<level value="DEBUG" />
<appender-ref ref="FILE" />
</logger>
<logger name="jclouds.wire">
<level value="DEBUG" />
<appender-ref ref="WIREFILE" />
</logger>
<logger name="jclouds.headers">
<level value="DEBUG" />
<appender-ref ref="WIREFILE" />
</logger>
<logger name="jclouds.blobstore">
<level value="DEBUG" />
<appender-ref ref="BLOBSTOREFILE" />
</logger>
</configuration>
<?xml version="1.0"?>
<configuration scan="false">
<appender name="FILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds-wire.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<appender name="COMPUTEFILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds-compute.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<appender name="SSHFILE" class="ch.qos.logback.core.FileAppender">
<file>target/test-data/jclouds-ssh.log</file>
<encoder>
<Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
</encoder>
</appender>
<root>
<level value="warn" />
</root>
<logger name="org.jclouds">
<level value="DEBUG" />
<appender-ref ref="FILE" />
</logger>
<logger name="jclouds.wire">
<level value="DEBUG" />
<appender-ref ref="WIREFILE" />
</logger>
<logger name="jclouds.headers">
<level value="DEBUG" />
<appender-ref ref="WIREFILE" />
</logger>
<logger name="jclouds.compute">
<level value="DEBUG" />
<appender-ref ref="COMPUTEFILE" />
</logger>
<logger name="jclouds.ssh">
<level value="DEBUG" />
<appender-ref ref="SSHFILE" />
</logger>
</configuration>

View File

@ -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"
}
}
}

View File

@ -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"
}]
}
}
}

Some files were not shown because too many files have changed in this diff Show More