JCLOUDS-646: Copied Cloud Identity v1.1 classes from openstack-common and fixed incorrect Keystone package names

This commit is contained in:
Jeremy Daggett 2014-07-31 10:28:33 -07:00 committed by Jeremy Daggett
parent e3d9851216
commit 95a3c7ec2c
22 changed files with 1683 additions and 0 deletions

View File

@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1;
import javax.ws.rs.Consumes;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.core.MediaType;
import org.jclouds.rackspace.cloudidentity.v1_1.binders.BindCredentialsToJsonPayload;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Auth;
import org.jclouds.rest.annotations.MapBinder;
import org.jclouds.rest.annotations.SelectJson;
import com.google.inject.name.Named;
/**
* Provides access to the Rackspace Cloud Identity v1.1 API.
*/
@Consumes(MediaType.APPLICATION_JSON)
@Path("/v1.1/auth")
public interface AuthenticationApi {
/**
* Authenticate to generate a token.
*
* @return access with token
*/
@Named("authenticate")
@POST
@SelectJson("auth")
@MapBinder(BindCredentialsToJsonPayload.class)
Auth authenticate(String username, String key);
}

View File

@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.binders;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.http.HttpRequest;
import org.jclouds.json.Json;
import org.jclouds.rest.MapBinder;
import org.jclouds.rest.binders.BindToJsonPayload;
import com.google.common.collect.ImmutableMap;
@Singleton
public class BindCredentialsToJsonPayload extends BindToJsonPayload implements MapBinder {
@Inject
public BindCredentialsToJsonPayload(Json jsonBinder) {
super(jsonBinder);
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Object toBind) {
throw new IllegalStateException("BindCredentialsToJsonPayload needs parameters");
}
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
return super.bindToRequest(request, ImmutableMap.of("credentials", postParams));
}
}

View File

@ -0,0 +1,31 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.config;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import javax.inject.Qualifier;
@Retention(value = RetentionPolicy.RUNTIME)
@Target(value = { ElementType.TYPE, ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
@Qualifier
public @interface Authentication {
}

View File

@ -0,0 +1,117 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.config;
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.annotation.ClientError;
import org.jclouds.location.Provider;
import org.jclouds.location.suppliers.ImplicitRegionIdSupplier;
import org.jclouds.location.suppliers.RegionIdToURISupplier;
import org.jclouds.rackspace.cloudidentity.v1_1.AuthenticationApi;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Auth;
import org.jclouds.rackspace.cloudidentity.v1_1.handlers.RetryOnRenew;
import org.jclouds.rackspace.cloudidentity.v1_1.suppliers.RegionIdToURIFromAuthForServiceSupplier;
import org.jclouds.rackspace.cloudidentity.v1_1.suppliers.V1DefaultRegionIdSupplier;
import com.google.common.base.Supplier;
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.assistedinject.FactoryModuleBuilder;
import com.google.inject.name.Named;
public class AuthenticationServiceModule extends AbstractModule {
@Override
protected void configure() {
// ServiceClient is used directly for filters and retry handlers, so let's bind it explicitly
bindHttpApi(binder(), AuthenticationApi.class);
install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
RegionIdToURIFromAuthForServiceSupplier.class).build(RegionIdToURISupplier.Factory.class));
install(new FactoryModuleBuilder().implement(ImplicitRegionIdSupplier.class, V1DefaultRegionIdSupplier.class)
.build(V1DefaultRegionIdSupplier.Factory.class));
bind(HttpRetryHandler.class).annotatedWith(ClientError.class).to(RetryOnRenew.class);
}
/**
* borrowing concurrency code to ensure that caching takes place properly
*/
@Provides
@Singleton
@Authentication
protected Supplier<String> provideAuthenticationTokenCache(final Supplier<Auth> supplier)
throws InterruptedException, ExecutionException, TimeoutException {
return new Supplier<String>() {
public String get() {
return supplier.get().getToken().getId();
}
};
}
@Singleton
public static class GetAuth extends CacheLoader<Credentials, Auth> {
private final AuthenticationApi client;
@Inject
public GetAuth(final AuthenticationApi client) {
this.client = client;
}
@Override
public Auth load(Credentials input) {
return client.authenticate(input.identity, input.credential);
}
@Override
public String toString() {
return "authenticate()";
}
}
@Provides
@Singleton
protected LoadingCache<Credentials, Auth> provideAuthCache(GetAuth getAuth,
@Named(PROPERTY_SESSION_INTERVAL) long sessionInterval) {
return CacheBuilder.newBuilder().expireAfterWrite(sessionInterval, TimeUnit.SECONDS).build(getAuth);
}
@Provides
@Singleton
protected Supplier<Auth> provideAuthSupplier(final LoadingCache<Credentials, Auth> cache,
@Provider final Supplier<Credentials> creds) {
return new Supplier<Auth>() {
@Override
public Auth get() {
return cache.getUnchecked(creds.get());
}
};
}
}

