mirror of https://github.com/apache/jclouds.git
made openstack multi-region, and now select correct endpoint via apiversion property
This commit is contained in:
parent
61314015dc
commit
ae1effd748
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.jclouds.cloudfiles.config;
|
||||
|
||||
import static org.jclouds.util.Suppliers2.getLastValueInMap;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
|
@ -27,22 +28,21 @@ import org.jclouds.cloudfiles.CDNManagement;
|
|||
import org.jclouds.cloudfiles.CloudFilesAsyncClient;
|
||||
import org.jclouds.cloudfiles.CloudFilesClient;
|
||||
import org.jclouds.http.HttpErrorHandler;
|
||||
import org.jclouds.http.HttpRetryHandler;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.http.annotation.ClientError;
|
||||
import org.jclouds.http.annotation.Redirection;
|
||||
import org.jclouds.http.annotation.ServerError;
|
||||
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
||||
import org.jclouds.openstack.keystone.v1_1.config.AuthenticationServiceModule;
|
||||
import org.jclouds.openstack.keystone.v1_1.functions.PublicURLFromAuthResponseForService;
|
||||
import org.jclouds.openstack.keystone.v1_1.handlers.RetryOnRenew;
|
||||
import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
|
||||
import org.jclouds.openstack.swift.CommonSwiftClient;
|
||||
import org.jclouds.openstack.swift.Storage;
|
||||
import org.jclouds.openstack.swift.config.SwiftObjectModule;
|
||||
import org.jclouds.openstack.swift.handlers.ParseSwiftErrorFromHttpResponse;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.annotations.ApiVersion;
|
||||
import org.jclouds.rest.config.RestClientModule;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
|
@ -55,17 +55,11 @@ import com.google.inject.Provides;
|
|||
@ConfiguresRestClient
|
||||
@RequiresHttp
|
||||
public class CloudFilesRestClientModule extends RestClientModule<CloudFilesClient, CloudFilesAsyncClient> {
|
||||
private final AuthenticationServiceModule module;
|
||||
|
||||
public CloudFilesRestClientModule(AuthenticationServiceModule module) {
|
||||
super(CloudFilesClient.class, CloudFilesAsyncClient.class);
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
public CloudFilesRestClientModule() {
|
||||
this(new AuthenticationServiceModule());
|
||||
super(CloudFilesClient.class, CloudFilesAsyncClient.class);
|
||||
}
|
||||
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
CommonSwiftClient provideCommonSwiftClient(CloudFilesClient in) {
|
||||
|
@ -77,24 +71,9 @@ public class CloudFilesRestClientModule extends RestClientModule<CloudFilesClien
|
|||
CommonSwiftAsyncClient provideCommonSwiftClient(CloudFilesAsyncClient in) {
|
||||
return in;
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@CDNManagement
|
||||
protected Supplier<URI> provideCDNUrl(PublicURLFromAuthResponseForService.Factory factory) {
|
||||
return factory.create("cloudFilesCDN");
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Storage
|
||||
protected Supplier<URI> provideStorageUrl(PublicURLFromAuthResponseForService.Factory factory) {
|
||||
return factory.create("cloudFiles");
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(module);
|
||||
install(new SwiftObjectModule());
|
||||
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
|
||||
super.configure();
|
||||
|
@ -108,9 +87,23 @@ public class CloudFilesRestClientModule extends RestClientModule<CloudFilesClien
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void bindRetryHandlers() {
|
||||
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
|
||||
protected void installLocations() {
|
||||
super.installLocations();
|
||||
install(new AuthenticationServiceModule());
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@CDNManagement
|
||||
protected Supplier<URI> provideCDNUrl(RegionIdToURISupplier.Factory factory, @ApiVersion String apiVersion) {
|
||||
return getLastValueInMap(factory.createForApiTypeAndVersion("cloudFilesCDN", apiVersion));
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Storage
|
||||
protected Supplier<URI> provideStorageUrl(RegionIdToURISupplier.Factory factory, @ApiVersion String apiVersion) {
|
||||
return getLastValueInMap(factory.createForApiTypeAndVersion("cloudFiles", apiVersion));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package org.jclouds.cloudloadbalancers.config;
|
||||
|
||||
import static org.jclouds.util.Suppliers2.getLastValueInMap;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
|
||||
|
@ -35,28 +37,26 @@ import org.jclouds.cloudloadbalancers.handlers.ParseCloudLoadBalancersErrorFromH
|
|||
import org.jclouds.cloudloadbalancers.location.RegionUrisFromPropertiesAndAccountIDPathSuffix;
|
||||
import org.jclouds.cloudloadbalancers.reference.RackspaceConstants;
|
||||
import org.jclouds.http.HttpErrorHandler;
|
||||
import org.jclouds.http.HttpRetryHandler;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.http.annotation.ClientError;
|
||||
import org.jclouds.http.annotation.Redirection;
|
||||
import org.jclouds.http.annotation.ServerError;
|
||||
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
||||
import org.jclouds.location.Region;
|
||||
import org.jclouds.location.config.LocationModule;
|
||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
||||
import org.jclouds.openstack.keystone.v1_1.config.AuthenticationServiceModule;
|
||||
import org.jclouds.openstack.keystone.v1_1.functions.PublicURLFromAuthResponseForService;
|
||||
import org.jclouds.openstack.keystone.v1_1.handlers.RetryOnRenew;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.annotations.ApiVersion;
|
||||
import org.jclouds.rest.config.RestClientModule;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.Scopes;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
|
||||
/**
|
||||
|
@ -67,75 +67,65 @@ import com.google.inject.assistedinject.FactoryModuleBuilder;
|
|||
@RequiresHttp
|
||||
@ConfiguresRestClient
|
||||
public class CloudLoadBalancersRestClientModule extends
|
||||
RestClientModule<CloudLoadBalancersClient, CloudLoadBalancersAsyncClient> {
|
||||
RestClientModule<CloudLoadBalancersClient, CloudLoadBalancersAsyncClient> {
|
||||
|
||||
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
|
||||
.put(LoadBalancerClient.class, LoadBalancerAsyncClient.class)//
|
||||
.put(NodeClient.class, NodeAsyncClient.class)//
|
||||
.build();
|
||||
|
||||
private final AuthenticationServiceModule module;
|
||||
|
||||
public CloudLoadBalancersRestClientModule(AuthenticationServiceModule module) {
|
||||
super(CloudLoadBalancersClient.class, CloudLoadBalancersAsyncClient.class, DELEGATE_MAP);
|
||||
this.module = module;
|
||||
}
|
||||
.put(LoadBalancerClient.class, LoadBalancerAsyncClient.class)//
|
||||
.put(NodeClient.class, NodeAsyncClient.class)//
|
||||
.build();
|
||||
|
||||
public CloudLoadBalancersRestClientModule() {
|
||||
this(new AuthenticationServiceModule());
|
||||
super(CloudLoadBalancersClient.class, CloudLoadBalancersAsyncClient.class, DELEGATE_MAP);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installLocations() {
|
||||
super.installLocations();
|
||||
bind(RegionIdToURISupplier.class).to(RegionUrisFromPropertiesAndAccountIDPathSuffix.class).in(Scopes.SINGLETON);
|
||||
install(new LocationModule());
|
||||
install(new URIWithAccountIDPathSuffixAuthenticationServiceModule());
|
||||
}
|
||||
|
||||
protected void bindRegionsToProvider(Class<? extends javax.inject.Provider<Map<String, URI>>> providerClass) {
|
||||
bind(new TypeLiteral<Map<String, URI>>() {
|
||||
}).annotatedWith(Region.class).toProvider(providerClass).in(Scopes.SINGLETON);
|
||||
|
||||
public static class URIWithAccountIDPathSuffixAuthenticationServiceModule extends AbstractModule {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new AuthenticationServiceModule());
|
||||
bind(RegionIdToURISupplier.class).to(RegionUrisFromPropertiesAndAccountIDPathSuffix.class)
|
||||
.in(Scopes.SINGLETON);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named(RackspaceConstants.PROPERTY_ACCOUNT_ID)
|
||||
protected Supplier<String> accountID(RegionIdToURISupplier.Factory factory, @ApiVersion String apiVersion) {
|
||||
return Suppliers.compose(new Function<URI, String>() {
|
||||
|
||||
@Override
|
||||
public String apply(URI arg0) {
|
||||
return arg0.getPath().substring(arg0.getPath().lastIndexOf('/') + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "getAccountIdFromCloudServers()";
|
||||
}
|
||||
}, getLastValueInMap(factory.createForApiTypeAndVersion("cloudServers", apiVersion)));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(module);
|
||||
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
|
||||
install(new FactoryModuleBuilder().build(ConvertLB.Factory.class));
|
||||
super.configure();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Named(RackspaceConstants.PROPERTY_ACCOUNT_ID)
|
||||
protected Supplier<String> accountID(PublicURLFromAuthResponseForService.Factory factory) {
|
||||
return Suppliers.compose(new Function<URI, String>() {
|
||||
|
||||
@Override
|
||||
public String apply(URI arg0) {
|
||||
return arg0.getPath().substring(arg0.getPath().lastIndexOf('/') + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "getAccountIdFromCloudServers()";
|
||||
}
|
||||
}, factory.create("cloudServers"));
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindErrorHandlers() {
|
||||
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(
|
||||
ParseCloudLoadBalancersErrorFromHttpResponse.class);
|
||||
ParseCloudLoadBalancersErrorFromHttpResponse.class);
|
||||
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(
|
||||
ParseCloudLoadBalancersErrorFromHttpResponse.class);
|
||||
ParseCloudLoadBalancersErrorFromHttpResponse.class);
|
||||
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(
|
||||
ParseCloudLoadBalancersErrorFromHttpResponse.class);
|
||||
ParseCloudLoadBalancersErrorFromHttpResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindRetryHandlers() {
|
||||
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -42,8 +42,8 @@ import org.jclouds.domain.Credentials;
|
|||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.internal.ClassMethodArgs;
|
||||
import org.jclouds.location.config.LocationModule;
|
||||
import org.jclouds.openstack.filters.AuthenticateRequest;
|
||||
import org.jclouds.openstack.keystone.v1_1.config.AuthenticationServiceModule;
|
||||
import org.jclouds.openstack.keystone.v1_1.config.AuthenticationServiceModule.GetAuth;
|
||||
import org.jclouds.openstack.keystone.v1_1.domain.Auth;
|
||||
import org.jclouds.openstack.keystone.v1_1.parse.ParseAuthTest;
|
||||
|
@ -55,6 +55,7 @@ import org.testng.annotations.BeforeClass;
|
|||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Module;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
|
@ -77,21 +78,27 @@ public abstract class BaseCloudLoadBalancersAsyncClientTest<T> extends RestClien
|
|||
@ConfiguresRestClient
|
||||
@RequiresHttp
|
||||
protected static class TestCloudLoadBalancersRestClientModule extends CloudLoadBalancersRestClientModule {
|
||||
private TestCloudLoadBalancersRestClientModule() {
|
||||
super(new AuthenticationServiceModule());
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
GetAuth provideGetAuth() {
|
||||
return new GetAuth(null) {
|
||||
@Override
|
||||
public Auth apply(Credentials in) {
|
||||
return new ParseAuthTest().expected();
|
||||
@Override
|
||||
protected void installLocations() {
|
||||
install(new AbstractModule() {
|
||||
protected void configure() {
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
GetAuth provideGetAuth() {
|
||||
return new GetAuth(null) {
|
||||
@Override
|
||||
public Auth apply(Credentials in) {
|
||||
return new ParseAuthTest().expected();
|
||||
}
|
||||
};
|
||||
}
|
||||
});
|
||||
install(new LocationModule());
|
||||
install(new URIWithAccountIDPathSuffixAuthenticationServiceModule());
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -106,8 +113,8 @@ public abstract class BaseCloudLoadBalancersAsyncClientTest<T> extends RestClien
|
|||
super.setupFactory();
|
||||
try {
|
||||
processor.setCaller(new ClassMethodArgs(CloudLoadBalancersAsyncClient.class,
|
||||
CloudLoadBalancersAsyncClient.class.getMethod("getLoadBalancerClient", String.class),
|
||||
new Object[] { Region.LON }));
|
||||
CloudLoadBalancersAsyncClient.class.getMethod("getLoadBalancerClient", String.class),
|
||||
new Object[] { Region.LON }));
|
||||
} catch (Exception e) {
|
||||
Throwables.propagate(e);
|
||||
}
|
||||
|
@ -119,20 +126,20 @@ public abstract class BaseCloudLoadBalancersAsyncClientTest<T> extends RestClien
|
|||
overrides.setProperty(provider + ".endpoint", "https://auth");
|
||||
overrides.setProperty(PROPERTY_REGIONS, LON);
|
||||
overrides.setProperty(PROPERTY_REGION + "." + LON + "." + ISO3166_CODES, "GB-SLG");
|
||||
overrides.setProperty(PROPERTY_REGION + "." + LON + "." + ENDPOINT,
|
||||
String.format("https://lon.loadbalancers.api.rackspacecloud.com/v${%s}", PROPERTY_API_VERSION));
|
||||
overrides.setProperty(PROPERTY_REGION + "." + LON + "." + ENDPOINT, String.format(
|
||||
"https://lon.loadbalancers.api.rackspacecloud.com/v${%s}", PROPERTY_API_VERSION));
|
||||
return overrides;
|
||||
}
|
||||
|
||||
/**
|
||||
* this is only here as "cloudloadbalancers" is not in rest.properties
|
||||
*/
|
||||
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||
@SuppressWarnings( { "unchecked", "rawtypes" })
|
||||
@Override
|
||||
public RestContextSpec<?, ?> createContextSpec() {
|
||||
return RestContextFactory.<LoadBalancerClient, LoadBalancerAsyncClient> contextSpec(provider, "https://auth",
|
||||
"1.0", "", "", "identity", "credential", LoadBalancerClient.class, LoadBalancerAsyncClient.class,
|
||||
(Class)CloudLoadBalancersPropertiesBuilder.class, (Class)CloudLoadBalancersContextBuilder.class,
|
||||
ImmutableSet.<Module> of());
|
||||
"1.0", "", "", "identity", "credential", LoadBalancerClient.class, LoadBalancerAsyncClient.class,
|
||||
(Class) CloudLoadBalancersPropertiesBuilder.class, (Class) CloudLoadBalancersContextBuilder.class,
|
||||
ImmutableSet.<Module> of());
|
||||
}
|
||||
}
|
|
@ -19,6 +19,7 @@
|
|||
package org.jclouds.cloudservers.config;
|
||||
|
||||
import static com.google.common.base.Suppliers.memoizeWithExpiration;
|
||||
import static org.jclouds.util.Suppliers2.getLastValueInMap;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
|
@ -31,18 +32,17 @@ import org.jclouds.cloudservers.CloudServersClient;
|
|||
import org.jclouds.cloudservers.handlers.ParseCloudServersErrorFromHttpResponse;
|
||||
import org.jclouds.date.TimeStamp;
|
||||
import org.jclouds.http.HttpErrorHandler;
|
||||
import org.jclouds.http.HttpRetryHandler;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.http.annotation.ClientError;
|
||||
import org.jclouds.http.annotation.Redirection;
|
||||
import org.jclouds.http.annotation.ServerError;
|
||||
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
||||
import org.jclouds.openstack.keystone.v1_1.config.AuthenticationServiceModule;
|
||||
import org.jclouds.openstack.keystone.v1_1.functions.PublicURLFromAuthResponseForService;
|
||||
import org.jclouds.openstack.keystone.v1_1.handlers.RetryOnRenew;
|
||||
import org.jclouds.openstack.services.Compute;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.annotations.ApiVersion;
|
||||
import org.jclouds.rest.config.RestClientModule;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
|
@ -56,20 +56,12 @@ import com.google.inject.Provides;
|
|||
@RequiresHttp
|
||||
public class CloudServersRestClientModule extends RestClientModule<CloudServersClient, CloudServersAsyncClient> {
|
||||
|
||||
private final AuthenticationServiceModule module;
|
||||
|
||||
public CloudServersRestClientModule(AuthenticationServiceModule module) {
|
||||
super(CloudServersClient.class, CloudServersAsyncClient.class);
|
||||
this.module = module;
|
||||
}
|
||||
|
||||
public CloudServersRestClientModule() {
|
||||
this(new AuthenticationServiceModule());
|
||||
super(CloudServersClient.class, CloudServersAsyncClient.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(module);
|
||||
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
|
||||
super.configure();
|
||||
}
|
||||
|
@ -82,18 +74,19 @@ public class CloudServersRestClientModule extends RestClientModule<CloudServersC
|
|||
}
|
||||
|
||||
@Override
|
||||
protected void bindRetryHandlers() {
|
||||
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
|
||||
protected void installLocations() {
|
||||
super.installLocations();
|
||||
install(new AuthenticationServiceModule());
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Compute
|
||||
protected Supplier<URI> provideServerUrl(PublicURLFromAuthResponseForService.Factory factory) {
|
||||
return factory.create("cloudServers");
|
||||
protected Supplier<URI> provideCloudServers(RegionIdToURISupplier.Factory factory, @ApiVersion String apiVersion) {
|
||||
return getLastValueInMap(factory.createForApiTypeAndVersion("cloudServers", apiVersion));
|
||||
}
|
||||
|
||||
//TODO: see if we still need this.
|
||||
|
||||
// TODO: see if we still need this.
|
||||
@Provides
|
||||
@Singleton
|
||||
@TimeStamp
|
||||
|
|
|
@ -43,7 +43,6 @@ import org.jclouds.cloudservers.domain.BackupSchedule;
|
|||
import org.jclouds.cloudservers.domain.DailyBackup;
|
||||
import org.jclouds.cloudservers.domain.RebootType;
|
||||
import org.jclouds.cloudservers.domain.WeeklyBackup;
|
||||
import org.jclouds.cloudservers.internal.BaseCloudServersRestClientExpectTest.TestAuthenticationServiceModule;
|
||||
import org.jclouds.cloudservers.options.CreateServerOptions;
|
||||
import org.jclouds.cloudservers.options.CreateSharedIpGroupOptions;
|
||||
import org.jclouds.cloudservers.options.ListOptions;
|
||||
|
@ -894,9 +893,6 @@ public class CloudServersAsyncClientTest extends RestClientTest<CloudServersAsyn
|
|||
@ConfiguresRestClient
|
||||
@RequiresHttp
|
||||
protected static class TestCloudServersRestClientModule extends CloudServersRestClientModule {
|
||||
private TestCloudServersRestClientModule() {
|
||||
super(new TestAuthenticationServiceModule());
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
|
|
|
@ -79,9 +79,6 @@ public class BaseCloudServersRestClientExpectTest extends BaseKeystoneRestClient
|
|||
@ConfiguresRestClient
|
||||
@RequiresHttp
|
||||
protected static class TestCloudServersRestClientModule extends CloudServersRestClientModule {
|
||||
private TestCloudServersRestClientModule() {
|
||||
super(new TestAuthenticationServiceModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Supplier<Date> provideCacheBusterDate() {
|
||||
|
|
|
@ -18,12 +18,8 @@
|
|||
*/
|
||||
package org.jclouds.ec2.config;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.aws.config.WithZonesFormSigningRestClientModule;
|
||||
import org.jclouds.ec2.EC2AsyncClient;
|
||||
|
@ -47,18 +43,14 @@ import org.jclouds.ec2.services.WindowsClient;
|
|||
import org.jclouds.ec2.suppliers.DescribeAvailabilityZonesInRegion;
|
||||
import org.jclouds.ec2.suppliers.DescribeRegionsForConfiguredRegions;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.location.Zone;
|
||||
import org.jclouds.location.config.LocationModule;
|
||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
||||
import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
|
||||
import org.jclouds.location.suppliers.ZoneIdsSupplier;
|
||||
import org.jclouds.location.suppliers.derived.ZoneIdsFromRegionIdToZoneIdsValues;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.Scopes;
|
||||
|
||||
/**
|
||||
|
@ -97,27 +89,4 @@ public class EC2RestClientModule<S extends EC2Client, A extends EC2AsyncClient>
|
|||
bind(RegionIdToURISupplier.class).to(DescribeRegionsForConfiguredRegions.class).in(Scopes.SINGLETON);
|
||||
bind(ZoneIdsSupplier.class).to(ZoneIdsFromRegionIdToZoneIdsValues.class).in(Scopes.SINGLETON);
|
||||
}
|
||||
|
||||
/**
|
||||
* as opposed to via properties, lets look up zones via api, as they are more likely to change
|
||||
*/
|
||||
@Singleton
|
||||
public static class ZoneIdsFromRegionIdToZoneIdsValues implements ZoneIdsSupplier {
|
||||
|
||||
private final Supplier<Map<String, Supplier<Set<String>>>> regionIdToZoneIdsSupplier;
|
||||
|
||||
@Inject
|
||||
protected ZoneIdsFromRegionIdToZoneIdsValues(
|
||||
@Zone Supplier<Map<String, Supplier<Set<String>>>> regionIdToZoneIdsSupplier) {
|
||||
this.regionIdToZoneIdsSupplier = regionIdToZoneIdsSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> get() {
|
||||
Collection<Supplier<Set<String>>> zones = regionIdToZoneIdsSupplier.get().values();
|
||||
return ImmutableSet.copyOf(Iterables.concat(Iterables.transform(zones, Suppliers
|
||||
.<Set<String>> supplierFunction())));
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -77,11 +77,6 @@ public class NovaRestClientModule extends RestClientModule<NovaClient, NovaAsync
|
|||
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseNovaErrorFromHttpResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindRetryHandlers() {
|
||||
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@ServerManagement
|
||||
|
|
|
@ -23,7 +23,6 @@ import java.net.URI;
|
|||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.http.HttpErrorHandler;
|
||||
import org.jclouds.http.HttpRetryHandler;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.http.annotation.ClientError;
|
||||
import org.jclouds.http.annotation.Redirection;
|
||||
|
@ -32,7 +31,6 @@ import org.jclouds.json.config.GsonModule.DateAdapter;
|
|||
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
||||
import org.jclouds.openstack.config.OpenStackAuthenticationModule;
|
||||
import org.jclouds.openstack.functions.URIFromAuthenticationResponseForService;
|
||||
import org.jclouds.openstack.handlers.RetryOnRenew;
|
||||
import org.jclouds.openstack.reference.AuthHeaders;
|
||||
import org.jclouds.openstack.swift.CommonSwiftAsyncClient;
|
||||
import org.jclouds.openstack.swift.CommonSwiftClient;
|
||||
|
@ -79,11 +77,6 @@ public class BaseSwiftRestClientModule<S extends CommonSwiftClient, A extends Co
|
|||
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(ParseSwiftErrorFromHttpResponse.class);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindRetryHandlers() {
|
||||
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
@Storage
|
||||
|
|
|
@ -32,13 +32,16 @@ import javax.inject.Singleton;
|
|||
import org.jclouds.concurrent.RetryOnTimeOutExceptionFunction;
|
||||
import org.jclouds.date.TimeStamp;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.http.HttpRetryHandler;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.http.annotation.ClientError;
|
||||
import org.jclouds.location.Provider;
|
||||
import org.jclouds.openstack.Authentication;
|
||||
import org.jclouds.openstack.OpenStackAuthAsyncClient;
|
||||
import org.jclouds.openstack.OpenStackAuthClient;
|
||||
import org.jclouds.openstack.domain.AuthenticationResponse;
|
||||
import org.jclouds.openstack.functions.URIFromAuthenticationResponseForService;
|
||||
import org.jclouds.openstack.handlers.RetryOnRenew;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
|
@ -66,6 +69,7 @@ public class OpenStackAuthenticationModule extends AbstractModule {
|
|||
// explicitly
|
||||
bindClientAndAsyncClient(binder(), OpenStackAuthClient.class, OpenStackAuthAsyncClient.class);
|
||||
install(new FactoryModuleBuilder().build(URIFromAuthenticationResponseForService.Factory.class));
|
||||
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -30,13 +30,17 @@ import javax.inject.Singleton;
|
|||
|
||||
import org.jclouds.concurrent.RetryOnTimeOutExceptionFunction;
|
||||
import org.jclouds.domain.Credentials;
|
||||
import org.jclouds.http.HttpRetryHandler;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.http.annotation.ClientError;
|
||||
import org.jclouds.location.Provider;
|
||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
||||
import org.jclouds.openstack.Authentication;
|
||||
import org.jclouds.openstack.keystone.v1_1.ServiceAsyncClient;
|
||||
import org.jclouds.openstack.keystone.v1_1.ServiceClient;
|
||||
import org.jclouds.openstack.keystone.v1_1.domain.Auth;
|
||||
import org.jclouds.openstack.keystone.v1_1.functions.PublicURLFromAuthResponseForService;
|
||||
import org.jclouds.openstack.keystone.v1_1.handlers.RetryOnRenew;
|
||||
import org.jclouds.openstack.keystone.v1_1.suppliers.RegionIdToURIFromAuthForServiceSupplier;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
|
@ -62,7 +66,9 @@ public class AuthenticationServiceModule extends AbstractModule {
|
|||
// ServiceClient is used directly for filters and retry handlers, so let's bind it
|
||||
// explicitly
|
||||
bindClientAndAsyncClient(binder(), ServiceClient.class, ServiceAsyncClient.class);
|
||||
install(new FactoryModuleBuilder().build(PublicURLFromAuthResponseForService.Factory.class));
|
||||
install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
|
||||
RegionIdToURIFromAuthForServiceSupplier.class).build(RegionIdToURISupplier.Factory.class));
|
||||
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -104,10 +104,10 @@ public class Endpoint implements Comparable<Endpoint> {
|
|||
protected final URI publicURL;
|
||||
protected final URI internalURL;
|
||||
|
||||
protected Endpoint(boolean v1Default, @Nullable String region, URI publicURL, @Nullable URI internalURL) {
|
||||
protected Endpoint(boolean v1Default, @Nullable String region, @Nullable URI publicURL, @Nullable URI internalURL) {
|
||||
this.v1Default = v1Default;
|
||||
this.region = region;
|
||||
this.publicURL = checkNotNull(publicURL, "publicURL");
|
||||
this.publicURL = publicURL;
|
||||
this.internalURL = internalURL;
|
||||
}
|
||||
|
||||
|
@ -141,11 +141,12 @@ public class Endpoint implements Comparable<Endpoint> {
|
|||
}
|
||||
|
||||
/**
|
||||
* A public URL is accessible from anywhere. Access to a public URL usually
|
||||
* incurs traffic charges.
|
||||
* A public URL is accessible from anywhere. Access to a public URL usually incurs traffic
|
||||
* charges.
|
||||
*
|
||||
* @return the public endpoint of the service
|
||||
*/
|
||||
@Nullable
|
||||
public URI getPublicURL() {
|
||||
return publicURL;
|
||||
}
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* 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.v1_1.functions;
|
||||
|
||||
import org.jclouds.openstack.keystone.v1_1.domain.Endpoint;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
@ImplementedBy(RegionFirstPartOfDNSNameOrProvider.class)
|
||||
public interface EndpointToRegion extends Function<Endpoint, String> {
|
||||
|
||||
}
|
|
@ -18,24 +18,14 @@
|
|||
*/
|
||||
package org.jclouds.openstack.keystone.v1_1.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.openstack.keystone.v1_1.domain.Auth;
|
||||
import org.jclouds.openstack.keystone.v1_1.domain.Endpoint;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
public class PublicUrlForService implements Function<Auth, URI> {
|
||||
private final String serviceId;
|
||||
|
||||
public PublicUrlForService(String serviceId) {
|
||||
this.serviceId = checkNotNull(serviceId, "serviceId");
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI apply(Auth arg0) {
|
||||
return Iterables.get(arg0.getServiceCatalog().get(serviceId), 0).getPublicURL();
|
||||
}
|
||||
@ImplementedBy(PublicURLOrInternalIfNull.class)
|
||||
public interface EndpointToSupplierURI extends Function<Endpoint, Supplier<URI>> {
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v1_1.functions;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.openstack.keystone.v1_1.domain.Endpoint;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
|
||||
@Singleton
|
||||
public class PublicURLOrInternalIfNull implements EndpointToSupplierURI {
|
||||
// TODO: check accessibility and prioritize private first
|
||||
@Override
|
||||
public Supplier<URI> apply(Endpoint input) {
|
||||
return Suppliers.ofInstance(input.getPublicURL() != null ? input.getPublicURL() : input.getInternalURL());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "supplyPublicURL()";
|
||||
}
|
||||
}
|
|
@ -18,39 +18,32 @@
|
|||
*/
|
||||
package org.jclouds.openstack.keystone.v1_1.functions;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.openstack.keystone.v1_1.domain.Auth;
|
||||
import org.jclouds.location.Provider;
|
||||
import org.jclouds.openstack.keystone.v1_1.domain.Endpoint;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
import com.google.common.net.InternetDomainName;
|
||||
|
||||
@Singleton
|
||||
public class PublicURLFromAuthResponseForService implements Supplier<URI> {
|
||||
public static interface Factory {
|
||||
PublicURLFromAuthResponseForService create(String service);
|
||||
}
|
||||
|
||||
private final Supplier<Auth> auth;
|
||||
private final String service;
|
||||
public class RegionFirstPartOfDNSNameOrProvider implements EndpointToRegion {
|
||||
private final String provider;
|
||||
|
||||
@Inject
|
||||
public PublicURLFromAuthResponseForService(Supplier<Auth> auth, @Assisted String service) {
|
||||
this.auth = auth;
|
||||
this.service = service;
|
||||
RegionFirstPartOfDNSNameOrProvider(@Provider String provider) {
|
||||
this.provider = provider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI get() {
|
||||
return Iterables.get(auth.get().getServiceCatalog().get(service), 0).getPublicURL();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "getPublicURLForService(" + service + ")";
|
||||
public String apply(Endpoint input) {
|
||||
if (input.getRegion() != null)
|
||||
return input.getRegion();
|
||||
String host = input.getPublicURL().getHost();
|
||||
if (InternetDomainName.isValid(host)) {
|
||||
InternetDomainName domain = InternetDomainName.from(host);
|
||||
return domain.parts().get(0);
|
||||
}
|
||||
return provider;
|
||||
}
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* 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.v1_1.suppliers;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
||||
import org.jclouds.logging.Logger;
|
||||
import org.jclouds.openstack.keystone.v1_1.domain.Auth;
|
||||
import org.jclouds.openstack.keystone.v1_1.domain.Endpoint;
|
||||
import org.jclouds.openstack.keystone.v1_1.functions.EndpointToRegion;
|
||||
import org.jclouds.openstack.keystone.v1_1.functions.EndpointToSupplierURI;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
@Singleton
|
||||
public class RegionIdToURIFromAuthForServiceSupplier implements RegionIdToURISupplier {
|
||||
@Resource
|
||||
protected Logger logger = Logger.NULL;
|
||||
|
||||
private final Supplier<Auth> auth;
|
||||
private final EndpointToSupplierURI endpointToSupplierURI;
|
||||
private final EndpointToRegion endpointToRegion;
|
||||
private final String apiType;
|
||||
private final String apiVersion;
|
||||
|
||||
@Inject
|
||||
public RegionIdToURIFromAuthForServiceSupplier(Supplier<Auth> auth, EndpointToSupplierURI endpointToSupplierURI,
|
||||
EndpointToRegion endpointToRegion, @Assisted("apiType") String apiType,
|
||||
@Assisted("apiVersion") String apiVersion) {
|
||||
this.auth = auth;
|
||||
this.endpointToSupplierURI = endpointToSupplierURI;
|
||||
this.endpointToRegion = endpointToRegion;
|
||||
this.apiType = apiType;
|
||||
this.apiVersion = apiVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<URI>> get() {
|
||||
logger.trace("current version of keystone doesn't allow us to validate the apiVersion %s", apiVersion);
|
||||
Auth authResponse = auth.get();
|
||||
Collection<Endpoint> endpointsForService = authResponse.getServiceCatalog().get(apiType);
|
||||
Map<String, Endpoint> regionIdToEndpoint = Maps.uniqueIndex(endpointsForService, endpointToRegion);
|
||||
return Maps.transformValues(regionIdToEndpoint, endpointToSupplierURI);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "getPublicURLForService(" + apiType + ")";
|
||||
}
|
||||
}
|
|
@ -53,7 +53,7 @@ public interface ServiceAsyncClient {
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/tokens")
|
||||
@MapBinder(BindAuthToJsonPayload.class)
|
||||
ListenableFuture<Access> authenticateTenantWithCredentials(@PayloadParam("tenantId") String tenantId,
|
||||
ListenableFuture<Access> authenticateTenantWithCredentials(@PayloadParam("tenantName") String tenantId,
|
||||
PasswordCredentials passwordCredentials);
|
||||
|
||||
/**
|
||||
|
@ -64,6 +64,8 @@ public interface ServiceAsyncClient {
|
|||
@Consumes(MediaType.APPLICATION_JSON)
|
||||
@Path("/tokens")
|
||||
@MapBinder(BindAuthToJsonPayload.class)
|
||||
ListenableFuture<Access> authenticateTenantWithCredentials(@PayloadParam("tenantId") String tenantId,
|
||||
// TODO: is tenantName permanent? or should we switch to tenantId at some point. seems most tools
|
||||
// still use tenantName
|
||||
ListenableFuture<Access> authenticateTenantWithCredentials(@PayloadParam("tenantName") String tenantId,
|
||||
ApiAccessKeyCredentials apiAccessKeyCredentials);
|
||||
}
|
||||
|
|
|
@ -75,8 +75,10 @@ public class BindAuthToJsonPayload extends BindToJsonPayload implements MapBinde
|
|||
|
||||
Builder<String, Object> builder = ImmutableMap.<String, Object> builder();
|
||||
addCredentialsInArgsOrNull(gRequest, builder);
|
||||
if (Strings.emptyToNull(postParams.get("tenantId")) != null)
|
||||
builder.put("tenantId", postParams.get("tenantId"));
|
||||
// TODO: is tenantName permanent? or should we switch to tenantId at some point. seems most tools
|
||||
// still use tenantName
|
||||
if (Strings.emptyToNull(postParams.get("tenantName")) != null)
|
||||
builder.put("tenantName", postParams.get("tenantName"));
|
||||
return super.bindToRequest(request, ImmutableMap.of("auth", builder.build()));
|
||||
}
|
||||
|
||||
|
|
|
@ -34,14 +34,18 @@ import org.jclouds.http.HttpRetryHandler;
|
|||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.http.annotation.ClientError;
|
||||
import org.jclouds.location.Provider;
|
||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
||||
import org.jclouds.location.suppliers.RegionIdsSupplier;
|
||||
import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet;
|
||||
import org.jclouds.openstack.Authentication;
|
||||
import org.jclouds.openstack.keystone.v2_0.ServiceAsyncClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.ServiceClient;
|
||||
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.functions.PublicURLFromAccessForService;
|
||||
import org.jclouds.openstack.keystone.v2_0.handlers.RetryOnRenew;
|
||||
import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToURIFromAccessForTypeAndVersionSupplier;
|
||||
import org.jclouds.rest.annotations.ApiVersion;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
|
@ -67,7 +71,19 @@ public class KeystoneAuthenticationModule extends AbstractModule {
|
|||
// ServiceClient is used directly for filters and retry handlers, so let's bind it
|
||||
// explicitly
|
||||
bindClientAndAsyncClient(binder(), ServiceClient.class, ServiceAsyncClient.class);
|
||||
install(new FactoryModuleBuilder().build(PublicURLFromAccessForService.Factory.class));
|
||||
install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
|
||||
RegionIdToURIFromAccessForTypeAndVersionSupplier.class).build(RegionIdToURISupplier.Factory.class));
|
||||
// dynamically build the region list as opposed to from properties
|
||||
bind(RegionIdsSupplier.class).to(RegionIdsFromRegionIdToURIKeySet.class);
|
||||
}
|
||||
|
||||
// supply the region to id map from keystone, based on the servicetype and api version in config
|
||||
@Provides
|
||||
@Singleton
|
||||
protected RegionIdToURISupplier provideRegionIdToURISupplierForApiVersion(
|
||||
@Named(KeystoneProperties.SERVICE_TYPE) String serviceType, @ApiVersion String apiVersion,
|
||||
RegionIdToURISupplier.Factory factory) {
|
||||
return factory.createForApiTypeAndVersion(serviceType, apiVersion);
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -18,6 +18,8 @@
|
|||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.config;
|
||||
|
||||
import org.jclouds.openstack.services.ServiceType;
|
||||
|
||||
/**
|
||||
* Configuration properties and constants used in Keystone connections.
|
||||
*
|
||||
|
@ -40,4 +42,15 @@ public interface KeystoneProperties {
|
|||
*/
|
||||
public static final String CREDENTIAL_TYPE = "jclouds.keystone.credential-type";
|
||||
|
||||
/**
|
||||
* version of the keystone service
|
||||
*/
|
||||
public static final String VERSION = "jclouds.keystone.version";
|
||||
|
||||
/**
|
||||
* type of the keystone service. ex. {@code compute}
|
||||
*
|
||||
* @see ServiceType
|
||||
*/
|
||||
public static final String SERVICE_TYPE = "jclouds.keystone.service-type";
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.net.URI;
|
|||
import org.jclouds.javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.ComparisonChain;
|
||||
|
||||
/**
|
||||
* An network-accessible address, usually described by URL, where a service may be accessed. If
|
||||
|
@ -50,16 +51,17 @@ public class Endpoint implements Comparable<Endpoint> {
|
|||
|
||||
public static class Builder {
|
||||
|
||||
protected String id;
|
||||
protected String versionId;
|
||||
protected String region;
|
||||
protected URI publicURL;
|
||||
protected URI internalURL;
|
||||
protected String tenantId;
|
||||
|
||||
/**
|
||||
* @see Endpoint#getId()
|
||||
* @see Endpoint#getVersionId()
|
||||
*/
|
||||
public Builder id(String id) {
|
||||
this.id = checkNotNull(id, "id");
|
||||
public Builder versionId(String versionId) {
|
||||
this.versionId = checkNotNull(versionId, "versionId");
|
||||
return this;
|
||||
}
|
||||
|
||||
|
@ -79,6 +81,14 @@ public class Endpoint implements Comparable<Endpoint> {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Endpoint#getInternalURL()
|
||||
*/
|
||||
public Builder internalURL(URI internalURL) {
|
||||
this.internalURL = checkNotNull(internalURL, "internalURL");
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* @see Endpoint#getTenantId()
|
||||
*/
|
||||
|
@ -88,34 +98,43 @@ public class Endpoint implements Comparable<Endpoint> {
|
|||
}
|
||||
|
||||
public Endpoint build() {
|
||||
return new Endpoint(id, region, publicURL, tenantId);
|
||||
return new Endpoint(versionId, region, publicURL, internalURL, tenantId);
|
||||
}
|
||||
|
||||
public Builder fromEndpoint(Endpoint from) {
|
||||
return id(from.getId()).region(from.getRegion()).publicURL(from.getPublicURL()).tenantId(from.getTenantId());
|
||||
return versionId(from.getVersionId()).region(from.getRegion()).publicURL(from.getPublicURL()).internalURL(
|
||||
from.getInternalURL()).tenantId(from.getTenantId());
|
||||
}
|
||||
}
|
||||
|
||||
protected final String id;
|
||||
// renamed half-way through
|
||||
@Deprecated
|
||||
protected String id;
|
||||
protected final String versionId;
|
||||
protected final String region;
|
||||
protected final URI publicURL;
|
||||
protected final URI internalURL;
|
||||
// renamed half-way through
|
||||
@Deprecated
|
||||
protected String tenantName;
|
||||
protected final String tenantId;
|
||||
|
||||
protected Endpoint(String id, String region, URI publicURL, @Nullable String tenantId) {
|
||||
this.id = checkNotNull(id, "id");
|
||||
protected Endpoint(String versionId, String region, @Nullable URI publicURL, @Nullable URI internalURL,
|
||||
@Nullable String tenantId) {
|
||||
this.versionId = checkNotNull(versionId, "versionId");
|
||||
this.region = checkNotNull(region, "region");
|
||||
this.publicURL = checkNotNull(publicURL, "publicURL");
|
||||
this.publicURL = publicURL;
|
||||
this.internalURL = internalURL;
|
||||
this.tenantId = tenantId;
|
||||
}
|
||||
|
||||
/**
|
||||
* When providing an ID, it is assumed that the endpoint exists in the current OpenStack
|
||||
* When provversionIding an ID, it is assumed that the endpoint exists in the current OpenStack
|
||||
* deployment
|
||||
*
|
||||
* @return the id of the endpoint in the current OpenStack deployment
|
||||
* @return the versionId of the endpoint in the current OpenStack deployment
|
||||
*/
|
||||
public String getId() {
|
||||
return id;
|
||||
public String getVersionId() {
|
||||
return versionId != null ? versionId : id;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,19 +145,27 @@ public class Endpoint implements Comparable<Endpoint> {
|
|||
}
|
||||
|
||||
/**
|
||||
* @return the service id of the endpoint
|
||||
* @return the public url of the endpoint
|
||||
*/
|
||||
|
||||
@Nullable
|
||||
public URI getPublicURL() {
|
||||
return publicURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the tenant id of the endpoint or null
|
||||
* @return the internal url of the endpoint
|
||||
*/
|
||||
@Nullable
|
||||
public URI getInternalURL() {
|
||||
return internalURL;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the tenant versionId of the endpoint or null
|
||||
*/
|
||||
@Nullable
|
||||
public String getTenantId() {
|
||||
return tenantId;
|
||||
return tenantId != null ? tenantId : tenantName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -148,8 +175,8 @@ public class Endpoint implements Comparable<Endpoint> {
|
|||
}
|
||||
if (object instanceof Endpoint) {
|
||||
final Endpoint other = Endpoint.class.cast(object);
|
||||
return equal(id, other.id) && equal(region, other.region) && equal(publicURL, other.publicURL)
|
||||
&& equal(tenantId, other.tenantId);
|
||||
return equal(getVersionId(), other.getVersionId()) && equal(region, other.region) && equal(publicURL, other.publicURL)
|
||||
&& equal(internalURL, other.internalURL) && equal(getTenantId(), other.getTenantId());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -157,22 +184,19 @@ public class Endpoint implements Comparable<Endpoint> {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(id, region, publicURL, tenantId);
|
||||
return Objects.hashCode(getVersionId(), region, publicURL, internalURL, getTenantId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper("").add("id", id).add("region", region).add("publicURL", publicURL).add("tenantId",
|
||||
tenantId).toString();
|
||||
return toStringHelper("").add("versionId", getVersionId()).add("region", region).add("publicURL", publicURL).add("internalURL",
|
||||
internalURL).add("tenantId", getTenantId()).toString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int compareTo(Endpoint that) {
|
||||
if (that == null)
|
||||
return 1;
|
||||
if (this == that)
|
||||
return 0;
|
||||
return this.id.compareTo(that.id);
|
||||
return ComparisonChain.start().compare(this.getTenantId(), that.getTenantId()).compare(this.getVersionId(), that.getVersionId())
|
||||
.compare(this.region, that.region).result();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,6 +26,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import org.jclouds.javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.collect.ComparisonChain;
|
||||
|
||||
/**
|
||||
* A personality that a user assumes when performing a specific set of operations. A role includes a
|
||||
|
@ -99,6 +100,9 @@ public class Role implements Comparable<Role> {
|
|||
protected final String id;
|
||||
protected final String name;
|
||||
protected final String serviceId;
|
||||
// renamed half-way through
|
||||
@Deprecated
|
||||
protected String tenantName;
|
||||
protected final String tenantId;
|
||||
|
||||
protected Role(String id, String name, @Nullable String serviceId, @Nullable String tenantId) {
|
||||
|
@ -137,7 +141,7 @@ public class Role implements Comparable<Role> {
|
|||
*/
|
||||
@Nullable
|
||||
public String getTenantId() {
|
||||
return tenantId;
|
||||
return tenantId != null ? tenantId : tenantName;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -148,7 +152,7 @@ public class Role implements Comparable<Role> {
|
|||
if (object instanceof Role) {
|
||||
final Role other = Role.class.cast(object);
|
||||
return equal(id, other.id) && equal(name, other.name) && equal(serviceId, other.serviceId)
|
||||
&& equal(tenantId, other.tenantId);
|
||||
&& equal(getTenantId(), other.getTenantId());
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
@ -156,22 +160,18 @@ public class Role implements Comparable<Role> {
|
|||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects.hashCode(id, name, serviceId, tenantId);
|
||||
return Objects.hashCode(id, name, serviceId, getTenantId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return toStringHelper("").add("id", id).add("name", name).add("serviceId", serviceId).add("tenantId", tenantId)
|
||||
return toStringHelper("").add("id", id).add("name", name).add("serviceId", serviceId).add("tenantId", getTenantId())
|
||||
.toString();
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public int compareTo(Role that) {
|
||||
if (that == null)
|
||||
return 1;
|
||||
if (this == that)
|
||||
return 0;
|
||||
return this.id.compareTo(that.id);
|
||||
return ComparisonChain.start().compare(this.id, that.id).result();
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -87,7 +87,7 @@ public class Service implements Comparable<Service> {
|
|||
}
|
||||
|
||||
public Builder fromService(Service from) {
|
||||
return type(from.getId()).name(from.getName()).endpoints(from.getEndpoints());
|
||||
return type(from.getType()).name(from.getName()).endpoints(from.getEndpoints());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ public class Service implements Comparable<Service> {
|
|||
*
|
||||
* @return the type of the service in the current OpenStack deployment
|
||||
*/
|
||||
public String getId() {
|
||||
public String getType() {
|
||||
return type;
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,29 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
@ImplementedBy(ReturnRegion.class)
|
||||
public interface EndpointToRegion extends Function<Endpoint, String> {
|
||||
|
||||
}
|
|
@ -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.keystone.v2_0.functions;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.ImplementedBy;
|
||||
|
||||
@ImplementedBy(PublicURLOrInternalIfNull.class)
|
||||
public interface EndpointToSupplierURI extends Function<Endpoint, Supplier<URI>> {
|
||||
}
|
|
@ -1,65 +0,0 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Service;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
@Singleton
|
||||
public class PublicURLFromAccessForService implements Supplier<URI> {
|
||||
public static interface Factory {
|
||||
PublicURLFromAccessForService create(String service);
|
||||
}
|
||||
|
||||
private final Supplier<Access> auth;
|
||||
private final String service;
|
||||
|
||||
@Inject
|
||||
public PublicURLFromAccessForService(Supplier<Access> auth, @Assisted String service) {
|
||||
this.auth = auth;
|
||||
this.service = service;
|
||||
}
|
||||
|
||||
@Override
|
||||
public URI get() {
|
||||
return Iterables.getOnlyElement(Iterables.find(auth.get().getServiceCatalog(), new Predicate<Service>(){
|
||||
|
||||
@Override
|
||||
public boolean apply(Service input) {
|
||||
return input.getId().equals(service);
|
||||
}
|
||||
|
||||
}).getEndpoints()).getPublicURL();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "getPublicURLForService(" + service + ")";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,46 @@
|
|||
/**
|
||||
*
|
||||
* Copyright (C) 2009 Global Cloud Specialists, Inc. <info@globalcloudspecialists.com>
|
||||
*
|
||||
* ====================================================================
|
||||
* Licensed to the Apache Software Foundation (ASF) under one
|
||||
* or more contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. The ASF licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
* ====================================================================
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
|
||||
@Singleton
|
||||
public class PublicURLOrInternalIfNull implements EndpointToSupplierURI {
|
||||
// TODO: check accessibility and prioritize private first
|
||||
@Override
|
||||
public Supplier<URI> apply(Endpoint input) {
|
||||
return Suppliers.ofInstance(input.getPublicURL() != null ? input.getPublicURL() : input.getInternalURL());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "supplyPublicURL()";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
||||
|
||||
@Singleton
|
||||
public class ReturnRegion implements EndpointToRegion {
|
||||
|
||||
@Override
|
||||
public String apply(Endpoint input) {
|
||||
return checkNotNull(input.getRegion(), "no region for endpoint %s", input);
|
||||
}
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/**
|
||||
* 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 java.net.URI;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Service;
|
||||
import org.jclouds.openstack.keystone.v2_0.functions.EndpointToRegion;
|
||||
import org.jclouds.openstack.keystone.v2_0.functions.EndpointToSupplierURI;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
@Singleton
|
||||
public class RegionIdToURIFromAccessForTypeAndVersionSupplier implements RegionIdToURISupplier {
|
||||
private final Supplier<Access> access;
|
||||
private final EndpointToSupplierURI endpointToSupplierURI;
|
||||
private final EndpointToRegion endpointToRegion;
|
||||
private final String apiType;
|
||||
private final String apiVersion;
|
||||
|
||||
@Inject
|
||||
public RegionIdToURIFromAccessForTypeAndVersionSupplier(Supplier<Access> access,
|
||||
EndpointToSupplierURI endpointToSupplierURI, EndpointToRegion endpointToRegion,
|
||||
@Assisted("apiType") String apiType, @Assisted("apiVersion") String apiVersion) {
|
||||
this.access = access;
|
||||
this.endpointToSupplierURI = endpointToSupplierURI;
|
||||
this.endpointToRegion = endpointToRegion;
|
||||
this.apiType = apiType;
|
||||
this.apiVersion = apiVersion;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Map<String, Supplier<URI>> get() {
|
||||
Access accessResponse = access.get();
|
||||
Service service = Iterables.find(accessResponse.getServiceCatalog(), new Predicate<Service>() {
|
||||
|
||||
@Override
|
||||
public boolean apply(Service input) {
|
||||
return input.getType().equals(apiType);
|
||||
}
|
||||
|
||||
});
|
||||
Map<String, Endpoint> regionIdToEndpoint = Maps.uniqueIndex(Iterables.filter(service.getEndpoints(),
|
||||
new Predicate<Endpoint>() {
|
||||
|
||||
@Override
|
||||
public boolean apply(Endpoint input) {
|
||||
return input.getVersionId().equals(apiVersion);
|
||||
}
|
||||
|
||||
}), endpointToRegion);
|
||||
return Maps.transformValues(regionIdToEndpoint, endpointToSupplierURI);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "regionIdToURIFromAccessForTypeAndVersion(" + apiType + ", " + apiVersion + ")";
|
||||
}
|
||||
}
|
|
@ -0,0 +1,48 @@
|
|||
/**
|
||||
* 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.v1_1.functions;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.openstack.keystone.v1_1.domain.Endpoint;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "PublicURLOrInternalIfNullTest")
|
||||
public class PublicURLOrInternalIfNullTest {
|
||||
private final PublicURLOrInternalIfNull fn = new PublicURLOrInternalIfNull();
|
||||
|
||||
public void testPublicURLNotNullReturnsPublicURL() {
|
||||
assertEquals(fn.apply(
|
||||
Endpoint.builder().region("LON").publicURL(
|
||||
URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
|
||||
.v1Default(true).build()).get(), URI
|
||||
.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"));
|
||||
}
|
||||
|
||||
public void testPublicURLNullReturnsInternalURL() {
|
||||
assertEquals(fn.apply(Endpoint.builder().internalURL(URI.create("https://192.168.1.1")).v1Default(true).build())
|
||||
.get(), URI.create("https://192.168.1.1"));
|
||||
}
|
||||
|
||||
}
|
|
@ -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, 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.v1_1.functions;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.openstack.keystone.v1_1.domain.Endpoint;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "RegionFirstPartOfDNSNameOrProviderTest")
|
||||
public class RegionFirstPartOfDNSNameOrProviderTest {
|
||||
private final RegionFirstPartOfDNSNameOrProvider fn = new RegionFirstPartOfDNSNameOrProvider("keystone");
|
||||
|
||||
public void testRegionNotNullReturnsRegion() {
|
||||
assertEquals(fn.apply(Endpoint.builder().region("LON").publicURL(
|
||||
URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
|
||||
.v1Default(true).build()), "LON");
|
||||
}
|
||||
|
||||
public void testRegionNullReturnsFirstPartOfHostWhenValid() {
|
||||
assertEquals(fn.apply(Endpoint.builder().publicURL(
|
||||
URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
|
||||
.v1Default(true).build()), "cdn3");
|
||||
}
|
||||
|
||||
public void testRegionNullReturnsProvioderWhenHostNotValid() {
|
||||
assertEquals(fn.apply(Endpoint.builder().publicURL(URI.create("https://1.1.1.4")).v1Default(true).build()),
|
||||
"keystone");
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,75 @@
|
|||
/**
|
||||
* 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.v1_1.suppliers;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.location.Provider;
|
||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
||||
import org.jclouds.openstack.keystone.v1_1.domain.Auth;
|
||||
import org.jclouds.openstack.keystone.v1_1.parse.ParseAuthTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "RegionIdToURIFromAuthForServiceSupplierTest")
|
||||
public class RegionIdToURIFromAuthForServiceSupplierTest {
|
||||
private final RegionIdToURISupplier.Factory factory = Guice.createInjector(new AbstractModule() {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bindConstant().annotatedWith(Provider.class).to("keystone");
|
||||
install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
|
||||
RegionIdToURIFromAuthForServiceSupplier.class).build(RegionIdToURISupplier.Factory.class));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Provides
|
||||
@Singleton
|
||||
public Supplier<Auth> provide() {
|
||||
return Suppliers.ofInstance(new ParseAuthTest().expected());
|
||||
}
|
||||
}).getInstance(RegionIdToURISupplier.Factory.class);
|
||||
|
||||
public void testRegionMatches() {
|
||||
assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("cloudFilesCDN", "1.0").get(), Suppliers
|
||||
.<URI> supplierFunction()), ImmutableMap.of("LON", URI
|
||||
.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953")));
|
||||
}
|
||||
|
||||
public void testTakesFirstPartOfDNSWhenNoRegion() {
|
||||
assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("cloudServers", "1.1").get(), Suppliers
|
||||
.<URI> supplierFunction()), ImmutableMap.of("lon", URI
|
||||
.create("https://lon.servers.api.rackspacecloud.com/v1.0/10001786")));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,51 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "PublicURLOrInternalIfNullTest")
|
||||
public class PublicURLOrInternalIfNullTest {
|
||||
private final PublicURLOrInternalIfNull fn = new PublicURLOrInternalIfNull();
|
||||
|
||||
public void testPublicURLNotNullReturnsPublicURL() {
|
||||
assertEquals(fn.apply(
|
||||
Endpoint.builder().region("LON").versionId("1.0").publicURL(
|
||||
URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
|
||||
.build()).get(), URI
|
||||
.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"));
|
||||
}
|
||||
|
||||
public void testPublicURLNullReturnsInternalURL() {
|
||||
assertEquals(fn
|
||||
.apply(
|
||||
Endpoint.builder().region("lon").versionId("1.0")
|
||||
.internalURL(URI.create("https://192.168.1.1")).build()).get(), URI
|
||||
.create("https://192.168.1.1"));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,53 @@
|
|||
/**
|
||||
* 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;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "ReturnRegionTest")
|
||||
public class ReturnRegionTest {
|
||||
private final ReturnRegion fn = new ReturnRegion();
|
||||
|
||||
public void testRegionNotNullReturnsRegion() {
|
||||
assertEquals(
|
||||
fn.apply(Endpoint.builder().region("LON").versionId("1.0").publicURL(
|
||||
URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
|
||||
.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");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -17,15 +17,18 @@
|
|||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.internal;
|
||||
|
||||
import static java.lang.String.format;
|
||||
import static org.jclouds.rest.BaseRestClientExpectTest.payloadFromStringWithContentType;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneAuthenticationModule;
|
||||
import org.jclouds.rest.BaseRestClientExpectTest;
|
||||
import org.jclouds.io.Payload;
|
||||
import org.jclouds.util.Strings2;
|
||||
|
||||
import com.google.common.base.Throwables;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.net.HttpHeaders;
|
||||
|
||||
|
@ -34,13 +37,15 @@ import com.google.common.net.HttpHeaders;
|
|||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class BaseKeystoneRestClientExpectTest<S> extends BaseRestClientExpectTest<S> {
|
||||
public enum KeystoneFixture {
|
||||
INSTANCE;
|
||||
|
||||
protected static final String tenantId = "12346637803162";
|
||||
public String getTenantName(){
|
||||
return "12346637803162";
|
||||
}
|
||||
|
||||
protected static final String username = "user@jclouds.org";
|
||||
protected static final String password = "Password1234";
|
||||
protected static final HttpRequest initialAuthWithPasswordCredentials = HttpRequest
|
||||
public HttpRequest initialAuthWithUsernameAndPassword(String username, String password){
|
||||
return HttpRequest
|
||||
.builder()
|
||||
.method("POST")
|
||||
.endpoint(URI.create("http://localhost:5000/v2.0/tokens"))
|
||||
|
@ -48,12 +53,12 @@ public class BaseKeystoneRestClientExpectTest<S> extends BaseRestClientExpectTes
|
|||
.payload(
|
||||
payloadFromStringWithContentType(
|
||||
format(
|
||||
"{\"auth\":{\"passwordCredentials\":{\"username\":\"%s\",\"password\":\"%s\"},\"tenantId\":\"%s\"}}",
|
||||
username, password, tenantId), "application/json")).build();
|
||||
|
||||
protected static final String accessKey = "FH6FU8GMZFLKP5BUR2X1";
|
||||
protected static final String secretKey = "G4QWed0lh5SH7kBrcvOM1cHygKWk81EBt+Hr1dsl";
|
||||
protected static final HttpRequest initialAuthWithApiAccessKeyCredentials = HttpRequest
|
||||
"{\"auth\":{\"passwordCredentials\":{\"username\":\"%s\",\"password\":\"%s\"},\"tenantName\":\"%s\"}}",
|
||||
username, password, getTenantName()), "application/json")).build();
|
||||
}
|
||||
|
||||
public HttpRequest initialAuthWithAccessKeyAndSecretKey(String accessKey, String secretKey){
|
||||
return HttpRequest
|
||||
.builder()
|
||||
.method("POST")
|
||||
.endpoint(URI.create("http://localhost:5000/v2.0/tokens"))
|
||||
|
@ -61,30 +66,27 @@ public class BaseKeystoneRestClientExpectTest<S> extends BaseRestClientExpectTes
|
|||
.payload(
|
||||
payloadFromStringWithContentType(
|
||||
format(
|
||||
"{\"auth\":{\"apiAccessKeyCredentials\":{\"accessKey\":\"%s\",\"secretKey\":\"%s\"},\"tenantId\":\"%s\"}}",
|
||||
accessKey, secretKey, tenantId), "application/json")).build();
|
||||
"{\"auth\":{\"apiAccessKeyCredentials\":{\"accessKey\":\"%s\",\"secretKey\":\"%s\"},\"tenantName\":\"%s\"}}",
|
||||
accessKey, secretKey, getTenantName()), "application/json")).build();
|
||||
}
|
||||
|
||||
public BaseKeystoneRestClientExpectTest() {
|
||||
identity = tenantId + ":" + accessKey;
|
||||
credential = secretKey;
|
||||
public String getAuthToken(){
|
||||
return "Auth_4f173437e4b013bee56d1007";
|
||||
}
|
||||
|
||||
public HttpResponse responseWithAccess(){
|
||||
return HttpResponse.builder().statusCode(200).message("HTTP/1.1 200").payload(
|
||||
payloadFromResourceWithContentType("/keystoneAuthResponse.json", "application/json")).build();
|
||||
}
|
||||
|
||||
|
||||
protected String authToken = "Auth_4f173437e4b013bee56d1007";
|
||||
|
||||
protected HttpResponse responseWithAccess = HttpResponse.builder().statusCode(200).message("HTTP/1.1 200").payload(
|
||||
payloadFromResourceWithContentType("/keystoneAuthResponse.json", "application/json")).build();
|
||||
|
||||
|
||||
/**
|
||||
* in case you need to override anything
|
||||
*/
|
||||
public static class TestKeystoneAuthenticationModule extends KeystoneAuthenticationModule {
|
||||
@Override
|
||||
protected void configure() {
|
||||
super.configure();
|
||||
public Payload payloadFromResourceWithContentType(String resource, String contentType) {
|
||||
try {
|
||||
return payloadFromStringWithContentType(Strings2.toStringAndClose(getClass().getResourceAsStream(resource)),
|
||||
contentType);
|
||||
} catch (IOException e) {
|
||||
throw Throwables.propagate(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -63,23 +63,28 @@ public class ParseAccessTest extends BaseItemParserTest<Access> {
|
|||
Role.builder().id("00000000004004").serviceId("100").name("domainuser").build(),
|
||||
Role.builder().id("00000000004016").serviceId("120").name("netadmin")
|
||||
.tenantId("40806637803162").build()).build()).serviceCatalog(
|
||||
|
||||
Service.builder().name("Object Storage").type("object-store").endpoints(
|
||||
Endpoint.builder().tenantId("40806637803162").publicURL(
|
||||
URI.create("https://objects.jclouds.org/v1.0/40806637803162"))
|
||||
.region("region-a.geo-1").id("1.0").build()).build(),
|
||||
.region("region-a.geo-1").versionId("1.0").build()).build(),
|
||||
|
||||
Service.builder().name("Identity").type("identity").endpoints(
|
||||
Endpoint.builder().publicURL(URI.create("https://csnode.jclouds.org/v2.0/")).region(
|
||||
"region-a.geo-1").id("2.0").build()).build(),
|
||||
Service.builder()
|
||||
"region-a.geo-1").versionId("2.0").build()).build(),
|
||||
|
||||
.name("Image Management").type("image").endpoints(
|
||||
Service.builder().name("Image Management").type("image").endpoints(
|
||||
Endpoint.builder().tenantId("40806637803162").publicURL(
|
||||
URI.create("https://glance.jclouds.org:9292/v1.0")).region("az-1.region-a.geo-1").id(
|
||||
"1.0").build()).build(),
|
||||
Service.builder().name("Compute").type("compute").endpoints(
|
||||
Endpoint.builder().tenantId("40806637803162").publicURL(
|
||||
URI.create("http://compute-1.jclouds.org:8774/v1.1/40806637803162")).region(
|
||||
"az-1.region-a.geo-1").id("1.1").build()).build()).build();
|
||||
URI.create("https://glance.jclouds.org:9292/v1.0")).region("az-1.region-a.geo-1")
|
||||
.versionId("1.0").build()).build(),
|
||||
|
||||
Service.builder().name("Cloud Servers").type("compute").endpoints(
|
||||
Endpoint.builder().tenantId("1").publicURL(URI.create("https://compute.north.host/v1/1234"))
|
||||
.internalURL(URI.create("https://compute.north.host/v1/1234")).region("North")
|
||||
.versionId("1.0").build(),
|
||||
Endpoint.builder().tenantId("2").publicURL(URI.create("https://compute.north.host/v1.1/3456"))
|
||||
.internalURL(URI.create("https://compute.north.host/v1.1/3456")).region("North")
|
||||
.versionId("1.1").build()).build()).build();
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,69 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.suppliers;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.location.suppliers.RegionIdToURISupplier;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.Access;
|
||||
import org.jclouds.openstack.keystone.v2_0.parse.ParseAccessTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Guice;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.assistedinject.FactoryModuleBuilder;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
@Test(groups = "unit", testName = "RegionIdToURIFromAccessForTypeAndVersionSupplierTest")
|
||||
public class RegionIdToURIFromAccessForTypeAndVersionSupplierTest {
|
||||
private final RegionIdToURISupplier.Factory factory = Guice.createInjector(new AbstractModule() {
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
|
||||
RegionIdToURIFromAccessForTypeAndVersionSupplier.class).build(RegionIdToURISupplier.Factory.class));
|
||||
}
|
||||
|
||||
@SuppressWarnings("unused")
|
||||
@Provides
|
||||
@Singleton
|
||||
public Supplier<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("North", URI.create("https://compute.north.host/v1/1234")));
|
||||
assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.1").get(), Suppliers
|
||||
.<URI> supplierFunction()), ImmutableMap.of("North", URI.create("https://compute.north.host/v1.1/3456")));
|
||||
}
|
||||
|
||||
}
|
|
@ -16,13 +16,13 @@
|
|||
"id": "00000000004022",
|
||||
"serviceId": "110",
|
||||
"name": "Admin",
|
||||
"tenantId": "40806637803162"
|
||||
"tenantName": "40806637803162"
|
||||
},
|
||||
{
|
||||
"id": "00000000004024",
|
||||
"serviceId": "140",
|
||||
"name": "user",
|
||||
"tenantId": "40806637803162"
|
||||
"tenantName": "40806637803162"
|
||||
},
|
||||
{
|
||||
"id": "00000000004004",
|
||||
|
@ -33,7 +33,7 @@
|
|||
"id": "00000000004016",
|
||||
"serviceId": "120",
|
||||
"name": "netadmin",
|
||||
"tenantId": "40806637803162"
|
||||
"tenantName": "40806637803162"
|
||||
}
|
||||
]
|
||||
},
|
||||
|
@ -43,7 +43,7 @@
|
|||
"type": "object-store",
|
||||
"endpoints": [
|
||||
{
|
||||
"tenantId": "40806637803162",
|
||||
"tenantName": "40806637803162",
|
||||
"adminURL": "https://objects.jclouds.org/v1.0/",
|
||||
"publicURL": "https://objects.jclouds.org/v1.0/40806637803162",
|
||||
"region": "region-a.geo-1",
|
||||
|
@ -68,7 +68,7 @@
|
|||
"type": "image",
|
||||
"endpoints": [
|
||||
{
|
||||
"tenantId": "40806637803162",
|
||||
"tenantName": "40806637803162",
|
||||
"publicURL": "https://glance.jclouds.org:9292/v1.0",
|
||||
"region": "az-1.region-a.geo-1",
|
||||
"id": "1.0"
|
||||
|
@ -76,17 +76,28 @@
|
|||
]
|
||||
},
|
||||
{
|
||||
"name": "Compute",
|
||||
"type": "compute",
|
||||
"endpoints": [
|
||||
"name":"Cloud Servers",
|
||||
"type":"compute",
|
||||
"endpoints":[{
|
||||
"tenantId":"1",
|
||||
"publicURL":"https://compute.north.host/v1/1234",
|
||||
"internalURL":"https://compute.north.host/v1/1234",
|
||||
"region":"North",
|
||||
"versionId":"1.0",
|
||||
"versionInfo":"https://compute.north.host/v1.0/",
|
||||
"versionList":"https://compute.north.host/"
|
||||
},
|
||||
{
|
||||
"tenantId": "40806637803162",
|
||||
"publicURL": "http://compute-1.jclouds.org:8774/v1.1/40806637803162",
|
||||
"region": "az-1.region-a.geo-1",
|
||||
"id": "1.1",
|
||||
"list": "http://compute-1.jclouds.org:8774"
|
||||
"tenantId":"2",
|
||||
"publicURL":"https://compute.north.host/v1.1/3456",
|
||||
"internalURL":"https://compute.north.host/v1.1/3456",
|
||||
"region":"North",
|
||||
"versionId":"1.1",
|
||||
"versionInfo":"https://compute.north.host/v1.1/",
|
||||
"versionList":"https://compute.north.host/"
|
||||
}
|
||||
]
|
||||
],
|
||||
"endpoints_links":[]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -25,6 +25,7 @@ import org.jclouds.location.suppliers.fromconfig.RegionIdToURIFromConfigurationO
|
|||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.ImplementedBy;
|
||||
import com.google.inject.assistedinject.Assisted;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -33,5 +34,18 @@ import com.google.inject.ImplementedBy;
|
|||
*/
|
||||
@ImplementedBy(RegionIdToURIFromConfigurationOrDefaultToProvider.class)
|
||||
public interface RegionIdToURISupplier extends Supplier<Map<String, Supplier<URI>>> {
|
||||
static interface Factory {
|
||||
/**
|
||||
*
|
||||
* @param apiType
|
||||
* type of the api, according to the provider. ex. {@code compute} {@code
|
||||
* object-store}
|
||||
* @param apiVersion
|
||||
* version of the api
|
||||
* @return regions mapped to default uri
|
||||
*/
|
||||
RegionIdToURISupplier createForApiTypeAndVersion(@Assisted("apiType") String apiType,
|
||||
@Assisted("apiVersion") String apiVersion);
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,50 @@
|
|||
/**
|
||||
* 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.location.suppliers.derived;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.location.Region;
|
||||
import org.jclouds.location.suppliers.RegionIdsSupplier;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
* as opposed to via properties, lets look up regions via api, as they are more likely to change
|
||||
*/
|
||||
@Singleton
|
||||
public class RegionIdsFromRegionIdToURIKeySet implements RegionIdsSupplier {
|
||||
|
||||
private final Supplier<Map<String, Supplier<URI>>> regionIdToURISupplier;
|
||||
|
||||
@Inject
|
||||
protected RegionIdsFromRegionIdToURIKeySet(@Region Supplier<Map<String, Supplier<URI>>> regionIdToURISupplier) {
|
||||
this.regionIdToURISupplier = regionIdToURISupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> get() {
|
||||
return regionIdToURISupplier.get().keySet();
|
||||
}
|
||||
}
|
|
@ -0,0 +1,57 @@
|
|||
/**
|
||||
* 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.location.suppliers.derived;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.location.Zone;
|
||||
import org.jclouds.location.suppliers.ZoneIdsSupplier;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* as opposed to via properties, lets look up zones via api, as they are more likely to change
|
||||
*/
|
||||
@Singleton
|
||||
public class ZoneIdsFromRegionIdToZoneIdsValues implements ZoneIdsSupplier {
|
||||
|
||||
private final Supplier<Map<String, Supplier<Set<String>>>> regionIdToZoneIdsSupplier;
|
||||
|
||||
@Inject
|
||||
protected ZoneIdsFromRegionIdToZoneIdsValues(
|
||||
@Zone Supplier<Map<String, Supplier<Set<String>>>> regionIdToZoneIdsSupplier) {
|
||||
this.regionIdToZoneIdsSupplier = regionIdToZoneIdsSupplier;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Set<String> get() {
|
||||
Collection<Supplier<Set<String>>> zones = regionIdToZoneIdsSupplier.get().values();
|
||||
return ImmutableSet.copyOf(Iterables.concat(Iterables.transform(zones, Suppliers
|
||||
.<Set<String>> supplierFunction())));
|
||||
}
|
||||
|
||||
}
|
|
@ -18,10 +18,10 @@
|
|||
*/
|
||||
package org.jclouds.rest.internal;
|
||||
|
||||
|
||||
import java.lang.annotation.Annotation;
|
||||
import java.lang.reflect.InvocationHandler;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
|
@ -45,38 +45,38 @@ import org.jclouds.util.Throwables2;
|
|||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.util.concurrent.Futures;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import com.google.inject.Binding;
|
||||
import com.google.inject.Inject;
|
||||
import com.google.inject.Injector;
|
||||
import com.google.inject.Key;
|
||||
import com.google.inject.Provides;
|
||||
import com.google.inject.ProvisionException;
|
||||
import com.google.inject.TypeLiteral;
|
||||
import com.google.inject.util.Types;
|
||||
|
||||
/**
|
||||
* Generates RESTful clients from appropriately annotated interfaces.
|
||||
* <p/>
|
||||
* Particularly, this code delegates calls to other things.
|
||||
* <ol>
|
||||
* <li>if the method has a {@link Provides} annotation, it responds via a
|
||||
* {@link Injector} lookup</li>
|
||||
* <li>if the method has a {@link Delegate} annotation, it responds with an
|
||||
* instance of interface set in returnVal, adding the current JAXrs annotations
|
||||
* to whatever are on that class.</li>
|
||||
* <li>if the method has a {@link Provides} annotation, it responds via a {@link Injector} lookup</li>
|
||||
* <li>if the method has a {@link Delegate} annotation, it responds with an instance of interface
|
||||
* set in returnVal, adding the current JAXrs annotations to whatever are on that class.</li>
|
||||
* <ul>
|
||||
* <li>ex. if the method with {@link Delegate} has a {@link Path} annotation,
|
||||
* and the returnval interface also has {@link Path}, these values are combined.
|
||||
* </li>
|
||||
* <li>ex. if the method with {@link Delegate} has a {@link Path} annotation, and the returnval
|
||||
* interface also has {@link Path}, these values are combined.</li>
|
||||
* </ul>
|
||||
* <li>if {@link RestAnnotationProcessor#delegationMap} contains a mapping for
|
||||
* this, and the returnVal is properly assigned as a {@link ListenableFuture},
|
||||
* it responds with an http implementation.</li>
|
||||
* <li>otherwise a RuntimeException is thrown with a message including:
|
||||
* {@code method is intended solely to set constants}</li>
|
||||
* <li>if {@link RestAnnotationProcessor#delegationMap} contains a mapping for this, and the
|
||||
* returnVal is properly assigned as a {@link ListenableFuture}, it responds with an http
|
||||
* implementation.</li>
|
||||
* <li>otherwise a RuntimeException is thrown with a message including: {@code method is intended
|
||||
* solely to set constants}</li>
|
||||
* </ol>
|
||||
*
|
||||
* @author Adrian Cole
|
||||
|
@ -133,7 +133,8 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
|
|||
} else if (isRestCall(method)) {
|
||||
return createListenableFutureForHttpRequestMappedToMethodAndArgs(method, args);
|
||||
} else {
|
||||
throw new RuntimeException(String.format("Method is not annotated as either http or provider method: %s", method));
|
||||
throw new RuntimeException(String.format("Method is not annotated as either http or provider method: %s",
|
||||
method));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -148,11 +149,18 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
|
|||
|
||||
public Object lookupValueFromGuice(Method method) {
|
||||
try {
|
||||
Type genericReturnType = method.getGenericReturnType();
|
||||
try {
|
||||
Annotation qualifier = Iterables.find(ImmutableList.copyOf(method.getAnnotations()), isQualifierPresent);
|
||||
return injector.getInstance(Key.get(method.getGenericReturnType(), qualifier));
|
||||
Binding<?> binding = injector.getExistingBinding(Key.get(genericReturnType, qualifier));
|
||||
if (binding != null)
|
||||
return binding.getProvider().get();
|
||||
// try looking via supplier
|
||||
return Supplier.class.cast(
|
||||
injector.getInstance(Key.get(Types.newParameterizedType(Supplier.class, genericReturnType),
|
||||
qualifier))).get();
|
||||
} catch (NoSuchElementException e) {
|
||||
return injector.getInstance(Key.get(method.getGenericReturnType()));
|
||||
return injector.getInstance(Key.get(genericReturnType));
|
||||
}
|
||||
} catch (ProvisionException e) {
|
||||
AuthorizationException aex = Throwables2.getFirstThrowableOfType(e, AuthorizationException.class);
|
||||
|
@ -163,7 +171,8 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
|
|||
}
|
||||
|
||||
@SuppressWarnings( { "unchecked", "rawtypes" })
|
||||
private ListenableFuture<?> createListenableFutureForHttpRequestMappedToMethodAndArgs(Method method, Object[] args) throws ExecutionException {
|
||||
private ListenableFuture<?> createListenableFutureForHttpRequestMappedToMethodAndArgs(Method method, Object[] args)
|
||||
throws ExecutionException {
|
||||
method = annotationProcessor.getDelegateOrNull(method);
|
||||
logger.trace("Converting %s.%s", declaring.getSimpleName(), method.getName());
|
||||
Function<Exception, ?> exceptionParser = annotationProcessor
|
||||
|
|
|
@ -734,7 +734,7 @@ public class RestAnnotationProcessor<T> {
|
|||
String.format("endpoint for [%s] not configured for %s", args[index], method));
|
||||
return returnVal;
|
||||
} catch (NullPointerException e) {
|
||||
throw new IllegalArgumentException(String.format("argument at index %d on method %s", index, method), e);
|
||||
throw new IllegalArgumentException(String.format("argument at index %d on method %s was null", index, method), e);
|
||||
}
|
||||
} else {
|
||||
SortedSet<Integer> keys = newTreeSet(map.keySet());
|
||||
|
|
|
@ -23,6 +23,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
|||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
|
@ -30,6 +31,7 @@ import com.google.common.base.Function;
|
|||
import com.google.common.base.Preconditions;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.io.OutputSupplier;
|
||||
|
||||
/**
|
||||
|
@ -38,6 +40,21 @@ import com.google.common.io.OutputSupplier;
|
|||
*/
|
||||
public class Suppliers2 {
|
||||
|
||||
public static <K, V> Supplier<V> getLastValueInMap(Supplier<Map<K, Supplier<V>>> input) {
|
||||
return Suppliers.compose(new Function<Map<K, Supplier<V>>, V>() {
|
||||
|
||||
@Override
|
||||
public V apply(Map<K, Supplier<V>> input) {
|
||||
return Iterables.getLast(input.values()).get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "getLastValueInMap()";
|
||||
}
|
||||
}, input);
|
||||
}
|
||||
|
||||
public static <X> Function<X, Supplier<X>> ofInstanceFunction() {
|
||||
return new Function<X, Supplier<X>>(){
|
||||
|
||||
|
|
|
@ -201,7 +201,12 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
@Endpoint(Localhost2.class)
|
||||
@Timeout(duration = 10, timeUnit = TimeUnit.NANOSECONDS)
|
||||
public static interface Caller {
|
||||
|
||||
|
||||
// tests that we can pull from suppliers
|
||||
@Provides
|
||||
@Localhost2
|
||||
URI getURI();
|
||||
|
||||
@Delegate
|
||||
public Callee getCallee();
|
||||
|
||||
|
@ -216,7 +221,10 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
}
|
||||
|
||||
public static interface AsyncCaller {
|
||||
|
||||
@Provides
|
||||
@Localhost2
|
||||
URI getURI();
|
||||
|
||||
@Delegate
|
||||
public AsyncCallee getCallee();
|
||||
|
||||
|
@ -267,6 +275,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
}
|
||||
|
||||
child.getInstance(Caller.class).getCallee().onePath("foo");
|
||||
child.getInstance(Caller.class).getCallee().onePath("foo");
|
||||
|
||||
}
|
||||
|
||||
|
@ -292,6 +301,8 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
|
||||
child.getInstance(AsyncCaller.class).getCallee(URI.create("http://howdyboys")).onePath("foo").get();
|
||||
|
||||
assertEquals(child.getInstance(AsyncCaller.class).getURI(), URI.create("http://localhost:1111"));
|
||||
|
||||
}
|
||||
|
||||
public void testDelegateIsLazyLoadedAndRequestIncludesEndpointVersionAndPath() throws InterruptedException, ExecutionException {
|
||||
|
@ -313,7 +324,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
|||
|
||||
}
|
||||
|
||||
child.getInstance(Caller.class).getCallee(URI.create("http://howdyboys")).onePath("foo");
|
||||
assertEquals(child.getInstance(Caller.class).getURI(), URI.create("http://localhost:1111"));
|
||||
|
||||
}
|
||||
|
||||
|
|
|
@ -28,6 +28,7 @@ import java.io.IOException;
|
|||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
import java.util.Map;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.TimeoutException;
|
||||
import java.util.concurrent.atomic.AtomicInteger;
|
||||
|
@ -37,9 +38,24 @@ import org.testng.annotations.Test;
|
|||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
|
||||
public class Suppliers2Test {
|
||||
|
||||
@Test
|
||||
public void testGetLastValueInMap() {
|
||||
assertEquals(Suppliers2
|
||||
.<String, String> getLastValueInMap(
|
||||
Suppliers.<Map<String, Supplier<String>>> ofInstance(ImmutableMap.of("foo", Suppliers
|
||||
.ofInstance("bar")))).get(), "bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testOfInstanceFunction() {
|
||||
assertEquals(Suppliers2.ofInstanceFunction().apply("foo").get(), "foo");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMemoizeKeepsValueForFullDurationWhenDelegateCallIsSlow() {
|
||||
final long SLEEP_TIME = 250;
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
<!-- keystone endpoint -->
|
||||
<test.openstack-nova.endpoint>http://localhost:5000</test.openstack-nova.endpoint>
|
||||
<!-- keystone version -->
|
||||
<test.openstack-nova.api-version>2.0</test.openstack-nova.api-version>
|
||||
<test.openstack-nova.api-version>1.1</test.openstack-nova.api-version>
|
||||
<test.openstack-nova.build-version></test.openstack-nova.build-version>
|
||||
<test.openstack-nova.identity>FIXME_IDENTITY</test.openstack-nova.identity>
|
||||
<test.openstack-nova.credential>FIXME_CREDENTIALS</test.openstack-nova.credential>
|
||||
|
|
|
@ -18,8 +18,16 @@
|
|||
*/
|
||||
package org.jclouds.openstack.nova.v1_1;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.location.Region;
|
||||
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
|
||||
import org.jclouds.openstack.nova.v1_1.features.ServerAsyncClient;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Nova via their REST API.
|
||||
|
@ -31,10 +39,19 @@ import org.jclouds.rest.annotations.Delegate;
|
|||
*/
|
||||
public interface NovaAsyncClient {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the region codes configured
|
||||
*/
|
||||
@Provides
|
||||
@Region
|
||||
Set<String> getConfiguredRegions();
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Server features.
|
||||
*/
|
||||
@Delegate
|
||||
ServerAsyncClient getServerClient();
|
||||
ServerAsyncClient getServerClientForRegion(
|
||||
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
|
||||
|
||||
}
|
||||
|
|
|
@ -18,11 +18,18 @@
|
|||
*/
|
||||
package org.jclouds.openstack.nova.v1_1;
|
||||
|
||||
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.RegionToEndpointOrProviderIfNull;
|
||||
import org.jclouds.openstack.nova.v1_1.features.ServerClient;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Nova.
|
||||
|
@ -34,11 +41,19 @@ import org.jclouds.rest.annotations.Delegate;
|
|||
*/
|
||||
@Timeout(duration = 60, timeUnit = TimeUnit.SECONDS)
|
||||
public interface NovaClient {
|
||||
|
||||
/**
|
||||
*
|
||||
* @return the region codes configured
|
||||
*/
|
||||
@Provides
|
||||
@Region
|
||||
Set<String> getConfiguredRegions();
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Server features.
|
||||
*/
|
||||
@Delegate
|
||||
ServerClient getServerClient();
|
||||
ServerClient getServerClientForRegion(
|
||||
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
|
||||
|
||||
}
|
||||
|
|
|
@ -24,6 +24,8 @@ import static org.jclouds.Constants.PROPERTY_ENDPOINT;
|
|||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.PropertiesBuilder;
|
||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
||||
import org.jclouds.openstack.services.ServiceType;
|
||||
|
||||
/**
|
||||
* Builds properties used in Nova Clients
|
||||
|
@ -34,9 +36,11 @@ public class NovaPropertiesBuilder extends PropertiesBuilder {
|
|||
@Override
|
||||
protected Properties defaultProperties() {
|
||||
Properties properties = super.defaultProperties();
|
||||
// TODO: keystone
|
||||
properties.setProperty(PROPERTY_ENDPOINT, "http://localhost:5000");
|
||||
properties.setProperty(PROPERTY_API_VERSION, "2.0");
|
||||
properties.setProperty(KeystoneProperties.SERVICE_TYPE, ServiceType.COMPUTE);
|
||||
// TODO: this doesn't actually do anything yet.
|
||||
properties.setProperty(KeystoneProperties.VERSION, "2.0");
|
||||
properties.setProperty(PROPERTY_API_VERSION, "1.1");
|
||||
return properties;
|
||||
}
|
||||
|
||||
|
|
|
@ -18,31 +18,23 @@
|
|||
*/
|
||||
package org.jclouds.openstack.nova.v1_1.config;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.http.HttpErrorHandler;
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
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.config.KeystoneAuthenticationModule;
|
||||
import org.jclouds.openstack.keystone.v2_0.functions.PublicURLFromAccessForService;
|
||||
import org.jclouds.openstack.nova.v1_1.NovaAsyncClient;
|
||||
import org.jclouds.openstack.nova.v1_1.NovaClient;
|
||||
import org.jclouds.openstack.nova.v1_1.features.ServerAsyncClient;
|
||||
import org.jclouds.openstack.nova.v1_1.features.ServerClient;
|
||||
import org.jclouds.openstack.nova.v1_1.handlers.NovaErrorHandler;
|
||||
import org.jclouds.openstack.services.Compute;
|
||||
import org.jclouds.openstack.services.ServiceType;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.config.RestClientModule;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Configures the Nova connection.
|
||||
|
@ -57,35 +49,29 @@ public class NovaRestClientModule extends RestClientModule<NovaClient, NovaAsync
|
|||
.put(ServerClient.class, ServerAsyncClient.class)//
|
||||
.build();
|
||||
|
||||
private final KeystoneAuthenticationModule authModule;
|
||||
|
||||
public NovaRestClientModule() {
|
||||
this(new KeystoneAuthenticationModule());
|
||||
}
|
||||
|
||||
public NovaRestClientModule(KeystoneAuthenticationModule authModule) {
|
||||
super(NovaClient.class, NovaAsyncClient.class, DELEGATE_MAP);
|
||||
this.authModule = authModule;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
install(authModule);
|
||||
install(new NovaParserModule());
|
||||
super.configure();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void installLocations() {
|
||||
super.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(new KeystoneAuthenticationModule());
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindErrorHandlers() {
|
||||
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(NovaErrorHandler.class);
|
||||
bind(HttpErrorHandler.class).annotatedWith(ClientError.class).to(NovaErrorHandler.class);
|
||||
bind(HttpErrorHandler.class).annotatedWith(ServerError.class).to(NovaErrorHandler.class);
|
||||
}
|
||||
@Provides
|
||||
@Singleton
|
||||
@Compute
|
||||
protected Supplier<URI> provideServerUrl(PublicURLFromAccessForService.Factory factory) {
|
||||
return factory.create(ServiceType.COMPUTE);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -29,8 +29,6 @@ import javax.ws.rs.core.MediaType;
|
|||
import org.jclouds.openstack.domain.Resource;
|
||||
import org.jclouds.openstack.filters.AuthenticateRequest;
|
||||
import org.jclouds.openstack.nova.v1_1.domain.Server;
|
||||
import org.jclouds.openstack.services.Compute;
|
||||
import org.jclouds.rest.annotations.Endpoint;
|
||||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.SelectJson;
|
||||
|
@ -51,7 +49,6 @@ import com.google.common.util.concurrent.ListenableFuture;
|
|||
*/
|
||||
@SkipEncoding({ '/', '=' })
|
||||
@RequestFilters(AuthenticateRequest.class)
|
||||
@Endpoint(Compute.class)
|
||||
public interface ServerAsyncClient {
|
||||
|
||||
/**
|
||||
|
|
|
@ -25,12 +25,13 @@ import java.util.Properties;
|
|||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.openstack.nova.v1_1.features.ServerClient;
|
||||
import org.jclouds.openstack.keystone.v2_0.config.KeystoneProperties;
|
||||
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaRestClientExpectTest;
|
||||
import org.jclouds.openstack.nova.v1_1.parse.ParseServerListTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
*
|
||||
|
@ -40,12 +41,6 @@ import com.google.common.collect.ImmutableMultimap;
|
|||
@Test(groups = "unit", testName = "PasswordAuthenticationExpectTest")
|
||||
public class PasswordAuthenticationExpectTest extends BaseNovaRestClientExpectTest {
|
||||
|
||||
public PasswordAuthenticationExpectTest() {
|
||||
provider = "openstack-nova";
|
||||
identity = tenantId + ":" + username;
|
||||
credential = password;
|
||||
}
|
||||
|
||||
/**
|
||||
* this reflects the properties that a user would pass to createContext
|
||||
*/
|
||||
|
@ -58,17 +53,19 @@ public class PasswordAuthenticationExpectTest extends BaseNovaRestClientExpectTe
|
|||
|
||||
public void testListServersWhenResponseIs2xx() throws Exception {
|
||||
HttpRequest listServers = HttpRequest.builder().method("GET").endpoint(
|
||||
URI.create("http://compute-1.jclouds.org:8774/v1.1/40806637803162/servers")).headers(
|
||||
URI.create("https://compute.north.host/v1.1/3456/servers")).headers(
|
||||
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
|
||||
authToken).build()).build();
|
||||
|
||||
HttpResponse listServersResponse = HttpResponse.builder().statusCode(200).payload(
|
||||
payloadFromResource("/server_list.json")).build();
|
||||
|
||||
ServerClient clientWhenServersExist = requestsSendResponses(initialAuthWithPasswordCredentials,
|
||||
responseWithAccess, listServers, listServersResponse).getServerClient();
|
||||
|
||||
assertEquals(clientWhenServersExist.listServers().toString(), new ParseServerListTest().expected().toString());
|
||||
NovaClient clientWhenServersExist = requestsSendResponses(keystoneAuthWithUsernameAndPassword,
|
||||
responseWithKeystoneAccess, listServers, listServersResponse);
|
||||
|
||||
assertEquals(clientWhenServersExist.getConfiguredRegions(), ImmutableSet.of("North"));
|
||||
|
||||
assertEquals(clientWhenServersExist.getServerClientForRegion("North").listServers().toString(), new ParseServerListTest().expected().toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -7,12 +7,14 @@ import java.net.URI;
|
|||
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.openstack.nova.v1_1.NovaClient;
|
||||
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaRestClientExpectTest;
|
||||
import org.jclouds.openstack.nova.v1_1.parse.ParseServerListTest;
|
||||
import org.jclouds.openstack.nova.v1_1.parse.ParseServerTest;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* Tests annotation parsing of {@code ServerAsyncClient}
|
||||
|
@ -22,53 +24,53 @@ import com.google.common.collect.ImmutableMultimap;
|
|||
@Test(groups = "unit", testName = "ServerAsyncClientTest")
|
||||
public class ServerClientExpectTest extends BaseNovaRestClientExpectTest {
|
||||
|
||||
public ServerClientExpectTest() {
|
||||
provider = "openstack-nova";
|
||||
}
|
||||
|
||||
public void testListServersWhenResponseIs2xx() throws Exception {
|
||||
HttpRequest listServers = HttpRequest.builder().method("GET").endpoint(
|
||||
URI.create("http://compute-1.jclouds.org:8774/v1.1/40806637803162/servers")).headers(
|
||||
URI.create("https://compute.north.host/v1.1/3456/servers")).headers(
|
||||
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
|
||||
authToken).build()).build();
|
||||
|
||||
HttpResponse listServersResponse = HttpResponse.builder().statusCode(200).payload(
|
||||
payloadFromResource("/server_list.json")).build();
|
||||
|
||||
ServerClient clientWhenServersExist = requestsSendResponses(initialAuthWithApiAccessKeyCredentials,
|
||||
responseWithAccess, listServers, listServersResponse).getServerClient();
|
||||
NovaClient clientWhenServersExist = requestsSendResponses(keystoneAuthWithAccessKeyAndSecretKey,
|
||||
responseWithKeystoneAccess, listServers, listServersResponse);
|
||||
|
||||
assertEquals(clientWhenServersExist.listServers().toString(), new ParseServerListTest().expected().toString());
|
||||
assertEquals(clientWhenServersExist.getConfiguredRegions(), ImmutableSet.of("North"));
|
||||
|
||||
assertEquals(clientWhenServersExist.getServerClientForRegion("North").listServers().toString(),
|
||||
new ParseServerListTest().expected().toString());
|
||||
}
|
||||
|
||||
public void testListServersWhenReponseIs404IsEmpty() throws Exception {
|
||||
HttpRequest listServers = HttpRequest.builder().method("GET").endpoint(
|
||||
URI.create("http://compute-1.jclouds.org:8774/v1.1/40806637803162/servers")).headers(
|
||||
URI.create("https://compute.north.host/v1.1/3456/servers")).headers(
|
||||
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
|
||||
authToken).build()).build();
|
||||
|
||||
HttpResponse listServersResponse = HttpResponse.builder().statusCode(404).build();
|
||||
|
||||
ServerClient clientWhenServersExist = requestsSendResponses(initialAuthWithApiAccessKeyCredentials,
|
||||
responseWithAccess, listServers, listServersResponse).getServerClient();
|
||||
NovaClient clientWhenNoServersExist = requestsSendResponses(keystoneAuthWithAccessKeyAndSecretKey,
|
||||
responseWithKeystoneAccess, listServers, listServersResponse);
|
||||
|
||||
assertTrue(clientWhenServersExist.listServers().isEmpty());
|
||||
assertTrue(clientWhenNoServersExist.getServerClientForRegion("North").listServers().isEmpty());
|
||||
}
|
||||
|
||||
// TODO: gson deserializer for Multimap
|
||||
public void testGetServerWhenResponseIs2xx() throws Exception {
|
||||
HttpRequest listServers = HttpRequest.builder().method("GET").endpoint(
|
||||
URI.create("http://compute-1.jclouds.org:8774/v1.1/40806637803162/servers/foo")).headers(
|
||||
URI.create("https://compute.north.host/v1.1/3456/servers/foo")).headers(
|
||||
ImmutableMultimap.<String, String> builder().put("Accept", "application/json").put("X-Auth-Token",
|
||||
authToken).build()).build();
|
||||
|
||||
HttpResponse listServersResponse = HttpResponse.builder().statusCode(200).payload(
|
||||
payloadFromResource("/server_details.json")).build();
|
||||
|
||||
ServerClient clientWhenServersExist = requestsSendResponses(initialAuthWithApiAccessKeyCredentials,
|
||||
responseWithAccess, listServers, listServersResponse).getServerClient();
|
||||
NovaClient clientWhenServersExist = requestsSendResponses(keystoneAuthWithAccessKeyAndSecretKey,
|
||||
responseWithKeystoneAccess, listServers, listServersResponse);
|
||||
|
||||
assertEquals(clientWhenServersExist.getServer("foo").toString(), new ParseServerTest().expected().toString());
|
||||
assertEquals(clientWhenServersExist.getServerClientForRegion("North").getServer("foo").toString(),
|
||||
new ParseServerTest().expected().toString());
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,7 +26,6 @@ import java.util.Set;
|
|||
import org.jclouds.openstack.domain.Resource;
|
||||
import org.jclouds.openstack.nova.v1_1.domain.Server;
|
||||
import org.jclouds.openstack.nova.v1_1.internal.BaseNovaClientLiveTest;
|
||||
import org.testng.annotations.BeforeGroups;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
|
@ -37,25 +36,20 @@ import org.testng.annotations.Test;
|
|||
@Test(groups = "live", testName = "ServerClientLiveTest")
|
||||
public class ServerClientLiveTest extends BaseNovaClientLiveTest {
|
||||
|
||||
@BeforeGroups(groups = { "live" })
|
||||
public void setupClient() {
|
||||
super.setupClient();
|
||||
client = context.getApi().getServerClient();
|
||||
}
|
||||
|
||||
private ServerClient client;
|
||||
|
||||
@Test
|
||||
public void testListServersInDetail() throws Exception {
|
||||
Set<Resource> response = client.listServers();
|
||||
assert null != response;
|
||||
assertTrue(response.size() >= 0);
|
||||
for (Resource server : response) {
|
||||
Server newDetails = client.getServer(server.getId());
|
||||
assertEquals(newDetails.getId(), server.getId());
|
||||
assertEquals(newDetails.getName(), server.getName());
|
||||
assertEquals(newDetails.getLinks(), server.getLinks());
|
||||
checkServer(newDetails);
|
||||
for (String regionId : context.getApi().getConfiguredRegions()) {
|
||||
ServerClient client = context.getApi().getServerClientForRegion(regionId);
|
||||
Set<Resource> response = client.listServers();
|
||||
assert null != response;
|
||||
assertTrue(response.size() >= 0);
|
||||
for (Resource server : response) {
|
||||
Server newDetails = client.getServer(server.getId());
|
||||
assertEquals(newDetails.getId(), server.getId());
|
||||
assertEquals(newDetails.getName(), server.getName());
|
||||
assertEquals(newDetails.getLinks(), server.getLinks());
|
||||
checkServer(newDetails);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -18,36 +18,32 @@
|
|||
*/
|
||||
package org.jclouds.openstack.nova.v1_1.internal;
|
||||
|
||||
import org.jclouds.http.RequiresHttp;
|
||||
import org.jclouds.openstack.keystone.v2_0.internal.BaseKeystoneRestClientExpectTest;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.jclouds.openstack.keystone.v2_0.internal.KeystoneFixture;
|
||||
import org.jclouds.openstack.nova.v1_1.NovaClient;
|
||||
import org.jclouds.openstack.nova.v1_1.config.NovaRestClientModule;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
|
||||
import com.google.inject.Module;
|
||||
import org.jclouds.rest.BaseRestClientExpectTest;
|
||||
|
||||
/**
|
||||
* Base class for writing KeyStone Rest Client Expect tests
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
public class BaseNovaRestClientExpectTest extends BaseKeystoneRestClientExpectTest<NovaClient> {
|
||||
public class BaseNovaRestClientExpectTest extends BaseRestClientExpectTest<NovaClient> {
|
||||
protected HttpRequest keystoneAuthWithUsernameAndPassword;
|
||||
protected HttpRequest keystoneAuthWithAccessKeyAndSecretKey;
|
||||
protected String authToken;
|
||||
protected HttpResponse responseWithKeystoneAccess;
|
||||
|
||||
public BaseNovaRestClientExpectTest() {
|
||||
provider = "openstack-nova";
|
||||
keystoneAuthWithUsernameAndPassword = KeystoneFixture.INSTANCE.initialAuthWithUsernameAndPassword(identity,
|
||||
credential);
|
||||
keystoneAuthWithAccessKeyAndSecretKey = KeystoneFixture.INSTANCE.initialAuthWithAccessKeyAndSecretKey(identity,
|
||||
credential);
|
||||
authToken = KeystoneFixture.INSTANCE.getAuthToken();
|
||||
responseWithKeystoneAccess = KeystoneFixture.INSTANCE.responseWithAccess();
|
||||
// now, createContext arg will need tenant prefix
|
||||
identity = KeystoneFixture.INSTANCE.getTenantName() + ":" + identity;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Module createModule() {
|
||||
return new TestNovaRestClientModule();
|
||||
}
|
||||
|
||||
@ConfiguresRestClient
|
||||
@RequiresHttp
|
||||
protected static class TestNovaRestClientModule extends NovaRestClientModule {
|
||||
private TestNovaRestClientModule() {
|
||||
super(new TestKeystoneAuthenticationModule());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -37,17 +37,17 @@ import com.google.common.base.Function;
|
|||
*/
|
||||
@Singleton
|
||||
public class OSTemplateToImage implements Function<OSTemplate, Image> {
|
||||
private final Function<String, OsFamilyVersion64Bit> imageParser;
|
||||
private final Function<String, OsFamilyVersion64Bit> osParser;
|
||||
|
||||
@Inject
|
||||
public OSTemplateToImage(Function<String, OsFamilyVersion64Bit> imageParser) {
|
||||
this.imageParser = imageParser;
|
||||
public OSTemplateToImage(Function<String, OsFamilyVersion64Bit> osParser) {
|
||||
this.osParser = osParser;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Image apply(OSTemplate template) {
|
||||
checkNotNull(template, "template");
|
||||
OsFamilyVersion64Bit parsed = imageParser.apply(template.getName());
|
||||
OsFamilyVersion64Bit parsed = osParser.apply(template.getName());
|
||||
Builder builder = OperatingSystem.builder();
|
||||
builder.name(template.getName()).description(template.getName()).is64Bit(parsed.is64Bit).version(parsed.version)
|
||||
.family(parsed.family);
|
||||
|
|
Loading…
Reference in New Issue