added id to endpoint and used only endpoint.versionId to enforce endpointVersion

This commit is contained in:
Adrian Cole 2012-10-07 16:18:34 -07:00
parent a02c79c7f4
commit 99d3422b4d
16 changed files with 826 additions and 337 deletions

View File

@ -37,25 +37,33 @@ public interface KeystoneProperties {
* </ul>
*
* @see CredentialTypes
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_authenticate_v2.0_tokens_Service_API_Api_Operations.html"
* @see <a href=
* "http://docs.openstack.org/api/openstack-identity-service/2.0/content/POST_authenticate_v2.0_tokens_Service_API_Api_Operations.html"
* />
*/
public static final String CREDENTIAL_TYPE = "jclouds.keystone.credential-type";
/**
* set this property to specify the tenant id of the authenticated user. Cannot be used simultaneously with {@link #TENANT_NAME}
* set this property to specify the tenant id of the authenticated user.
* Cannot be used simultaneously with {@link #TENANT_NAME}
*
* @see <a href="http://wiki.openstack.org/CLIAuth">openstack docs</a>
*/
public static final String TENANT_ID = "jclouds.keystone.tenant-id";
/**
* set this property to specify the tenant name of the authenticated user. Cannot be used simultaneously with {@link #TENANT_ID}
* set this property to specify the tenant name of the authenticated user.
* Cannot be used simultaneously with {@link #TENANT_ID}
*
* @see <a href="http://wiki.openstack.org/CLIAuth">openstack docs</a>
*/
public static final String TENANT_NAME = "jclouds.keystone.tenant-name";
/**
* set this property to {@code true} to designate that the service requires explicit specification of either {@link #TENANT_NAME} or {@link #TENANT_ID}
* set this property to {@code true} to designate that the service requires
* explicit specification of either {@link #TENANT_NAME} or
* {@link #TENANT_ID}
*
* @see <a href="http://wiki.openstack.org/CLIAuth">openstack docs</a>
*/
public static final String REQUIRES_TENANT = "jclouds.keystone.requires-tenant";

View File

@ -27,16 +27,18 @@ import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ForwardingSet;
import com.google.common.collect.ImmutableSet;
/**
* TODO
*
* @author Adrian Cole
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Service_API_Api_Operations.html"
/>
* @see <a href=
* "http://docs.openstack.org/api/openstack-identity-service/2.0/content/Identity-Service-Concepts-e1362.html"
* />
*/
public class Access implements Comparable<Access> {
public class Access extends ForwardingSet<Service> implements Comparable<Access> {
public static Builder<?> builder() {
return new ConcreteBuilder();
@ -51,7 +53,7 @@ public class Access implements Comparable<Access> {
protected Token token;
protected User user;
protected Set<Service> serviceCatalog = ImmutableSet.of();
protected ImmutableSet.Builder<Service> serviceCatalog = ImmutableSet.<Service> builder();
/**
* @see Access#getToken()
@ -70,26 +72,44 @@ public class Access implements Comparable<Access> {
}
/**
* @see Access#getServiceCatalog()
* @see Access#delegate()
*/
public T serviceCatalog(Set<Service> serviceCatalog) {
this.serviceCatalog = ImmutableSet.copyOf(checkNotNull(serviceCatalog, "serviceCatalog"));
public T service(Service service) {
this.serviceCatalog.add(service);
return self();
}
/**
* @see Access#delegate()
*/
public T services(Iterable<Service> serviceCatalog) {
this.serviceCatalog.addAll(serviceCatalog);
return self();
}
/**
* @see #services(Iterable)
*/
@Deprecated
public T serviceCatalog(Set<Service> serviceCatalog) {
this.serviceCatalog.addAll(serviceCatalog);
return self();
}
/**
* @see #services(Iterable)
*/
@Deprecated
public T serviceCatalog(Service... in) {
return serviceCatalog(ImmutableSet.copyOf(in));
}
public Access build() {
return new Access(token, user, serviceCatalog);
return new Access(token, user, serviceCatalog.build());
}
public T fromAccess(Access in) {
return this
.token(in.getToken())
.user(in.getUser())
.serviceCatalog(in.getServiceCatalog());
return this.token(in.getToken()).user(in.getUser()).services(in);
}
}
@ -104,9 +124,7 @@ public class Access implements Comparable<Access> {
private final User user;
private final Set<Service> serviceCatalog;
@ConstructorProperties({
"token", "user", "serviceCatalog"
})
@ConstructorProperties({ "token", "user", "serviceCatalog" })
protected Access(Token token, User user, @Nullable Set<Service> serviceCatalog) {
this.token = checkNotNull(token, "token");
this.user = checkNotNull(user, "user");
@ -128,8 +146,9 @@ public class Access implements Comparable<Access> {
}
/**
* TODO
* Please access the service catalog via normal collection mechanisms
*/
@Deprecated
public Set<Service> getServiceCatalog() {
return this.serviceCatalog;
}
@ -141,17 +160,18 @@ public class Access implements Comparable<Access> {
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
Access that = Access.class.cast(obj);
return Objects.equal(this.token, that.token)
&& Objects.equal(this.user, that.user)
return Objects.equal(this.token, that.token) && Objects.equal(this.user, that.user)
&& Objects.equal(this.serviceCatalog, that.serviceCatalog);
}
protected ToStringHelper string() {
return Objects.toStringHelper(this)
.add("token", token).add("user", user).add("serviceCatalog", serviceCatalog);
return Objects.toStringHelper(this).omitNullValues().add("token", token).add("user", user)
.add("serviceCatalog", serviceCatalog);
}
@Override
@ -168,4 +188,9 @@ public class Access implements Comparable<Access> {
return this.token.compareTo(that.token);
}
@Override
protected Set<Service> delegate() {
return serviceCatalog;
}
}

View File

@ -27,13 +27,15 @@ import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
/**
* An network-accessible address, usually described by URL, where a service may be accessed. If
* using an extension for templates, you can create an endpoint template, which represents the
* templates of all the consumable services that are available across the regions.
* An network-accessible address, usually described by URL, where a service may
* be accessed. If using an extension for templates, you can create an endpoint
* template, which represents the templates of all the consumable services that
* are available across the regions.
*
* @author AdrianCole
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Identity-Endpoint-Concepts-e1362.html"
/>
* @see <a href=
* "http://docs.openstack.org/api/openstack-identity-service/2.0/content/Identity-Endpoint-Concepts-e1362.html"
* />
*/
public class Endpoint {
@ -48,6 +50,7 @@ public class Endpoint {
public static abstract class Builder<T extends Builder<T>> {
protected abstract T self();
protected String id;
protected String versionId;
protected String region;
protected URI publicURL;
@ -57,6 +60,15 @@ public class Endpoint {
protected URI versionInfo;
protected URI versionList;
/**
* @see Endpoint#getId()
*/
public T id(String id) {
this.id = id;
return self();
}
/**
* @see Endpoint#getVersionId()
*/
@ -113,6 +125,41 @@ public class Endpoint {
return self();
}
/**
* @see Endpoint#getPublicURL()
*/
public T publicURL(String publicURL) {
return publicURL(URI.create(publicURL));
}
/**
* @see Endpoint#getInternalURL()
*/
public T internalURL(String internalURL) {
return internalURL(URI.create(internalURL));
}
/**
* @see Endpoint#getAdminURL()
*/
public T adminURL(String adminURL) {
return adminURL(URI.create(adminURL));
}
/**
* @see Endpoint#getVersionInfo()
*/
public T versionInfo(String versionInfo) {
return versionInfo(URI.create(versionInfo));
}
/**
* @see Endpoint#getVersionList()
*/
public T versionList(String versionList) {
return versionList(URI.create(versionList));
}
/**
* @see Endpoint#getTenantId()
*/
@ -122,19 +169,14 @@ public class Endpoint {
}
public Endpoint build() {
return new Endpoint(null, versionId, region, publicURL, internalURL, adminURL, versionInfo, versionList, null, tenantId);
return new Endpoint(id, versionId, region, publicURL, internalURL, adminURL, versionInfo, versionList, null,
tenantId);
}
public T fromEndpoint(Endpoint in) {
return this
.versionId(in.getVersionId())
.region(in.getRegion())
.publicURL(in.getPublicURL())
.internalURL(in.getInternalURL())
.adminURL(in.getAdminURL())
.versionInfo(in.getVersionInfo())
.versionList(in.getVersionList())
.tenantId(in.getTenantId());
return this.versionId(in.getVersionId()).region(in.getRegion()).publicURL(in.getPublicURL())
.internalURL(in.getInternalURL()).adminURL(in.getAdminURL()).versionInfo(in.getVersionInfo())
.versionList(in.getVersionList()).tenantId(in.getTenantId());
}
}
@ -145,22 +187,26 @@ public class Endpoint {
}
}
private final String versionId;
private final String id;
private final String tenantId;
private final String region;
private final URI publicURL;
private final URI internalURL;
private final URI adminURL;
// fields not defined in
// https://github.com/openstack/keystone/blob/master/keystone/service.py
private final String versionId;
private final URI versionInfo;
private final URI versionList;
private final String tenantId;
@ConstructorProperties({
"id", "versionId", "region", "publicURL", "internalURL", "adminURL", "versionInfo", "versionList", "tenantName", "tenantId"
})
protected Endpoint(@Nullable String id, @Nullable String versionId, @Nullable String region, @Nullable URI publicURL,
@Nullable URI internalURL, @Nullable URI adminURL, @Nullable URI versionInfo, @Nullable URI versionList,
@Nullable String tenantName, @Nullable String tenantId) {
this.versionId = versionId != null ? versionId : id;
@ConstructorProperties({ "id", "versionId", "region", "publicURL", "internalURL", "adminURL", "versionInfo",
"versionList", "tenantName", "tenantId" })
protected Endpoint(@Nullable String id, @Nullable String versionId, @Nullable String region,
@Nullable URI publicURL, @Nullable URI internalURL, @Nullable URI adminURL, @Nullable URI versionInfo,
@Nullable URI versionList, @Nullable String tenantName, @Nullable String tenantId) {
this.id = id;
this.versionId = versionId;
this.tenantId = tenantId != null ? tenantId : tenantName;
this.region = region;
this.publicURL = publicURL;
@ -171,10 +217,26 @@ public class Endpoint {
}
/**
* When providing an ID, it is assumed that the endpoint exists in the current OpenStack
* deployment
* When providing an ID, it is assumed that the endpoint exists in the
* current OpenStack deployment
*
* @return the versionId of the endpoint in the current OpenStack deployment, or null if not specified
* @return the id of the endpoint in the current OpenStack deployment, or
* null if not specified
*/
@Nullable
public String getId() {
return this.id;
}
/**
*
* <h4>Note</h4>
*
* This is not defined in <a href=
* "https://github.com/openstack/keystone/blob/master/keystone/service.py"
* >KeyStone</a>, rather only in <a href=
* "http://docs.rackspace.com/auth/api/v2.0/auth-client-devguide/content/Release_Notes-d1e140.html"
* >Rackspace</a>
*/
@Nullable
public String getVersionId() {
@ -213,11 +275,31 @@ public class Endpoint {
return this.adminURL;
}
/**
*
* <h4>Note</h4>
*
* This is not defined in <a href=
* "https://github.com/openstack/keystone/blob/master/keystone/service.py"
* >KeyStone</a>, rather only in <a href=
* "http://docs.rackspace.com/auth/api/v2.0/auth-client-devguide/content/Release_Notes-d1e140.html"
* >Rackspace</a>
*/
@Nullable
public URI getVersionInfo() {
return this.versionInfo;
}
/**
*
* <h4>Note</h4>
*
* This is not defined in <a href=
* "https://github.com/openstack/keystone/blob/master/keystone/service.py"
* >KeyStone</a>, rather only in <a href=
* "http://docs.rackspace.com/auth/api/v2.0/auth-client-devguide/content/Release_Notes-d1e140.html"
* >Rackspace</a>
*/
@Nullable
public URI getVersionList() {
return this.versionList;
@ -233,28 +315,29 @@ public class Endpoint {
@Override
public int hashCode() {
return Objects.hashCode(versionId, region, publicURL, internalURL, adminURL, versionInfo, versionList, tenantId);
return Objects.hashCode(id, versionId, region, publicURL, internalURL, adminURL, versionInfo, versionList,
tenantId);
}
@Override
public boolean equals(Object obj) {
if (this == obj) return true;
if (obj == null || getClass() != obj.getClass()) return false;
if (this == obj)
return true;
if (obj == null || getClass() != obj.getClass())
return false;
Endpoint that = Endpoint.class.cast(obj);
return Objects.equal(this.versionId, that.versionId)
&& Objects.equal(this.region, that.region)
&& Objects.equal(this.publicURL, that.publicURL)
&& Objects.equal(this.internalURL, that.internalURL)
&& Objects.equal(this.adminURL, that.adminURL)
&& Objects.equal(this.versionInfo, that.versionInfo)
&& Objects.equal(this.versionList, that.versionList)
return Objects.equal(this.id, that.id) && Objects.equal(this.versionId, that.versionId)
&& Objects.equal(this.region, that.region) && Objects.equal(this.publicURL, that.publicURL)
&& Objects.equal(this.internalURL, that.internalURL) && Objects.equal(this.adminURL, that.adminURL)
&& Objects.equal(this.versionInfo, that.versionInfo) && Objects.equal(this.versionList, that.versionList)
&& Objects.equal(this.tenantId, that.tenantId);
}
protected ToStringHelper string() {
return Objects.toStringHelper(this).omitNullValues()
.add("versionId", versionId).add("region", region).add("publicURL", publicURL).add("internalURL", internalURL)
.add("adminURL", adminURL).add("versionInfo", versionInfo).add("versionList", versionList).add("tenantId", tenantId);
return Objects.toStringHelper(this).omitNullValues().add("id", id).add("versionId", versionId)
.add("region", region).add("publicURL", publicURL).add("internalURL", internalURL)
.add("adminURL", adminURL).add("versionInfo", versionInfo).add("versionList", versionList)
.add("tenantId", tenantId);
}
@Override

View File

@ -195,7 +195,7 @@ public class Role {
}
protected ToStringHelper string() {
return Objects.toStringHelper(this)
return Objects.toStringHelper(this).omitNullValues()
.add("id", id).add("name", name).add("description", description).add("serviceId", serviceId).add("tenantId", tenantId);
}

View File

@ -25,7 +25,6 @@ import java.util.Set;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ComparisonChain;
import com.google.common.collect.ForwardingSet;
import com.google.common.collect.ImmutableSet;
@ -38,7 +37,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"
/>
*/
public class Service extends ForwardingSet<Endpoint> implements Comparable<Service> {
public class Service extends ForwardingSet<Endpoint> {
public static Builder<?> builder() {
return new ConcreteBuilder();
@ -53,7 +52,7 @@ public class Service extends ForwardingSet<Endpoint> implements Comparable<Servi
protected String type;
protected String name;
protected Set<Endpoint> endpoints = ImmutableSet.of();
protected ImmutableSet.Builder<Endpoint> endpoints = ImmutableSet.<Endpoint>builder();
/**
* @see Service#getType()
@ -72,26 +71,38 @@ public class Service extends ForwardingSet<Endpoint> implements Comparable<Servi
}
/**
* @see Service#getEndpoints()
* @see Service#delegate()
*/
public T endpoints(Set<Endpoint> endpoints) {
this.endpoints = ImmutableSet.copyOf(checkNotNull(endpoints, "endpoints"));
public T endpoint(Endpoint endpoint) {
this.endpoints.add(endpoint);
return self();
}
/**
* @see Service#delegate()
*/
public T endpoints(Iterable<Endpoint> endpoints) {
this.endpoints.addAll(endpoints);
return self();
}
/**
* @see #endpoints(Iterable)
*/
@Deprecated
public T endpoints(Endpoint... in) {
return endpoints(ImmutableSet.copyOf(in));
}
public Service build() {
return new Service(type, name, endpoints);
return new Service(type, name, endpoints.build());
}
public T fromService(Service in) {
return this
.type(in.getType())
.name(in.getName())
.endpoints(in.getEndpoints());
.endpoints(in);
}
}
private static class ConcreteBuilder extends Builder<ConcreteBuilder> {
@ -131,8 +142,9 @@ public class Service extends ForwardingSet<Endpoint> implements Comparable<Servi
}
/**
* @return the endpoints assigned to the service
* Please use this as a Set
*/
@Deprecated
public Set<Endpoint> getEndpoints() {
return this.endpoints;
}
@ -153,7 +165,7 @@ public class Service extends ForwardingSet<Endpoint> implements Comparable<Servi
}
protected ToStringHelper string() {
return Objects.toStringHelper(this)
return Objects.toStringHelper(this).omitNullValues()
.add("type", type).add("name", name).add("endpoints", endpoints);
}
@ -162,14 +174,6 @@ public class Service extends ForwardingSet<Endpoint> implements Comparable<Servi
return string().toString();
}
@Override
public int compareTo(Service that) {
return ComparisonChain.start()
.compare(this.type, that.type)
.compare(this.name, that.name)
.result();
}
@Override
protected Set<Endpoint> delegate() {
return endpoints;

View File

@ -148,7 +148,7 @@ public class Tenant {
}
protected ToStringHelper string() {
return Objects.toStringHelper(this)
return Objects.toStringHelper(this).omitNullValues()
.add("id", id).add("name", name).add("description", description);
}

View File

@ -27,6 +27,7 @@ import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
import com.google.common.base.Objects.ToStringHelper;
import com.google.common.collect.ForwardingSet;
import com.google.common.collect.ImmutableSet;
/**
@ -37,10 +38,10 @@ import com.google.common.collect.ImmutableSet;
* tenant.
*
* @author Adrian Cole
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Identity-Service-Concepts-e1362.html"
* @see <a href="http://docs.openstack.org/api/openstack-identity-service/2.0/content/Identity-User-Concepts-e1362.html"
* />
*/
public class User {
public class User extends ForwardingSet<Role> {
public static Builder<?> builder() {
return new ConcreteBuilder();
@ -55,7 +56,7 @@ public class User {
protected String id;
protected String name;
protected Set<Role> roles = ImmutableSet.of();
protected ImmutableSet.Builder<Role> roles = ImmutableSet.<Role> builder();
/**
* @see User#getId()
@ -74,26 +75,38 @@ public class User {
}
/**
* @see User#getRoles()
* @see User#delegate()
*/
public T roles(Set<Role> roles) {
this.roles = ImmutableSet.copyOf(checkNotNull(roles, "roles"));
public T role(Role role) {
this.roles.add(role);
return self();
}
/**
* @see User#delegate()
*/
public T roles(Iterable<Role> roles) {
this.roles.addAll(roles);
return self();
}
/**
* @see #roles(Iterable)
*/
@Deprecated
public T roles(Role... in) {
return roles(ImmutableSet.copyOf(in));
}
public User build() {
return new User(id, name, roles);
return new User(id, name, roles.build());
}
public T fromUser(User in) {
return this
.id(in.getId())
.name(in.getName())
.roles(in.getRoles());
.roles(in);
}
}
@ -114,7 +127,7 @@ public class User {
protected User(String id, String name, @Nullable Set<Role> roles) {
this.id = checkNotNull(id, "id");
this.name = checkNotNull(name, "name");
this.roles = roles == null ? ImmutableSet.<Role>of() : ImmutableSet.copyOf(checkNotNull(roles, "roles"));
this.roles = roles == null ? ImmutableSet.<Role>of() : ImmutableSet.copyOf(roles);
}
/**
@ -134,8 +147,10 @@ public class User {
}
/**
* Please use User as a Set
* @return the roles assigned to the user
*/
@Deprecated
public Set<Role> getRoles() {
return this.roles;
}
@ -156,7 +171,7 @@ public class User {
}
protected ToStringHelper string() {
return Objects.toStringHelper(this)
return Objects.toStringHelper(this).omitNullValues()
.add("id", id).add("name", name).add("roles", roles);
}
@ -165,4 +180,9 @@ public class User {
return string().toString();
}
@Override
protected Set<Role> delegate() {
return roles;
}
}

View File

@ -18,29 +18,63 @@
*/
package org.jclouds.openstack.keystone.v2_0.suppliers;
import static com.google.common.collect.Iterables.any;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.size;
import static com.google.common.collect.Iterables.tryFind;
import static com.google.common.collect.Multimaps.index;
import java.net.URI;
import java.util.Collection;
import java.util.Map;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.inject.Inject;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.logging.Logger;
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.EndpointToSupplierURI;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.Iterables;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import com.google.common.collect.Multimap;
import com.google.inject.Inject;
import com.google.inject.assistedinject.Assisted;
@Singleton
public class LocationIdToURIFromAccessForTypeAndVersion implements Supplier<Map<String, Supplier<URI>>> {
public 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, or null if not available
* @return locations mapped to default uri
* @throws NoSuchElementException
* if the {@code apiType} is not present in the catalog
*/
LocationIdToURIFromAccessForTypeAndVersion createForApiTypeAndVersion(@Assisted("apiType") String apiType,
@Nullable @Assisted("apiVersion") String apiVersion) throws NoSuchElementException;
}
@Resource
protected Logger logger = Logger.NULL;
protected final Supplier<Access> access;
protected final EndpointToSupplierURI endpointToSupplierURI;
protected final Function<Endpoint, String> endpointToLocationId;
@ -50,7 +84,7 @@ public class LocationIdToURIFromAccessForTypeAndVersion implements Supplier<Map<
@Inject
public LocationIdToURIFromAccessForTypeAndVersion(Supplier<Access> access,
EndpointToSupplierURI endpointToSupplierURI, Function<Endpoint, String> endpointToLocationId,
@Assisted("apiType") String apiType, @Assisted("apiVersion") String apiVersion) {
@Assisted("apiType") String apiType, @Nullable @Assisted("apiVersion") String apiVersion) {
this.access = access;
this.endpointToSupplierURI = endpointToSupplierURI;
this.endpointToLocationId = endpointToLocationId;
@ -60,38 +94,112 @@ public class LocationIdToURIFromAccessForTypeAndVersion implements Supplier<Map<
@Override
public Map<String, Supplier<URI>> get() {
Access accessResponse = access.get();
Set<Service> services = Sets.filter(accessResponse.getServiceCatalog(), new Predicate<Service>() {
FluentIterable<Service> services = FluentIterable.from(access.get()).filter(apiTypeEquals);
if (services.toImmutableSet().size() == 0)
throw new NoSuchElementException(String.format("apiType %s not found in catalog %s", apiType, services));
Iterable<Endpoint> endpoints = concat(services);
if (size(endpoints) == 0)
throw new NoSuchElementException(
String.format("no endpoints for apiType %s in services %s", apiType, services));
boolean checkVersionId = any(endpoints, versionAware);
Multimap<String, Endpoint> locationToEndpoints = index(endpoints, endpointToLocationId);
Map<String, Endpoint> locationToEndpoint;
if (checkVersionId && apiVersion != null) {
locationToEndpoint = refineToVersionSpecificEndpoint(locationToEndpoints);
if (locationToEndpoint.size() == 0)
throw new NoSuchElementException(String.format(
"no endpoints for apiType %s are of version %s, or version agnostic: %s", apiType, apiVersion,
locationToEndpoints));
} else {
locationToEndpoint = firstEndpointInLocation(locationToEndpoints);
}
logger.debug("endpoints for apiType %s and version %s: %s", apiType, apiVersion, locationToEndpoints);
return Maps.transformValues(locationToEndpoint, endpointToSupplierURI);
}
@VisibleForTesting
Map<String, Endpoint> firstEndpointInLocation(Multimap<String, Endpoint> locationToEndpoints) {
Builder<String, Endpoint> locationToEndpointBuilder = ImmutableMap.<String, Endpoint> builder();
for (String locationId : locationToEndpoints.keySet()) {
Collection<Endpoint> endpoints = locationToEndpoints.get(locationId);
switch (endpoints.size()) {
case 0:
logNoEndpointsInLocation(locationId);
break;
default:
locationToEndpointBuilder.put(locationId, Iterables.get(endpoints, 0));
}
}
return locationToEndpointBuilder.build();
}
@VisibleForTesting
Map<String, Endpoint> refineToVersionSpecificEndpoint(Multimap<String, Endpoint> locationToEndpoints) {
Builder<String, Endpoint> locationToEndpointBuilder = ImmutableMap.<String, Endpoint> builder();
for (String locationId : locationToEndpoints.keySet()) {
Collection<Endpoint> endpoints = locationToEndpoints.get(locationId);
switch (endpoints.size()) {
case 0:
logNoEndpointsInLocation(locationId);
break;
default:
putIfPresent(locationId, strictMatchEndpointVersion(endpoints, locationId), locationToEndpointBuilder);
}
}
return locationToEndpointBuilder.build();
}
/**
* Prioritizes endpoint.versionId over endpoint.id when matching
*/
private Optional<Endpoint> strictMatchEndpointVersion(Iterable<Endpoint> endpoints, String locationId) {
Optional<Endpoint> endpointOfVersion = tryFind(endpoints, apiVersionEqualsVersionId);
if (!endpointOfVersion.isPresent())
logger.debug("no endpoints of apiType %s matched expected version %s in location %s: %s", apiType, apiVersion,
locationId, endpoints);
return endpointOfVersion;
}
private void logNoEndpointsInLocation(String locationId) {
logger.debug("no endpoints found for apiType %s in location %s", apiType, locationId);
}
private final Predicate<Endpoint> apiVersionEqualsVersionId = new Predicate<Endpoint>() {
@Override
public boolean apply(Endpoint input) {
return input.getVersionId().equals(apiVersion);
}
};
private final Predicate<Endpoint> versionAware = new Predicate<Endpoint>() {
@Override
public boolean apply(Endpoint input) {
return input.getVersionId() != null;
}
};
private final Predicate<Service> apiTypeEquals = new Predicate<Service>() {
@Override
public boolean apply(Service input) {
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);
}
});
if (Iterables.size(endpoints) == 0)
throw new NoSuchElementException(String.format(
"no endpoints for apiType %s are of version %s, or version agnostic: %s", apiType, apiVersion,
services));
Map<String, Endpoint> locationIdToEndpoint = Maps.uniqueIndex(endpoints, endpointToLocationId);
return Maps.transformValues(locationIdToEndpoint, endpointToSupplierURI);
private static <K, V> void putIfPresent(K key, Optional<V> value, Builder<K, V> builder) {
if (value.isPresent())
builder.put(key, value.get());
}
@Override

View File

@ -143,7 +143,7 @@ public class TokenApiExpectTest extends BaseKeystoneRestApiExpectTest<KeystoneAp
assertEquals(endpoints, ImmutableSet.of(
Endpoint.builder().publicURL(URI.create("https://csnode.jclouds.org/v2.0/"))
.adminURL(URI.create("https://csnode.jclouds.org:35357/v2.0/"))
.region("region-a.geo-1").versionId("2.0").build()
.region("region-a.geo-1").id("2.0").versionId("2.0").build()
));
}

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.openstack.keystone.v2_0.parse;
import java.net.URI;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
@ -50,70 +48,67 @@ public class ParseAccessTest extends BaseItemParserTest<Access> {
@SelectJson("access")
@Consumes(MediaType.APPLICATION_JSON)
public Access expected() {
return Access.builder().token(
Token.builder().expires(new SimpleDateFormatDateService().iso8601DateParse("2012-01-18T21:35:59.050Z"))
.id("Auth_4f173437e4b013bee56d1007").tenant(
Tenant.builder().id("40806637803162").name("user@jclouds.org-default-tenant").build())
.build()).user(
User.builder().id("36980896575174").name("user@jclouds.org").roles(
Role.builder().id("00000000004022").serviceId("110").name("Admin").tenantId("40806637803162")
.build(),
Role.builder().id("00000000004024").serviceId("140").name("user").tenantId("40806637803162")
.build(),
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"))
.adminURL(URI.create("https://objects.jclouds.org/v1.0/"))
.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/"))
.adminURL(URI.create("https://csnode.jclouds.org:35357/v2.0/"))
.region("region-a.geo-1").versionId("2.0").build()).build(),
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")
.versionId("1.0").build()).build(),
Service.builder().name("Compute").type("compute").endpoints(
Endpoint.builder()
return Access.builder()
.token(Token.builder()
.expires(new SimpleDateFormatDateService().iso8601DateParse("2012-01-18T21:35:59.050Z"))
.id("Auth_4f173437e4b013bee56d1007")
.tenant(Tenant.builder().id("40806637803162").name("user@jclouds.org-default-tenant").build()).build())
.user(User.builder()
.id("36980896575174").name("user@jclouds.org")
.role(Role.builder().id("00000000004022").serviceId("110").name("Admin").tenantId("40806637803162").build())
.role(Role.builder().id("00000000004024").serviceId("140").name("user").tenantId("40806637803162").build())
.role(Role.builder().id("00000000004004").serviceId("100").name("domainuser").build())
.role(Role.builder().id("00000000004016").serviceId("120").name("netadmin").tenantId("40806637803162").build()).build())
.service(Service.builder().name("Object Storage").type("object-store")
.endpoint(Endpoint.builder()
.tenantId("40806637803162")
.publicURL("https://objects.jclouds.org/v1.0/40806637803162")
.adminURL("https://objects.jclouds.org/v1.0/")
.id("1.0")
.region("region-a.geo-1").build()).build())
.service(Service.builder().name("Identity").type("identity")
.endpoint(Endpoint.builder()
.publicURL("https://csnode.jclouds.org/v2.0/")
.adminURL("https://csnode.jclouds.org:35357/v2.0/")
.region("region-a.geo-1")
.id("2.0")
.versionId("2.0").build()).build())
.service(Service.builder().name("Image Management").type("image")
.endpoint(Endpoint.builder()
.tenantId("40806637803162")
.publicURL("https://glance.jclouds.org:9292/v1.0")
.region("az-1.region-a.geo-1")
.id("1.0").build()).build())
.service(Service.builder().name("Compute").type("compute")
.endpoint(Endpoint.builder()
.tenantId("3456")
.publicURL(URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"))
.publicURL("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456")
.region("az-1.region-a.geo-1")
.versionId("1.1")
.versionInfo(URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/"))
.versionList(URI.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com")).build(),
Endpoint.builder()
.versionInfo("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/")
.versionList("https://az-1.region-a.geo-1.compute.hpcloudsvc.com").build())
.endpoint(Endpoint.builder()
.tenantId("3456")
.publicURL(URI.create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"))
.publicURL("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456")
.region("az-2.region-a.geo-1")
.versionId("1.1")
.versionInfo(URI.create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v1.1/"))
.versionList(URI.create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com")).build(),
Endpoint.builder()
.versionInfo("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v1.1/")
.versionList("https://az-2.region-a.geo-1.compute.hpcloudsvc.com").build())
.endpoint(Endpoint.builder()
.tenantId("3456")
.publicURL(URI.create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"))
.publicURL("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456")
.region("az-3.region-a.geo-1")
.versionId("1.1")
.versionInfo(URI.create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v1.1/"))
.versionList(URI.create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com")).build()).build(),
Service.builder().name("Quantum Service").type("network").endpoints(
Endpoint.builder()
.versionInfo("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v1.1/")
.versionList("https://az-3.region-a.geo-1.compute.hpcloudsvc.com").build()).build())
.service(Service.builder().name("Quantum Service").type("network")
.endpoint(Endpoint.builder()
.tenantId("3456")
.publicURL(URI.create("https://csnode.jclouds.org:9696/v1.0/tenants/3456"))
.internalURL(URI.create("https://csnode.jclouds.org:9696/v1.0/tenants/3456"))
.adminURL(URI.create("https://csnode.jclouds.org:9696/v1.0"))
.publicURL("https://csnode.jclouds.org:9696/v1.0/tenants/3456")
.internalURL("https://csnode.jclouds.org:9696/v1.0/tenants/3456")
.adminURL("https://csnode.jclouds.org:9696/v1.0")
.region("region-a.geo-1")
.versionId("1.0").build()
).build())
.build();
.versionId("1.0").build()).build()).build();
}
}

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.openstack.keystone.v2_0.parse;
import java.net.URI;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
@ -36,7 +34,7 @@ import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
/**
* @author Adam Lowe
* @author Adam Lowe, Adrian Cole
*/
@Test(groups = "unit", testName = "ParseAdminAccessTest")
public class ParseAdminAccessTest extends BaseItemParserTest<Access> {
@ -50,52 +48,52 @@ public class ParseAdminAccessTest extends BaseItemParserTest<Access> {
@SelectJson("access")
@Consumes(MediaType.APPLICATION_JSON)
public Access expected() {
return Access.builder().token(
Token.builder().expires(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-08-01T13:08:52Z"))
.id("946b8ad1ede4422f87ab21dcba27896d").tenant(
Tenant.builder().id("2fdc88ae152948c690b97ba307acae9b").name("admin").build())
.build()).user(
User.builder().id("b4d134cfe3cf43ad8ba0c2fc5b5d8f91").name("admin").roles(
Role.builder().name("admin").build(),
Role.builder().name("KeystoneServiceAdmin").build(),
Role.builder().name("KeystoneAdmin").build()).build())
.serviceCatalog(
Service.builder().name("Compute Service").type("compute").endpoints(
Endpoint.builder()
.adminURL(URI.create("http://10.0.1.13:8774/v2/2fdc88ae152948c690b97ba307acae9b"))
.internalURL(URI.create("http://10.0.1.13:8774/v2/2fdc88ae152948c690b97ba307acae9b"))
.publicURL(URI.create("http://10.0.1.13:8774/v2/2fdc88ae152948c690b97ba307acae9b"))
.region("RegionOne").build()).build(),
Service.builder().name("S3 Service").type("s3").endpoints(
Endpoint.builder()
.adminURL(URI.create("http://10.0.1.13:3333"))
.internalURL(URI.create("http://10.0.1.13:3333"))
.publicURL(URI.create("http://10.0.1.13:3333"))
.region("RegionOne").build()).build(),
Service.builder().name("Image Service").type("image").endpoints(
Endpoint.builder()
.adminURL(URI.create("http://10.0.1.13:9292"))
.internalURL(URI.create("http://10.0.1.13:9292"))
.publicURL(URI.create("http://10.0.1.13:9292"))
.region("RegionOne").build()).build(),
Service.builder().name("Volume Service").type("volume").endpoints(
Endpoint.builder()
.adminURL(URI.create("http://10.0.1.13:8776/v1/2fdc88ae152948c690b97ba307acae9b"))
.internalURL(URI.create("http://10.0.1.13:8776/v1/2fdc88ae152948c690b97ba307acae9b"))
.publicURL(URI.create("http://10.0.1.13:8776/v1/2fdc88ae152948c690b97ba307acae9b"))
.region("RegionOne").build()).build(),
Service.builder().name("EC2 Service").type("ec2").endpoints(
Endpoint.builder()
.adminURL(URI.create("http://10.0.1.13:8773/services/Admin"))
.internalURL(URI.create("http://10.0.1.13:8773/services/Cloud"))
.publicURL(URI.create("http://10.0.1.13:8773/services/Cloud"))
.region("RegionOne").build()).build(),
Service.builder().name("Identity Service").type("identity").endpoints(
Endpoint.builder()
.adminURL(URI.create("http://10.0.1.13:35357/v2.0"))
.internalURL(URI.create("http://10.0.1.13:5000/v2.0"))
.publicURL(URI.create("http://10.0.1.13:5000/v2.0"))
.region("RegionOne").build()).build()
).build();
return Access.builder()
.token(Token.builder()
.expires(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-08-01T13:08:52Z"))
.id("946b8ad1ede4422f87ab21dcba27896d")
.tenant(Tenant.builder().id("2fdc88ae152948c690b97ba307acae9b").name("admin").build()).build())
.user(User.builder()
.id("b4d134cfe3cf43ad8ba0c2fc5b5d8f91")
.name("admin")
.role(Role.builder().name("admin").build())
.role(Role.builder().name("KeystoneServiceAdmin").build())
.role(Role.builder().name("KeystoneAdmin").build()).build())
.service(Service.builder().name("Compute Service").type("compute")
.endpoint(Endpoint.builder()
.adminURL("http://10.0.1.13:8774/v2/2fdc88ae152948c690b97ba307acae9b")
.internalURL("http://10.0.1.13:8774/v2/2fdc88ae152948c690b97ba307acae9b")
.publicURL("http://10.0.1.13:8774/v2/2fdc88ae152948c690b97ba307acae9b")
.region("RegionOne").build()).build())
.service(Service.builder().name("S3 Service").type("s3")
.endpoint(Endpoint.builder()
.adminURL("http://10.0.1.13:3333")
.internalURL("http://10.0.1.13:3333")
.publicURL("http://10.0.1.13:3333")
.region("RegionOne").build()).build())
.service(Service.builder().name("Image Service").type("image")
.endpoint(Endpoint.builder()
.adminURL("http://10.0.1.13:9292")
.internalURL("http://10.0.1.13:9292")
.publicURL("http://10.0.1.13:9292")
.region("RegionOne").build()).build())
.service(Service.builder().name("Volume Service").type("volume")
.endpoint(Endpoint.builder()
.adminURL("http://10.0.1.13:8776/v1/2fdc88ae152948c690b97ba307acae9b")
.internalURL("http://10.0.1.13:8776/v1/2fdc88ae152948c690b97ba307acae9b")
.publicURL("http://10.0.1.13:8776/v1/2fdc88ae152948c690b97ba307acae9b")
.region("RegionOne").build()).build())
.service(Service.builder().name("EC2 Service").type("ec2")
.endpoint(Endpoint.builder()
.adminURL("http://10.0.1.13:8773/services/Admin")
.internalURL("http://10.0.1.13:8773/services/Cloud")
.publicURL("http://10.0.1.13:8773/services/Cloud")
.region("RegionOne").build()).build())
.service(Service.builder().name("Identity Service").type("identity")
.endpoint(Endpoint.builder()
.adminURL("http://10.0.1.13:35357/v2.0")
.internalURL("http://10.0.1.13:5000/v2.0")
.publicURL("http://10.0.1.13:5000/v2.0")
.region("RegionOne").build()).build()).build();
}
}

View File

@ -18,8 +18,6 @@
*/
package org.jclouds.openstack.keystone.v2_0.parse;
import java.net.URI;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
@ -38,7 +36,7 @@ import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ParseAccessTest")
@Test(groups = "unit", testName = "ParseRackspaceAccessTest")
public class ParseRackspaceAccessTest extends BaseItemParserTest<Access> {
@Override
@ -50,64 +48,69 @@ public class ParseRackspaceAccessTest extends BaseItemParserTest<Access> {
@SelectJson("access")
@Consumes(MediaType.APPLICATION_JSON)
public Access expected() {
return Access.builder().token(
Token.builder().expires(new SimpleDateFormatDateService().iso8601DateParse("2012-06-06T20:56:47.000-05:00"))
.id("Auth_4f173437e4b013bee56d1007").tenant(
Tenant.builder().id("40806637803162").name("40806637803162").build())
.build()).user(
User.builder().id("54321").name("joe").roles(
Role.builder().id("3").name("identity:user-admin").description("User Admin Role.")
.build()).build()).serviceCatalog(
Service.builder().name("cloudDatabases").type("rax:database").endpoints(
Endpoint.builder().tenantId("40806637803162").publicURL(
URI.create("https://dfw.databases.api.rackspacecloud.com/v1.0/40806637803162"))
.region("DFW").build(),
Endpoint.builder().tenantId("40806637803162").publicURL(
URI.create("https://ord.databases.api.rackspacecloud.com/v1.0/40806637803162"))
.region("ORD").build()).build(),
Service.builder().name("cloudServers").type("compute").endpoints(
Endpoint.builder().tenantId("40806637803162").publicURL(
URI.create("https://servers.api.rackspacecloud.com/v1.0/40806637803162"))
.versionId("1.0").versionInfo(URI.create("https://servers.api.rackspacecloud.com/v1.0"))
.versionList(URI.create("https://servers.api.rackspacecloud.com/")).build()).build(),
Service.builder().name("cloudFiles").type("object-store").endpoints(
Endpoint.builder().tenantId("MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22").publicURL(
URI.create("https://storage101.dfw1.clouddrive.com/v1/MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22"))
.internalURL(
URI.create("https://snet-storage101.dfw1.clouddrive.com/v1/MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22"))
.region("DFW").build()).build(),
Service.builder().name("cloudServersOpenStack").type("compute").endpoints(
Endpoint.builder().tenantId("40806637803162").publicURL(
URI.create("https://dfw.servers.api.rackspacecloud.com/v2/40806637803162"))
.versionInfo(URI.create("https://dfw.servers.api.rackspacecloud.com/v2"))
.versionList(URI.create("https://dfw.servers.api.rackspacecloud.com/"))
return Access.builder()
.token(Token.builder()
.expires(new SimpleDateFormatDateService().iso8601DateParse("2012-06-06T20:56:47.000-05:00"))
.id("Auth_4f173437e4b013bee56d1007")
.tenant(Tenant.builder().id("40806637803162").name("40806637803162").build()).build())
.user(User.builder()
.id("54321")
.name("joe")
.role(Role.builder()
.id("3")
.name("identity:user-admin")
.description("User Admin Role.").build()).build())
.service(Service.builder().name("cloudDatabases").type("rax:database")
.endpoint(Endpoint.builder()
.tenantId("40806637803162")
.publicURL("https://dfw.databases.api.rackspacecloud.com/v1.0/40806637803162")
.region("DFW").build())
.endpoint(Endpoint.builder()
.tenantId("40806637803162")
.publicURL("https://ord.databases.api.rackspacecloud.com/v1.0/40806637803162")
.region("ORD").build()).build())
.service(Service.builder().name("cloudServers").type("compute")
.endpoint(Endpoint.builder()
.tenantId("40806637803162")
.publicURL("https://servers.api.rackspacecloud.com/v1.0/40806637803162")
.versionId("1.0")
.versionInfo("https://servers.api.rackspacecloud.com/v1.0")
.versionList("https://servers.api.rackspacecloud.com/").build()).build())
.service(Service.builder().name("cloudFiles").type("object-store")
.endpoint(Endpoint.builder()
.tenantId("MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22")
.publicURL("https://storage101.dfw1.clouddrive.com/v1/MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22")
.internalURL("https://snet-storage101.dfw1.clouddrive.com/v1/MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22")
.region("DFW").build()).build())
.service(Service.builder().name("cloudServersOpenStack").type("compute")
.endpoint(Endpoint.builder()
.tenantId("40806637803162")
.publicURL("https://dfw.servers.api.rackspacecloud.com/v2/40806637803162")
.versionInfo("https://dfw.servers.api.rackspacecloud.com/v2")
.versionList("https://dfw.servers.api.rackspacecloud.com/")
.versionId("2")
.region("DFW").build()).build(),
Service.builder().name("cloudLoadBalancers").type("rax:load-balancer").endpoints(
Endpoint.builder().tenantId("40806637803162").publicURL(
URI.create("https://ord.loadbalancers.api.rackspacecloud.com/v1.0/40806637803162"))
.region("ORD").build(),
Endpoint.builder().tenantId("40806637803162").publicURL(
URI.create("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/40806637803162"))
.region("DFW").build()).build(),
Service.builder().name("cloudMonitoring").type("rax:monitor").endpoints(
Endpoint.builder().tenantId("40806637803162").publicURL(
URI.create("https://monitoring.api.rackspacecloud.com/v1.0/40806637803162")).build()).build(),
Service.builder().name("cloudDNS").type("dnsextension:dns").endpoints(
Endpoint.builder().tenantId("40806637803162").publicURL(
URI.create("https://dns.api.rackspacecloud.com/v1.0/40806637803162")).build()).build(),
Service.builder().name("cloudFilesCDN").type("rax:object-cdn").endpoints(
Endpoint.builder().tenantId("MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22").publicURL(
URI.create("https://cdn1.clouddrive.com/v1/MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22"))
.region("DFW").build()).build()
).build();
.region("DFW").build()).build())
.service(Service.builder().name("cloudLoadBalancers").type("rax:load-balancer")
.endpoint(Endpoint.builder()
.tenantId("40806637803162")
.publicURL("https://ord.loadbalancers.api.rackspacecloud.com/v1.0/40806637803162")
.region("ORD").build())
.endpoint(Endpoint.builder()
.tenantId("40806637803162")
.publicURL("https://dfw.loadbalancers.api.rackspacecloud.com/v1.0/40806637803162")
.region("DFW").build()).build())
.service(Service.builder().name("cloudMonitoring").type("rax:monitor")
.endpoint(Endpoint.builder()
.tenantId("40806637803162")
.publicURL("https://monitoring.api.rackspacecloud.com/v1.0/40806637803162").build()).build())
.service(Service.builder().name("cloudDNS").type("dnsextension:dns")
.endpoint(Endpoint.builder()
.tenantId("40806637803162")
.publicURL("https://dns.api.rackspacecloud.com/v1.0/40806637803162").build()).build())
.service(Service.builder().name("cloudFilesCDN").type("rax:object-cdn")
.endpoint(Endpoint.builder()
.tenantId("MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22")
.publicURL("https://cdn1.clouddrive.com/v1/MossoCloudFS_dc1f419c-5059-4c87-a389-3f2e33a77b22")
.region("DFW").build()).build()).build();
}
}

View File

@ -0,0 +1,112 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.keystone.v2_0.parse;
import javax.ws.rs.Consumes;
import javax.ws.rs.core.MediaType;
import org.jclouds.date.internal.SimpleDateFormatDateService;
import org.jclouds.json.BaseItemParserTest;
import org.jclouds.openstack.keystone.v2_0.domain.Access;
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
import org.jclouds.openstack.keystone.v2_0.domain.Role;
import org.jclouds.openstack.keystone.v2_0.domain.Service;
import org.jclouds.openstack.keystone.v2_0.domain.Tenant;
import org.jclouds.openstack.keystone.v2_0.domain.Token;
import org.jclouds.openstack.keystone.v2_0.domain.User;
import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ParseRandomEndpointVersionAccessTest")
public class ParseRandomEndpointVersionAccessTest extends BaseItemParserTest<Access> {
@Override
public String resource() {
return "/access_version_uids.json";
}
@Override
@SelectJson("access")
@Consumes(MediaType.APPLICATION_JSON)
public Access expected() {
return Access.builder()
.token(Token.builder()
.expires(new SimpleDateFormatDateService().iso8601SecondsDateParse("2012-09-29T19:53:45Z"))
.id("b267e2e240624b108b1ed5bba6e5882e")
.tenant(Tenant.builder()
// "enabled": true,
.id("82d8d2f865484776a1daf1e2245d3317")
.name("demo").build()).build())
.service(Service.builder().type("compute").name("nova")
.endpoint(Endpoint.builder()
.adminURL("http://10.10.10.10:8774/v2/82d8d2f865484776a1daf1e2245d3317")
.region("RegionOne")
.internalURL("http://10.10.10.10:8774/v2/82d8d2f865484776a1daf1e2245d3317")
.id("bb3ce9ccdc5045909882688b90cc3ff0")
.publicURL("http://10.10.10.10:8774/v2/82d8d2f865484776a1daf1e2245d3317").build()).build())
.service(Service.builder().type("s3").name("s3")
.endpoint(Endpoint.builder()
.adminURL("http://10.10.10.10:3333")
.region("RegionOne")
.internalURL("http://10.10.10.10:3333")
.id("9646263f31ea4f499732c5e1370ecf5e")
.publicURL("http://10.10.10.10:3333").build()).build())
.service(Service.builder().type("image").name("glance")
.endpoint(Endpoint.builder()
.adminURL("http://10.10.10.10:9292")
.region("RegionOne")
.internalURL("http://10.10.10.10:9292")
.id("aa5d0b2574824ba097dc07faacf3be65")
.publicURL("http://10.10.10.10:9292").build()).build())
.service(Service.builder().type("volume").name("cinder")
.endpoint(Endpoint.builder()
.adminURL("http://10.10.10.10:8776/v1/82d8d2f865484776a1daf1e2245d3317")
.region("RegionOne")
.internalURL("http://10.10.10.10:8776/v1/82d8d2f865484776a1daf1e2245d3317")
.id("7679065b1405447eb5f1a38a6b99ccc0")
.publicURL("http://10.10.10.10:8776/v1/82d8d2f865484776a1daf1e2245d3317").build()).build())
.service(Service.builder().type("ec2").name("ec2")
.endpoint(Endpoint.builder()
.adminURL("http://10.10.10.10:8773/services/Admin")
.region("RegionOne")
.internalURL("http://10.10.10.10:8773/services/Cloud")
.id("22b007f023fb4c42be094916eb2bf18b")
.publicURL("http://10.10.10.10:8773/services/Cloud").build()).build())
.service(Service.builder().type("identity").name("keystone")
.endpoint(Endpoint.builder()
.adminURL("http://10.10.10.10:35357/v2.0")
.region("RegionOne")
.internalURL("http://10.10.10.10:5000/v2.0")
.id("57ee5fb4f9a840f3b965909681d0fc53")
.publicURL("http://10.10.10.10:5000/v2.0").build()).build())
.user(User.builder()
.id("ca248caf55844c14a4876c22112bbbb9")
.name("demo")
// .username("demo")
.role(Role.builder().name("Member").build()).build()).build();
// "metadata": {
// "is_admin": 0,
// "roles": ["1f697d8e3ace4f5a80f7701e554ee5d9"]
// }
}
}

View File

@ -0,0 +1,131 @@
/**
* Licensed to jclouds, Inc. (jclouds) under one or more
* contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. jclouds licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*/
package org.jclouds.openstack.keystone.v2_0.suppliers;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import java.util.Map;
import java.util.NoSuchElementException;
import javax.inject.Singleton;
import org.jclouds.location.Provider;
import org.jclouds.openstack.keystone.v2_0.domain.Access;
import org.jclouds.openstack.keystone.v2_0.domain.Endpoint;
import org.jclouds.openstack.keystone.v2_0.functions.EndpointToRegion;
import org.jclouds.openstack.keystone.v2_0.parse.ParseAccessTest;
import org.jclouds.openstack.keystone.v2_0.parse.ParseRackspaceAccessTest;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Provides;
import com.google.inject.TypeLiteral;
import com.google.inject.assistedinject.FactoryModuleBuilder;
/**
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "LocationIdToURIFromAccessForTypeAndVersionTest")
public class LocationIdToURIFromAccessForTypeAndVersionTest {
private final LocationIdToURIFromAccessForTypeAndVersion.Factory factory = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Provider.class).to("openstack-keystone");
bind(new TypeLiteral<Supplier<URI>>(){
}).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
bind(new TypeLiteral<Function<Endpoint, String>>(){}).to(EndpointToRegion.class);
install(new FactoryModuleBuilder().implement(LocationIdToURIFromAccessForTypeAndVersion.class,
LocationIdToURIFromAccessForTypeAndVersion.class).build(
LocationIdToURIFromAccessForTypeAndVersion.Factory.class));
}
@Provides
@Singleton
public Supplier<Access> provide() {
return Suppliers.ofInstance(new ParseAccessTest().expected());
}
}).getInstance(LocationIdToURIFromAccessForTypeAndVersion.Factory.class);
public void testRegionUnmatchesOkWhenNoVersionIdSet() {
assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.1").get(), Suppliers
.<URI> supplierFunction()), ImmutableMap.of("az-1.region-a.geo-1", URI
.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"), "az-2.region-a.geo-1", URI
.create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"), "az-3.region-a.geo-1", URI
.create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456")));
}
public void testRegionMatches() {
assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("compute", "1.1").get(), Suppliers
.<URI> supplierFunction()), ImmutableMap.of("az-1.region-a.geo-1", URI
.create("https://az-1.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"), "az-2.region-a.geo-1", URI
.create("https://az-2.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456"), "az-3.region-a.geo-1", URI
.create("https://az-3.region-a.geo-1.compute.hpcloudsvc.com/v1.1/3456")));
}
private final LocationIdToURIFromAccessForTypeAndVersion.Factory raxFactory = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Provider.class).to("rackspace");
bind(new TypeLiteral<Supplier<URI>>() {
}).annotatedWith(Provider.class).toInstance(Suppliers.ofInstance(URI.create("https://identity")));
bind(new TypeLiteral<Function<Endpoint, String>>(){}).to(EndpointToRegion.class);
install(new FactoryModuleBuilder().implement(LocationIdToURIFromAccessForTypeAndVersion.class,
LocationIdToURIFromAccessForTypeAndVersion.class).build(
LocationIdToURIFromAccessForTypeAndVersion.Factory.class));
}
@Provides
@Singleton
public Supplier<Access> provide() {
return Suppliers.ofInstance(new ParseRackspaceAccessTest().expected());
}
}).getInstance(LocationIdToURIFromAccessForTypeAndVersion.Factory.class);
@Test(expectedExceptions = NoSuchElementException.class)
public void testWhenNotInList() {
assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("goo", "1.0").get(), Suppliers
.<URI> supplierFunction()), ImmutableMap.of("rackspace", URI
.create("https://servers.api.rackspacecloud.com/v1.0/40806637803162")));
}
public void testProviderWhenNoRegions() {
Map<String, URI> withNoRegions = Maps.transformValues(raxFactory.createForApiTypeAndVersion("compute", "1.0")
.get(), Suppliers.<URI> supplierFunction());
assertEquals(withNoRegions, ImmutableMap.of("rackspace", URI
.create("https://servers.api.rackspacecloud.com/v1.0/40806637803162")));
}
public void testOkWithNoVersions() {
assertEquals(Maps.transformValues(raxFactory.createForApiTypeAndVersion("rax:database", null).get(), Suppliers
.<URI> supplierFunction()), ImmutableMap.of("DFW", URI
.create("https://dfw.databases.api.rackspacecloud.com/v1.0/40806637803162"), "ORD", URI
.create("https://ord.databases.api.rackspacecloud.com/v1.0/40806637803162")));
}
}

View File

@ -18,11 +18,11 @@
*/
package org.jclouds.openstack.nova.v2_0;
import static org.jclouds.Constants.PROPERTY_ENDPOINT;
import static org.testng.Assert.assertEquals;
import java.util.Properties;
import org.jclouds.Constants;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiExpectTest;
@ -31,13 +31,14 @@ import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* Tests to ensure that we can pick the only endpoint of a service
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "OverrideApiVersionExpectTest")
public class OverrideApiVersionExpectTest extends BaseNovaApiExpectTest {
@Test(groups = "unit", testName = "EndpointIdIsRandomExpectTest")
public class EndpointIdIsRandomExpectTest extends BaseNovaApiExpectTest {
public OverrideApiVersionExpectTest() {
public EndpointIdIsRandomExpectTest() {
this.identity = "demo:demo";
this.credential = "password";
}
@ -45,20 +46,21 @@ public class OverrideApiVersionExpectTest extends BaseNovaApiExpectTest {
@Override
protected Properties setupProperties() {
Properties overrides = super.setupProperties();
overrides.setProperty(Constants.PROPERTY_ENDPOINT, "http://10.10.10.10:5000/v2.0/");
overrides.setProperty(provider + ".api-version", "bb3ce9ccdc5045909882688b90cc3ff0");
overrides.setProperty(PROPERTY_ENDPOINT, "http://10.10.10.10:5000/v2.0/");
return overrides;
}
public void testVersionMatchOnConfiguredZonesWhenResponseIs2xx() {
HttpRequest authenticate = HttpRequest.builder().method("POST")
HttpRequest authenticate = HttpRequest
.builder()
.method("POST")
.endpoint("http://10.10.10.10:5000/v2.0/tokens")
.addHeader("Accept", "application/json")
.payload(payloadFromStringWithContentType(
"{\"auth\":{\"passwordCredentials\":{\"username\":\"demo\",\"password\":\"password\"},\"tenantName\":\"demo\"}}"
, "application/json")).build();
.payload(
payloadFromStringWithContentType(
"{\"auth\":{\"passwordCredentials\":{\"username\":\"demo\",\"password\":\"password\"},\"tenantName\":\"demo\"}}",
"application/json")).build();
HttpResponse authenticationResponse = HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/access_version_uids.json", "application/json")).build();