View File

@ -0,0 +1,123 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.domain;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Multimap;
/**
* Represents an Auth response.
*/
public class Auth implements Comparable<Auth> {
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromAccess(this);
}
public static class Builder {
protected Token token;
protected Multimap<String, Endpoint> serviceCatalog = ImmutableMultimap.of();
/**
* @see Auth#getToken()
*/
public Builder token(Token token) {
this.token = checkNotNull(token, "token");
return this;
}
/**
* @see Auth#getServiceCatalog()
*/
public Builder serviceCatalog(Multimap<String, Endpoint> serviceCatalog) {
this.serviceCatalog = ImmutableMultimap.copyOf(checkNotNull(serviceCatalog, "serviceCatalog"));
return this;
}
public Auth build() {
return new Auth(token, serviceCatalog);
}
public Builder fromAccess(Auth from) {
return token(from.getToken()).serviceCatalog(from.getServiceCatalog());
}
}
protected final Token token;
protected final Multimap<String, Endpoint> serviceCatalog;
public Auth(Token token, Multimap<String, Endpoint> serviceCatalog) {
this.token = checkNotNull(token, "token");
this.serviceCatalog = ImmutableMultimap.copyOf(checkNotNull(serviceCatalog, "serviceCatalog"));
}
/**
* TODO
*/
public Token getToken() {
return token;
}
/**
* TODO
*/
public Multimap<String, Endpoint> getServiceCatalog() {
return serviceCatalog;
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof Auth) {
final Auth other = Auth.class.cast(object);
return equal(token, other.token) && equal(serviceCatalog, other.serviceCatalog);
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hashCode(token, serviceCatalog);
}
@Override
public String toString() {
return toStringHelper("").add("token", token).add("serviceCatalog", serviceCatalog).toString();
}
@Override
public int compareTo(Auth that) {
if (that == null)
return 1;
if (this == that)
return 0;
return this.token.compareTo(that.token);
}
}

View File

@ -0,0 +1,198 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.domain;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import java.net.URI;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Objects;
/**
* 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.
*
*/
public class Endpoint implements Comparable<Endpoint> {
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromEndpoint(this);
}
public static class Builder {
protected boolean v1Default;
protected String region;
protected URI publicURL;
protected URI internalURL;
/**
* @see Endpoint#isV1Default()
*/
public Builder v1Default(boolean v1Default) {
this.v1Default = v1Default;
return this;
}
/**
* @see Endpoint#getRegion()
*/
public Builder region(String region) {
this.region = checkNotNull(region, "region");
return this;
}
/**
* @see Endpoint#getPublicURL()
*/
public Builder publicURL(URI publicURL) {
this.publicURL = checkNotNull(publicURL, "publicURL");
return this;
}
/**
* @see Endpoint#getTenantId()
*/
public Builder internalURL(@Nullable URI internalURL) {
this.internalURL = internalURL;
return this;
}
public Endpoint build() {
return new Endpoint(v1Default, region, publicURL, internalURL);
}
public Builder fromEndpoint(Endpoint from) {
return v1Default(from.isV1Default()).region(from.getRegion()).publicURL(from.getPublicURL())
.internalURL(from.getInternalURL());
}
}
protected Endpoint() {
// we want serializers like Gson to work w/o using sun.misc.Unsafe,
// prohibited in GAE. This also implies fields are not final.
// see http://code.google.com/p/jclouds/issues/detail?id=925
}
protected boolean v1Default;
protected String region;
protected URI publicURL;
protected URI internalURL;
protected Endpoint(boolean v1Default, @Nullable String region, @Nullable URI publicURL, @Nullable URI internalURL) {
this.v1Default = v1Default;
this.region = region;
this.publicURL = publicURL;
this.internalURL = internalURL;
}
/**
* The v1Default attribute denotes that an endpoint is being returned in
* version 1.0 of the Cloud Authentication Service. The default value of
* v1Default is false; clients should assume the value is false when the
* attribute is missing. Auth 1.0 does not offer support for regional
* endpoints and therefore only returns one endpoint per service. Resources
* stored in endpoints where v1Default is false will not be seen by Auth 1.0
* clients.
*
* @return whether this endpoint is visible to v1.0 clients
*/
public boolean isV1Default() {
return v1Default;
}
/**
* A service may expose endpoints in different regions. Regional endpoints
* allow clients to provision resources in a manner that provides high
* availability. <br/>
* <h3>Note</h3> Some services are not region-specific. These services supply
* a single non-regional endpoint and do not provide access to internal URLs.
*
* @return the region of the endpoint
*/
@Nullable
public String getRegion() {
return region;
}
/**
* A public URL is accessible from anywhere. Access to a public URL usually incurs traffic
* charges.
*
* @return the public endpoint of the service
*/
@Nullable
public URI getPublicURL() {
return publicURL;
}
/**
* Internal URLs are only accessible to services within the same region.
* Access to an internal URL is free of charge.
*
* @return the internal url of the endpoint
*/
@Nullable
public URI getInternalURL() {
return internalURL;
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof Endpoint) {
final Endpoint other = Endpoint.class.cast(object);
return equal(v1Default, other.v1Default) && equal(region, other.region) && equal(publicURL, other.publicURL)
&& equal(internalURL, other.internalURL);
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hashCode(v1Default, region, publicURL, internalURL);
}
@Override
public String toString() {
return toStringHelper("").add("v1Default", v1Default).add("region", region).add("publicURL", publicURL)
.add("internalURL", internalURL).toString();
}
@Override
public int compareTo(Endpoint that) {
if (that == null)
return 1;
if (this == that)
return 0;
return this.publicURL.compareTo(that.publicURL);
}
}

