mirror of https://github.com/apache/jclouds.git
JCLOUDS-646: Copied Cloud Identity v1.1 classes from openstack-common and fixed incorrect Keystone package names
This commit is contained in:
parent
e3d9851216
commit
95a3c7ec2c
|
@ -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);
|
||||||
|
}
|
|
@ -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));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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 {
|
||||||
|
|
||||||
|
}
|
|
@ -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());
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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> {
|
||||||
|
|
||||||
|
}
|
|
@ -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>> {
|
||||||
|
}
|
|
@ -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()";
|
||||||
|
}
|
||||||
|
}
|
|
@ -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;
|
||||||
|
}
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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 + ")";
|
||||||
|
}
|
||||||
|
}
|
|
@ -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 + ")";
|
||||||
|
}
|
||||||
|
}
|
|
@ -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"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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");
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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);
|
||||||
|
}
|
||||||
|
}
|
|
@ -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();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -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();
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
|
@ -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")));
|
||||||
|
}
|
||||||
|
}
|
|
@ -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");
|
||||||
|
}
|
||||||
|
}
|
|
@ -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
|
||||||
|
}]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue