Repository: jclouds Updated Branches: refs/heads/master e3d985121 -> 95a3c7ec2
JCLOUDS-646: Copied Cloud Identity v1.1 classes from openstack-common and fixed incorrect Keystone package names Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/95a3c7ec Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/95a3c7ec Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/95a3c7ec Branch: refs/heads/master Commit: 95a3c7ec2c26edf66da793d0d7a05ef37a58491d Parents: e3d9851 Author: Jeremy Daggett <[email protected]> Authored: Thu Jul 31 10:28:33 2014 -0700 Committer: Jeremy Daggett <[email protected]> Committed: Tue Aug 5 09:01:21 2014 -0700 ---------------------------------------------------------------------- .../cloudidentity/v1_1/AuthenticationApi.java | 48 +++++ .../binders/BindCredentialsToJsonPayload.java | 48 +++++ .../v1_1/config/Authentication.java | 31 +++ .../config/AuthenticationServiceModule.java | 117 +++++++++++ .../cloudidentity/v1_1/domain/Auth.java | 123 ++++++++++++ .../cloudidentity/v1_1/domain/Endpoint.java | 198 +++++++++++++++++++ .../cloudidentity/v1_1/domain/Token.java | 137 +++++++++++++ .../v1_1/functions/EndpointToRegion.java | 27 +++ .../v1_1/functions/EndpointToSupplierURI.java | 29 +++ .../functions/PublicURLOrInternalIfNull.java | 39 ++++ .../RegionFirstPartOfDNSNameOrProvider.java | 47 +++++ .../v1_1/handlers/RetryOnRenew.java | 133 +++++++++++++ ...RegionIdToURIFromAuthForServiceSupplier.java | 67 +++++++ .../suppliers/V1DefaultRegionIdSupplier.java | 85 ++++++++ .../PublicURLOrInternalIfNullTest.java | 44 +++++ .../RegionFirstPartOfDNSNameOrProviderTest.java | 48 +++++ .../v1_1/handlers/RetryOnRenewTest.java | 166 ++++++++++++++++ .../BaseKeystoneRestClientExpectTest.java | 62 ++++++ .../cloudidentity/v1_1/parse/ParseAuthTest.java | 77 ++++++++ ...onIdToURIFromAuthForServiceSupplierTest.java | 70 +++++++ .../V1DefaultRegionIdSupplierTest.java | 62 ++++++ .../src/test/resources/auth1_1.json | 25 +++ 22 files changed, 1683 insertions(+) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/AuthenticationApi.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/AuthenticationApi.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/AuthenticationApi.java new file mode 100644 index 0000000..a3128fb --- /dev/null +++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/AuthenticationApi.java @@ -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); +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/binders/BindCredentialsToJsonPayload.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/binders/BindCredentialsToJsonPayload.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/binders/BindCredentialsToJsonPayload.java new file mode 100644 index 0000000..d2e6526 --- /dev/null +++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/binders/BindCredentialsToJsonPayload.java @@ -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)); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/config/Authentication.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/config/Authentication.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/config/Authentication.java new file mode 100644 index 0000000..ed4fda1 --- /dev/null +++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/config/Authentication.java @@ -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 { + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/config/AuthenticationServiceModule.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/config/AuthenticationServiceModule.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/config/AuthenticationServiceModule.java new file mode 100644 index 0000000..f26d4c2 --- /dev/null +++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/config/AuthenticationServiceModule.java @@ -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()); + } + }; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/domain/Auth.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/domain/Auth.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/domain/Auth.java new file mode 100644 index 0000000..04bdba5 --- /dev/null +++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/domain/Auth.java @@ -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); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/domain/Endpoint.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/domain/Endpoint.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/domain/Endpoint.java new file mode 100644 index 0000000..020ed85 --- /dev/null +++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/domain/Endpoint.java @@ -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); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/domain/Token.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/domain/Token.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/domain/Token.java new file mode 100644 index 0000000..9d9845b --- /dev/null +++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/domain/Token.java @@ -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); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/EndpointToRegion.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/EndpointToRegion.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/EndpointToRegion.java new file mode 100644 index 0000000..e75a8f5 --- /dev/null +++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/EndpointToRegion.java @@ -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> { + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/EndpointToSupplierURI.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/EndpointToSupplierURI.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/EndpointToSupplierURI.java new file mode 100644 index 0000000..12d1d2d --- /dev/null +++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/EndpointToSupplierURI.java @@ -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>> { +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/PublicURLOrInternalIfNull.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/PublicURLOrInternalIfNull.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/PublicURLOrInternalIfNull.java new file mode 100644 index 0000000..b4cd7a4 --- /dev/null +++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/PublicURLOrInternalIfNull.java @@ -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()"; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/RegionFirstPartOfDNSNameOrProvider.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/RegionFirstPartOfDNSNameOrProvider.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/RegionFirstPartOfDNSNameOrProvider.java new file mode 100644 index 0000000..d6ed6b0 --- /dev/null +++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/RegionFirstPartOfDNSNameOrProvider.java @@ -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; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/handlers/RetryOnRenew.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/handlers/RetryOnRenew.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/handlers/RetryOnRenew.java new file mode 100644 index 0000000..5df757a --- /dev/null +++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/handlers/RetryOnRenew.java @@ -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); + } + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplier.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplier.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplier.java new file mode 100644 index 0000000..15b655f --- /dev/null +++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplier.java @@ -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 + ")"; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/V1DefaultRegionIdSupplier.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/V1DefaultRegionIdSupplier.java b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/V1DefaultRegionIdSupplier.java new file mode 100644 index 0000000..5ea0c48 --- /dev/null +++ b/apis/rackspace-cloudidentity/src/main/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/V1DefaultRegionIdSupplier.java @@ -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 + ")"; + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/PublicURLOrInternalIfNullTest.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/PublicURLOrInternalIfNullTest.java b/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/PublicURLOrInternalIfNullTest.java new file mode 100644 index 0000000..9370d2b --- /dev/null +++ b/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/PublicURLOrInternalIfNullTest.java @@ -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")); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/RegionFirstPartOfDNSNameOrProviderTest.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/RegionFirstPartOfDNSNameOrProviderTest.java b/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/RegionFirstPartOfDNSNameOrProviderTest.java new file mode 100644 index 0000000..7b336ad --- /dev/null +++ b/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/functions/RegionFirstPartOfDNSNameOrProviderTest.java @@ -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"); + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/handlers/RetryOnRenewTest.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/handlers/RetryOnRenewTest.java b/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/handlers/RetryOnRenewTest.java new file mode 100644 index 0000000..17fa2fc --- /dev/null +++ b/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/handlers/RetryOnRenewTest.java @@ -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); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/internal/BaseKeystoneRestClientExpectTest.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/internal/BaseKeystoneRestClientExpectTest.java b/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/internal/BaseKeystoneRestClientExpectTest.java new file mode 100644 index 0000000..4638c3e --- /dev/null +++ b/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/internal/BaseKeystoneRestClientExpectTest.java @@ -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 = "[email protected]"; + credential = "Password1234"; + } + + protected HttpRequest initialAuth = HttpRequest.builder().method("POST") + .endpoint(endpoint + "/v1.1/auth") + .addHeader(HttpHeaders.ACCEPT, "application/json") + .payload( + payloadFromStringWithContentType( + "{\"credentials\":{\"username\":\"[email protected]\",\"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(); + } + + } + +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/parse/ParseAuthTest.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/parse/ParseAuthTest.java b/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/parse/ParseAuthTest.java new file mode 100644 index 0000000..7d8518a --- /dev/null +++ b/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/parse/ParseAuthTest.java @@ -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(); + + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplierTest.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplierTest.java b/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplierTest.java new file mode 100644 index 0000000..3578771 --- /dev/null +++ b/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/RegionIdToURIFromAuthForServiceSupplierTest.java @@ -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"))); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/V1DefaultRegionIdSupplierTest.java ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/V1DefaultRegionIdSupplierTest.java b/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/V1DefaultRegionIdSupplierTest.java new file mode 100644 index 0000000..6325833 --- /dev/null +++ b/apis/rackspace-cloudidentity/src/test/java/org/jclouds/rackspace/cloudidentity/v1_1/suppliers/V1DefaultRegionIdSupplierTest.java @@ -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"); + } +} http://git-wip-us.apache.org/repos/asf/jclouds/blob/95a3c7ec/apis/rackspace-cloudidentity/src/test/resources/auth1_1.json ---------------------------------------------------------------------- diff --git a/apis/rackspace-cloudidentity/src/test/resources/auth1_1.json b/apis/rackspace-cloudidentity/src/test/resources/auth1_1.json new file mode 100644 index 0000000..545adbd --- /dev/null +++ b/apis/rackspace-cloudidentity/src/test/resources/auth1_1.json @@ -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 + }] + } + } +}