View File

@ -0,0 +1,137 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.domain;
import static com.google.common.base.Objects.equal;
import static com.google.common.base.Objects.toStringHelper;
import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Date;
import com.google.common.base.Objects;
/**
* Tokens are valid for a finite duration. The expires attribute denotes the
* time after which the token will automatically become invalid. A token may be
* manually revoked before the time identified by the expires attribute; expires
* predicts a token's maximum possible lifespan but does not guarantee that it
* will reach that lifespan. Clients are encouraged to cache a token until it
* expires.
*/
public class Token implements Comparable<Token> {
public static Builder builder() {
return new Builder();
}
public Builder toBuilder() {
return builder().fromToken(this);
}
public static class Builder {
protected String id;
protected Date expires;
/**
* @see Token#getId()
*/
public Builder id(String id) {
this.id = checkNotNull(id, "id");
return this;
}
/**
* @see Token#getExpires()
*/
public Builder expires(Date expires) {
this.expires = checkNotNull(expires, "expires");
return this;
}
public Token build() {
return new Token(id, expires);
}
public Builder fromToken(Token from) {
return id(from.getId()).expires(from.getExpires());
}
}
protected Token() {
// we want serializers like Gson to work w/o using sun.misc.Unsafe,
// prohibited in GAE. This also implies fields are not final.
// see http://code.google.com/p/jclouds/issues/detail?id=925
}
protected String id;
protected Date expires;
public Token(String id, Date expires) {
this.id = checkNotNull(id, "id");
this.expires = checkNotNull(expires, "expires");
}
/**
* When providing an ID, it is assumed that the token exists in the current
* OpenStack deployment
*
* @return the id of the token in the current OpenStack deployment
*/
public String getId() {
return id;
}
/**
* @return the expires of the token
*/
public Date getExpires() {
return expires;
}
@Override
public boolean equals(Object object) {
if (this == object) {
return true;
}
if (object instanceof Token) {
final Token other = Token.class.cast(object);
return equal(id, other.id) && equal(expires, other.expires);
} else {
return false;
}
}
@Override
public int hashCode() {
return Objects.hashCode(id, expires);
}
@Override
public String toString() {
return toStringHelper("").add("id", id).add("expires", expires).toString();
}
@Override
public int compareTo(Token that) {
if (that == null)
return 1;
if (this == that)
return 0;
return this.id.compareTo(that.id);
}
}

View File

@ -0,0 +1,27 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.functions;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Endpoint;
import com.google.common.base.Function;
import com.google.inject.ImplementedBy;
@ImplementedBy(RegionFirstPartOfDNSNameOrProvider.class)
public interface EndpointToRegion extends Function<Endpoint, String> {
}

View File

@ -0,0 +1,29 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.functions;
import java.net.URI;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Endpoint;
import com.google.common.base.Function;
import com.google.common.base.Supplier;
import com.google.inject.ImplementedBy;
@ImplementedBy(PublicURLOrInternalIfNull.class)
public interface EndpointToSupplierURI extends Function<Endpoint, Supplier<URI>> {
}

