Skip to content

Commit

Permalink
Issue 815: refactored the 3 major features of keystone into separate …
Browse files Browse the repository at this point in the history
…clients. removed cyclic dependency needed to support keystone controlling keystones in other regions
  • Loading branch information
Adrian Cole committed Jun 7, 2012
1 parent a8b5c71 commit d00e360
Show file tree
Hide file tree
Showing 72 changed files with 2,178 additions and 1,402 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
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;
Expand Down Expand Up @@ -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);

/**
Expand All @@ -64,7 +65,7 @@ ListenableFuture<Access> authenticateWithTenantNameAndCredentials(@PayloadParam(
@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);

/**
Expand All @@ -77,7 +78,7 @@ ListenableFuture<Access> authenticateWithTenantIdAndCredentials(@PayloadParam("t
@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);

/**
Expand All @@ -88,6 +89,6 @@ ListenableFuture<Access> authenticateWithTenantNameAndCredentials(@PayloadParam(
@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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
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;
Expand All @@ -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);
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,12 +18,14 @@
*/
package org.jclouds.openstack.keystone.v2_0;

import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.CREDENTIAL_TYPE;
import static org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties.SERVICE_TYPE;

import java.net.URI;
import java.util.Properties;

import org.jclouds.apis.ApiMetadata;
import org.jclouds.openstack.keystone.v2_0.config.CredentialTypes;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
import org.jclouds.openstack.keystone.v2_0.config.KeystoneRestClientModule;
import org.jclouds.openstack.v2_0.ServiceType;
Expand All @@ -44,19 +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>>() {

/** The serialVersionUID */
private static final long serialVersionUID = 3030344682235783904L;

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) {
Expand All @@ -67,14 +68,15 @@ public static Properties defaultProperties() {
Properties properties = BaseRestApiMetadata.defaultProperties();
// TODO: this doesn't actually do anything yet.
properties.setProperty(KeystoneProperties.VERSION, "2.0");
properties.setProperty(CREDENTIAL_TYPE, CredentialTypes.PASSWORD_CREDENTIALS);
properties.put(SERVICE_TYPE, ServiceType.IDENTITY);
return properties;
}

public static class Builder extends BaseRestApiMetadata.Builder {

protected Builder() {
super(KeystoneClient.class, KeystoneAsyncClient.class);
protected Builder(Class<?> api, Class<?> asyncApi) {
super(api, asyncApi);
id("openstack-keystone")
.name("OpenStack Keystone Essex+ API")
.identityName("tenantId:user")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,21 +18,22 @@
*/
package org.jclouds.openstack.keystone.v2_0;

import java.util.Set;

import javax.ws.rs.Consumes;
import javax.ws.rs.GET;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;

import org.jclouds.Constants;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Region;
import org.jclouds.location.functions.RegionToEndpoint;
import org.jclouds.openstack.keystone.v2_0.features.AdminAsyncClient;
import org.jclouds.openstack.keystone.v2_0.features.ServiceAsyncClient;
import org.jclouds.openstack.keystone.v2_0.functions.RegionToAdminEndpointURI;
import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata;
import org.jclouds.openstack.keystone.v2_0.features.TenantAsyncClient;
import org.jclouds.openstack.keystone.v2_0.features.TokenAsyncClient;
import org.jclouds.openstack.keystone.v2_0.features.UserAsyncClient;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.ExceptionParser;
import org.jclouds.rest.annotations.SelectJson;
import org.jclouds.rest.functions.ReturnNullOnNotFoundOr404;

import com.google.inject.Provides;
import com.google.common.util.concurrent.ListenableFuture;

/**
* Provides access to Openstack keystone resources via their REST API.
Expand All @@ -42,20 +43,34 @@
* @see <a href="http://keystone.openstack.org/" />
* @see KeystoneClient
*/
@Path("/v{" + Constants.PROPERTY_API_VERSION + "}")
public interface KeystoneAsyncClient {

/**
* @see KeystoneClient#getApiMetadata()
*/
@GET
@SelectJson("version")
@Consumes(MediaType.APPLICATION_JSON)
@Path("/v{" + Constants.PROPERTY_API_VERSION + "}/")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<ApiMetadata> getApiMetadata();

/**
* @return the Region codes configured
* @see KeystoneClient#getTokenClient()
*/
@Provides
@Region
Set<String> getConfiguredRegions();
@Delegate
TokenAsyncClient getTokenClient();

/** Provides asynchronous access to Identity user-accessible features */
/**
* @see KeystoneClient#getUserClient()
*/
@Delegate
ServiceAsyncClient getServiceClientForRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region);
UserAsyncClient getUserClient();


/** Provides asynchronous access to the KeyStone Admin API */
/**
* @see KeystoneClient#getTenantClient()
*/
@Delegate
AdminAsyncClient getAdminClientForRegion(@EndpointParam(parser = RegionToAdminEndpointURI.class) @Nullable String region);
TenantAsyncClient getTenantClient();
}
Original file line number Diff line number Diff line change
Expand Up @@ -18,43 +18,49 @@
*/
package org.jclouds.openstack.keystone.v2_0;

import java.util.Set;
import java.util.concurrent.TimeUnit;

import org.jclouds.concurrent.Timeout;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Region;
import org.jclouds.location.functions.RegionToEndpoint;
import org.jclouds.openstack.keystone.v2_0.features.AdminClient;
import org.jclouds.openstack.keystone.v2_0.features.ServiceClient;
import org.jclouds.openstack.keystone.v2_0.functions.RegionToAdminEndpointURI;
import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata;
import org.jclouds.openstack.keystone.v2_0.features.TenantClient;
import org.jclouds.openstack.keystone.v2_0.features.TokenClient;
import org.jclouds.openstack.keystone.v2_0.features.UserClient;
import org.jclouds.rest.annotations.Delegate;
import org.jclouds.rest.annotations.EndpointParam;

import com.google.inject.Provides;

/**
* Provides access to Openstack keystone resources via their REST API.
* <p/>
*
* @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();
}
Original file line number Diff line number Diff line change
Expand Up @@ -29,14 +29,15 @@

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;

/**
Expand All @@ -57,11 +58,9 @@ public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
}

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);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,29 +18,25 @@
*/
package org.jclouds.openstack.keystone.v2_0.config;

import static com.google.common.base.Preconditions.checkNotNull;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;

import com.google.common.base.CaseFormat;
import javax.inject.Qualifier;

/**
* Configuration properties and constants used in Keystone connections.
*
* @see CredentialTypes
* @author Adrian Cole
*
*/
public enum CredentialType {

API_ACCESS_KEY_CREDENTIALS,

PASSWORD_CREDENTIALS;

@Override
public String toString() {
return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, name());
}

public static CredentialType fromValue(String credentialType) {
return valueOf(CaseFormat.LOWER_CAMEL.to(CaseFormat.UPPER_UNDERSCORE, checkNotNull(credentialType,
"credentialType")));
}

}
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface CredentialType {
/**
* @see CredentialTypes
*
*/
String value();
}
Loading

0 comments on commit d00e360

Please sign in to comment.