mirror of https://github.com/apache/jclouds.git
Merge pull request #782 from grkvlt/openstack
Further OpenStack extensibility changes
This commit is contained in:
commit
e0ecf3aea1
|
@ -21,12 +21,16 @@ package org.jclouds.openstack.keystone.v2_0;
|
|||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.concurrent.Timeout;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.location.functions.ZoneToEndpoint;
|
||||
import org.jclouds.openstack.keystone.v2_0.domain.ApiMetadata;
|
||||
import org.jclouds.openstack.keystone.v2_0.features.ServiceApi;
|
||||
import org.jclouds.openstack.keystone.v2_0.features.TenantApi;
|
||||
import org.jclouds.openstack.keystone.v2_0.features.TokenApi;
|
||||
import org.jclouds.openstack.keystone.v2_0.features.UserApi;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionApi;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
|
||||
|
@ -54,6 +58,12 @@ public interface KeystoneApi {
|
|||
@Delegate
|
||||
ServiceApi getServiceApi();
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Extension features.
|
||||
*/
|
||||
@Delegate
|
||||
ExtensionApi getExtensionApi();
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Token features
|
||||
*/
|
||||
|
@ -66,7 +76,6 @@ public interface KeystoneApi {
|
|||
@Delegate
|
||||
Optional<UserApi> getUserApi();
|
||||
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Tenant features
|
||||
*/
|
||||
|
|
|
@ -27,6 +27,7 @@ import org.jclouds.openstack.keystone.v2_0.features.ServiceAsyncApi;
|
|||
import org.jclouds.openstack.keystone.v2_0.features.TenantAsyncApi;
|
||||
import org.jclouds.openstack.keystone.v2_0.features.TokenAsyncApi;
|
||||
import org.jclouds.openstack.keystone.v2_0.features.UserAsyncApi;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.SelectJson;
|
||||
|
@ -60,6 +61,12 @@ public interface KeystoneAsyncApi {
|
|||
@Delegate
|
||||
ServiceAsyncApi getServiceApi();
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Extension features.
|
||||
*/
|
||||
@Delegate
|
||||
ExtensionAsyncApi getExtensionApi();
|
||||
|
||||
/**
|
||||
* @see KeystoneApi#getTokenApi()
|
||||
*/
|
||||
|
@ -72,7 +79,6 @@ public interface KeystoneAsyncApi {
|
|||
@Delegate
|
||||
Optional<UserAsyncApi> getUserApi();
|
||||
|
||||
|
||||
/**
|
||||
* @see KeystoneApi#getTenantApi()
|
||||
*/
|
||||
|
|
|
@ -23,6 +23,8 @@ import static org.jclouds.util.Suppliers2.getLastValueInMap;
|
|||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.NoSuchElementException;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
|
@ -41,11 +43,14 @@ import org.jclouds.openstack.keystone.v2_0.features.TokenApi;
|
|||
import org.jclouds.openstack.keystone.v2_0.features.TokenAsyncApi;
|
||||
import org.jclouds.openstack.keystone.v2_0.features.UserApi;
|
||||
import org.jclouds.openstack.keystone.v2_0.features.UserAsyncApi;
|
||||
import org.jclouds.openstack.keystone.v2_0.functions.PresentWhenAdminURLExistsForIdentityService;
|
||||
import org.jclouds.openstack.keystone.v2_0.handlers.KeystoneErrorHandler;
|
||||
import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURIFromAccessForTypeAndVersion;
|
||||
import org.jclouds.openstack.keystone.v2_0.suppliers.RegionIdToAdminURISupplier;
|
||||
import org.jclouds.openstack.v2_0.ServiceType;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionApi;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.openstack.v2_0.functions.PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet;
|
||||
import org.jclouds.openstack.v2_0.services.Identity;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.annotations.ApiVersion;
|
||||
|
@ -54,7 +59,13 @@ import org.jclouds.rest.functions.ImplicitOptionalConverter;
|
|||
import org.jclouds.util.Suppliers2;
|
||||
|
||||
import com.google.common.base.Supplier;
|
||||
import com.google.common.base.Suppliers;
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.inject.AbstractModule;
|
||||
import com.google.inject.Provides;
|
||||
|
@ -70,17 +81,18 @@ public class KeystoneRestClientModule<S extends KeystoneApi, A extends KeystoneA
|
|||
RestClientModule<S, A> {
|
||||
|
||||
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
|
||||
.put(ServiceApi.class, ServiceAsyncApi.class).put(TokenApi.class, TokenAsyncApi.class)
|
||||
.put(UserApi.class, UserAsyncApi.class).put(TenantApi.class, TenantAsyncApi.class).build();
|
||||
.put(ServiceApi.class, ServiceAsyncApi.class)
|
||||
.put(ExtensionApi.class, ExtensionAsyncApi.class)
|
||||
.put(TokenApi.class, TokenAsyncApi.class)
|
||||
.put(UserApi.class, UserAsyncApi.class)
|
||||
.put(TenantApi.class, TenantAsyncApi.class)
|
||||
.build();
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public KeystoneRestClientModule() {
|
||||
super(TypeToken.class.cast(TypeToken.of(KeystoneApi.class)), TypeToken.class.cast(TypeToken
|
||||
.of(KeystoneAsyncApi.class)), DELEGATE_MAP);
|
||||
super(TypeToken.class.cast(TypeToken.of(KeystoneApi.class)), TypeToken.class.cast(TypeToken.of(KeystoneAsyncApi.class)), DELEGATE_MAP);
|
||||
}
|
||||
|
||||
protected KeystoneRestClientModule(TypeToken<S> syncApiType, TypeToken<A> asyncApiType,
|
||||
Map<Class<?>, Class<?>> sync2Async) {
|
||||
protected KeystoneRestClientModule(TypeToken<S> syncApiType, TypeToken<A> asyncApiType, Map<Class<?>, Class<?>> sync2Async) {
|
||||
super(syncApiType, asyncApiType, sync2Async);
|
||||
}
|
||||
|
||||
|
@ -88,7 +100,6 @@ public class KeystoneRestClientModule<S extends KeystoneApi, A extends KeystoneA
|
|||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(ImplicitOptionalConverter.class).to(PresentWhenAdminURLExistsForIdentityService.class);
|
||||
install(new FactoryModuleBuilder().implement(RegionIdToAdminURISupplier.class,
|
||||
RegionIdToAdminURIFromAccessForTypeAndVersion.class).build(RegionIdToAdminURISupplier.Factory.class));
|
||||
}
|
||||
|
@ -112,6 +123,31 @@ public class KeystoneRestClientModule<S extends KeystoneApi, A extends KeystoneA
|
|||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(ImplicitOptionalConverter.class).to(PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.class);
|
||||
super.configure();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public Multimap<URI, URI> aliases() {
|
||||
return ImmutableMultimap.<URI, URI>builder()
|
||||
.build();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public LoadingCache<String, Set<? extends Extension>> provideExtensionsByZone(final javax.inject.Provider<KeystoneApi> keystoneApi) {
|
||||
return CacheBuilder.newBuilder().expireAfterWrite(23, TimeUnit.HOURS)
|
||||
.build(CacheLoader.from(Suppliers.memoize(new Supplier<Set<? extends Extension>>() {
|
||||
@Override
|
||||
public Set<? extends Extension> get() {
|
||||
return keystoneApi.get().getExtensionApi().listExtensions();
|
||||
}
|
||||
})));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindErrorHandlers() {
|
||||
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(KeystoneErrorHandler.class);
|
||||
|
|
|
@ -1,46 +0,0 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.keystone.v2_0.functions;
|
||||
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.internal.ClassMethodArgsAndReturnVal;
|
||||
import org.jclouds.rest.functions.ImplicitOptionalConverter;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
@Singleton
|
||||
public class PresentWhenAdminURLExistsForIdentityService implements ImplicitOptionalConverter {
|
||||
|
||||
@Override
|
||||
public Optional<Object> apply(ClassMethodArgsAndReturnVal input) {
|
||||
//TODO: log and return absent when the admin url for identity service isn't available
|
||||
return Optional.of(input.getReturnVal());
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "presentWhenAdminURLExistsForIdentityService()";
|
||||
}
|
||||
|
||||
}
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.nova.v2_0.domain;
|
||||
package org.jclouds.openstack.v2_0.domain;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
|
@ -26,8 +26,6 @@ import java.util.Date;
|
|||
import java.util.Set;
|
||||
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.openstack.v2_0.domain.Link;
|
||||
import org.jclouds.openstack.v2_0.domain.Resource;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Objects.ToStringHelper;
|
|
@ -16,13 +16,13 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.nova.v2_0.features;
|
||||
package org.jclouds.openstack.v2_0.features;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import org.jclouds.concurrent.Timeout;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Extensions via their REST API.
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.nova.v2_0.features;
|
||||
package org.jclouds.openstack.v2_0.features;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
|
@ -27,7 +27,7 @@ import javax.ws.rs.PathParam;
|
|||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.RequestFilters;
|
||||
import org.jclouds.rest.annotations.SelectJson;
|
|
@ -16,7 +16,7 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.nova.v2_0.functions;
|
||||
package org.jclouds.openstack.v2_0.functions;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
|
@ -25,7 +25,7 @@ import javax.inject.Provider;
|
|||
import javax.inject.Singleton;
|
||||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
|
|
@ -0,0 +1,88 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.v2_0.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
|
||||
import org.jclouds.internal.ClassMethodArgsAndReturnVal;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.predicates.ExtensionPredicates;
|
||||
import org.jclouds.rest.functions.ImplicitOptionalConverter;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* We use the annotation {@link org.jclouds.openstack.services.Extension} to
|
||||
* bind a class that iimplements an extension API to an {@link Extension}.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet implements
|
||||
ImplicitOptionalConverter {
|
||||
private final LoadingCache<String, Set<? extends Extension>> extensions;
|
||||
private final Multimap<URI, URI> aliases;
|
||||
|
||||
@Inject
|
||||
public PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet(
|
||||
LoadingCache<String, Set<? extends Extension>> extensions,
|
||||
Multimap<URI, URI> aliases) {
|
||||
this.extensions = checkNotNull(extensions, "extensions");
|
||||
this.aliases = aliases == null ? ImmutableMultimap.<URI, URI>of() : ImmutableMultimap.copyOf(aliases);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Object> apply(ClassMethodArgsAndReturnVal input) {
|
||||
Optional<org.jclouds.openstack.v2_0.services.Extension> ext = Optional.fromNullable(input.getClazz().getAnnotation(
|
||||
org.jclouds.openstack.v2_0.services.Extension.class));
|
||||
if (ext.isPresent()) {
|
||||
URI namespace = URI.create(ext.get().namespace());
|
||||
if (input.getArgs() == null || input.getArgs().length == 0) {
|
||||
if (Iterables.any(extensions.getUnchecked(""),
|
||||
ExtensionPredicates.namespaceOrAliasEquals(namespace, aliases.get(namespace))))
|
||||
return Optional.of(input.getReturnVal());
|
||||
} else if (input.getArgs() != null && input.getArgs().length == 1) {
|
||||
if (Iterables.any(extensions.getUnchecked(checkNotNull(input.getArgs()[0], "arg[0] in %s", input).toString()),
|
||||
ExtensionPredicates.namespaceOrAliasEquals(namespace, aliases.get(namespace))))
|
||||
return Optional.of(input.getReturnVal());
|
||||
} else {
|
||||
throw new RuntimeException(String.format("expecting zero or one args %s", input));
|
||||
}
|
||||
return Optional.absent();
|
||||
} else {
|
||||
// No extension annotation, should check whether to return absent
|
||||
return Optional.of(input.getReturnVal());
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "presentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet()";
|
||||
}
|
||||
|
||||
}
|
|
@ -16,14 +16,14 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.nova.v2_0.predicates;
|
||||
package org.jclouds.openstack.v2_0.predicates;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Collection;
|
||||
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
|
||||
import com.google.common.base.Predicate;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
package org.jclouds.openstack.nova.v2_0.functions;
|
||||
package org.jclouds.openstack.v2_0.functions;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
|
@ -8,8 +8,7 @@ import javax.inject.Provider;
|
|||
import javax.ws.rs.core.UriBuilder;
|
||||
|
||||
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.ExtensionNamespaces;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.sun.jersey.api.uri.UriBuilderImpl;
|
||||
|
@ -39,6 +38,6 @@ public class ExtensionToNameSpaceTest {
|
|||
assertEquals(fn.apply(Extension.builder().alias("security_groups").name("SecurityGroups").namespace(
|
||||
URI.create("https://docs.openstack.org/ext/securitygroups/api/v1.1")).updated(
|
||||
new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-07-21T00:00:00+00:00")).description(
|
||||
"Security group support").build()), URI.create(ExtensionNamespaces.SECURITY_GROUPS));
|
||||
"Security group support").build()), URI.create("http://docs.openstack.org/ext/securitygroups/api/v1.1"));
|
||||
}
|
||||
}
|
|
@ -1,4 +1,4 @@
|
|||
package org.jclouds.openstack.nova.v2_0.functions;
|
||||
package org.jclouds.openstack.v2_0.functions;
|
||||
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
|
@ -9,10 +9,9 @@ import javax.inject.Named;
|
|||
|
||||
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||
import org.jclouds.internal.ClassMethodArgsAndReturnVal;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.ExtensionNamespaces;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.KeyPairAsyncApi;
|
||||
import org.jclouds.openstack.v2_0.ServiceType;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.functions.PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
@ -40,8 +39,8 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
|
|||
new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-08-08T00:00:00+00:00")).description(
|
||||
"Keypair Support").build();
|
||||
|
||||
@org.jclouds.openstack.v2_0.services.Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.KEYPAIRS)
|
||||
static interface KeyPairIPAsyncApi {
|
||||
@org.jclouds.openstack.v2_0.services.Extension(of = ServiceType.COMPUTE, namespace = "http://docs.openstack.org/ext/keypairs/api/v1.1")
|
||||
static interface KeyPairAsyncApi {
|
||||
|
||||
}
|
||||
|
||||
|
@ -50,7 +49,7 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
|
|||
new SimpleDateFormatDateService().iso8601SecondsDateParse("2011-06-16T00:00:00+00:00")).description(
|
||||
"Floating IPs support").build();
|
||||
|
||||
@org.jclouds.openstack.v2_0.services.Extension(of = ServiceType.COMPUTE, namespace = ExtensionNamespaces.FLOATING_IPS)
|
||||
@org.jclouds.openstack.v2_0.services.Extension(of = ServiceType.COMPUTE, namespace = "http://docs.openstack.org/ext/floating_ips/api/v1.1")
|
||||
static interface FloatingIPAsyncApi {
|
||||
|
||||
}
|
||||
|
@ -68,27 +67,27 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
|
|||
ClassMethodArgsAndReturnVal getFloatingIPExtension() throws SecurityException, NoSuchMethodException {
|
||||
return ClassMethodArgsAndReturnVal.builder().clazz(FloatingIPAsyncApi.class).method(
|
||||
NovaAsyncApi.class.getDeclaredMethod("getFloatingIPExtensionForZone", String.class)).args(
|
||||
new Object[] { "expectedzone" }).returnVal("foo").build();
|
||||
new Object[] { "zone" }).returnVal("foo").build();
|
||||
}
|
||||
|
||||
ClassMethodArgsAndReturnVal getKeyPairExtension() throws SecurityException, NoSuchMethodException {
|
||||
return ClassMethodArgsAndReturnVal.builder().clazz(KeyPairAsyncApi.class).method(
|
||||
NovaAsyncApi.class.getDeclaredMethod("getKeyPairExtensionForZone", String.class)).args(
|
||||
new Object[] { "expectedzone" }).returnVal("foo").build();
|
||||
new Object[] { "zone" }).returnVal("foo").build();
|
||||
}
|
||||
|
||||
public void testPresentWhenExtensionsIncludeNamespaceFromAnnotationAbsentWhenNot() throws SecurityException, NoSuchMethodException {
|
||||
|
||||
assertEquals(whenExtensionsInclude(keypairs, floatingIps).apply(getFloatingIPExtension()), Optional.of("foo"));
|
||||
assertEquals(whenExtensionsInclude(keypairs, floatingIps).apply(getKeyPairExtension()), Optional.of("foo"));
|
||||
assertEquals(whenExtensionsInclude(keypairs).apply(getFloatingIPExtension()), Optional.absent());
|
||||
assertEquals(whenExtensionsInclude(floatingIps).apply(getKeyPairExtension()), Optional.absent());
|
||||
assertEquals(whenExtensionsInZoneInclude("zone", keypairs, floatingIps).apply(getFloatingIPExtension()), Optional.of("foo"));
|
||||
assertEquals(whenExtensionsInZoneInclude("zone", keypairs, floatingIps).apply(getKeyPairExtension()), Optional.of("foo"));
|
||||
assertEquals(whenExtensionsInZoneInclude("zone", keypairs).apply(getFloatingIPExtension()), Optional.absent());
|
||||
assertEquals(whenExtensionsInZoneInclude("zone", floatingIps).apply(getKeyPairExtension()), Optional.absent());
|
||||
}
|
||||
|
||||
public void testZoneWithoutExtensionsReturnsAbsent() throws SecurityException, NoSuchMethodException {
|
||||
assertEquals(whenExtensionsInclude(floatingIps).apply(
|
||||
assertEquals(whenExtensionsInZoneInclude("zone", floatingIps).apply(
|
||||
getFloatingIPExtension().toBuilder().args(new Object[] { "differentzone" }).build()), Optional.absent());
|
||||
assertEquals(whenExtensionsInclude(keypairs).apply(
|
||||
assertEquals(whenExtensionsInZoneInclude("zone", keypairs).apply(
|
||||
getKeyPairExtension().toBuilder().args(new Object[] { "differentzone" }).build()), Optional.absent());
|
||||
}
|
||||
|
||||
|
@ -105,22 +104,22 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
|
|||
Multimap<URI, URI> aliases = ImmutableMultimap.of(keypairs.getNamespace(), keypairsWithDifferentNamespace
|
||||
.getNamespace());
|
||||
|
||||
assertEquals(whenExtensionsAndAliasesInclude(ImmutableSet.of(keypairsWithDifferentNamespace), aliases).apply(
|
||||
assertEquals(whenExtensionsAndAliasesInZoneInclude("zone", ImmutableSet.of(keypairsWithDifferentNamespace), aliases).apply(
|
||||
getKeyPairExtension()), Optional.of("foo"));
|
||||
assertEquals(whenExtensionsAndAliasesInclude(ImmutableSet.of(keypairsWithDifferentNamespace), aliases).apply(
|
||||
assertEquals(whenExtensionsAndAliasesInZoneInclude("zone", ImmutableSet.of(keypairsWithDifferentNamespace), aliases).apply(
|
||||
getFloatingIPExtension()), Optional.absent());
|
||||
|
||||
}
|
||||
|
||||
private PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet whenExtensionsInclude(
|
||||
Extension... extensions) {
|
||||
return whenExtensionsAndAliasesInclude(ImmutableSet.copyOf(extensions), ImmutableMultimap.<URI, URI> of());
|
||||
private PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet whenExtensionsInZoneInclude(
|
||||
String zone, Extension... extensions) {
|
||||
return whenExtensionsAndAliasesInZoneInclude(zone, ImmutableSet.copyOf(extensions), ImmutableMultimap.<URI, URI> of());
|
||||
}
|
||||
|
||||
private PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet whenExtensionsAndAliasesInclude(
|
||||
final Set<Extension> extensions, final Multimap<URI, URI> aliases) {
|
||||
private PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet whenExtensionsAndAliasesInZoneInclude(
|
||||
String zone, final Set<Extension> extensions, final Multimap<URI, URI> aliases) {
|
||||
final LoadingCache<String, Set<? extends Extension>> extensionsForZone = CacheBuilder.newBuilder().build(
|
||||
CacheLoader.from(Functions.forMap(ImmutableMap.<String, Set<? extends Extension>>of("expectedzone", extensions, "differentzone",
|
||||
CacheLoader.from(Functions.forMap(ImmutableMap.<String, Set<? extends Extension>>of(zone, extensions, "differentzone",
|
||||
ImmutableSet.<Extension> of()))));
|
||||
|
||||
PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet fn = Guice.createInjector(
|
||||
|
@ -135,7 +134,6 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
|
|||
}
|
||||
|
||||
@Provides
|
||||
@Named("openstack.nova.extensions")
|
||||
Multimap<URI, URI> getAliases() {
|
||||
return aliases;
|
||||
}
|
|
@ -16,15 +16,15 @@
|
|||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.nova.v2_0.predicates;
|
||||
package org.jclouds.openstack.v2_0.predicates;
|
||||
|
||||
import static org.jclouds.openstack.nova.v2_0.predicates.ExtensionPredicates.aliasEquals;
|
||||
import static org.jclouds.openstack.nova.v2_0.predicates.ExtensionPredicates.namespaceEquals;
|
||||
import static org.jclouds.openstack.v2_0.predicates.ExtensionPredicates.aliasEquals;
|
||||
import static org.jclouds.openstack.v2_0.predicates.ExtensionPredicates.namespaceEquals;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import org.jclouds.date.internal.SimpleDateFormatDateService;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
|
@ -39,10 +39,10 @@ import org.jclouds.openstack.nova.v2_0.extensions.SimpleTenantUsageApi;
|
|||
import org.jclouds.openstack.nova.v2_0.extensions.VirtualInterfaceApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.VolumeApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.VolumeTypeApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ExtensionApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.FlavorApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ImageApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ServerApi;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionApi;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
|
||||
|
|
|
@ -37,10 +37,10 @@ import org.jclouds.openstack.nova.v2_0.extensions.SimpleTenantUsageAsyncApi;
|
|||
import org.jclouds.openstack.nova.v2_0.extensions.VirtualInterfaceAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.VolumeAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.VolumeTypeAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.FlavorAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ImageAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ServerAsyncApi;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@
|
|||
*/
|
||||
package org.jclouds.openstack.nova.v2_0.config;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -29,47 +30,48 @@ import org.jclouds.http.HttpErrorHandler;
|
|||
import org.jclouds.http.annotation.ClientError;
|
||||
import org.jclouds.http.annotation.Redirection;
|
||||
import org.jclouds.http.annotation.ServerError;
|
||||
import org.jclouds.openstack.nova.v2_0.NovaAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.NovaApi;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.AdminActionsAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.NovaAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.AdminActionsApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.FlavorExtraSpecsAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.AdminActionsAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.ExtensionNamespaces;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.FlavorExtraSpecsApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.FlavorExtraSpecsAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.HostAdministrationAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.FloatingIPAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.HostAdministrationApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.HostAggregateAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.HostAdministrationAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.HostAggregateApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.KeyPairAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.HostAggregateAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.KeyPairApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.QuotaAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.QuotaClassAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.QuotaClassApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.KeyPairAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.QuotaApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.SecurityGroupAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.QuotaAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.QuotaClassApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.QuotaClassAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.SecurityGroupApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.ServerWithSecurityGroupsAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.SecurityGroupAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.ServerWithSecurityGroupsApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.SimpleTenantUsageAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.ServerWithSecurityGroupsAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.SimpleTenantUsageApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.VirtualInterfaceAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.SimpleTenantUsageAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.VirtualInterfaceApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.VolumeAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.VirtualInterfaceAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.VolumeApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.VolumeTypeAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.VolumeAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.VolumeTypeApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ExtensionApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.FlavorAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.VolumeTypeAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.FlavorApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ImageAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.FlavorAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ImageApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ServerAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ImageAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ServerApi;
|
||||
import org.jclouds.openstack.nova.v2_0.functions.PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ServerAsyncApi;
|
||||
import org.jclouds.openstack.nova.v2_0.handlers.NovaErrorHandler;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionApi;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.openstack.v2_0.functions.PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.config.RestClientModule;
|
||||
import org.jclouds.rest.functions.ImplicitOptionalConverter;
|
||||
|
@ -78,6 +80,8 @@ import com.google.common.cache.CacheBuilder;
|
|||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
|
@ -122,22 +126,54 @@ public class NovaRestClientModule<S extends NovaApi, A extends NovaAsyncApi> ext
|
|||
@Override
|
||||
protected void configure() {
|
||||
install(new NovaParserModule());
|
||||
bind(ImplicitOptionalConverter.class).to(
|
||||
PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.class);
|
||||
bind(ImplicitOptionalConverter.class).to(PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.class);
|
||||
super.configure();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public Multimap<URI, URI> aliases() {
|
||||
return ImmutableMultimap.<URI, URI>builder()
|
||||
.put(URI.create(ExtensionNamespaces.SECURITY_GROUPS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/securitygroups/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.FLOATING_IPS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/floating_ips/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.KEYPAIRS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/keypairs/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.SIMPLE_TENANT_USAGE),
|
||||
URI.create("http://docs.openstack.org/compute/ext/os-simple-tenant-usage/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.HOSTS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/hosts/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.VOLUMES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/volumes/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.VIRTUAL_INTERFACES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/virtual_interfaces/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.CREATESERVEREXT),
|
||||
URI.create("http://docs.openstack.org/compute/ext/createserverext/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.ADMIN_ACTIONS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/admin-actions/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.AGGREGATES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/aggregates/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.FLAVOR_EXTRA_SPECS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/flavor_extra_specs/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.QUOTAS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/quotas-sets/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.QUOTA_CLASSES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/quota-classes-sets/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.VOLUME_TYPES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/volume_types/api/v1.1"))
|
||||
.build();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public LoadingCache<String, Set<? extends Extension>> provideExtensionsByZone(final Provider<NovaApi> novaApi) {
|
||||
return CacheBuilder.newBuilder().expireAfterWrite(23, TimeUnit.HOURS)
|
||||
.build(new CacheLoader<String, Set<? extends Extension>>() {
|
||||
|
||||
@Override
|
||||
public Set<? extends Extension> load(String key) throws Exception {
|
||||
return novaApi.get().getExtensionApiForZone(key).listExtensions();
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
|
|
@ -31,8 +31,8 @@ import javax.ws.rs.core.MediaType;
|
|||
|
||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.FloatingIP;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.openstack.v2_0.ServiceType;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.openstack.v2_0.services.Extension;
|
||||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.Payload;
|
||||
|
|
|
@ -32,8 +32,8 @@ import javax.ws.rs.core.MediaType;
|
|||
|
||||
import org.jclouds.openstack.keystone.v2_0.filters.AuthenticateRequest;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.KeyPair;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.openstack.v2_0.ServiceType;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.openstack.v2_0.services.Extension;
|
||||
import org.jclouds.rest.annotations.ExceptionParser;
|
||||
import org.jclouds.rest.annotations.Payload;
|
||||
|
|
|
@ -1,113 +0,0 @@
|
|||
/**
|
||||
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||
* contributor license agreements. See the NOTICE file
|
||||
* distributed with this work for additional information
|
||||
* regarding copyright ownership. jclouds licenses this file
|
||||
* to you under the Apache License, Version 2.0 (the
|
||||
* "License"); you may not use this file except in compliance
|
||||
* with the License. You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing,
|
||||
* software distributed under the License is distributed on an
|
||||
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||
* KIND, either express or implied. See the License for the
|
||||
* specific language governing permissions and limitations
|
||||
* under the License.
|
||||
*/
|
||||
package org.jclouds.openstack.nova.v2_0.functions;
|
||||
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Set;
|
||||
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.internal.ClassMethodArgsAndReturnVal;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.nova.v2_0.extensions.ExtensionNamespaces;
|
||||
import org.jclouds.openstack.nova.v2_0.predicates.ExtensionPredicates;
|
||||
import org.jclouds.rest.functions.ImplicitOptionalConverter;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* We use the annotation {@link org.jclouds.openstack.services.Extension} to
|
||||
* bind a class that is an extension to an extension found in the
|
||||
* {@link org.jclouds.openstack.nova.v2_0.features.ExtensionApi#listExtensions} call.
|
||||
*
|
||||
* @author Adrian Cole
|
||||
*
|
||||
*/
|
||||
@Singleton
|
||||
public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet implements
|
||||
ImplicitOptionalConverter {
|
||||
private final LoadingCache<String, Set<? extends Extension>> extensions;
|
||||
|
||||
@com.google.inject.Inject(optional=true)
|
||||
@Named("openstack.nova.extensions")
|
||||
Multimap<URI, URI> aliases = ImmutableMultimap.<URI, URI>builder()
|
||||
.put(URI.create(ExtensionNamespaces.SECURITY_GROUPS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/securitygroups/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.FLOATING_IPS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/floating_ips/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.KEYPAIRS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/keypairs/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.SIMPLE_TENANT_USAGE),
|
||||
URI.create("http://docs.openstack.org/compute/ext/os-simple-tenant-usage/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.HOSTS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/hosts/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.VOLUMES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/volumes/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.VIRTUAL_INTERFACES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/virtual_interfaces/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.CREATESERVEREXT),
|
||||
URI.create("http://docs.openstack.org/compute/ext/createserverext/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.ADMIN_ACTIONS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/admin-actions/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.AGGREGATES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/aggregates/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.FLAVOR_EXTRA_SPECS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/flavor_extra_specs/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.QUOTAS),
|
||||
URI.create("http://docs.openstack.org/compute/ext/quotas-sets/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.QUOTA_CLASSES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/quota-classes-sets/api/v1.1"))
|
||||
.put(URI.create(ExtensionNamespaces.VOLUME_TYPES),
|
||||
URI.create("http://docs.openstack.org/compute/ext/volume_types/api/v1.1"))
|
||||
.build();
|
||||
|
||||
@Inject
|
||||
public PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet(
|
||||
LoadingCache<String, Set<? extends Extension>> extensions) {
|
||||
this.extensions = checkNotNull(extensions, "extensions");
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Object> apply(ClassMethodArgsAndReturnVal input) {
|
||||
Optional<org.jclouds.openstack.v2_0.services.Extension> ext = Optional.fromNullable(input.getClazz().getAnnotation(
|
||||
org.jclouds.openstack.v2_0.services.Extension.class));
|
||||
if (ext.isPresent()) {
|
||||
checkState(input.getArgs() != null && input.getArgs().length == 1, "expecting an arg %s", input);
|
||||
URI namespace = URI.create(ext.get().namespace());
|
||||
if (Iterables.any(extensions.getUnchecked(checkNotNull(input.getArgs()[0], "arg[0] in %s", input).toString()),
|
||||
ExtensionPredicates.namespaceOrAliasEquals(namespace, aliases.get(namespace))))
|
||||
return Optional.of(input.getReturnVal());
|
||||
}
|
||||
return Optional.absent();
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return "presentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet()";
|
||||
}
|
||||
|
||||
}
|
|
@ -27,11 +27,11 @@ import org.jclouds.http.HttpResponseException;
|
|||
import org.jclouds.openstack.nova.v2_0.domain.BackupType;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Image;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Server.Status;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ExtensionApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ImageApi;
|
||||
import org.jclouds.openstack.nova.v2_0.features.ServerApi;
|
||||
import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiLiveTest;
|
||||
import org.jclouds.openstack.nova.v2_0.options.CreateBackupOfServerOptions;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionApi;
|
||||
import org.testng.annotations.AfterGroups;
|
||||
import org.testng.annotations.AfterMethod;
|
||||
import org.testng.annotations.BeforeGroups;
|
||||
|
|
|
@ -23,8 +23,9 @@ import static org.testng.Assert.assertTrue;
|
|||
|
||||
import java.util.Set;
|
||||
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.nova.v2_0.internal.BaseNovaApiLiveTest;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionApi;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
/**
|
||||
|
|
|
@ -28,7 +28,7 @@ import org.jclouds.date.internal.SimpleDateFormatDateService;
|
|||
import org.jclouds.json.BaseSetParserTest;
|
||||
import org.jclouds.json.config.GsonModule;
|
||||
import org.jclouds.openstack.nova.v2_0.config.NovaParserModule;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.jclouds.rest.annotations.SelectJson;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
|
|
|
@ -28,7 +28,7 @@ import org.jclouds.date.internal.SimpleDateFormatDateService;
|
|||
import org.jclouds.json.BaseSetParserTest;
|
||||
import org.jclouds.json.config.GsonModule;
|
||||
import org.jclouds.openstack.nova.v2_0.config.NovaParserModule;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.domain.Link;
|
||||
import org.jclouds.openstack.v2_0.domain.Link.Relation;
|
||||
import org.jclouds.rest.annotations.SelectJson;
|
||||
|
|
|
@ -27,7 +27,7 @@ import org.jclouds.date.internal.SimpleDateFormatDateService;
|
|||
import org.jclouds.json.BaseItemParserTest;
|
||||
import org.jclouds.json.config.GsonModule;
|
||||
import org.jclouds.openstack.nova.v2_0.config.NovaParserModule;
|
||||
import org.jclouds.openstack.nova.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.domain.Link;
|
||||
import org.jclouds.openstack.v2_0.domain.Link.Relation;
|
||||
import org.jclouds.rest.annotations.SelectJson;
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.jclouds.javax.annotation.Nullable;
|
|||
import org.jclouds.location.Region;
|
||||
import org.jclouds.location.functions.RegionToEndpoint;
|
||||
import org.jclouds.openstack.glance.v1_0.features.ImageApi;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionApi;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
|
||||
|
@ -49,6 +50,13 @@ public interface GlanceApi {
|
|||
@Region
|
||||
Set<String> getConfiguredRegions();
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Extension features.
|
||||
*/
|
||||
@Delegate
|
||||
ExtensionApi getExtensionApiForRegion(
|
||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region);
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Image features.
|
||||
*/
|
||||
|
|
|
@ -24,6 +24,7 @@ import org.jclouds.javax.annotation.Nullable;
|
|||
import org.jclouds.location.Region;
|
||||
import org.jclouds.location.functions.RegionToEndpoint;
|
||||
import org.jclouds.openstack.glance.v1_0.features.ImageAsyncApi;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
|
||||
|
@ -46,6 +47,13 @@ public interface GlanceAsyncApi {
|
|||
@Region
|
||||
Set<String> getConfiguredRegions();
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Extension features.
|
||||
*/
|
||||
@Delegate
|
||||
ExtensionAsyncApi getExtensionApiForRegion(
|
||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region);
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Image features.
|
||||
*/
|
||||
|
|
|
@ -18,7 +18,13 @@
|
|||
*/
|
||||
package org.jclouds.openstack.glance.v1_0.config;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.http.HttpErrorHandler;
|
||||
import org.jclouds.http.annotation.ClientError;
|
||||
|
@ -26,15 +32,27 @@ import org.jclouds.http.annotation.Redirection;
|
|||
import org.jclouds.http.annotation.ServerError;
|
||||
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
||||
import org.jclouds.openstack.glance.v1_0.GlanceAsyncApi;
|
||||
import org.jclouds.openstack.glance.v1_0.GlanceApi;
|
||||
import org.jclouds.openstack.glance.v1_0.features.ImageAsyncApi;
|
||||
import org.jclouds.openstack.glance.v1_0.GlanceAsyncApi;
|
||||
import org.jclouds.openstack.glance.v1_0.features.ImageApi;
|
||||
import org.jclouds.openstack.glance.v1_0.features.ImageAsyncApi;
|
||||
import org.jclouds.openstack.glance.v1_0.handlers.GlanceErrorHandler;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionApi;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.openstack.v2_0.functions.PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.config.RestClientModule;
|
||||
import org.jclouds.rest.functions.ImplicitOptionalConverter;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Configures the Glance connection.
|
||||
|
@ -42,22 +60,47 @@ import com.google.common.collect.ImmutableMap;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
@ConfiguresRestClient
|
||||
public class GlanceRestClientModule extends RestClientModule<GlanceApi, GlanceAsyncApi> {
|
||||
public class GlanceRestClientModule<S extends GlanceApi, A extends GlanceAsyncApi> extends RestClientModule<S, A> {
|
||||
|
||||
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
|
||||
.put(ExtensionApi.class, ExtensionAsyncApi.class)
|
||||
.put(ImageApi.class, ImageAsyncApi.class)
|
||||
.build();
|
||||
|
||||
public GlanceRestClientModule() {
|
||||
super(DELEGATE_MAP);
|
||||
super(TypeToken.class.cast(TypeToken.of(GlanceApi.class)), TypeToken.class.cast(TypeToken.of(GlanceAsyncApi.class)), DELEGATE_MAP);
|
||||
}
|
||||
|
||||
protected GlanceRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType, Map<Class<?>, Class<?>> sync2Async) {
|
||||
super(syncClientType, asyncClientType, sync2Async);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
|
||||
bind(ImplicitOptionalConverter.class).to(PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.class);
|
||||
super.configure();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public Multimap<URI, URI> aliases() {
|
||||
return ImmutableMultimap.<URI, URI>builder()
|
||||
.build();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public LoadingCache<String, Set<? extends Extension>> provideExtensionsByZone(final Provider<GlanceApi> glanceApi) {
|
||||
return CacheBuilder.newBuilder().expireAfterWrite(23, TimeUnit.HOURS)
|
||||
.build(new CacheLoader<String, Set<? extends Extension>>() {
|
||||
@Override
|
||||
public Set<? extends Extension> load(String key) throws Exception {
|
||||
return glanceApi.get().getExtensionApiForRegion(key).listExtensions();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindErrorHandlers() {
|
||||
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(GlanceErrorHandler.class);
|
||||
|
|
|
@ -28,8 +28,10 @@ import org.jclouds.concurrent.Timeout;
|
|||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.location.Region;
|
||||
import org.jclouds.location.functions.RegionToEndpoint;
|
||||
import org.jclouds.location.functions.ZoneToEndpoint;
|
||||
import org.jclouds.openstack.quantum.v1_0.features.NetworkApi;
|
||||
import org.jclouds.openstack.quantum.v1_0.features.PortApi;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionApi;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
|
||||
|
@ -52,6 +54,13 @@ public interface QuantumApi {
|
|||
@Region
|
||||
Set<String> getConfiguredRegions();
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Extension features.
|
||||
*/
|
||||
@Delegate
|
||||
ExtensionApi getExtensionApiForRegion(
|
||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region);
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Network features.
|
||||
*/
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.jclouds.location.Region;
|
|||
import org.jclouds.location.functions.RegionToEndpoint;
|
||||
import org.jclouds.openstack.quantum.v1_0.features.NetworkAsyncApi;
|
||||
import org.jclouds.openstack.quantum.v1_0.features.PortAsyncApi;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
|
||||
|
@ -50,6 +51,13 @@ public interface QuantumAsyncApi {
|
|||
@Region
|
||||
Set<String> getConfiguredRegions();
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Extension features.
|
||||
*/
|
||||
@Delegate
|
||||
ExtensionAsyncApi getExtensionApiForRegion(
|
||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region);
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Network features.
|
||||
*/
|
||||
|
|
|
@ -18,7 +18,13 @@
|
|||
*/
|
||||
package org.jclouds.openstack.quantum.v1_0.config;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.http.HttpErrorHandler;
|
||||
import org.jclouds.http.annotation.ClientError;
|
||||
|
@ -26,17 +32,29 @@ import org.jclouds.http.annotation.Redirection;
|
|||
import org.jclouds.http.annotation.ServerError;
|
||||
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
||||
import org.jclouds.openstack.quantum.v1_0.QuantumAsyncApi;
|
||||
import org.jclouds.openstack.quantum.v1_0.QuantumApi;
|
||||
import org.jclouds.openstack.quantum.v1_0.features.NetworkAsyncApi;
|
||||
import org.jclouds.openstack.quantum.v1_0.QuantumAsyncApi;
|
||||
import org.jclouds.openstack.quantum.v1_0.features.NetworkApi;
|
||||
import org.jclouds.openstack.quantum.v1_0.features.PortAsyncApi;
|
||||
import org.jclouds.openstack.quantum.v1_0.features.NetworkAsyncApi;
|
||||
import org.jclouds.openstack.quantum.v1_0.features.PortApi;
|
||||
import org.jclouds.openstack.quantum.v1_0.features.PortAsyncApi;
|
||||
import org.jclouds.openstack.quantum.v1_0.handlers.QuantumErrorHandler;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionApi;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.openstack.v2_0.functions.PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.config.RestClientModule;
|
||||
import org.jclouds.rest.functions.ImplicitOptionalConverter;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Configures the Quantum connection.
|
||||
|
@ -44,23 +62,48 @@ import com.google.common.collect.ImmutableMap;
|
|||
* @author Adam Lowe
|
||||
*/
|
||||
@ConfiguresRestClient
|
||||
public class QuantumRestClientModule extends RestClientModule<QuantumApi, QuantumAsyncApi> {
|
||||
public class QuantumRestClientModule<S extends QuantumApi, A extends QuantumAsyncApi> extends RestClientModule<S, A> {
|
||||
|
||||
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
|
||||
.put(ExtensionApi.class, ExtensionAsyncApi.class)
|
||||
.put(NetworkApi.class, NetworkAsyncApi.class)
|
||||
.put(PortApi.class, PortAsyncApi.class)
|
||||
.build();
|
||||
|
||||
public QuantumRestClientModule() {
|
||||
super(DELEGATE_MAP);
|
||||
super(TypeToken.class.cast(TypeToken.of(QuantumApi.class)), TypeToken.class.cast(TypeToken.of(QuantumAsyncApi.class)), DELEGATE_MAP);
|
||||
}
|
||||
|
||||
protected QuantumRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType, Map<Class<?>, Class<?>> sync2Async) {
|
||||
super(syncClientType, asyncClientType, sync2Async);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
|
||||
bind(ImplicitOptionalConverter.class).to(PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.class);
|
||||
super.configure();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public Multimap<URI, URI> aliases() {
|
||||
return ImmutableMultimap.<URI, URI>builder()
|
||||
.build();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public LoadingCache<String, Set<? extends Extension>> provideExtensionsByZone(final Provider<QuantumApi> quantumApi) {
|
||||
return CacheBuilder.newBuilder().expireAfterWrite(23, TimeUnit.HOURS)
|
||||
.build(new CacheLoader<String, Set<? extends Extension>>() {
|
||||
@Override
|
||||
public Set<? extends Extension> load(String key) throws Exception {
|
||||
return quantumApi.get().getExtensionApiForRegion(key).listExtensions();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindErrorHandlers() {
|
||||
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(QuantumErrorHandler.class);
|
||||
|
|
|
@ -28,6 +28,7 @@ import org.jclouds.location.functions.RegionToEndpoint;
|
|||
import org.jclouds.openstack.swift.v1.features.AccountApi;
|
||||
import org.jclouds.openstack.swift.v1.features.ContainerApi;
|
||||
import org.jclouds.openstack.swift.v1.features.ObjectApi;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionApi;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
|
||||
|
@ -51,6 +52,13 @@ public interface SwiftApi {
|
|||
@Region
|
||||
Set<String> getConfiguredRegions();
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Extension features.
|
||||
*/
|
||||
@Delegate
|
||||
ExtensionApi getExtensionApiForRegion(
|
||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region);
|
||||
|
||||
/**
|
||||
* Provides synchronous access to Account features.
|
||||
*/
|
||||
|
|
|
@ -26,6 +26,7 @@ import org.jclouds.location.functions.RegionToEndpoint;
|
|||
import org.jclouds.openstack.swift.v1.features.AccountAsyncApi;
|
||||
import org.jclouds.openstack.swift.v1.features.ContainerAsyncApi;
|
||||
import org.jclouds.openstack.swift.v1.features.ObjectAsyncApi;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.rest.annotations.Delegate;
|
||||
import org.jclouds.rest.annotations.EndpointParam;
|
||||
|
||||
|
@ -48,6 +49,13 @@ public interface SwiftAsyncApi {
|
|||
@Region
|
||||
Set<String> getConfiguredRegions();
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Extension features.
|
||||
*/
|
||||
@Delegate
|
||||
ExtensionAsyncApi getExtensionApiForRegion(
|
||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region);
|
||||
|
||||
/**
|
||||
* Provides asynchronous access to Account features.
|
||||
*/
|
||||
|
|
|
@ -18,7 +18,13 @@
|
|||
*/
|
||||
package org.jclouds.openstack.swift.v1.config;
|
||||
|
||||
import java.net.URI;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
|
||||
import org.jclouds.http.HttpErrorHandler;
|
||||
import org.jclouds.http.annotation.ClientError;
|
||||
|
@ -26,19 +32,31 @@ import org.jclouds.http.annotation.Redirection;
|
|||
import org.jclouds.http.annotation.ServerError;
|
||||
import org.jclouds.json.config.GsonModule.DateAdapter;
|
||||
import org.jclouds.json.config.GsonModule.Iso8601DateAdapter;
|
||||
import org.jclouds.openstack.swift.v1.SwiftAsyncApi;
|
||||
import org.jclouds.openstack.swift.v1.SwiftApi;
|
||||
import org.jclouds.openstack.swift.v1.features.AccountAsyncApi;
|
||||
import org.jclouds.openstack.swift.v1.SwiftAsyncApi;
|
||||
import org.jclouds.openstack.swift.v1.features.AccountApi;
|
||||
import org.jclouds.openstack.swift.v1.features.ContainerAsyncApi;
|
||||
import org.jclouds.openstack.swift.v1.features.AccountAsyncApi;
|
||||
import org.jclouds.openstack.swift.v1.features.ContainerApi;
|
||||
import org.jclouds.openstack.swift.v1.features.ObjectAsyncApi;
|
||||
import org.jclouds.openstack.swift.v1.features.ContainerAsyncApi;
|
||||
import org.jclouds.openstack.swift.v1.features.ObjectApi;
|
||||
import org.jclouds.openstack.swift.v1.features.ObjectAsyncApi;
|
||||
import org.jclouds.openstack.swift.v1.handlers.SwiftErrorHandler;
|
||||
import org.jclouds.openstack.v2_0.domain.Extension;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionApi;
|
||||
import org.jclouds.openstack.v2_0.features.ExtensionAsyncApi;
|
||||
import org.jclouds.openstack.v2_0.functions.PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet;
|
||||
import org.jclouds.rest.ConfiguresRestClient;
|
||||
import org.jclouds.rest.config.RestClientModule;
|
||||
import org.jclouds.rest.functions.ImplicitOptionalConverter;
|
||||
|
||||
import com.google.common.cache.CacheBuilder;
|
||||
import com.google.common.cache.CacheLoader;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.reflect.TypeToken;
|
||||
import com.google.inject.Provides;
|
||||
|
||||
/**
|
||||
* Configures the Swift connection.
|
||||
|
@ -46,24 +64,49 @@ import com.google.common.collect.ImmutableMap;
|
|||
* @author Adrian Cole
|
||||
*/
|
||||
@ConfiguresRestClient
|
||||
public class SwiftRestClientModule extends RestClientModule<SwiftApi, SwiftAsyncApi> {
|
||||
public class SwiftRestClientModule<S extends SwiftApi, A extends SwiftAsyncApi> extends RestClientModule<S, A> {
|
||||
|
||||
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
|
||||
.put(ExtensionApi.class, ExtensionAsyncApi.class)
|
||||
.put(AccountApi.class, AccountAsyncApi.class)
|
||||
.put(ContainerApi.class, ContainerAsyncApi.class)
|
||||
.put(ObjectApi.class, ObjectAsyncApi.class)
|
||||
.build();
|
||||
|
||||
public SwiftRestClientModule() {
|
||||
super(DELEGATE_MAP);
|
||||
super(TypeToken.class.cast(TypeToken.of(SwiftApi.class)), TypeToken.class.cast(TypeToken.of(SwiftAsyncApi.class)), DELEGATE_MAP);
|
||||
}
|
||||
|
||||
protected SwiftRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType, Map<Class<?>, Class<?>> sync2Async) {
|
||||
super(syncClientType, asyncClientType, sync2Async);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void configure() {
|
||||
bind(DateAdapter.class).to(Iso8601DateAdapter.class);
|
||||
bind(ImplicitOptionalConverter.class).to(PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet.class);
|
||||
super.configure();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public Multimap<URI, URI> aliases() {
|
||||
return ImmutableMultimap.<URI, URI>builder()
|
||||
.build();
|
||||
}
|
||||
|
||||
@Provides
|
||||
@Singleton
|
||||
public LoadingCache<String, Set<? extends Extension>> provideExtensionsByZone(final Provider<SwiftApi> swiftApi) {
|
||||
return CacheBuilder.newBuilder().expireAfterWrite(23, TimeUnit.HOURS)
|
||||
.build(new CacheLoader<String, Set<? extends Extension>>() {
|
||||
@Override
|
||||
public Set<? extends Extension> load(String key) throws Exception {
|
||||
return swiftApi.get().getExtensionApiForRegion(key).listExtensions();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void bindErrorHandlers() {
|
||||
bind(HttpErrorHandler.class).annotatedWith(Redirection.class).to(SwiftErrorHandler.class);
|
||||
|
|
Loading…
Reference in New Issue