query across all keystone services of type, as opposed to chosing the first one

This commit is contained in:
Adrian Cole 2012-07-02 19:40:27 -07:00
parent fb98ce82f7
commit 3fd65f25ce
4 changed files with 57 additions and 44 deletions

View File

@ -22,9 +22,12 @@ import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper; import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import java.beans.ConstructorProperties;
import java.util.Set; import java.util.Set;
import com.google.common.base.Objects; import com.google.common.base.Objects;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ForwardingSet;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
/** /**
@ -36,7 +39,7 @@ import com.google.common.collect.ImmutableSet;
* @see <a href="http://docs.openstack.org/api/openstack-typeentity-service/2.0/content/Identity-Service-Concepts-e1362.html" * @see <a href="http://docs.openstack.org/api/openstack-typeentity-service/2.0/content/Identity-Service-Concepts-e1362.html"
* /> * />
*/ */
public class Service implements Comparable<Service> { public class Service extends ForwardingSet<Endpoint> implements Comparable<Service> {
public static Builder builder() { public static Builder builder() {
return new Builder(); return new Builder();
@ -91,16 +94,11 @@ public class Service implements Comparable<Service> {
} }
} }
protected Service() { protected final String type;
// we want serializers like Gson to work w/o using sun.misc.Unsafe, protected final String name;
// prohibited in GAE. This also implies fields are not final. protected final Set<Endpoint> endpoints;
// see http://code.google.com/p/jclouds/issues/detail?id=925
}
protected String type;
protected String name;
protected Set<Endpoint> endpoints = ImmutableSet.of();
@ConstructorProperties({ "type", "name", "endpoints" })
public Service(String type, String name, Set<Endpoint> endpoints) { public Service(String type, String name, Set<Endpoint> endpoints) {
this.type = checkNotNull(type, "type"); this.type = checkNotNull(type, "type");
this.name = checkNotNull(name, "name"); this.name = checkNotNull(name, "name");
@ -155,11 +153,15 @@ public class Service implements Comparable<Service> {
@Override @Override
public int compareTo(Service that) { public int compareTo(Service that) {
if (that == null) return ComparisonChain.start()
return 1; .compare(this.type, that.type)
if (this == that) .compare(this.name, that.name)
return 0; .result();
return this.type.compareTo(that.type); }
@Override
protected Set<Endpoint> delegate() {
return endpoints;
} }
} }

View File

@ -21,6 +21,7 @@ package org.jclouds.openstack.keystone.v2_0.suppliers;
import java.net.URI; import java.net.URI;
import java.util.Map; import java.util.Map;
import java.util.NoSuchElementException; import java.util.NoSuchElementException;
import java.util.Set;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Singleton; import javax.inject.Singleton;
@ -35,6 +36,7 @@ import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.Iterables; import com.google.common.collect.Iterables;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.inject.assistedinject.Assisted; import com.google.inject.assistedinject.Assisted;
@Singleton @Singleton
@ -59,32 +61,36 @@ public class LocationIdToURIFromAccessForTypeAndVersion implements Supplier<Map<
@Override @Override
public Map<String, Supplier<URI>> get() { public Map<String, Supplier<URI>> get() {
Access accessResponse = access.get(); Access accessResponse = access.get();
Service service = null; Set<Service> services = Sets.filter(accessResponse.getServiceCatalog(), new Predicate<Service>() {
try {
service = Iterables.find(accessResponse.getServiceCatalog(), new Predicate<Service>() {
@Override @Override
public boolean apply(Service input) { public boolean apply(Service input) {
return input.getType().equals(apiType); return input.getType().equals(apiType);
}
});
if (services.size() == 0)
throw new NoSuchElementException(String.format("apiType %s not found in catalog %s", apiType,
accessResponse.getServiceCatalog()));
Iterable<Endpoint> endpoints = Iterables.filter(Iterables.concat(services), new Predicate<Endpoint>() {
@Override
public boolean apply(Endpoint input) {
if (input.getVersionId() == null) {
return true;
} }
return input.getVersionId().equals(apiVersion);
}
}); });
} catch (NoSuchElementException e) {
throw new NoSuchElementException(String.format("apiType %s not found in catalog %s", apiType, accessResponse
.getServiceCatalog()));
}
Map<String, Endpoint> locationIdToEndpoint = Maps.uniqueIndex(Iterables.filter(service.getEndpoints(),
new Predicate<Endpoint>() {
@Override if (Iterables.size(endpoints) == 0)
public boolean apply(Endpoint input) { throw new NoSuchElementException(String.format(
if (input.getVersionId() == null) { "no endpoints for apiType %s are of version %s, or version agnostic: %s", apiType, apiVersion,
return true; services));
}
return input.getVersionId().equals(apiVersion);
}
}), endpointToLocationId); Map<String, Endpoint> locationIdToEndpoint = Maps.uniqueIndex(endpoints, endpointToLocationId);
return Maps.transformValues(locationIdToEndpoint, endpointToSupplierURI); return Maps.transformValues(locationIdToEndpoint, endpointToSupplierURI);
} }

View File

@ -59,7 +59,6 @@ public class RegionIdToURIFromAccessForTypeAndVersionTest {
RegionIdToURISupplier.Factory.class)); RegionIdToURISupplier.Factory.class));
} }
@SuppressWarnings("unused")
@Provides @Provides
@Singleton @Singleton
public Supplier<Access> provide() { public Supplier<Access> provide() {
@ -67,9 +66,13 @@ public class RegionIdToURIFromAccessForTypeAndVersionTest {
} }
}).getInstance(RegionIdToURISupplier.Factory.class); }).getInstance(RegionIdToURISupplier.Factory.class);
@Test(expectedExceptions = NoSuchElementException.class)
public void testRegionUnmatches() {
Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.0").get(),
Suppliers.<URI> supplierFunction());
}
public void testRegionMatches() { public void testRegionMatches() {
assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.0").get(), Suppliers
.<URI> supplierFunction()), ImmutableMap.of());
assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.1").get(), Suppliers assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.1").get(), Suppliers
.<URI> supplierFunction()), ImmutableMap.of("az-1.region-a.geo-1", URI .<URI> supplierFunction()), ImmutableMap.of("az-1.region-a.geo-1", URI
.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"), "az-2.region-a.geo-1", URI .create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"), "az-2.region-a.geo-1", URI
@ -89,7 +92,6 @@ public class RegionIdToURIFromAccessForTypeAndVersionTest {
RegionIdToURISupplier.Factory.class)); RegionIdToURISupplier.Factory.class));
} }
@SuppressWarnings("unused")
@Provides @Provides
@Singleton @Singleton
public Supplier<Access> provide() { public Supplier<Access> provide() {

View File

@ -58,7 +58,6 @@ public class ZoneIdToURIFromAccessForTypeAndVersionTest {
ZoneIdToURIFromAccessForTypeAndVersion.class).build(ZoneIdToURISupplier.Factory.class)); ZoneIdToURIFromAccessForTypeAndVersion.class).build(ZoneIdToURISupplier.Factory.class));
} }
@SuppressWarnings("unused")
@Provides @Provides
@Singleton @Singleton
public Supplier<Access> provide() { public Supplier<Access> provide() {
@ -66,9 +65,14 @@ public class ZoneIdToURIFromAccessForTypeAndVersionTest {
} }
}).getInstance(ZoneIdToURISupplier.Factory.class); }).getInstance(ZoneIdToURISupplier.Factory.class);
@Test(expectedExceptions = NoSuchElementException.class)
public void testZoneUnmatches() {
Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.0").get(),
Suppliers.<URI> supplierFunction());
}
public void testZoneMatches() { public void testZoneMatches() {
assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.0").get(), Suppliers
.<URI> supplierFunction()), ImmutableMap.of());
assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.1").get(), Suppliers assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.1").get(), Suppliers
.<URI> supplierFunction()), ImmutableMap.of("az-1.region-a.geo-1", URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"), .<URI> supplierFunction()), ImmutableMap.of("az-1.region-a.geo-1", URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"),
"az-2.region-a.geo-1", URI.create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"), "az-2.region-a.geo-1", URI.create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"),
@ -86,7 +90,6 @@ public class ZoneIdToURIFromAccessForTypeAndVersionTest {
ZoneIdToURIFromAccessForTypeAndVersion.class).build(ZoneIdToURISupplier.Factory.class)); ZoneIdToURIFromAccessForTypeAndVersion.class).build(ZoneIdToURISupplier.Factory.class));
} }
@SuppressWarnings("unused")
@Provides @Provides
@Singleton @Singleton
public Supplier<Access> provide() { public Supplier<Access> provide() {