diff --git a/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/config/CloudFilesRestClientModule.java b/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/config/CloudFilesRestClientModule.java index 31e18d93c3..be8e3459ed 100644 --- a/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/config/CloudFilesRestClientModule.java +++ b/apis/cloudfiles/src/main/java/org/jclouds/cloudfiles/config/CloudFilesRestClientModule.java @@ -18,6 +18,7 @@ */ package org.jclouds.cloudfiles.config; + import java.net.URI; import javax.inject.Singleton; @@ -34,7 +35,7 @@ import org.jclouds.http.annotation.ServerError; import org.jclouds.json.config.GsonModule.DateAdapter; import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; import org.jclouds.openstack.keystone.v1_1.config.AuthenticationServiceModule; -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.swift.CommonSwiftAsyncClient; import org.jclouds.openstack.swift.CommonSwiftClient; @@ -44,7 +45,7 @@ import org.jclouds.openstack.swift.handlers.ParseSwiftErrorFromHttpResponse; import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.config.RestClientModule; -import com.google.common.collect.Iterables; +import com.google.common.base.Supplier; import com.google.inject.Provides; /** @@ -76,19 +77,19 @@ public class CloudFilesRestClientModule extends RestClientModule provideCDNUrl(PublicURLFromAuthResponseForService.Factory factory) { + return factory.create("cloudFilesCDN"); } - + @Provides @Singleton @Storage - protected URI provideStorageUrl(Auth response) { - return Iterables.get(response.getServiceCatalog().get("cloudFiles"), 0).getPublicURL(); + protected Supplier provideStorageUrl(PublicURLFromAuthResponseForService.Factory factory) { + return factory.create("cloudFiles"); } @Override diff --git a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java index 219a9ab4ec..63bdaa2957 100644 --- a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java +++ b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/config/CloudLoadBalancersRestClientModule.java @@ -18,16 +18,11 @@ */ package org.jclouds.cloudloadbalancers.config; -import static com.google.common.collect.Iterables.get; - import java.net.URI; import java.util.Map; -import java.util.Set; -import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; -import javax.ws.rs.core.UriBuilder; import org.jclouds.cloudloadbalancers.CloudLoadBalancersAsyncClient; import org.jclouds.cloudloadbalancers.CloudLoadBalancersClient; @@ -37,6 +32,7 @@ import org.jclouds.cloudloadbalancers.features.NodeAsyncClient; import org.jclouds.cloudloadbalancers.features.NodeClient; import org.jclouds.cloudloadbalancers.functions.ConvertLB; import org.jclouds.cloudloadbalancers.handlers.ParseCloudLoadBalancersErrorFromHttpResponse; +import org.jclouds.cloudloadbalancers.location.RegionUrisFromPropertiesAndAccountIDPathSuffix; import org.jclouds.cloudloadbalancers.reference.RackspaceConstants; import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpRetryHandler; @@ -44,25 +40,20 @@ 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.javax.annotation.Nullable; import org.jclouds.json.config.GsonModule.DateAdapter; import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; -import org.jclouds.location.Provider; import org.jclouds.location.Region; -import org.jclouds.location.config.ProvideRegionToURIViaProperties; -import org.jclouds.logging.Logger.LoggerFactory; +import org.jclouds.location.suppliers.RegionIdToURISupplier; import org.jclouds.openstack.keystone.v1_1.config.AuthenticationServiceModule; -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.rest.ConfiguresRestClient; import org.jclouds.rest.config.RestClientModule; import com.google.common.base.Function; -import com.google.common.collect.ImmutableBiMap; +import com.google.common.base.Supplier; +import com.google.common.base.Suppliers; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; -import com.google.common.collect.Maps; -import com.google.inject.Injector; import com.google.inject.Provides; import com.google.inject.Scopes; import com.google.inject.TypeLiteral; @@ -93,37 +84,13 @@ public class CloudLoadBalancersRestClientModule extends public CloudLoadBalancersRestClientModule() { this(new AuthenticationServiceModule()); } - protected void bindRegionsToProvider() { - bindRegionsToProvider(RegionUrisFromPropertiesAndAccountIDPathSuffix.class); + + @Override + protected void installLocations() { + super.installLocations(); + bind(RegionIdToURISupplier.class).to(RegionUrisFromPropertiesAndAccountIDPathSuffix.class).in(Scopes.SINGLETON); } - - @Singleton - public static class RegionUrisFromPropertiesAndAccountIDPathSuffix extends ProvideRegionToURIViaProperties { - - private final String accountID; - private final javax.inject.Provider builders; - - @Inject - protected RegionUrisFromPropertiesAndAccountIDPathSuffix(Injector injector, - javax.inject.Provider builders, @Named(RackspaceConstants.PROPERTY_ACCOUNT_ID) String accountID) { - super(injector); - this.builders = builders; - this.accountID = accountID; - } - - @Override - public Map get() { - return Maps.transformValues(super.get(), new Function(){ - - @Override - public URI apply(URI input) { - return builders.get().uri(input).path(accountID).build(); - } - - }); - } - } - + protected void bindRegionsToProvider(Class>> providerClass) { bind(new TypeLiteral>() { }).annotatedWith(Region.class).toProvider(providerClass).in(Scopes.SINGLETON); @@ -133,7 +100,6 @@ public class CloudLoadBalancersRestClientModule extends protected void configure() { install(module); bind(DateAdapter.class).to(Iso8601DateAdapter.class); - bindRegionsToProvider(); install(new FactoryModuleBuilder().build(ConvertLB.Factory.class)); super.configure(); } @@ -141,30 +107,20 @@ public class CloudLoadBalancersRestClientModule extends @Provides @Singleton @Named(RackspaceConstants.PROPERTY_ACCOUNT_ID) - protected String accountID(Auth response) { - URI serverURL = Iterables.get(response.getServiceCatalog().get("cloudServers"), 0).getPublicURL(); - return serverURL.getPath().substring(serverURL.getPath().lastIndexOf('/') + 1); - } + protected Supplier accountID(PublicURLFromAuthResponseForService.Factory factory) { + return Suppliers.compose(new Function() { - @Provides - @Singleton - @Region - public Set regions(@Region Map endpoints) { - return endpoints.keySet(); - } + @Override + public String apply(URI arg0) { + return arg0.getPath().substring(arg0.getPath().lastIndexOf('/') + 1); + } + + @Override + public String toString() { + return "getAccountIdFromCloudServers()"; + } + }, factory.create("cloudServers")); - @Provides - @Singleton - @Nullable - @Region - protected String getDefaultRegion(@Provider URI uri, @Region Map map, LoggerFactory logFactory) { - String region = ImmutableBiMap.copyOf(map).inverse().get(uri); - if (region == null && map.size() > 0) { - logFactory.getLogger(getClass().getName()).warn( - "failed to find region for current endpoint %s in %s; choosing first: %s", uri, map, region); - region = get(map.keySet(), 0); - } - return region; } @Override @@ -181,4 +137,5 @@ public class CloudLoadBalancersRestClientModule extends protected void bindRetryHandlers() { bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class); } + } diff --git a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/functions/AppendAccountIdToURI.java b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/functions/AppendAccountIdToURI.java new file mode 100644 index 0000000000..40f1a931c0 --- /dev/null +++ b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/functions/AppendAccountIdToURI.java @@ -0,0 +1,62 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.cloudloadbalancers.functions; + +import java.net.URI; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; +import javax.ws.rs.core.UriBuilder; + +import org.jclouds.cloudloadbalancers.reference.RackspaceConstants; + +import com.google.common.base.Function; +import com.google.common.base.Supplier; + +@Singleton +public final class AppendAccountIdToURI implements Function, Supplier> { + + private final Supplier accountID; + private final javax.inject.Provider builders; + + @Inject + public AppendAccountIdToURI(javax.inject.Provider builders, + @Named(RackspaceConstants.PROPERTY_ACCOUNT_ID) Supplier accountID) { + this.accountID = accountID; + this.builders = builders; + } + + @Override + public Supplier apply(final Supplier input) { + return new Supplier() { + + @Override + public URI get() { + return builders.get().uri(input.get()).path(accountID.get()).build(); + } + + @Override + public String toString() { + return "appendAccountId()"; + } + + }; + } +} \ No newline at end of file diff --git a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/loadbalancer/config/CloudLoadBalancersLoadBalancerContextModule.java b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/loadbalancer/config/CloudLoadBalancersLoadBalancerContextModule.java index b1c6429e54..0c2a3864b5 100644 --- a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/loadbalancer/config/CloudLoadBalancersLoadBalancerContextModule.java +++ b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/loadbalancer/config/CloudLoadBalancersLoadBalancerContextModule.java @@ -30,7 +30,6 @@ public class CloudLoadBalancersLoadBalancerContextModule extends BaseLoadBalance @Override protected void configure() { - install(new CloudLoadBalancersBindLoadBalancerSuppliersByClass()); install(new CloudLoadBalancersBindLoadBalancerStrategiesByClass()); install(new CloudLoadBalancersLoadBalancerServiceDependenciesModule()); super.configure(); diff --git a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/loadbalancer/strategy/CloudLoadBalancersListLoadBalancersStrategy.java b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/loadbalancer/strategy/CloudLoadBalancersListLoadBalancersStrategy.java index b52e0d8769..a720ce7855 100644 --- a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/loadbalancer/strategy/CloudLoadBalancersListLoadBalancersStrategy.java +++ b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/loadbalancer/strategy/CloudLoadBalancersListLoadBalancersStrategy.java @@ -27,7 +27,6 @@ import java.util.Set; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; -import org.jclouds.javax.annotation.Nullable; import javax.annotation.Resource; import javax.inject.Inject; import javax.inject.Named; @@ -43,6 +42,7 @@ import org.jclouds.location.Region; import org.jclouds.logging.Logger; import com.google.common.base.Function; +import com.google.common.base.Supplier; import com.google.common.util.concurrent.ListenableFuture; /** @@ -58,12 +58,12 @@ public class CloudLoadBalancersListLoadBalancersStrategy implements ListLoadBala private final CloudLoadBalancersAsyncClient aclient; private final Function converter; private final ExecutorService executor; - private final Set regions; + private final Supplier> regions; @Inject protected CloudLoadBalancersListLoadBalancersStrategy(CloudLoadBalancersAsyncClient aclient, Function converter, - @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, @Nullable @Region Set regions) { + @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, @Region Supplier> regions) { this.aclient = checkNotNull(aclient, "aclient"); this.regions = checkNotNull(regions, "regions"); this.converter = checkNotNull(converter, "converter"); @@ -72,7 +72,7 @@ public class CloudLoadBalancersListLoadBalancersStrategy implements ListLoadBala @Override public Iterable listLoadBalancers() { - return transform(concat(transformParallel(regions, new Function>>() { + return transform(concat(transformParallel(regions.get(), new Function>>() { @Override public ListenableFuture> apply(String from) { diff --git a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/location/RegionUrisFromPropertiesAndAccountIDPathSuffix.java b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/location/RegionUrisFromPropertiesAndAccountIDPathSuffix.java new file mode 100644 index 0000000000..020b65acfc --- /dev/null +++ b/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/location/RegionUrisFromPropertiesAndAccountIDPathSuffix.java @@ -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.cloudloadbalancers.location; + +import java.net.URI; +import java.util.Map; +import java.util.Set; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.cloudloadbalancers.functions.AppendAccountIdToURI; +import org.jclouds.config.ValueOfConfigurationKeyOrNull; +import org.jclouds.location.Provider; +import org.jclouds.location.Region; +import org.jclouds.location.suppliers.fromconfig.RegionIdToURIFromConfigurationOrDefaultToProvider; + +import com.google.common.base.Supplier; +import com.google.common.collect.Maps; + +@Singleton +public class RegionUrisFromPropertiesAndAccountIDPathSuffix extends RegionIdToURIFromConfigurationOrDefaultToProvider { + + private AppendAccountIdToURI filter; + + @Inject + protected RegionUrisFromPropertiesAndAccountIDPathSuffix(ValueOfConfigurationKeyOrNull config, + @Provider Supplier providerURI, @Region Supplier> regionIds, AppendAccountIdToURI filter) { + super(config, providerURI, regionIds); + this.filter = filter; + } + + @Override + public Map> get() { + return Maps.transformValues(super.get(), filter); + } +} \ No newline at end of file diff --git a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/config/CloudServersComputeServiceContextModule.java b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/config/CloudServersComputeServiceContextModule.java index 8400689e79..feef8869bd 100644 --- a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/config/CloudServersComputeServiceContextModule.java +++ b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/config/CloudServersComputeServiceContextModule.java @@ -42,7 +42,7 @@ import org.jclouds.compute.domain.OperatingSystem; import org.jclouds.compute.internal.BaseComputeService; import org.jclouds.domain.Location; import org.jclouds.functions.IdentityFunction; -import org.jclouds.location.suppliers.OnlyLocationOrFirstZone; +import org.jclouds.location.suppliers.implicit.OnlyLocationOrFirstZone; import com.google.common.annotations.VisibleForTesting; import com.google.common.base.Function; @@ -85,13 +85,9 @@ public class CloudServersComputeServiceContextModule // we aren't converting location from a provider-specific type bind(new TypeLiteral>() { }).to((Class) IdentityFunction.class); - - // there are no locations except the provider - bind(new TypeLiteral>() { - }).to(OnlyLocationOrFirstZone.class); } - + @VisibleForTesting public static final Map serverToNodeState = ImmutableMap . builder().put(ServerStatus.ACTIVE, NodeState.RUNNING)// @@ -125,4 +121,5 @@ public class CloudServersComputeServiceContextModule return serverToNodeState; } + } diff --git a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/strategy/CloudServersComputeServiceAdapter.java b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/strategy/CloudServersComputeServiceAdapter.java index da2bdb96e6..4ff7c642f5 100644 --- a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/strategy/CloudServersComputeServiceAdapter.java +++ b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/compute/strategy/CloudServersComputeServiceAdapter.java @@ -36,7 +36,8 @@ import org.jclouds.compute.ComputeServiceAdapter; import org.jclouds.compute.domain.Template; import org.jclouds.domain.Location; import org.jclouds.domain.LoginCredentials; -import org.jclouds.location.suppliers.JustProvider; + +import com.google.common.collect.ImmutableSet; /** * defines the connection between the {@link CloudServersClient} implementation and the jclouds @@ -47,13 +48,10 @@ import org.jclouds.location.suppliers.JustProvider; public class CloudServersComputeServiceAdapter implements ComputeServiceAdapter { protected final CloudServersClient client; - protected final JustProvider locationSupplier; @Inject - protected CloudServersComputeServiceAdapter(CloudServersClient client, JustProvider locationSupplier) { + protected CloudServersComputeServiceAdapter(CloudServersClient client) { this.client = checkNotNull(client, "client"); - this.locationSupplier = checkNotNull(locationSupplier, "locationSupplier"); - } @Override @@ -83,10 +81,10 @@ public class CloudServersComputeServiceAdapter implements ComputeServiceAdapter< return client.listServers(ListOptions.Builder.withDetails()); } - @SuppressWarnings("unchecked") @Override public Iterable listLocations() { - return (Iterable) locationSupplier.get(); + // Not using the adapter to determine locations + return ImmutableSet.of(); } @Override diff --git a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/config/CloudServersRestClientModule.java b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/config/CloudServersRestClientModule.java index be2f144294..c59b2e1572 100644 --- a/apis/cloudservers/src/main/java/org/jclouds/cloudservers/config/CloudServersRestClientModule.java +++ b/apis/cloudservers/src/main/java/org/jclouds/cloudservers/config/CloudServersRestClientModule.java @@ -39,14 +39,13 @@ import org.jclouds.http.annotation.ServerError; import org.jclouds.json.config.GsonModule.DateAdapter; import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; import org.jclouds.openstack.keystone.v1_1.config.AuthenticationServiceModule; -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.services.Compute; import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.config.RestClientModule; import com.google.common.base.Supplier; -import com.google.common.collect.Iterables; import com.google.inject.Provides; /** @@ -90,10 +89,10 @@ public class CloudServersRestClientModule extends RestClientModule provideServerUrl(PublicURLFromAuthResponseForService.Factory factory) { + return factory.create("cloudServers"); } - + //TODO: see if we still need this. @Provides @Singleton diff --git a/apis/cloudservers/src/test/java/org/jclouds/cloudservers/CloudServersAsyncClientTest.java b/apis/cloudservers/src/test/java/org/jclouds/cloudservers/CloudServersAsyncClientTest.java index fe4b7529ff..339bd59e7f 100644 --- a/apis/cloudservers/src/test/java/org/jclouds/cloudservers/CloudServersAsyncClientTest.java +++ b/apis/cloudservers/src/test/java/org/jclouds/cloudservers/CloudServersAsyncClientTest.java @@ -31,7 +31,6 @@ import static org.testng.Assert.assertEquals; import java.io.IOException; import java.lang.reflect.Method; -import java.net.URI; import java.net.UnknownHostException; import java.util.Date; import java.util.Properties; @@ -96,7 +95,7 @@ public class CloudServersAsyncClientTest extends RestClientTest>() { }).to((Class) IdentityFunction.class); - // there are no locations except the provider - bind(new TypeLiteral>() { - }).to(OnlyLocationOrFirstZone.class); - } - + @VisibleForTesting public static final Map serverToNodeState = ImmutableMap . builder().put(ServerStatus.ACTIVE, NodeState.RUNNING)// diff --git a/apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaComputeServiceAdapter.java b/apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaComputeServiceAdapter.java index 5318b5e7c5..1fe73bc1d8 100644 --- a/apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaComputeServiceAdapter.java +++ b/apis/nova/src/main/java/org/jclouds/openstack/nova/compute/strategy/NovaComputeServiceAdapter.java @@ -25,18 +25,19 @@ import static org.jclouds.openstack.nova.options.ListOptions.Builder.withDetails import javax.inject.Inject; import javax.inject.Singleton; +import org.jclouds.compute.ComputeService; +import org.jclouds.compute.ComputeServiceAdapter; +import org.jclouds.compute.domain.Template; +import org.jclouds.domain.Location; +import org.jclouds.domain.LoginCredentials; import org.jclouds.openstack.nova.NovaClient; import org.jclouds.openstack.nova.domain.Flavor; import org.jclouds.openstack.nova.domain.Image; import org.jclouds.openstack.nova.domain.RebootType; import org.jclouds.openstack.nova.domain.Server; import org.jclouds.openstack.nova.options.ListOptions; -import org.jclouds.compute.ComputeService; -import org.jclouds.compute.ComputeServiceAdapter; -import org.jclouds.compute.domain.Template; -import org.jclouds.domain.Location; -import org.jclouds.domain.LoginCredentials; -import org.jclouds.location.suppliers.JustProvider; + +import com.google.common.collect.ImmutableSet; /** * defines the connection between the {@link NovaClient} implementation and the jclouds @@ -47,13 +48,10 @@ import org.jclouds.location.suppliers.JustProvider; public class NovaComputeServiceAdapter implements ComputeServiceAdapter { protected final NovaClient client; - protected final JustProvider locationSupplier; @Inject - protected NovaComputeServiceAdapter(NovaClient client, JustProvider locationSupplier) { + protected NovaComputeServiceAdapter(NovaClient client) { this.client = checkNotNull(client, "client"); - this.locationSupplier = checkNotNull(locationSupplier, "locationSupplier"); - } @Override @@ -82,10 +80,10 @@ public class NovaComputeServiceAdapter implements ComputeServiceAdapter listLocations() { - return (Iterable) locationSupplier.get(); + // Not using the adapter to determine locations + return ImmutableSet.of(); } @Override diff --git a/apis/nova/src/main/java/org/jclouds/openstack/nova/config/NovaRestClientModule.java b/apis/nova/src/main/java/org/jclouds/openstack/nova/config/NovaRestClientModule.java index 205eb746eb..5c5209cd36 100644 --- a/apis/nova/src/main/java/org/jclouds/openstack/nova/config/NovaRestClientModule.java +++ b/apis/nova/src/main/java/org/jclouds/openstack/nova/config/NovaRestClientModule.java @@ -22,10 +22,6 @@ import java.net.URI; import javax.inject.Singleton; -import org.jclouds.openstack.nova.NovaAsyncClient; -import org.jclouds.openstack.nova.NovaClient; -import org.jclouds.openstack.nova.ServerManagement; -import org.jclouds.openstack.nova.handlers.ParseNovaErrorFromHttpResponse; import org.jclouds.http.HttpErrorHandler; import org.jclouds.http.HttpRetryHandler; import org.jclouds.http.RequiresHttp; @@ -34,13 +30,18 @@ import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.ServerError; import org.jclouds.json.config.GsonModule.DateAdapter; import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; -import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse; import org.jclouds.openstack.config.OpenStackAuthenticationModule; +import org.jclouds.openstack.functions.URIFromAuthenticationResponseForService; import org.jclouds.openstack.handlers.RetryOnRenew; +import org.jclouds.openstack.nova.NovaAsyncClient; +import org.jclouds.openstack.nova.NovaClient; +import org.jclouds.openstack.nova.ServerManagement; +import org.jclouds.openstack.nova.handlers.ParseNovaErrorFromHttpResponse; import org.jclouds.openstack.reference.AuthHeaders; import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.config.RestClientModule; +import com.google.common.base.Supplier; import com.google.inject.Provides; /** @@ -80,12 +81,11 @@ public class NovaRestClientModule extends RestClientModule provideServerUrl(URIFromAuthenticationResponseForService.Factory factory) { + return factory.create(AuthHeaders.SERVER_MANAGEMENT_URL); } - } diff --git a/apis/nova/src/test/java/org/jclouds/openstack/nova/NovaAsyncClientTest.java b/apis/nova/src/test/java/org/jclouds/openstack/nova/NovaAsyncClientTest.java index 4726502b5c..d2e6c2387f 100644 --- a/apis/nova/src/test/java/org/jclouds/openstack/nova/NovaAsyncClientTest.java +++ b/apis/nova/src/test/java/org/jclouds/openstack/nova/NovaAsyncClientTest.java @@ -28,7 +28,6 @@ import static org.testng.Assert.assertEquals; import java.io.IOException; import java.lang.reflect.Method; -import java.net.URI; import java.util.Date; import java.util.Properties; @@ -39,7 +38,6 @@ import org.jclouds.http.RequiresHttp; import org.jclouds.http.functions.ReleasePayloadAndReturn; import org.jclouds.http.functions.ReturnTrueIf2xx; import org.jclouds.http.functions.UnwrapOnlyJsonValue; -import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse; import org.jclouds.openstack.TestOpenStackAuthenticationModule; import org.jclouds.openstack.filters.AddTimestampQuery; import org.jclouds.openstack.filters.AuthenticateRequest; @@ -777,11 +775,6 @@ public class NovaAsyncClientTest extends RestClientTest { super(new TestOpenStackAuthenticationModule()); } - @Override - protected URI provideServerUrl(AuthenticationResponse response) { - return URI.create("http://endpoint/vapi-version"); - } - } protected String provider = "nova"; diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/SwiftBlobStoreContextModule.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/SwiftBlobStoreContextModule.java index 9e1491e265..ff440f8b59 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/SwiftBlobStoreContextModule.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/blobstore/config/SwiftBlobStoreContextModule.java @@ -25,7 +25,6 @@ import org.jclouds.blobstore.BlobStoreContext; import org.jclouds.blobstore.attr.ConsistencyModel; import org.jclouds.blobstore.config.BlobStoreMapModule; import org.jclouds.blobstore.internal.BlobStoreContextImpl; -import org.jclouds.location.config.JustProviderLocationModule; import org.jclouds.openstack.swift.CommonSwiftAsyncClient; import org.jclouds.openstack.swift.CommonSwiftClient; import org.jclouds.openstack.swift.blobstore.SwiftAsyncBlobStore; @@ -47,7 +46,6 @@ public class SwiftBlobStoreContextModule extends AbstractModule { @Override protected void configure() { install(new BlobStoreMapModule()); - install(new JustProviderLocationModule()); bind(ConsistencyModel.class).toInstance(ConsistencyModel.STRICT); bind(AsyncBlobStore.class).to(SwiftAsyncBlobStore.class).in(Scopes.SINGLETON); bind(BlobStore.class).to(SwiftBlobStore.class).in(Scopes.SINGLETON); diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/config/BaseSwiftRestClientModule.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/config/BaseSwiftRestClientModule.java index b0a1445e30..1bde05cb34 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/config/BaseSwiftRestClientModule.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/config/BaseSwiftRestClientModule.java @@ -30,8 +30,8 @@ import org.jclouds.http.annotation.Redirection; import org.jclouds.http.annotation.ServerError; import org.jclouds.json.config.GsonModule.DateAdapter; import org.jclouds.json.config.GsonModule.Iso8601DateAdapter; -import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse; 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; @@ -41,6 +41,7 @@ import org.jclouds.openstack.swift.handlers.ParseSwiftErrorFromHttpResponse; import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.config.RestClientModule; +import com.google.common.base.Supplier; import com.google.inject.Provides; /** @@ -82,11 +83,11 @@ public class BaseSwiftRestClientModule provideStorageUrl(URIFromAuthenticationResponseForService.Factory factory) { + return factory.create(AuthHeaders.STORAGE_URL); } } diff --git a/apis/swift/src/main/java/org/jclouds/openstack/swift/config/SwiftRestClientModule.java b/apis/swift/src/main/java/org/jclouds/openstack/swift/config/SwiftRestClientModule.java index e7506fcd4e..9186c7e38c 100644 --- a/apis/swift/src/main/java/org/jclouds/openstack/swift/config/SwiftRestClientModule.java +++ b/apis/swift/src/main/java/org/jclouds/openstack/swift/config/SwiftRestClientModule.java @@ -18,13 +18,9 @@ */ package org.jclouds.openstack.swift.config; -import java.net.URI; - import javax.inject.Singleton; import org.jclouds.http.RequiresHttp; -import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse; -import org.jclouds.openstack.reference.AuthHeaders; import org.jclouds.openstack.swift.CommonSwiftAsyncClient; import org.jclouds.openstack.swift.CommonSwiftClient; import org.jclouds.openstack.swift.SwiftAsyncClient; @@ -57,7 +53,4 @@ public class SwiftRestClientModule extends BaseSwiftRestClientModule ex private TestSwiftRestClientModule() { super(new TestOpenStackAuthenticationModule(), CommonSwiftClient.class, CommonSwiftAsyncClient.class); } - - @Override - protected URI provideStorageUrl(AuthenticationResponse response) { - return URI.create("http://storage"); - } - } protected String provider = "swift"; diff --git a/common/openstack/src/main/java/org/jclouds/openstack/OpenStackAuthAsyncClient.java b/common/openstack/src/main/java/org/jclouds/openstack/OpenStackAuthAsyncClient.java index d3def32aed..cd5030cc28 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/OpenStackAuthAsyncClient.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/OpenStackAuthAsyncClient.java @@ -18,23 +18,17 @@ */ package org.jclouds.openstack; -import static com.google.common.base.Preconditions.checkNotNull; - -import java.net.URI; -import java.util.Map; - import javax.ws.rs.Consumes; import javax.ws.rs.GET; import javax.ws.rs.HeaderParam; import javax.ws.rs.Path; import org.jclouds.Constants; +import org.jclouds.openstack.domain.AuthenticationResponse; import org.jclouds.openstack.functions.ParseAuthenticationResponseFromHeaders; import org.jclouds.openstack.reference.AuthHeaders; import org.jclouds.rest.annotations.ResponseParser; -import com.google.common.base.Objects; -import com.google.common.collect.ImmutableMap; import com.google.common.util.concurrent.ListenableFuture; /** @@ -48,48 +42,6 @@ import com.google.common.util.concurrent.ListenableFuture; public interface OpenStackAuthAsyncClient { public static final String VERSION = "1.0"; - public static class AuthenticationResponse { - private final String authToken; - private Map services; - - public AuthenticationResponse(String authToken, Map services) { - this.authToken = checkNotNull(authToken, "authToken"); - this.services = ImmutableMap.copyOf(checkNotNull(services, "services")); - } - - public Map getServices() { - return services; - } - - public void setEndpoints(Map services) { - this.services = services; - } - - public String getAuthToken() { - return authToken; - } - - // performance isn't a concern on a infrequent object like this, so using shortcuts; - - @Override - public int hashCode() { - return Objects.hashCode(authToken, services); - } - - @Override - public boolean equals(Object that) { - if (that == null) - return false; - return Objects.equal(this.toString(), that.toString()); - } - - @Override - public String toString() { - return Objects.toStringHelper(this).add("authToken", authToken).add("services", services).toString(); - } - - } - @GET @Consumes @ResponseParser(ParseAuthenticationResponseFromHeaders.class) diff --git a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/loadbalancer/config/CloudLoadBalancersBindLoadBalancerSuppliersByClass.java b/common/openstack/src/main/java/org/jclouds/openstack/OpenStackAuthClient.java similarity index 59% rename from apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/loadbalancer/config/CloudLoadBalancersBindLoadBalancerSuppliersByClass.java rename to common/openstack/src/main/java/org/jclouds/openstack/OpenStackAuthClient.java index d31f6a7f8a..ebd9256066 100644 --- a/apis/cloudloadbalancers/src/main/java/org/jclouds/cloudloadbalancers/loadbalancer/config/CloudLoadBalancersBindLoadBalancerSuppliersByClass.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/OpenStackAuthClient.java @@ -16,23 +16,21 @@ * specific language governing permissions and limitations * under the License. */ -package org.jclouds.cloudloadbalancers.loadbalancer.config; +package org.jclouds.openstack; +import java.util.concurrent.TimeUnit; -import java.util.Set; - -import org.jclouds.domain.Location; -import org.jclouds.loadbalancer.config.BindLoadBalancerSuppliersByClass; -import org.jclouds.location.suppliers.RegionToProviderOrJustProvider; - -import com.google.common.base.Supplier; +import org.jclouds.concurrent.Timeout; +import org.jclouds.openstack.domain.AuthenticationResponse; /** + * Provides access to Rackspace resources via their REST API. + *

+ * + * @see * @author Adrian Cole */ -public class CloudLoadBalancersBindLoadBalancerSuppliersByClass extends BindLoadBalancerSuppliersByClass { +@Timeout(duration = 10, timeUnit = TimeUnit.SECONDS) +public interface OpenStackAuthClient { - @Override - protected Class>> defineLocationSupplier() { - return RegionToProviderOrJustProvider.class; - } + AuthenticationResponse authenticate(String user, String key); } \ No newline at end of file diff --git a/common/openstack/src/main/java/org/jclouds/openstack/config/OpenStackAuthenticationModule.java b/common/openstack/src/main/java/org/jclouds/openstack/config/OpenStackAuthenticationModule.java index 142d420722..8ead843ee9 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/config/OpenStackAuthenticationModule.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/config/OpenStackAuthenticationModule.java @@ -19,11 +19,10 @@ package org.jclouds.openstack.config; import static com.google.common.base.Suppliers.memoizeWithExpiration; -import static com.google.common.base.Throwables.propagate; +import static org.jclouds.rest.config.BinderUtils.bindClientAndAsyncClient; import java.util.Date; import java.util.concurrent.ExecutionException; -import java.util.concurrent.Future; import java.util.concurrent.TimeUnit; import java.util.concurrent.TimeoutException; @@ -37,8 +36,9 @@ import org.jclouds.http.RequiresHttp; import org.jclouds.location.Provider; import org.jclouds.openstack.Authentication; import org.jclouds.openstack.OpenStackAuthAsyncClient; -import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse; -import org.jclouds.rest.AsyncClientFactory; +import org.jclouds.openstack.OpenStackAuthClient; +import org.jclouds.openstack.domain.AuthenticationResponse; +import org.jclouds.openstack.functions.URIFromAuthenticationResponseForService; import com.google.common.base.Function; import com.google.common.base.Supplier; @@ -48,6 +48,7 @@ import com.google.common.cache.LoadingCache; import com.google.inject.AbstractModule; import com.google.inject.Provides; import com.google.inject.TypeLiteral; +import com.google.inject.assistedinject.FactoryModuleBuilder; /** * Configures the Rackspace authentication service connection, including logging and http transport. @@ -61,6 +62,10 @@ public class OpenStackAuthenticationModule extends AbstractModule { protected void configure() { bind(new TypeLiteral>() { }).to(GetAuthenticationResponse.class); + // OpenStackAuthClient is used directly for filters and retry handlers, so let's bind it + // explicitly + bindClientAndAsyncClient(binder(), OpenStackAuthClient.class, OpenStackAuthAsyncClient.class); + install(new FactoryModuleBuilder().build(URIFromAuthenticationResponseForService.Factory.class)); } /** @@ -82,21 +87,13 @@ public class OpenStackAuthenticationModule extends AbstractModule { public static class GetAuthenticationResponse extends RetryOnTimeOutExceptionFunction { - // passing factory here to avoid a circular dependency on - // OpenStackAuthAsyncClient resolving OpenStackAuthAsyncClient @Inject - public GetAuthenticationResponse(final AsyncClientFactory factory) { + public GetAuthenticationResponse(final OpenStackAuthClient client) { super(new Function() { @Override public AuthenticationResponse apply(Credentials input) { - try { - Future response = factory.create(OpenStackAuthAsyncClient.class) - .authenticate(input.identity, input.credential); - return response.get(30, TimeUnit.SECONDS); - } catch (Exception e) { - throw propagate(e); - } + return client.authenticate(input.identity, input.credential); } @Override @@ -110,7 +107,7 @@ public class OpenStackAuthenticationModule extends AbstractModule { @Provides @Singleton - public LoadingCache provideAuthenticationResponseCache2( + public LoadingCache provideAuthenticationResponseCache( Function getAuthenticationResponse) { return CacheBuilder.newBuilder().expireAfterWrite(23, TimeUnit.HOURS).build( CacheLoader.from(getAuthenticationResponse)); @@ -123,11 +120,7 @@ public class OpenStackAuthenticationModule extends AbstractModule { return new Supplier() { @Override public AuthenticationResponse get() { - try { - return cache.get(creds); - } catch (ExecutionException e) { - throw propagate(e.getCause()); - } + return cache.getUnchecked(creds); } }; } @@ -143,11 +136,4 @@ public class OpenStackAuthenticationModule extends AbstractModule { }, 1, TimeUnit.SECONDS); } - @Provides - @Singleton - protected AuthenticationResponse provideAuthenticationResponse(Supplier supplier) - throws InterruptedException, ExecutionException, TimeoutException { - return supplier.get(); - } - } \ No newline at end of file diff --git a/common/openstack/src/main/java/org/jclouds/openstack/domain/AuthenticationResponse.java b/common/openstack/src/main/java/org/jclouds/openstack/domain/AuthenticationResponse.java new file mode 100644 index 0000000000..6311c657f1 --- /dev/null +++ b/common/openstack/src/main/java/org/jclouds/openstack/domain/AuthenticationResponse.java @@ -0,0 +1,67 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Href 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.openstack.domain; + +import static com.google.common.base.Preconditions.checkNotNull; + +import java.net.URI; +import java.util.Map; + +import com.google.common.base.Objects; +import com.google.common.collect.ImmutableMap; + +public class AuthenticationResponse { + private final String authToken; + private Map services; + + public AuthenticationResponse(String authToken, Map services) { + this.authToken = checkNotNull(authToken, "authToken"); + this.services = ImmutableMap.copyOf(checkNotNull(services, "services")); + } + + public Map getServices() { + return services; + } + + public void setEndpoints(Map services) { + this.services = services; + } + + public String getAuthToken() { + return authToken; + } + + @Override + public int hashCode() { + return Objects.hashCode(authToken, services); + } + + @Override + public boolean equals(Object that) { + if (that == null) + return false; + return Objects.equal(this.toString(), that.toString()); + } + + @Override + public String toString() { + return Objects.toStringHelper(this).add("authToken", authToken).add("services", services).toString(); + } + +} diff --git a/common/openstack/src/main/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeaders.java b/common/openstack/src/main/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeaders.java index d608266c6f..ca2a301c91 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeaders.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/functions/ParseAuthenticationResponseFromHeaders.java @@ -34,7 +34,7 @@ import javax.ws.rs.core.UriBuilder; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.logging.Logger; -import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse; +import org.jclouds.openstack.domain.AuthenticationResponse; import org.jclouds.rest.InvocationContext; import com.google.common.annotations.VisibleForTesting; diff --git a/common/openstack/src/main/java/org/jclouds/openstack/functions/URIFromAuthenticationResponseForService.java b/common/openstack/src/main/java/org/jclouds/openstack/functions/URIFromAuthenticationResponseForService.java new file mode 100644 index 0000000000..56be34a77a --- /dev/null +++ b/common/openstack/src/main/java/org/jclouds/openstack/functions/URIFromAuthenticationResponseForService.java @@ -0,0 +1,55 @@ +/** + * 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.functions; + +import java.net.URI; + +import javax.inject.Inject; +import javax.inject.Singleton; + +import org.jclouds.openstack.domain.AuthenticationResponse; + +import com.google.common.base.Supplier; +import com.google.inject.assistedinject.Assisted; + +@Singleton +public class URIFromAuthenticationResponseForService implements Supplier { + public static interface Factory { + URIFromAuthenticationResponseForService create(String service); + } + + private final Supplier auth; + private final String service; + + @Inject + public URIFromAuthenticationResponseForService(Supplier auth, @Assisted String service) { + this.auth = auth; + this.service = service; + } + + @Override + public URI get() { + return auth.get().getServices().get(service); + } + + @Override + public String toString() { + return "getURIForService(" + service + ")"; + } +} \ No newline at end of file diff --git a/common/openstack/src/main/java/org/jclouds/openstack/handlers/RetryOnRenew.java b/common/openstack/src/main/java/org/jclouds/openstack/handlers/RetryOnRenew.java index 87d073979d..8ef1113720 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/handlers/RetryOnRenew.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/handlers/RetryOnRenew.java @@ -28,7 +28,7 @@ import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpResponse; import org.jclouds.http.HttpRetryHandler; import org.jclouds.logging.Logger; -import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse; +import org.jclouds.openstack.domain.AuthenticationResponse; import org.jclouds.openstack.reference.AuthHeaders; import com.google.common.cache.LoadingCache; diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java index c6565ba20a..0ded49b82b 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/config/AuthenticationServiceModule.java @@ -19,6 +19,7 @@ package org.jclouds.openstack.keystone.v1_1.config; import static com.google.common.base.Throwables.propagate; +import static org.jclouds.rest.config.BinderUtils.bindClientAndAsyncClient; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -33,18 +34,19 @@ import org.jclouds.http.RequiresHttp; import org.jclouds.location.Provider; 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.rest.AsyncClientFactory; +import org.jclouds.openstack.keystone.v1_1.functions.PublicURLFromAuthResponseForService; import com.google.common.base.Function; import com.google.common.base.Supplier; -import com.google.common.base.Throwables; import com.google.common.cache.CacheBuilder; import com.google.common.cache.CacheLoader; import com.google.common.cache.LoadingCache; import com.google.inject.AbstractModule; import com.google.inject.Provides; import com.google.inject.TypeLiteral; +import com.google.inject.assistedinject.FactoryModuleBuilder; /** * @@ -57,6 +59,10 @@ public class AuthenticationServiceModule extends AbstractModule { protected void configure() { bind(new TypeLiteral>() { }).to(GetAuth.class); + // 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)); } /** @@ -74,28 +80,16 @@ public class AuthenticationServiceModule extends AbstractModule { }; } - @Provides - @Singleton - protected ServiceAsyncClient provideServiceClient(AsyncClientFactory factory) { - return factory.create(ServiceAsyncClient.class); - } - @Singleton public static class GetAuth extends RetryOnTimeOutExceptionFunction { - - // passing factory here to avoid a circular dependency on - // OpenStackAuthAsyncClient resolving OpenStackAuthAsyncClient + @Inject - public GetAuth(final AsyncClientFactory factory) { + public GetAuth(final ServiceClient client) { super(new Function() { @Override public Auth apply(Credentials input) { - try { - return factory.create(ServiceAsyncClient.class).authenticate(input.identity, input.credential).get(); - } catch (Exception e) { - throw Throwables.propagate(e); - } + return client.authenticate(input.identity, input.credential); } @Override @@ -109,7 +103,7 @@ public class AuthenticationServiceModule extends AbstractModule { @Provides @Singleton - public LoadingCache provideAuthCache2(Function getAuth) { + public LoadingCache provideAuthCache(Function getAuth) { return CacheBuilder.newBuilder().expireAfterWrite(23, TimeUnit.HOURS).build(CacheLoader.from(getAuth)); } @@ -128,11 +122,4 @@ public class AuthenticationServiceModule extends AbstractModule { } }; } - - @Provides - @Singleton - protected Auth provideAuth(Supplier supplier) { - return supplier.get(); - } - } \ No newline at end of file diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/functions/PublicURLFromAuthResponseForService.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/functions/PublicURLFromAuthResponseForService.java new file mode 100644 index 0000000000..7988a7615c --- /dev/null +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/functions/PublicURLFromAuthResponseForService.java @@ -0,0 +1,56 @@ +/** + * Licensed to jclouds, Inc. (jclouds) under one or more + * contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. jclouds licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.jclouds.openstack.keystone.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 com.google.common.base.Supplier; +import com.google.common.collect.Iterables; +import com.google.inject.assistedinject.Assisted; + +@Singleton +public class PublicURLFromAuthResponseForService implements Supplier { + public static interface Factory { + PublicURLFromAuthResponseForService create(String service); + } + + private final Supplier auth; + private final String service; + + @Inject + public PublicURLFromAuthResponseForService(Supplier auth, @Assisted String service) { + this.auth = auth; + this.service = service; + } + + @Override + public URI get() { + return Iterables.get(auth.get().getServiceCatalog().get(service), 0).getPublicURL(); + } + + @Override + public String toString() { + return "getPublicURLForService(" + service + ")"; + } +} \ No newline at end of file diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/functions/PublicUrlForService.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/functions/PublicUrlForService.java new file mode 100644 index 0000000000..54be11a464 --- /dev/null +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v1_1/functions/PublicUrlForService.java @@ -0,0 +1,41 @@ +/** + * 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 com.google.common.base.Preconditions.checkNotNull; + +import java.net.URI; + +import org.jclouds.openstack.keystone.v1_1.domain.Auth; + +import com.google.common.base.Function; +import com.google.common.collect.Iterables; + +public class PublicUrlForService implements Function { + 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(); + } +} \ No newline at end of file diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java index 2c4d906370..5b77713ba7 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/config/KeystoneAuthenticationModule.java @@ -19,6 +19,7 @@ package org.jclouds.openstack.keystone.v2_0.config; import static com.google.common.base.Throwables.propagate; +import static org.jclouds.rest.config.BinderUtils.bindClientAndAsyncClient; import java.util.concurrent.ExecutionException; import java.util.concurrent.TimeUnit; @@ -35,11 +36,12 @@ import org.jclouds.http.annotation.ClientError; import org.jclouds.location.Provider; 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.rest.AsyncClientFactory; import com.google.common.base.Function; import com.google.common.base.Supplier; @@ -49,6 +51,7 @@ import com.google.common.cache.LoadingCache; import com.google.inject.AbstractModule; import com.google.inject.Inject; import com.google.inject.Provides; +import com.google.inject.assistedinject.FactoryModuleBuilder; /** * @@ -61,6 +64,10 @@ public class KeystoneAuthenticationModule extends AbstractModule { protected void configure() { bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class); bind(CredentialType.class).toProvider(CredentialTypeFromPropertyOrDefault.class); + // ServiceClient is used directly for filters and retry handlers, so let's bind it + // explicitly + bindClientAndAsyncClient(binder(), ServiceClient.class, ServiceAsyncClient.class); + install(new FactoryModuleBuilder().build(PublicURLFromAccessForService.Factory.class)); } /** @@ -78,15 +85,6 @@ public class KeystoneAuthenticationModule extends AbstractModule { }; } - /** - * service is needed to locate endpoints and such - */ - @Provides - @Singleton - protected ServiceAsyncClient provideServiceClient(AsyncClientFactory factory) { - return factory.create(ServiceAsyncClient.class); - } - @Singleton static class CredentialTypeFromPropertyOrDefault implements javax.inject.Provider { /** @@ -150,14 +148,4 @@ public class KeystoneAuthenticationModule extends AbstractModule { }; } - /** - * currently, endpointParams are not configured to take their results from a supplier lazily, so - * we need to eagerly fetch. - */ - @Provides - @Singleton - protected Access provideAccess(Supplier supplier) { - return supplier.get(); - } - } \ No newline at end of file diff --git a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java index 4b90b4b183..dfd2018100 100644 --- a/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java +++ b/common/openstack/src/main/java/org/jclouds/openstack/keystone/v2_0/functions/AuthenticateApiAccessKeyCredentials.java @@ -19,22 +19,23 @@ package org.jclouds.openstack.keystone.v2_0.functions; import javax.inject.Inject; +import javax.inject.Singleton; import org.jclouds.domain.Credentials; -import org.jclouds.openstack.keystone.v2_0.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.domain.ApiAccessKeyCredentials; import com.google.common.base.Function; import com.google.common.base.Splitter; -import com.google.common.base.Throwables; import com.google.common.collect.Iterables; +@Singleton public class AuthenticateApiAccessKeyCredentials implements Function { - private final ServiceAsyncClient client; + private final ServiceClient client; @Inject - public AuthenticateApiAccessKeyCredentials(ServiceAsyncClient client) { + public AuthenticateApiAccessKeyCredentials(ServiceClient client) { this.client = client; } @@ -46,13 +47,9 @@ public class AuthenticateApiAccessKeyCredentials implements Function { - private final AsyncClientFactory factory; - // passing factory here to avoid a circular dependency on - // OpenStackAuthAsyncClient resolving ServiceAsyncClient + private final ServiceClient client; + @Inject - public AuthenticatePasswordCredentials(AsyncClientFactory factory) { - this.factory = factory; + public AuthenticatePasswordCredentials(ServiceClient client) { + this.client = client; } @Override @@ -48,14 +45,9 @@ public class AuthenticatePasswordCredentials implements Function { + public static interface Factory { + PublicURLFromAccessForService create(String service); + } + + private final Supplier auth; + private final String service; + + @Inject + public PublicURLFromAccessForService(Supplier auth, @Assisted String service) { + this.auth = auth; + this.service = service; + } + + @Override + public URI get() { + return Iterables.getOnlyElement(Iterables.find(auth.get().getServiceCatalog(), new Predicate(){ + + @Override + public boolean apply(Service input) { + return input.getId().equals(service); + } + + }).getEndpoints()).getPublicURL(); + } + + @Override + public String toString() { + return "getPublicURLForService(" + service + ")"; + } +} \ No newline at end of file diff --git a/common/openstack/src/test/java/org/jclouds/openstack/OpenStackAuthAsyncClientTest.java b/common/openstack/src/test/java/org/jclouds/openstack/OpenStackAuthAsyncClientTest.java index 293174f2cc..aa556da34a 100644 --- a/common/openstack/src/test/java/org/jclouds/openstack/OpenStackAuthAsyncClientTest.java +++ b/common/openstack/src/test/java/org/jclouds/openstack/OpenStackAuthAsyncClientTest.java @@ -22,12 +22,8 @@ import static org.jclouds.rest.RestContextFactory.contextSpec; import java.io.IOException; import java.lang.reflect.Method; -import java.util.concurrent.TimeUnit; -import org.jclouds.concurrent.Timeout; import org.jclouds.http.HttpRequest; -import org.jclouds.openstack.OpenStackAuthAsyncClient; -import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse; import org.jclouds.openstack.functions.ParseAuthenticationResponseFromHeaders; import org.jclouds.rest.RestClientTest; import org.jclouds.rest.RestContextSpec; @@ -90,9 +86,4 @@ public class OpenStackAuthAsyncClientTest extends RestClientTest supplier) { - return new AuthenticationResponse("authToken", ImmutableMap. of()); + @Singleton + public static class TestGetAuthenticationResponse extends GetAuthenticationResponse { + + @Inject + protected TestGetAuthenticationResponse() { + super(null); + } + + @Override + public AuthenticationResponse apply(Credentials input) { + return new AuthenticationResponse("authToken", ImmutableMap. of( + AuthHeaders.SERVER_MANAGEMENT_URL, URI.create("http://endpoint/vapi-version"), + AuthHeaders.STORAGE_URL, URI.create("http://storage"))); + } + } @Override diff --git a/common/openstack/src/test/java/org/jclouds/openstack/handlers/RetryOnRenewTest.java b/common/openstack/src/test/java/org/jclouds/openstack/handlers/RetryOnRenewTest.java index 36a6c3a7d4..272920d560 100644 --- a/common/openstack/src/test/java/org/jclouds/openstack/handlers/RetryOnRenewTest.java +++ b/common/openstack/src/test/java/org/jclouds/openstack/handlers/RetryOnRenewTest.java @@ -30,7 +30,7 @@ import org.jclouds.http.HttpCommand; import org.jclouds.http.HttpRequest; import org.jclouds.http.HttpResponse; import org.jclouds.io.Payloads; -import org.jclouds.openstack.OpenStackAuthAsyncClient.AuthenticationResponse; +import org.jclouds.openstack.domain.AuthenticationResponse; import org.testng.annotations.Test; import com.google.common.cache.LoadingCache; diff --git a/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java b/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java index 4cf88cc2da..f740cbe31a 100644 --- a/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java +++ b/labs/openstack-nova/src/main/java/org/jclouds/openstack/nova/v1_1/config/NovaRestClientModule.java @@ -29,8 +29,7 @@ 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.domain.Access; -import org.jclouds.openstack.keystone.v2_0.domain.Service; +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; @@ -41,9 +40,8 @@ import org.jclouds.openstack.services.ServiceType; import org.jclouds.rest.ConfiguresRestClient; import org.jclouds.rest.config.RestClientModule; -import com.google.common.base.Predicate; +import com.google.common.base.Supplier; import com.google.common.collect.ImmutableMap; -import com.google.common.collect.Iterables; import com.google.inject.Provides; /** @@ -83,19 +81,11 @@ public class NovaRestClientModule extends RestClientModule(){ - - @Override - public boolean apply(Service input) { - return input.getId().equals(ServiceType.COMPUTE); - } - - }).getEndpoints()).getPublicURL(); + protected Supplier provideServerUrl(PublicURLFromAccessForService.Factory factory) { + return factory.create(ServiceType.COMPUTE); } }