View File

@ -0,0 +1,39 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.functions;
import java.net.URI;
import javax.inject.Singleton;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Endpoint;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
@Singleton
public class PublicURLOrInternalIfNull implements EndpointToSupplierURI {
// TODO: check accessibility and prioritize private first
@Override
public Supplier<URI> apply(Endpoint input) {
return Suppliers.ofInstance(input.getPublicURL() != null ? input.getPublicURL() : input.getInternalURL());
}
public String toString() {
return "supplyPublicURL()";
}
}

View File

@ -0,0 +1,47 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.functions;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.location.Provider;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Endpoint;
import com.google.common.net.InternetDomainName;
@Singleton
public class RegionFirstPartOfDNSNameOrProvider implements EndpointToRegion {
private final String provider;
@Inject
RegionFirstPartOfDNSNameOrProvider(@Provider String provider) {
this.provider = provider;
}
@Override
public String apply(Endpoint input) {
if (input.getRegion() != null)
return input.getRegion();
String host = input.getPublicURL().getHost();
if (InternetDomainName.isValid(host)) {
InternetDomainName domain = InternetDomainName.from(host);
return domain.parts().get(0);
}
return provider;
}
}

View File

@ -0,0 +1,133 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.handlers;
import static org.jclouds.http.HttpUtils.closeClientButKeepContentStream;
import static org.jclouds.http.HttpUtils.releasePayload;
import java.util.concurrent.TimeUnit;
import javax.annotation.Resource;
import javax.inject.Named;
import org.jclouds.Constants;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.HttpRetryHandler;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.logging.Logger;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Auth;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.cache.Cache;
import com.google.common.cache.CacheBuilder;
import com.google.common.cache.LoadingCache;
import com.google.common.collect.Multimap;
import com.google.common.util.concurrent.Uninterruptibles;
import com.google.inject.Inject;
import com.google.inject.Singleton;
/**
* This will parse and set an appropriate exception on the command object.
*/
@Singleton
public class RetryOnRenew implements HttpRetryHandler {
@VisibleForTesting
@Inject(optional = true)
@Named(Constants.PROPERTY_MAX_RETRIES)
static int NUM_RETRIES = 5;
public final String AUTH_USER = "X-Auth-User";
public final String AUTH_KEY = "X-Auth-Key";
public final String AUTH_TOKEN = "X-Auth-Token";
@Resource
protected Logger logger = Logger.NULL;
private final LoadingCache<Credentials, Auth> authenticationResponseCache;
private final BackoffLimitedRetryHandler backoffHandler;
@Inject
protected RetryOnRenew(LoadingCache<Credentials, Auth> authenticationResponseCache,
BackoffLimitedRetryHandler backoffHandler) {
this.authenticationResponseCache = authenticationResponseCache;
this.backoffHandler = backoffHandler;
}
/*
* The reason retries need to be tracked is that it is possible that a token
* can be expired at any time. The reason we track by request is that only
* some requests might return a 401 (such as temporary URLs). However
* consistent failures of the magnitude this code tracks should indicate a
* problem.
*/
private static final Cache<HttpCommand, Integer> retryCountMap = CacheBuilder
.newBuilder().expireAfterWrite(5, TimeUnit.MINUTES).build();
@Override
public boolean shouldRetryRequest(HttpCommand command, HttpResponse response) {
boolean retry = false; // default
try {
switch (response.getStatusCode()) {
case 401:
// Do not retry on 401 from authentication request
Multimap<String, String> headers = command.getCurrentRequest().getHeaders();
if (headers != null && headers.containsKey(AUTH_USER)
&& headers.containsKey(AUTH_KEY) && !headers.containsKey(AUTH_TOKEN)) {
retry = false;
} else {
closeClientButKeepContentStream(response);
// This is not an authentication request returning 401
// Check if we already had seen this request
Integer count = retryCountMap.getIfPresent(command);
if (count == null) {
// First time this non-authentication request failed
logger.debug("invalidating authentication token - first time for %s", command);
retryCountMap.put(command, 1);
authenticationResponseCache.invalidateAll();
retry = true;
} else {
// This request has failed before
if (count + 1 >= NUM_RETRIES) {
logger.debug("too many 401s - giving up after: %s for %s", count, command);
retry = false;
} else {
// Retry just in case
logger.debug("invalidating authentication token - retry %s for %s", count, command);
retryCountMap.put(command, count + 1);
// Wait between retries
authenticationResponseCache.invalidateAll();
Uninterruptibles.sleepUninterruptibly(5, TimeUnit.SECONDS);
retry = true;
}
}
}
break;
case 408:
return backoffHandler.shouldRetryRequest(command, response);
}
return retry;
} finally {
releasePayload(response);
}
}
}

View File

@ -0,0 +1,67 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.suppliers;
import java.net.URI;
import java.util.Collection;
import java.util.Map;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.suppliers.RegionIdToURISupplier;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Auth;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Endpoint;
import org.jclouds.rackspace.cloudidentity.v1_1.functions.EndpointToRegion;
import org.jclouds.rackspace.cloudidentity.v1_1.functions.EndpointToSupplierURI;
import com.google.common.base.Supplier;
import com.google.common.collect.Maps;
import com.google.inject.assistedinject.Assisted;
@Singleton
public class RegionIdToURIFromAuthForServiceSupplier implements RegionIdToURISupplier {
private final Supplier<Auth> auth;
private final EndpointToSupplierURI endpointToSupplierURI;
private final EndpointToRegion endpointToRegion;
private final String apiType;
@Inject
public RegionIdToURIFromAuthForServiceSupplier(Supplier<Auth> auth, EndpointToSupplierURI endpointToSupplierURI,
EndpointToRegion endpointToRegion, @Assisted("apiType") String apiType,
@Nullable @Assisted("apiVersion") String apiVersion) {
this.auth = auth;
this.endpointToSupplierURI = endpointToSupplierURI;
this.endpointToRegion = endpointToRegion;
this.apiType = apiType;
}
@Override
public Map<String, Supplier<URI>> get() {
Auth authResponse = auth.get();
Collection<Endpoint> endpointsForService = authResponse.getServiceCatalog().get(apiType);
Map<String, Endpoint> regionIdToEndpoint = Maps.uniqueIndex(endpointsForService, endpointToRegion);
return Maps.transformValues(regionIdToEndpoint, endpointToSupplierURI);
}
@Override
public String toString() {
return "getPublicURLForService(" + apiType + ")";
}
}

View File

@ -0,0 +1,85 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.suppliers;
import static com.google.common.collect.Iterables.tryFind;
import java.util.NoSuchElementException;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.location.suppliers.ImplicitRegionIdSupplier;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Auth;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Endpoint;
import org.jclouds.rackspace.cloudidentity.v1_1.functions.EndpointToRegion;
import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.base.Supplier;
import com.google.common.collect.Iterables;
import com.google.inject.assistedinject.Assisted;
@Singleton
public class V1DefaultRegionIdSupplier implements ImplicitRegionIdSupplier {
public interface Factory {
/**
*
* @param apiType
* type of the api, according to the provider. ex. {@code compute}
* {@code object-store}
* @return region id
* @throws NoSuchElementException
* if the {@code apiType} is not present in the catalog
*/
ImplicitRegionIdSupplier createForApiType(@Assisted("apiType") String apiType) throws NoSuchElementException;
}
private final Supplier<Auth> auth;
private final EndpointToRegion endpointToRegion;
private final String apiType;
@Inject
public V1DefaultRegionIdSupplier(Supplier<Auth> auth, EndpointToRegion endpointToRegion,
@Assisted("apiType") String apiType) {
this.auth = auth;
this.endpointToRegion = endpointToRegion;
this.apiType = apiType;
}
/**
* returns {@link Endpoint#isV1Default()} or first endpoint for service
*/
@Override
public String get() {
Auth authResponse = auth.get();
Iterable<Endpoint> endpointsForService = authResponse.getServiceCatalog().get(apiType);
Optional<Endpoint> defaultEndpoint = tryFind(endpointsForService, new Predicate<Endpoint>() {
@Override
public boolean apply(Endpoint in) {
return in.isV1Default();
}
});
return endpointToRegion.apply(defaultEndpoint.or(Iterables.get(endpointsForService, 0)));
}
@Override
public String toString() {
return "defaultRegionIdFor(" + apiType + ")";
}
}

View File

@ -0,0 +1,44 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.functions;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Endpoint;
import org.jclouds.rackspace.cloudidentity.v1_1.functions.PublicURLOrInternalIfNull;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "PublicURLOrInternalIfNullTest")
public class PublicURLOrInternalIfNullTest {
private final PublicURLOrInternalIfNull fn = new PublicURLOrInternalIfNull();
public void testPublicURLNotNullReturnsPublicURL() {
assertEquals(fn.apply(
Endpoint.builder().region("LON").publicURL(
URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
.v1Default(true).build()).get(), URI
.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"));
}
public void testPublicURLNullReturnsInternalURL() {
assertEquals(fn.apply(Endpoint.builder().internalURL(URI.create("https://192.168.1.1")).v1Default(true).build())
.get(), URI.create("https://192.168.1.1"));
}
}

View File

@ -0,0 +1,48 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.functions;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Endpoint;
import org.jclouds.rackspace.cloudidentity.v1_1.functions.RegionFirstPartOfDNSNameOrProvider;
import org.testng.annotations.Test;
@Test(groups = "unit", testName = "RegionFirstPartOfDNSNameOrProviderTest")
public class RegionFirstPartOfDNSNameOrProviderTest {
private final RegionFirstPartOfDNSNameOrProvider fn = new RegionFirstPartOfDNSNameOrProvider("keystone");
public void testRegionNotNullReturnsRegion() {
assertEquals(fn.apply(Endpoint.builder().region("LON").publicURL(
URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
.v1Default(true).build()), "LON");
}
public void testRegionNullReturnsFirstPartOfHostWhenValid() {
assertEquals(fn.apply(Endpoint.builder().publicURL(
URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
.v1Default(true).build()), "cdn3");
}
public void testRegionNullReturnsProvioderWhenHostNotValid() {
assertEquals(fn.apply(Endpoint.builder().publicURL(URI.create("https://1.1.1.4")).v1Default(true).build()),
"keystone");
}
}

View File

@ -0,0 +1,166 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.handlers;
import static org.easymock.EasyMock.createMock;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.expectLastCall;
import static org.easymock.EasyMock.replay;
import static org.easymock.EasyMock.verify;
import static org.testng.Assert.assertFalse;
import static org.testng.Assert.assertTrue;
import org.jclouds.domain.Credentials;
import org.jclouds.http.HttpCommand;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
import org.jclouds.io.Payloads;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Auth;
import org.jclouds.rackspace.cloudidentity.v1_1.handlers.RetryOnRenew;
import org.testng.annotations.Test;
import com.google.common.cache.LoadingCache;
/**
* Tests behavior of {@code RetryOnRenew} handler
*/
@Test(groups = "unit", testName = "RetryOnRenewTest")
public class RetryOnRenewTest {
@Test
public void test401ShouldRetry() {
HttpCommand command = createMock(HttpCommand.class);
HttpRequest request = createMock(HttpRequest.class);
HttpResponse response = createMock(HttpResponse.class);
@SuppressWarnings("unchecked")
LoadingCache<Credentials, Auth> cache = createMock(LoadingCache.class);
BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class);
expect(command.getCurrentRequest()).andReturn(request);
cache.invalidateAll();
expectLastCall();
expect(response.getPayload()).andReturn(Payloads.newStringPayload("token expired, please renew")).anyTimes();
expect(response.getStatusCode()).andReturn(401).atLeastOnce();
replay(command);
replay(response);
replay(cache);
replay(backoffHandler);
RetryOnRenew retry = new RetryOnRenew(cache, backoffHandler);
assertTrue(retry.shouldRetryRequest(command, response));
verify(command);
verify(response);
verify(cache);
verify(backoffHandler);
}
@Test
public void test401ShouldRetry4Times() {
HttpCommand command = createMock(HttpCommand.class);
HttpRequest request = createMock(HttpRequest.class);
HttpResponse response = createMock(HttpResponse.class);
@SuppressWarnings("unchecked")
LoadingCache<Credentials, Auth> cache = createMock(LoadingCache.class);
BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class);
expect(command.getCurrentRequest()).andReturn(request).anyTimes();
expect(request.getHeaders()).andStubReturn(null);
cache.invalidateAll();
expectLastCall().anyTimes();
expect(response.getPayload()).andReturn(Payloads.newStringPayload(""))
.anyTimes();
expect(response.getStatusCode()).andReturn(401).anyTimes();
replay(command, request, response, cache);
RetryOnRenew retry = new RetryOnRenew(cache, backoffHandler);
for (int i = 0; i < RetryOnRenew.NUM_RETRIES - 1; ++i) {
assertTrue(retry.shouldRetryRequest(command, response),
"Expected retry to succeed");
}
assertFalse(retry.shouldRetryRequest(command, response),
"Expected retry to fail on attempt " + RetryOnRenew.NUM_RETRIES);
verify(command, response, cache);
}
@Test
public void test408ShouldRetry() {
HttpCommand command = createMock(HttpCommand.class);
HttpRequest request = createMock(HttpRequest.class);
HttpResponse response = createMock(HttpResponse.class);
@SuppressWarnings("unchecked")
LoadingCache<Credentials, Auth> cache = createMock(LoadingCache.class);
BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class);
expect(response.getPayload()).andReturn(Payloads.newStringPayload(
"The server has waited too long for the request to be sent by the client.")).times(2);
expect(backoffHandler.shouldRetryRequest(command, response)).andReturn(true).once();
expect(response.getStatusCode()).andReturn(408).once();
replay(command);
replay(response);
replay(cache);
replay(backoffHandler);
RetryOnRenew retry = new RetryOnRenew(cache, backoffHandler);
assertTrue(retry.shouldRetryRequest(command, response));
verify(command);
verify(response);
verify(cache);
verify(backoffHandler);
}
@Test
public void test404ShouldNotRetry() {
HttpCommand command = createMock(HttpCommand.class);
HttpRequest request = createMock(HttpRequest.class);
HttpResponse response = createMock(HttpResponse.class);
@SuppressWarnings("unchecked")
LoadingCache<Credentials, Auth> cache = createMock(LoadingCache.class);
BackoffLimitedRetryHandler backoffHandler = createMock(BackoffLimitedRetryHandler.class);
expect(response.getPayload()).andReturn(Payloads.newStringPayload("")).times(2);
expect(response.getStatusCode()).andReturn(404).once();
replay(command);
replay(response);
replay(cache);
replay(backoffHandler);
RetryOnRenew retry = new RetryOnRenew(cache, backoffHandler);
assertTrue(!retry.shouldRetryRequest(command, response));
verify(command);
verify(response);
verify(cache);
verify(backoffHandler);
}
}

View File

@ -0,0 +1,62 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.internal;
import org.jclouds.http.HttpRequest;
import org.jclouds.http.HttpResponse;
import org.jclouds.rackspace.cloudidentity.v1_1.config.AuthenticationServiceModule;
import org.jclouds.rest.internal.BaseRestClientExpectTest;
import com.google.common.net.HttpHeaders;
/**
* Base class for writing KeyStone Rest Client Expect tests
*/
public class BaseKeystoneRestClientExpectTest<S> extends BaseRestClientExpectTest<S> {
protected String endpoint = "http://localhost:5000";
public BaseKeystoneRestClientExpectTest() {
identity = "user@jclouds.org";
credential = "Password1234";
}
protected HttpRequest initialAuth = HttpRequest.builder().method("POST")
.endpoint(endpoint + "/v1.1/auth")
.addHeader(HttpHeaders.ACCEPT, "application/json")
.payload(
payloadFromStringWithContentType(
"{\"credentials\":{\"username\":\"user@jclouds.org\",\"key\":\"Password1234\"}}",
"application/json")).build();
protected String authToken = "118fb907-0786-4799-88f0-9a5b7963d1ab";
protected HttpResponse responseWithAuth = HttpResponse.builder().statusCode(200).message("HTTP/1.1 200")
.payload(payloadFromResourceWithContentType("/auth1_1.json", "application/json")).build();
/**
* in case you need to override anything
*/
public static class TestKeystoneAuthenticationModule extends AuthenticationServiceModule {
@Override
protected void configure() {
super.configure();
}
}
}

View File

@ -0,0 +1,77 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.parse;
import java.net.URI;
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.rackspace.cloudidentity.v1_1.domain.Auth;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Endpoint;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Token;
import org.jclouds.rest.annotations.SelectJson;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMultimap;
@Test(groups = "unit", testName = "ParseAuthTest")
public class ParseAuthTest extends BaseItemParserTest<Auth> {
@Override
public String resource() {
return "/auth1_1.json";
}
@Override
@SelectJson("auth")
@Consumes(MediaType.APPLICATION_JSON)
public Auth expected() {
return Auth
.builder()
.token(
Token.builder()
.expires(new SimpleDateFormatDateService().iso8601DateParse("2012-01-30T02:30:54.000-06:00"))
.id("118fb907-0786-4799-88f0-9a5b7963d1ab").build())
.serviceCatalog(
ImmutableMultimap.of(
"cloudFilesCDN",
Endpoint
.builder()
.region("LON")
.publicURL(
URI.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
.v1Default(true).build(),
"cloudFiles",
Endpoint
.builder()
.region("LON")
.publicURL(
URI.create("https://storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
.v1Default(true)
.internalURL(
URI.create("https://snet-storage101.lon3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"))
.build(),
"cloudServers",
Endpoint.builder()
.publicURL(URI.create("https://lon.servers.api.rackspacecloud.com/v1.0/10001786"))
.v1Default(true).build())).build();
}
}

View File

@ -0,0 +1,70 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.suppliers;
import static org.testng.Assert.assertEquals;
import java.net.URI;
import javax.inject.Singleton;
import org.jclouds.location.Provider;
import org.jclouds.location.suppliers.RegionIdToURISupplier;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Auth;
import org.jclouds.rackspace.cloudidentity.v1_1.parse.ParseAuthTest;
import org.jclouds.rackspace.cloudidentity.v1_1.suppliers.RegionIdToURIFromAuthForServiceSupplier;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.Maps;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Provides;
import com.google.inject.assistedinject.FactoryModuleBuilder;
@Test(groups = "unit", testName = "RegionIdToURIFromAuthForServiceSupplierTest")
public class RegionIdToURIFromAuthForServiceSupplierTest {
private final RegionIdToURISupplier.Factory factory = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Provider.class).to("keystone");
install(new FactoryModuleBuilder().implement(RegionIdToURISupplier.class,
RegionIdToURIFromAuthForServiceSupplier.class).build(RegionIdToURISupplier.Factory.class));
}
@Provides
@Singleton
public Supplier<Auth> provide() {
return Suppliers.ofInstance(new ParseAuthTest().expected());
}
}).getInstance(RegionIdToURISupplier.Factory.class);
public void testRegionMatches() {
assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("cloudFilesCDN", "1.0").get(), Suppliers
.<URI> supplierFunction()), ImmutableMap.of("LON", URI
.create("https://cdn3.clouddrive.com/v1/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953")));
}
public void testTakesFirstPartOfDNSWhenNoRegion() {
assertEquals(Maps.transformValues(factory.createForApiTypeAndVersion("cloudServers", "1.1").get(), Suppliers
.<URI> supplierFunction()), ImmutableMap.of("lon", URI
.create("https://lon.servers.api.rackspacecloud.com/v1.0/10001786")));
}
}

View File

@ -0,0 +1,62 @@
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jclouds.rackspace.cloudidentity.v1_1.suppliers;
import static org.testng.Assert.assertEquals;
import javax.inject.Singleton;
import org.jclouds.location.Provider;
import org.jclouds.location.suppliers.ImplicitRegionIdSupplier;
import org.jclouds.rackspace.cloudidentity.v1_1.domain.Auth;
import org.jclouds.rackspace.cloudidentity.v1_1.parse.ParseAuthTest;
import org.jclouds.rackspace.cloudidentity.v1_1.suppliers.V1DefaultRegionIdSupplier;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
import com.google.inject.Provides;
import com.google.inject.assistedinject.FactoryModuleBuilder;
@Test(groups = "unit", testName = "V1DefaultRegionIdSupplierTest")
public class V1DefaultRegionIdSupplierTest {
private final V1DefaultRegionIdSupplier.Factory factory = Guice.createInjector(new AbstractModule() {
@Override
protected void configure() {
bindConstant().annotatedWith(Provider.class).to("keystone");
install(new FactoryModuleBuilder().implement(ImplicitRegionIdSupplier.class, V1DefaultRegionIdSupplier.class)
.build(V1DefaultRegionIdSupplier.Factory.class));
}
@Provides
@Singleton
public Supplier<Auth> provide() {
return Suppliers.ofInstance(new ParseAuthTest().expected());
}
}).getInstance(V1DefaultRegionIdSupplier.Factory.class);
public void testRegionMatches() {
assertEquals(factory.createForApiType("cloudFilesCDN").get(), "LON");
}
public void testTakesFirstPartOfDNSWhenNoRegion() {
assertEquals(factory.createForApiType("cloudServers").get(), "lon");
}
}

View File

@ -0,0 +1,25 @@
{
"auth": {
"token": {
"id": "118fb907-0786-4799-88f0-9a5b7963d1ab",
"expires": "2012-01-30T02:30:54.000-06:00"
},
"serviceCatalog": {
"cloudFilesCDN": [{
"region": "LON",
"publicURL": "https:\/\/cdn3.clouddrive.com\/v1\/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953",
"v1Default": true
}],
"cloudFiles": [{
"region": "LON",
"publicURL": "https:\/\/storage101.lon3.clouddrive.com\/v1\/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953",
"v1Default": true,
"internalURL": "https:\/\/snet-storage101.lon3.clouddrive.com\/v1\/MossoCloudFS_83a9d536-2e25-4166-bd3b-a503a934f953"
}],
"cloudServers": [{
"publicURL": "https:\/\/lon.servers.api.rackspacecloud.com\/v1.0\/10001786",
"v1Default": true
}]
}
}
}