Merge branch 'master' of github.com:jclouds/jclouds into 1.5.x

* 'master' of github.com:jclouds/jclouds: (30 commits)
  Merge Keystone optional admin API provider with optional extension provider
  Added binding for optional extensions
  Make the OpenStack extension lists accessible for all APIs. Copied the Nova extension related code to the shared keystone package and added providers for extensions and aliases to all modules
  added statement to rebase dist packages
  added VAppNetworksLiveTest
  Further OpenStack extensibility changes. Fixing constructors in RestContext classes
  Fixed a possible NPE when ServiceFunctionLoader finds no OSGi service for a function.
  fixed broken test
  threading issue in test
  openstack-quantum extensibility
  openstack-swift extensibility
  openstack-glance extensibility
  openstack-nova extensibility
  openstack-keystone extensibility
  add FirstNetwork, in line with FirstRegion, etc., for use in FGCP provider
  missing class
  refactoring of smartos-ssh
  Extend the VmSpecification to allow for all the extra memory settings.
  Issue 1067:update to guava 13
  removed invalid @Nullable usage and also usage of javax package usage
  ...
This commit is contained in:
Adrian Cole 2012-08-13 20:29:15 -07:00
commit 81d5f31359
178 changed files with 2328 additions and 1226 deletions

View File

@ -24,7 +24,6 @@ import static com.google.common.base.Preconditions.checkState;
import java.util.Map;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
import javax.ws.rs.core.MediaType;
@ -68,7 +67,7 @@ public class BindCloneDriveOptionsToPlainTextString implements MapBinder {
request.setPayload(listOfMapsToListOfKeyValuesDelimitedByBlankLines.apply(ImmutableSet.of(Maps.transformValues(postParams, new Function<Object, String>() {
@Override
public String apply(@Nullable Object input) {
public String apply(Object input) {
return input == null ? null : input.toString();
}
}))));

View File

@ -27,7 +27,6 @@ import static org.jclouds.util.InetAddresses2.isPrivateIPAddress;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Singleton;
@ -153,12 +152,12 @@ public class VirtualMachineToNodeMetadata implements Function<VirtualMachine, No
filter(getIPForwardingRulesByVirtualMachine.getUnchecked(from.getId()),
new Predicate<IPForwardingRule>() {
@Override
public boolean apply(@Nullable IPForwardingRule rule) {
public boolean apply(IPForwardingRule rule) {
return !"Deleting".equals(rule.getState());
}
}), new Function<IPForwardingRule, String>() {
@Override
public String apply(@Nullable IPForwardingRule rule) {
public String apply(IPForwardingRule rule) {
return rule.getIPAddress();
}
}));

View File

@ -20,8 +20,6 @@ package org.jclouds.cloudstack.predicates;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Nullable;
import org.jclouds.cloudstack.domain.GuestIPType;
import org.jclouds.cloudstack.domain.Network;
import org.jclouds.cloudstack.domain.NetworkService;
@ -163,7 +161,7 @@ public class NetworkPredicates {
}
@Override
public boolean apply(@Nullable GuestIPType guestIPType) {
public boolean apply(GuestIPType guestIPType) {
return guestIPType == this.guestIPType;
}

View File

@ -26,8 +26,6 @@ import static org.testng.Assert.assertTrue;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Nullable;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.FirewallRule;
import org.jclouds.cloudstack.domain.Network;
@ -69,7 +67,7 @@ public class FirewallClientLiveTest extends BaseCloudStackClientLiveTest {
network = find(client.getNetworkClient().listNetworks(), Predicates.and(supportsPortForwarding(),
new Predicate<Network>() {
@Override
public boolean apply(@Nullable Network network) {
public boolean apply(Network network) {
return network.isDefault()
&& !network.isSecurityGroupEnabled()
&& network.getAccount().equals(user.getAccount());

View File

@ -24,8 +24,6 @@ import static org.testng.Assert.assertEquals;
import java.util.Set;
import javax.annotation.Nullable;
import org.jclouds.cloudstack.domain.ConfigurationEntry;
import org.jclouds.cloudstack.internal.BaseCloudStackClientLiveTest;
import org.testng.annotations.Test;
@ -97,7 +95,7 @@ public class GlobalConfigurationClientLiveTest extends BaseCloudStackClientLiveT
private ConfigurationEntry getEntryByName(Set<ConfigurationEntry> entries, final String name) {
return Iterables.find(entries, new Predicate<ConfigurationEntry>() {
@Override
public boolean apply(@Nullable ConfigurationEntry entry) {
public boolean apply(ConfigurationEntry entry) {
return entry != null && Objects.equal(name, entry.getName());
}
});

View File

@ -23,8 +23,6 @@ import static org.jclouds.cloudstack.options.UpdateDomainOptions.Builder.name;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNull;
import javax.annotation.Nullable;
import org.jclouds.cloudstack.domain.Domain;
import org.jclouds.cloudstack.internal.BaseCloudStackClientLiveTest;
import org.testng.annotations.BeforeMethod;
@ -48,7 +46,7 @@ public class GlobalDomainClientLiveTest extends BaseCloudStackClientLiveTest {
domainClient = globalAdminClient.getDomainClient();
rootDomain = find(domainClient.listDomains(), new Predicate<Domain>() {
@Override
public boolean apply(@Nullable Domain domain) {
public boolean apply(Domain domain) {
return domain != null && domain.getName().equals("ROOT");
}
});

View File

@ -30,8 +30,6 @@ import java.util.NoSuchElementException;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import org.jclouds.cloudstack.domain.AsyncJob;
import org.jclouds.cloudstack.domain.JobResult;
import org.jclouds.cloudstack.domain.LoadBalancerRule;
@ -78,7 +76,7 @@ public class LoadBalancerClientLiveTest extends BaseCloudStackClientLiveTest {
Predicates.and(hasLoadBalancerService(), isVirtualNetwork(),
new Predicate<Network>() {
@Override
public boolean apply(@Nullable Network network) {
public boolean apply(Network network) {
return network.isDefault()
&& !network.isSecurityGroupEnabled()
&& !network.isSystem()

View File

@ -27,8 +27,6 @@ import java.net.URI;
import java.net.URLDecoder;
import java.util.Set;
import javax.annotation.Nullable;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.AsyncJob;
import org.jclouds.cloudstack.domain.ExtractMode;
@ -107,7 +105,7 @@ public class TemplateClientLiveTest extends BaseCloudStackClientLiveTest {
Iterable<Network> networks = client.getNetworkClient().listNetworks(ListNetworksOptions.Builder.zoneId(zone.getId()).isDefault(true));
networks = Iterables.filter(networks, new Predicate<Network>() {
@Override
public boolean apply(@Nullable Network network) {
public boolean apply(Network network) {
return network != null && network.getState().equals("Implemented");
}
});
@ -160,7 +158,7 @@ public class TemplateClientLiveTest extends BaseCloudStackClientLiveTest {
Iterable<Network> networks = client.getNetworkClient().listNetworks(ListNetworksOptions.Builder.zoneId(zone.getId()).isDefault(true));
networks = Iterables.filter(networks, new Predicate<Network>() {
@Override
public boolean apply(@Nullable Network network) {
public boolean apply(Network network) {
return network != null && network.getName().equals("Virtual Network");
}
});
@ -181,7 +179,7 @@ public class TemplateClientLiveTest extends BaseCloudStackClientLiveTest {
final String zoneId = zone.getId();
Predicate<Template> templateReadyPredicate = new Predicate<Template>() {
@Override
public boolean apply(@Nullable Template template) {
public boolean apply(Template template) {
if (template == null) return false;
Template t2 = client.getTemplateClient().getTemplateInZone(template.getId(), zoneId);
Logger.CONSOLE.info("%s", t2.getStatus());

View File

@ -34,8 +34,6 @@ import java.util.Set;
import java.util.concurrent.ExecutionException;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import org.jclouds.cloudstack.CloudStackClient;
import org.jclouds.cloudstack.domain.AsyncCreateResponse;
import org.jclouds.cloudstack.domain.AsyncJob;
@ -94,7 +92,7 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
if (networks.size() > 0) {
Network network = get(filter(networks, new Predicate<Network>() {
@Override
public boolean apply(@Nullable Network network) {
public boolean apply(Network network) {
return network != null && network.getState().equals("Implemented");
}
}), 0);
@ -143,7 +141,7 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
String zoneId = getFirst(networks, null).getZoneId();
options.networkIds(Iterables.transform(networks, new Function<Network, String>() {
@Override
public String apply(@Nullable Network network) {
public String apply(Network network) {
return network.getId();
}
}));
@ -240,7 +238,7 @@ public class VirtualMachineClientLiveTest extends BaseCloudStackClientLiveTest {
Network requiredNetwork = getOnlyElement(filter(adminClient.getNetworkClient().listNetworks(
ListNetworksOptions.Builder.zoneId(template.getZoneId())), new Predicate<Network>() {
@Override
public boolean apply(@Nullable Network network) {
public boolean apply(Network network) {
return network.isDefault() &&
network.getGuestIPType() == GuestIPType.VIRTUAL;
}

View File

@ -26,8 +26,6 @@ import static org.testng.Assert.assertEquals;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.annotation.Nullable;
import org.jclouds.cloudstack.domain.IPForwardingRule;
import org.jclouds.cloudstack.domain.Network;
import org.jclouds.cloudstack.domain.PublicIPAddress;
@ -96,7 +94,7 @@ public class StaticNATVirtualMachineInNetworkLiveTest extends NATClientLiveTest
rule = getOnlyElement(filter(client.getNATClient().getIPForwardingRulesForIPAddress(ip.getId()),
new Predicate<IPForwardingRule>() {
@Override
public boolean apply(@Nullable IPForwardingRule rule) {
public boolean apply(IPForwardingRule rule) {
return rule != null && rule.getStartPort() == 22;
}
}));

View File

@ -20,8 +20,6 @@ package org.jclouds.ec2;
import java.util.Set;
import javax.annotation.Nullable;
import org.jclouds.ec2.features.WindowsAsyncApi;
import org.jclouds.ec2.services.AMIAsyncClient;
import org.jclouds.ec2.services.AvailabilityZoneAndRegionAsyncClient;
@ -31,6 +29,7 @@ import org.jclouds.ec2.services.InstanceAsyncClient;
import org.jclouds.ec2.services.KeyPairAsyncClient;
import org.jclouds.ec2.services.SecurityGroupAsyncClient;
import org.jclouds.ec2.services.WindowsAsyncClient;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Region;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.rest.annotations.Delegate;

View File

@ -21,8 +21,6 @@ package org.jclouds.ec2;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import org.jclouds.concurrent.Timeout;
import org.jclouds.ec2.features.WindowsApi;
import org.jclouds.ec2.services.AMIClient;
@ -33,6 +31,7 @@ import org.jclouds.ec2.services.InstanceClient;
import org.jclouds.ec2.services.KeyPairClient;
import org.jclouds.ec2.services.SecurityGroupClient;
import org.jclouds.ec2.services.WindowsClient;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Region;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.rest.annotations.Delegate;

View File

@ -23,7 +23,6 @@ import java.security.KeyFactory;
import java.security.PrivateKey;
import java.security.spec.KeySpec;
import javax.annotation.Nullable;
import javax.crypto.Cipher;
import javax.inject.Inject;
@ -32,6 +31,7 @@ import org.jclouds.crypto.Pems;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.ec2.compute.domain.PasswordDataAndPrivateKey;
import org.jclouds.encryption.internal.Base64;
import org.jclouds.javax.annotation.Nullable;
import com.google.common.base.Function;
import com.google.common.base.Throwables;

View File

@ -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
*/

View File

@ -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()
*/
@ -71,7 +78,6 @@ public interface KeystoneAsyncApi {
*/
@Delegate
Optional<UserAsyncApi> getUserApi();
/**
* @see KeystoneApi#getTenantApi()

View File

@ -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);

View File

@ -40,5 +40,5 @@ public interface ServiceApi {
/**
* The operation returns a list of tenants which the current token provides access to.
*/
Set<Tenant> listTenants();
Set<? extends Tenant> listTenants();
}

View File

@ -57,5 +57,5 @@ public interface ServiceAsyncApi {
@Path("/tenants")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Tenant>> listTenants();
ListenableFuture<? extends Set<? extends Tenant>> listTenants();
}

View File

@ -40,7 +40,7 @@ public interface TenantApi {
/**
* The operation returns a list of tenants which the current token provides access to.
*/
Set<Tenant> list();
Set<? extends Tenant> list();
/**
* Retrieve information about a tenant, by tenant ID

View File

@ -62,7 +62,7 @@ public interface TenantAsyncApi {
@Path("/tenants")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Tenant>> list();
ListenableFuture<? extends Set<? extends Tenant>> list();
/** @see TenantApi#get(String) */
@GET
@ -71,7 +71,7 @@ public interface TenantAsyncApi {
@Path("/tenants/{tenantId}")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Tenant> get(@PathParam("tenantId") String tenantId);
ListenableFuture<? extends Tenant> get(@PathParam("tenantId") String tenantId);
/** @see TenantApi#getByName(String) */
@GET
@ -80,6 +80,6 @@ public interface TenantAsyncApi {
@Path("/tenants")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Tenant> getByName(@QueryParam("name") String tenantName);
ListenableFuture<? extends Tenant> getByName(@QueryParam("name") String tenantName);
}

View File

@ -72,6 +72,6 @@ public interface TokenApi {
*
* @return the set of endpoints
*/
Set<Endpoint> listEndpointsForToken(String token);
Set<? extends Endpoint> listEndpointsForToken(String token);
}

View File

@ -64,7 +64,7 @@ public interface TokenAsyncApi {
@Path("/tokens/{token}")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Token> get(@PathParam("token") String token);
ListenableFuture<? extends Token> get(@PathParam("token") String token);
/** @see TokenApi#getUserOfToken(String) */
@GET
@ -73,7 +73,7 @@ public interface TokenAsyncApi {
@Path("/tokens/{token}")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<User> getUserOfToken(@PathParam("token") String token);
ListenableFuture<? extends User> getUserOfToken(@PathParam("token") String token);
/** @see TokenApi#isValid(String) */
@HEAD
@ -89,6 +89,6 @@ public interface TokenAsyncApi {
@Path("/tokens/{token}/endpoints")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Endpoint>> listEndpointsForToken(@PathParam("token") String token);
ListenableFuture<? extends Set<? extends Endpoint>> listEndpointsForToken(@PathParam("token") String token);
}

View File

@ -48,7 +48,7 @@ public interface UserApi {
*
* @return the list of users
*/
Set<User> list();
Set<? extends User> list();
/**
* Retrieve information about a user, by user ID
@ -73,13 +73,13 @@ public interface UserApi {
*
* @return the set of Roles granted to the user
*/
Set<Role> listRolesOfUser(String userId);
Set<? extends Role> listRolesOfUser(String userId);
/**
* List the roles a user has been granted on a specific tenant
*
* @return the set of roles
*/
Set<Role> listRolesOfUserOnTenant(String userId, String tenantId);
Set<? extends Role> listRolesOfUserOnTenant(String userId, String tenantId);
}

View File

@ -61,7 +61,7 @@ public interface UserAsyncApi {
@Path("/users")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<User>> list();
ListenableFuture<? extends Set<? extends User>> list();
/** @see UserApi#get(String) */
@GET
@ -70,7 +70,7 @@ public interface UserAsyncApi {
@Path("/users/{userId}")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<User> get(@PathParam("userId") String userId);
ListenableFuture<? extends User> get(@PathParam("userId") String userId);
/** @see UserApi#getByName(String) */
@GET
@ -79,7 +79,7 @@ public interface UserAsyncApi {
@Path("/users")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<User> getByName(@QueryParam("name") String userName);
ListenableFuture<? extends User> getByName(@QueryParam("name") String userName);
/** @see UserApi#listRolesOfUser(String) */
@GET
@ -88,7 +88,7 @@ public interface UserAsyncApi {
@Path("/users/{userId}/roles")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Role>> listRolesOfUser(@PathParam("userId") String userId);
ListenableFuture<? extends Set<? extends Role>> listRolesOfUser(@PathParam("userId") String userId);
/** @see UserApi#listRolesOfUserOnTenant(String, String) */
@GET
@ -97,5 +97,5 @@ public interface UserAsyncApi {
@Path("/tenants/{tenantId}/users/{userId}/roles")
@RequestFilters(AuthenticateRequest.class)
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Role>> listRolesOfUserOnTenant(@PathParam("userId") String userId, @PathParam("tenantId") String tenantId);
ListenableFuture<? extends Set<? extends Role>> listRolesOfUserOnTenant(@PathParam("userId") String userId, @PathParam("tenantId") String tenantId);
}

View File

@ -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()";
}
}

View File

@ -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;

View File

@ -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.
@ -42,7 +42,7 @@ public interface ExtensionApi {
*
* @return all extensions
*/
Set<Extension> listExtensions();
Set<? extends Extension> listExtensions();
/**
* Extensions may also be queried individually by their unique alias.

View File

@ -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;
@ -59,7 +59,7 @@ public interface ExtensionAsyncApi {
@Consumes(MediaType.APPLICATION_JSON)
@Path("/extensions")
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Extension>> listExtensions();
ListenableFuture<? extends Set<? extends Extension>> listExtensions();
/**
* @see ExtensionApi#getExtensionByAlias
@ -69,6 +69,6 @@ public interface ExtensionAsyncApi {
@Consumes(MediaType.APPLICATION_JSON)
@Path("/extensions/{alias}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Extension> getExtensionByAlias(@PathParam("alias") String id);
ListenableFuture<? extends Extension> getExtensionByAlias(@PathParam("alias") String id);
}

View File

@ -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;

View File

@ -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()";
}
}

View File

@ -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;

View File

@ -50,7 +50,7 @@ public class ServiceApiExpectTest extends BaseKeystoneRestApiExpectTest<Keystone
HttpResponse.builder().statusCode(200)
.payload(payloadFromResourceWithContentType("/tenant_list.json", APPLICATION_JSON)).build())
.getServiceApi();
Set<Tenant> tenants = api.listTenants();
Set<? extends Tenant> tenants = api.listTenants();
assertNotNull(tenants);
assertFalse(tenants.isEmpty());

View File

@ -37,7 +37,7 @@ public class ServiceApiLiveTest extends BaseKeystoneApiLiveTest {
public void testTenants() {
ServiceApi api = keystoneContext.getApi().getServiceApi();
Set<Tenant> result = api.listTenants();
Set<? extends Tenant> result = api.listTenants();
assertNotNull(result);
assertFalse(result.isEmpty());

View File

@ -56,7 +56,7 @@ public class TenantApiExpectTest extends BaseKeystoneRestApiExpectTest<KeystoneA
HttpResponse.builder().statusCode(200).payload(
payloadFromResourceWithContentType("/tenant_list.json", APPLICATION_JSON)).build())
.getTenantApi().get();
Set<Tenant> tenants = api.list();
Set<? extends Tenant> tenants = api.list();
assertNotNull(tenants);
assertFalse(tenants.isEmpty());
@ -74,7 +74,7 @@ public class TenantApiExpectTest extends BaseKeystoneRestApiExpectTest<KeystoneA
HttpResponse.builder().statusCode(200).payload(
payloadFromResourceWithContentType("/tenant_list_att.json", APPLICATION_JSON)).build())
.getTenantApi().get();
Set<Tenant> tenants = api.list();
Set<? extends Tenant> tenants = api.list();
assertNotNull(tenants);
assertFalse(tenants.isEmpty());

View File

@ -38,7 +38,7 @@ public class TenantApiLiveTest extends BaseKeystoneApiLiveTest {
public void testTenants() {
TenantApi api = keystoneContext.getApi().getTenantApi().get();
Set<Tenant> result = api.list();
Set<? extends Tenant> result = api.list();
assertNotNull(result);
assertFalse(result.isEmpty());

View File

@ -138,7 +138,7 @@ public class TokenApiExpectTest extends BaseKeystoneRestApiExpectTest<KeystoneAp
authenticatedGET().endpoint(endpoint + "/v2.0/tokens/XXXXXX/endpoints").build(),
HttpResponse.builder().statusCode(200).payload(payloadFromResourceWithContentType("/user_endpoints.json", APPLICATION_JSON)).build())
.getTokenApi().get();
Set<Endpoint> endpoints = api.listEndpointsForToken("XXXXXX");
Set<? extends Endpoint> endpoints = api.listEndpointsForToken("XXXXXX");
assertEquals(endpoints, ImmutableSet.of(
Endpoint.builder().publicURL(URI.create("https://csnode.jclouds.org/v2.0/"))

View File

@ -82,7 +82,7 @@ public class TokenApiLiveTest extends BaseKeystoneApiLiveTest {
public void testTokenEndpoints() {
TokenApi api = keystoneContext.getApi().getTokenApi().get();
Set<Endpoint> endpoints = api.listEndpointsForToken(token);
Set<? extends Endpoint> endpoints = api.listEndpointsForToken(token);
assertNotNull(endpoints);
assertFalse(endpoints.isEmpty());

View File

@ -56,7 +56,7 @@ public class UserApiExpectTest extends BaseKeystoneRestApiExpectTest<KeystoneApi
authenticatedGET().endpoint(endpoint + "/v2.0/users").build(),
HttpResponse.builder().statusCode(200).payload(payloadFromResourceWithContentType("/user_list.json", APPLICATION_JSON)).build())
.getUserApi().get();
Set<User> users = api.list();
Set<? extends User> users = api.list();
assertNotNull(users);
assertFalse(users.isEmpty());
@ -123,7 +123,7 @@ public class UserApiExpectTest extends BaseKeystoneRestApiExpectTest<KeystoneApi
authenticatedGET().endpoint(endpoint + "/v2.0/users/3f6c1c9ba993495ead7d2eb2192e284f/roles").build(),
HttpResponse.builder().statusCode(200).payload(payloadFromResourceWithContentType("/user_role_list.json", APPLICATION_JSON)).build())
.getUserApi().get();
Set<Role> roles = api.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f");
Set<? extends Role> roles = api.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f");
assertNotNull(roles);
assertFalse(roles.isEmpty());
assertEquals(roles, ImmutableSet.of(
@ -154,7 +154,7 @@ public class UserApiExpectTest extends BaseKeystoneRestApiExpectTest<KeystoneApi
authenticatedGET().endpoint(endpoint + "/v2.0/users/3f6c1c9ba993495ead7d2eb2192e284f/roles").build(),
HttpResponse.builder().statusCode(200).payload(payloadFromResourceWithContentType("/user_tenant_role_list.json", APPLICATION_JSON)).build())
.getUserApi().get();
Set<Role> roles = api.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f");
Set<? extends Role> roles = api.listRolesOfUser("3f6c1c9ba993495ead7d2eb2192e284f");
assertNotNull(roles);
assertFalse(roles.isEmpty());
assertEquals(roles, ImmutableSet.of(

View File

@ -41,7 +41,7 @@ public class UserApiLiveTest extends BaseKeystoneApiLiveTest {
public void testUsers() {
UserApi api = keystoneContext.getApi().getUserApi().get();
Set<User> users = api.list();
Set<? extends User> users = api.list();
assertNotNull(users);
assertFalse(users.isEmpty());
for (User user : users) {
@ -54,12 +54,12 @@ public class UserApiLiveTest extends BaseKeystoneApiLiveTest {
public void testUserRolesOnTenant() {
UserApi api = keystoneContext.getApi().getUserApi().get();
Set<User> users = api.list();
Set<Tenant> tenants = keystoneContext.getApi().getTenantApi().get().list();
Set<? extends User> users = api.list();
Set<? extends Tenant> tenants = keystoneContext.getApi().getTenantApi().get().list();
for (User user : users) {
for (Tenant tenant : tenants) {
Set<Role> roles = api.listRolesOfUserOnTenant(user.getId(), tenant.getId());
Set<? extends Role> roles = api.listRolesOfUserOnTenant(user.getId(), tenant.getId());
for (Role role : roles) {
assertNotNull(role.getId());
}
@ -72,7 +72,7 @@ public class UserApiLiveTest extends BaseKeystoneApiLiveTest {
UserApi api = keystoneContext.getApi().getUserApi().get();
for (User user : api.list()) {
Set<Role> roles = api.listRolesOfUser(user.getId());
Set<? extends Role> roles = api.listRolesOfUser(user.getId());
for (Role role : roles) {
assertNotNull(role.getId());
}

View File

@ -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"));
}
}

View File

@ -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) {
final LoadingCache<String, Set<Extension>> extensionsForZone = CacheBuilder.newBuilder().build(
CacheLoader.from(Functions.forMap(ImmutableMap.of("expectedzone", extensions, "differentzone",
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(zone, extensions, "differentzone",
ImmutableSet.<Extension> of()))));
PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensionsSet fn = Guice.createInjector(
@ -130,12 +129,11 @@ public class PresentWhenExtensionAnnotationNamespaceEqualsAnyNamespaceInExtensio
}
@Provides
LoadingCache<String, Set<Extension>> getExtensions() {
LoadingCache<String, Set<? extends Extension>> getExtensions() {
return extensionsForZone;
}
@Provides
@Named("openstack.nova.extensions")
Multimap<URI, URI> getAliases() {
return aliases;
}

View File

@ -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;
/**

View File

@ -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;
@ -100,98 +100,98 @@ public interface NovaApi {
* Provides synchronous access to Floating IP features.
*/
@Delegate
Optional<FloatingIPApi> getFloatingIPExtensionForZone(
Optional<? extends FloatingIPApi> getFloatingIPExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Security Group features.
*/
@Delegate
Optional<SecurityGroupApi> getSecurityGroupExtensionForZone(
Optional<? extends SecurityGroupApi> getSecurityGroupExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Key Pair features.
*/
@Delegate
Optional<KeyPairApi> getKeyPairExtensionForZone(
Optional<? extends KeyPairApi> getKeyPairExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Host Administration features.
*/
@Delegate
Optional<HostAdministrationApi> getHostAdministrationExtensionForZone(
Optional<? extends HostAdministrationApi> getHostAdministrationExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Simple Tenant Usage features.
*/
@Delegate
Optional<SimpleTenantUsageApi> getSimpleTenantUsageExtensionForZone(
Optional<? extends SimpleTenantUsageApi> getSimpleTenantUsageExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Volume features.
*/
@Delegate
Optional<VolumeApi> getVolumeExtensionForZone(
Optional<? extends VolumeApi> getVolumeExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Virtual Interface features.
*/
@Delegate
Optional<VirtualInterfaceApi> getVirtualInterfaceExtensionForZone(
Optional<? extends VirtualInterfaceApi> getVirtualInterfaceExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Server Extra Data features.
*/
@Delegate
Optional<ServerWithSecurityGroupsApi> getServerWithSecurityGroupsExtensionForZone(
Optional<? extends ServerWithSecurityGroupsApi> getServerWithSecurityGroupsExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Server Admin Actions features.
*/
@Delegate
Optional<AdminActionsApi> getAdminActionsExtensionForZone(
Optional<? extends AdminActionsApi> getAdminActionsExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Aggregate features.
*/
@Delegate
Optional<HostAggregateApi> getHostAggregateExtensionForZone(
Optional<? extends HostAggregateApi> getHostAggregateExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Flavor extra specs features.
*/
@Delegate
Optional<FlavorExtraSpecsApi> getFlavorExtraSpecsExtensionForZone(
Optional<? extends FlavorExtraSpecsApi> getFlavorExtraSpecsExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Quota features.
*/
@Delegate
Optional<QuotaApi> getQuotaExtensionForZone(
Optional<? extends QuotaApi> getQuotaExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Quota Classes features.
*/
@Delegate
Optional<QuotaClassApi> getQuotaClassExtensionForZone(
Optional<? extends QuotaClassApi> getQuotaClassExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides synchronous access to Volume Type features.
*/
@Delegate
Optional<VolumeTypeApi> getVolumeTypeExtensionForZone(
Optional<? extends VolumeTypeApi> getVolumeTypeExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
}

View File

@ -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;
@ -98,49 +98,49 @@ public interface NovaAsyncApi {
* Provides asynchronous access to Floating IP features.
*/
@Delegate
Optional<FloatingIPAsyncApi> getFloatingIPExtensionForZone(
Optional<? extends FloatingIPAsyncApi> getFloatingIPExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Security Group features.
*/
@Delegate
Optional<SecurityGroupAsyncApi> getSecurityGroupExtensionForZone(
Optional<? extends SecurityGroupAsyncApi> getSecurityGroupExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Key Pair features.
*/
@Delegate
Optional<KeyPairAsyncApi> getKeyPairExtensionForZone(
Optional<? extends KeyPairAsyncApi> getKeyPairExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Host Administration features.
*/
@Delegate
Optional<HostAdministrationAsyncApi> getHostAdministrationExtensionForZone(
Optional<? extends HostAdministrationAsyncApi> getHostAdministrationExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Simple Tenant Usage features.
*/
@Delegate
Optional<SimpleTenantUsageAsyncApi> getSimpleTenantUsageExtensionForZone(
Optional<? extends SimpleTenantUsageAsyncApi> getSimpleTenantUsageExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Volume features.
*/
@Delegate
Optional<VolumeAsyncApi> getVolumeExtensionForZone(
Optional<? extends VolumeAsyncApi> getVolumeExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Virtual Interface features.
*/
@Delegate
Optional<VirtualInterfaceAsyncApi> getVirtualInterfaceExtensionForZone(
Optional<? extends VirtualInterfaceAsyncApi> getVirtualInterfaceExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
@ -148,49 +148,49 @@ public interface NovaAsyncApi {
* Provides asynchronous access to Server Extra Data features.
*/
@Delegate
Optional<ServerWithSecurityGroupsAsyncApi> getServerWithSecurityGroupsExtensionForZone(
Optional<? extends ServerWithSecurityGroupsAsyncApi> getServerWithSecurityGroupsExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Server Admin Actions features.
*/
@Delegate
Optional<AdminActionsAsyncApi> getAdminActionsExtensionForZone(
Optional<? extends AdminActionsAsyncApi> getAdminActionsExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to HostAggregate features.
*/
@Delegate
Optional<HostAggregateAsyncApi> getHostAggregateExtensionForZone(
Optional<? extends HostAggregateAsyncApi> getHostAggregateExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Flavor extra specs features.
*/
@Delegate
Optional<FlavorExtraSpecsAsyncApi> getFlavorExtraSpecsExtensionForZone(
Optional<? extends FlavorExtraSpecsAsyncApi> getFlavorExtraSpecsExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Quota features.
*/
@Delegate
Optional<QuotaAsyncApi> getQuotaExtensionForZone(
Optional<? extends QuotaAsyncApi> getQuotaExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Quota Classes features.
*/
@Delegate
Optional<QuotaClassAsyncApi> getQuotaClassExtensionForZone(
Optional<? extends QuotaClassAsyncApi> getQuotaClassExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
/**
* Provides asynchronous access to Volume Type features.
*/
@Delegate
Optional<VolumeTypeAsyncApi> getVolumeTypeExtensionForZone(
Optional<? extends VolumeTypeAsyncApi> getVolumeTypeExtensionForZone(
@EndpointParam(parser = ZoneToEndpoint.class) @Nullable String zone);
}

View File

@ -135,7 +135,7 @@ public class NovaComputeService extends BaseComputeService {
}
private void cleanupOrphanedSecurityGroupsInZone(Set<String> groups, String zoneId) {
Optional<SecurityGroupApi> securityGroupApi = novaApi.getSecurityGroupExtensionForZone(zoneId);
Optional<? extends SecurityGroupApi> securityGroupApi = novaApi.getSecurityGroupExtensionForZone(zoneId);
if (securityGroupApi.isPresent()) {
for (String group : groups) {
for (SecurityGroup securityGroup : Iterables.filter(securityGroupApi.get().listSecurityGroups(),
@ -152,7 +152,7 @@ public class NovaComputeService extends BaseComputeService {
}
private void cleanupOrphanedKeyPairsInZone(Set<String> groups, String zoneId) {
Optional<KeyPairApi> keyPairApi = novaApi.getKeyPairExtensionForZone(zoneId);
Optional<? extends KeyPairApi> keyPairApi = novaApi.getKeyPairExtensionForZone(zoneId);
if (keyPairApi.isPresent()) {
for (String group : groups) {
for (Map<String, KeyPair> view : keyPairApi.get().listKeyPairs()) {

View File

@ -159,12 +159,12 @@ public class NovaComputeServiceAdapter implements
Set<String> zones = zoneIds.get();
checkState(zones.size() > 0, "no zones found in supplier %s", zoneIds);
for (final String zoneId : zones) {
Set<Image> images = novaApi.getImageApiForZone(zoneId).listImagesInDetail();
Set<? extends Image> images = novaApi.getImageApiForZone(zoneId).listImagesInDetail();
if (images.size() == 0) {
logger.debug("no images found in zone %s", zoneId);
continue;
}
Iterable<Image> active = filter(images, ImagePredicates.statusEquals(Image.Status.ACTIVE));
Iterable<? extends Image> active = filter(images, ImagePredicates.statusEquals(Image.Status.ACTIVE));
if (images.size() == 0) {
logger.debug("no images with status active in zone %s; non-active: %s", zoneId,
transform(active, new Function<Image, String>() {

View File

@ -62,7 +62,7 @@ public class CreateSecurityGroupIfNeeded implements Function<ZoneSecurityGroupNa
checkNotNull(zoneSecurityGroupNameAndPorts, "zoneSecurityGroupNameAndPorts");
String zoneId = zoneSecurityGroupNameAndPorts.getZone();
Optional<SecurityGroupApi> api = novaApi.getSecurityGroupExtensionForZone(zoneId);
Optional<? extends SecurityGroupApi> api = novaApi.getSecurityGroupExtensionForZone(zoneId);
checkArgument(api.isPresent(), "Security groups are required, but the extension is not availablein zone %s!", zoneId);
logger.debug(">> creating securityGroup %s", zoneSecurityGroupNameAndPorts);
try {

View File

@ -31,7 +31,6 @@ import java.util.NoSuchElementException;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Named;
@ -96,7 +95,7 @@ public class ImageToOperatingSystem implements Function<Image, OperatingSystem>
try {
osFamily = find(Arrays.asList(OsFamily.values()), new Predicate<OsFamily>() {
@Override
public boolean apply(@Nullable OsFamily osFamily) {
public boolean apply(OsFamily osFamily) {
return any(imageNameParts, equalTo(osFamily.name().toLowerCase()));
}
});

View File

@ -59,7 +59,7 @@ public class CreateUniqueKeyPair extends CacheLoader<ZoneAndName, KeyPair> {
String zoneId = checkNotNull(zoneAndName, "zoneAndName").getZone();
String prefix = zoneAndName.getName();
Optional<KeyPairApi> api = novaApi.getKeyPairExtensionForZone(zoneId);
Optional<? extends KeyPairApi> api = novaApi.getKeyPairExtensionForZone(zoneId);
checkArgument(api.isPresent(), "Key pairs are required, but the extension is not available in zone %s!",
zoneId);

View File

@ -51,7 +51,7 @@ public class LoadFloatingIpsForInstance extends CacheLoader<ZoneAndId, Iterable<
@Override
public Iterable<FloatingIP> load(final ZoneAndId key) throws Exception {
String zone = key.getZone();
Optional<FloatingIPApi> ipApiOptional = api.getFloatingIPExtensionForZone(zone);
Optional<? extends FloatingIPApi> ipApiOptional = api.getFloatingIPExtensionForZone(zone);
if (ipApiOptional.isPresent()) {
return Iterables.filter(ipApiOptional.get().listFloatingIPs(),
new Predicate<FloatingIP>() {

View File

@ -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,9 @@ 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;
/**
@ -86,11 +91,13 @@ import com.google.inject.Provides;
* @author Adrian Cole
*/
@ConfiguresRestClient
public class NovaRestClientModule extends RestClientModule<NovaApi, NovaAsyncApi> {
public class NovaRestClientModule<S extends NovaApi, A extends NovaAsyncApi> extends RestClientModule<S, A> {
public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()
.put(ServerApi.class, ServerAsyncApi.class).put(FlavorApi.class, FlavorAsyncApi.class)
.put(ImageApi.class, ImageAsyncApi.class).put(ExtensionApi.class, ExtensionAsyncApi.class)
.put(ServerApi.class, ServerAsyncApi.class)
.put(FlavorApi.class, FlavorAsyncApi.class)
.put(ImageApi.class, ImageAsyncApi.class)
.put(ExtensionApi.class, ExtensionAsyncApi.class)
.put(FloatingIPApi.class, FloatingIPAsyncApi.class)
.put(SecurityGroupApi.class, SecurityGroupAsyncApi.class)
.put(KeyPairApi.class, KeyPairAsyncApi.class)
@ -106,30 +113,67 @@ public class NovaRestClientModule extends RestClientModule<NovaApi, NovaAsyncApi
.put(QuotaClassApi.class, QuotaClassAsyncApi.class)
.put(VolumeTypeApi.class, VolumeTypeAsyncApi.class)
.build();
public NovaRestClientModule() {
super(DELEGATE_MAP);
super(TypeToken.class.cast(TypeToken.of(NovaApi.class)), TypeToken.class.cast(TypeToken.of(NovaAsyncApi.class)), DELEGATE_MAP);
}
protected NovaRestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType,
Map<Class<?>, Class<?>> sync2Async) {
super(syncClientType, asyncClientType, sync2Async);
}
@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<Extension>> provideExtensionsByZone(final Provider<NovaApi> novaApi) {
public LoadingCache<String, Set<? extends Extension>> provideExtensionsByZone(final Provider<NovaApi> novaApi) {
return CacheBuilder.newBuilder().expireAfterWrite(23, TimeUnit.HOURS)
.build(new CacheLoader<String, Set<Extension>>() {
.build(new CacheLoader<String, Set<? extends Extension>>() {
@Override
public Set<Extension> load(String key) throws Exception {
public Set<? extends Extension> load(String key) throws Exception {
return novaApi.get().getExtensionApiForZone(key).listExtensions();
}
});
}

View File

@ -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;

View File

@ -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;

View File

@ -43,14 +43,14 @@ public interface FlavorApi {
*
* @return all flavors (IDs, names, links)
*/
Set<Resource> listFlavors();
Set<? extends Resource> listFlavors();
/**
* List all flavors (all details)
*
* @return all flavors (all details)
*/
Set<Flavor> listFlavorsInDetail();
Set<? extends Flavor> listFlavorsInDetail();
/**
* List details of the specified flavor

View File

@ -61,7 +61,7 @@ public interface FlavorAsyncApi {
@Consumes(MediaType.APPLICATION_JSON)
@Path("/flavors")
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Resource>> listFlavors();
ListenableFuture<? extends Set<? extends Resource>> listFlavors();
/**
* @see FlavorApi#listFlavorsInDetail
@ -71,7 +71,7 @@ public interface FlavorAsyncApi {
@Consumes(MediaType.APPLICATION_JSON)
@Path("/flavors/detail")
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Flavor>> listFlavorsInDetail();
ListenableFuture<? extends Set<? extends Flavor>> listFlavorsInDetail();
/**
* @see FlavorApi#getFlavor
@ -81,6 +81,6 @@ public interface FlavorAsyncApi {
@Consumes(MediaType.APPLICATION_JSON)
@Path("/flavors/{id}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Flavor> getFlavor(@PathParam("id") String id);
ListenableFuture<? extends Flavor> getFlavor(@PathParam("id") String id);
}

View File

@ -43,14 +43,14 @@ public interface ImageApi {
*
* @return all images (IDs, names, links)
*/
Set<Resource> listImages();
Set<? extends Resource> listImages();
/**
* List all images (all details)
*
* @return all images (all details)
*/
Set<Image> listImagesInDetail();
Set<? extends Image> listImagesInDetail();
/**
* List details of the specified image

View File

@ -59,7 +59,7 @@ public interface ImageAsyncApi {
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images")
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Resource>> listImages();
ListenableFuture<? extends Set<? extends Resource>> listImages();
/**
* @see ImageApi#listImagesInDetail
@ -69,7 +69,7 @@ public interface ImageAsyncApi {
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images/detail")
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Image>> listImagesInDetail();
ListenableFuture<? extends Set<? extends Image>> listImagesInDetail();
/**
* @see ImageApi#getImage
@ -79,7 +79,7 @@ public interface ImageAsyncApi {
@Consumes(MediaType.APPLICATION_JSON)
@Path("/images/{id}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Image> getImage(@PathParam("id") String id);
ListenableFuture<? extends Image> getImage(@PathParam("id") String id);
/**
* @see ImageApi#deleteImage

View File

@ -47,14 +47,14 @@ public interface ServerApi {
*
* @return all servers (IDs, names, links)
*/
Set<Resource> listServers();
Set<? extends Resource> listServers();
/**
* List all servers (all details)
*
* @return all servers (all details)
*/
Set<Server> listServersInDetail();
Set<? extends Server> listServersInDetail();
/**
* List details of the specified server

View File

@ -76,7 +76,7 @@ public interface ServerAsyncApi {
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers")
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Resource>> listServers();
ListenableFuture<? extends Set<? extends Resource>> listServers();
/**
* @see ServerApi#listServersInDetail
@ -86,7 +86,7 @@ public interface ServerAsyncApi {
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers/detail")
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
ListenableFuture<Set<Server>> listServersInDetail();
ListenableFuture<? extends Set<? extends Server>> listServersInDetail();
/**
* @see ServerApi#getServer
@ -96,7 +96,7 @@ public interface ServerAsyncApi {
@Consumes(MediaType.APPLICATION_JSON)
@Path("/servers/{id}")
@ExceptionParser(ReturnNullOnNotFoundOr404.class)
ListenableFuture<Server> getServer(@PathParam("id") String id);
ListenableFuture<? extends Server> getServer(@PathParam("id") String id);
/**
* @see ServerApi#deleteServer
@ -144,7 +144,7 @@ public interface ServerAsyncApi {
@Path("/servers/{id}/action")
@Consumes
@Produces(MediaType.APPLICATION_JSON)
@Payload("%7B\"resize\":%7B\"flavorId\":{flavorId}%7D%7D")
@Payload("%7B\"resize\":%7B\"flavorRef\":{flavorId}%7D%7D")
ListenableFuture<Void> resizeServer(@PathParam("id") String id, @PayloadParam("flavorId") String flavorId);
/**

View File

@ -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<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<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()";
}
}

View File

@ -46,12 +46,12 @@ public class CreateVolumeOptions implements MapBinder {
@Inject
private BindToJsonPayload jsonBinder;
private String name;
private String description;
private String volumeType;
private String availabilityZone;
private String snapshotId;
private Map<String, String> metadata = ImmutableMap.of();
protected String name;
protected String description;
protected String volumeType;
protected String availabilityZone;
protected String snapshotId;
protected Map<String, String> metadata = ImmutableMap.of();
@Override
public <R extends HttpRequest> R bindToRequest(R request, Map<String, Object> postParams) {
@ -61,6 +61,12 @@ public class CreateVolumeOptions implements MapBinder {
image.put("display_name", name);
if (description != null)
image.put("display_description", description);
if (volumeType != null)
image.put("volume_type", volumeType);
if (availabilityZone != null)
image.put("availability_zone", availabilityZone);
if (snapshotId != null)
image.put("snapshot_id", snapshotId);
if (!metadata.isEmpty())
image.put("metadata", metadata);
return jsonBinder.bindToRequest(request, ImmutableMap.of("volume", image));

View File

@ -62,7 +62,7 @@ public class FindSecurityGroupWithNameAndReturnTrue implements Predicate<AtomicR
checkNotNull(securityGroupInZoneRef, "securityGroupRef");
final ZoneAndName securityGroupInZone = checkNotNull(securityGroupInZoneRef.get(), "securityGroupInZone");
Optional<SecurityGroupApi> api = novaApi.getSecurityGroupExtensionForZone(securityGroupInZone.getZone());
Optional<? extends SecurityGroupApi> api = novaApi.getSecurityGroupExtensionForZone(securityGroupInZone.getZone());
checkArgument(api.isPresent(), "Security groups are required, but the extension is not available!");
logger.trace("looking for security group %s", securityGroupInZone.slashEncode());

View File

@ -26,8 +26,6 @@ import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import javax.annotation.Nullable;
import org.jclouds.compute.domain.OperatingSystem;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.openstack.nova.v2_0.domain.Image;
@ -69,7 +67,7 @@ public class ImageToOperatingSystemTest {
return Iterables.toArray(
Iterables.transform(Arrays.asList(OsFamily.values()), new Function<OsFamily, Object[]>() {
@Override
public Object[] apply(@Nullable OsFamily osFamily) {
public Object[] apply(OsFamily osFamily) {
return new Object[] { osFamily };
}
}), Object[].class);

View File

@ -52,7 +52,9 @@ public class CreateUniqueKeyPairTest {
KeyPair pair = createMock(KeyPair.class);
expect(api.getKeyPairExtensionForZone("zone")).andReturn(Optional.of(keyApi)).atLeastOnce();
Optional optKeyApi = Optional.of(keyApi);
expect(api.getKeyPairExtensionForZone("zone")).andReturn(optKeyApi).atLeastOnce();
expect(keyApi.createKeyPair("group-1")).andReturn(pair);
@ -83,7 +85,7 @@ public class CreateUniqueKeyPairTest {
KeyPair pair = createMock(KeyPair.class);
expect(api.getKeyPairExtensionForZone("zone")).andReturn(Optional.of(keyApi)).atLeastOnce();
expect(api.getKeyPairExtensionForZone("zone")).andReturn((Optional) Optional.of(keyApi)).atLeastOnce();
expect(uniqueIdSupplier.get()).andReturn("1");
expect(keyApi.createKeyPair("group-1")).andThrow(new IllegalStateException());

View File

@ -46,7 +46,7 @@ public class LoadFloatingIpsForInstanceTest {
FloatingIPApi ipApi = createMock(FloatingIPApi.class);
FloatingIP testIp = FloatingIP.builder().id("1").ip("1.1.1.1").fixedIp("10.1.1.1").instanceId("i-blah").build();
expect(api.getFloatingIPExtensionForZone("Zone")).andReturn(Optional.of(ipApi)).atLeastOnce();
expect(api.getFloatingIPExtensionForZone("Zone")).andReturn((Optional) Optional.of(ipApi)).atLeastOnce();
expect(ipApi.listFloatingIPs()).andReturn(ImmutableSet.<FloatingIP>of(testIp)).atLeastOnce();
replay(api);
@ -65,7 +65,7 @@ public class LoadFloatingIpsForInstanceTest {
NovaApi api = createMock(NovaApi.class);
FloatingIPApi ipApi = createMock(FloatingIPApi.class);
expect(api.getFloatingIPExtensionForZone("Zone")).andReturn(Optional.of(ipApi)).atLeastOnce();
expect(api.getFloatingIPExtensionForZone("Zone")).andReturn((Optional) Optional.of(ipApi)).atLeastOnce();
expect(ipApi.listFloatingIPs()).andReturn(ImmutableSet.<FloatingIP>of()).atLeastOnce();
@ -86,7 +86,7 @@ public class LoadFloatingIpsForInstanceTest {
NovaApi api = createMock(NovaApi.class);
FloatingIPApi ipApi = createMock(FloatingIPApi.class);
expect(api.getFloatingIPExtensionForZone("Zone")).andReturn(Optional.of(ipApi)).atLeastOnce();
expect(api.getFloatingIPExtensionForZone("Zone")).andReturn((Optional) Optional.of(ipApi)).atLeastOnce();
expect(ipApi.listFloatingIPs()).andReturn(
ImmutableSet.<FloatingIP>of(FloatingIP.builder().id("1").ip("1.1.1.1").build()))

View File

@ -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;
@ -53,7 +53,7 @@ public class AdminActionsApiLiveTest extends BaseNovaApiLiveTest {
private ImageApi imageApi;
private ServerApi serverApi;
private ExtensionApi extensionApi;
private Optional<AdminActionsApi> apiOption;
private Optional<? extends AdminActionsApi> apiOption;
private String zone;
private String testServerId;

View File

@ -44,7 +44,7 @@ import com.google.common.collect.Maps;
@Test(groups = "live", testName = "FlavorExtraSpecsApiLiveTest", singleThreaded = true)
public class FlavorExtraSpecsApiLiveTest extends BaseNovaApiLiveTest {
private FlavorApi flavorApi;
private Optional<FlavorExtraSpecsApi> apiOption;
private Optional<? extends FlavorExtraSpecsApi> apiOption;
private String zone;
private Resource testFlavor;

View File

@ -48,7 +48,7 @@ public class FloatingIPApiLiveTest extends BaseNovaApiLiveTest {
@Test
public void testListFloatingIPs() throws Exception {
for (String zoneId : novaContext.getApi().getConfiguredZones()) {
Optional<FloatingIPApi> apiOption = novaContext.getApi().getFloatingIPExtensionForZone(zoneId);
Optional<? extends FloatingIPApi> apiOption = novaContext.getApi().getFloatingIPExtensionForZone(zoneId);
if (!apiOption.isPresent())
continue;
FloatingIPApi api = apiOption.get();
@ -70,7 +70,7 @@ public class FloatingIPApiLiveTest extends BaseNovaApiLiveTest {
@Test
public void testAllocateAndDeallocateFloatingIPs() throws Exception {
for (String zoneId : novaContext.getApi().getConfiguredZones()) {
Optional<FloatingIPApi> apiOption = novaContext.getApi().getFloatingIPExtensionForZone(zoneId);
Optional<? extends FloatingIPApi> apiOption = novaContext.getApi().getFloatingIPExtensionForZone(zoneId);
if (!apiOption.isPresent())
continue;
FloatingIPApi api = apiOption.get();
@ -101,7 +101,7 @@ public class FloatingIPApiLiveTest extends BaseNovaApiLiveTest {
@Test
public void testAddAndRemoveFloatingIp() throws Exception {
for (String zoneId : novaContext.getApi().getConfiguredZones()) {
Optional<FloatingIPApi> apiOption = novaContext.getApi().getFloatingIPExtensionForZone(zoneId);
Optional<? extends FloatingIPApi> apiOption = novaContext.getApi().getFloatingIPExtensionForZone(zoneId);
if (!apiOption.isPresent())
continue;
FloatingIPApi api = apiOption.get();

View File

@ -42,7 +42,7 @@ import com.google.common.collect.Iterables;
*/
@Test(groups = "live", testName = "HostAdministrationApiLiveTest", singleThreaded = true)
public class HostAdministrationApiLiveTest extends BaseNovaApiLiveTest {
private Optional<HostAdministrationApi> optApi = Optional.absent();
private Optional<? extends HostAdministrationApi> optApi = Optional.absent();
Predicate<Host> isComputeHost = new Predicate<Host>() {
@Override

View File

@ -44,8 +44,8 @@ import com.google.common.collect.Iterables;
*/
@Test(groups = "live", testName = "AggregateApiLiveTest", singleThreaded = true)
public class HostAggregateApiLiveTest extends BaseNovaApiLiveTest {
private Optional<HostAggregateApi> apiOption;
private Optional<HostAdministrationApi> hostAdminOption;
private Optional<? extends HostAggregateApi> apiOption;
private Optional<? extends HostAdministrationApi> hostAdminOption;
private HostAggregate testAggregate;

View File

@ -36,7 +36,7 @@ import com.google.common.collect.Iterables;
*/
@Test(groups = "live", testName = "QuotaApiLiveTest", singleThreaded = true)
public class QuotaApiLiveTest extends BaseNovaApiLiveTest {
private Optional<QuotaApi> apiOption;
private Optional<? extends QuotaApi> apiOption;
private String tenant;
@BeforeClass(groups = {"integration", "live"})

View File

@ -36,7 +36,7 @@ import com.google.common.collect.Iterables;
*/
@Test(groups = "live", testName = "QuotaClassApiLiveTest", singleThreaded = true)
public class QuotaClassApiLiveTest extends BaseNovaApiLiveTest {
private Optional<QuotaClassApi> apiOption;
private Optional<? extends QuotaClassApi> apiOption;
private String zone;
@BeforeClass(groups = {"integration", "live"})

View File

@ -41,7 +41,7 @@ import com.google.common.collect.Iterables;
@Test(groups = "live", testName = "ServerWithSecurityGroupsApiLiveTest", singleThreaded = true)
public class ServerWithSecurityGroupsApiLiveTest extends BaseNovaApiLiveTest {
private ServerApi serverApi;
private Optional<ServerWithSecurityGroupsApi> apiOption;
private Optional<? extends ServerWithSecurityGroupsApi> apiOption;
private String zone;
@BeforeGroups(groups = {"integration", "live"})

View File

@ -38,7 +38,7 @@ public class SimpleTenantUsageApiLiveTest extends BaseNovaApiLiveTest {
public void testList() throws Exception {
for (String zoneId : novaContext.getApi().getConfiguredZones()) {
Optional<SimpleTenantUsageApi> optApi = novaContext.getApi().getSimpleTenantUsageExtensionForZone(zoneId);
Optional<? extends SimpleTenantUsageApi> optApi = novaContext.getApi().getSimpleTenantUsageExtensionForZone(zoneId);
if (optApi.isPresent() && identity.endsWith(":admin")) {
SimpleTenantUsageApi api = optApi.get();
Set<SimpleTenantUsage> usages = api.listTenantUsages();

View File

@ -38,7 +38,7 @@ import com.google.common.collect.Iterables;
*/
@Test(groups = "live", testName = "VirtualInterfaceApiLiveTest", singleThreaded = true)
public class VirtualInterfaceApiLiveTest extends BaseNovaApiLiveTest {
private Optional<VirtualInterfaceApi> apiOption;
private Optional<? extends VirtualInterfaceApi> apiOption;
private String zone;

View File

@ -48,7 +48,7 @@ import com.google.common.collect.Iterables;
@Test(groups = "live", testName = "VolumeApiLiveTest", singleThreaded = true)
public class VolumeApiLiveTest extends BaseNovaApiLiveTest {
private Optional<VolumeApi> volumeOption;
private Optional<? extends VolumeApi> volumeOption;
private String zone;
private Volume testVolume;

View File

@ -46,7 +46,7 @@ import com.google.common.collect.Iterables;
@Test(groups = "live", testName = "VolumeTypeApiLiveTest", singleThreaded = true)
public class VolumeTypeApiLiveTest extends BaseNovaApiLiveTest {
private Optional<VolumeTypeApi> volumeTypeOption;
private Optional<? extends VolumeTypeApi> volumeTypeOption;
private String zone;
private VolumeType testVolumeType;

View File

@ -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;
/**
@ -44,7 +45,7 @@ public class ExtensionApiLiveTest extends BaseNovaApiLiveTest {
public void testListExtensions() throws Exception {
for (String zoneId : novaContext.getApi().getConfiguredZones()) {
ExtensionApi api = novaContext.getApi().getExtensionApiForZone(zoneId);
Set<Extension> response = api.listExtensions();
Set<? extends Extension> response = api.listExtensions();
assert null != response;
assertTrue(response.size() >= 0);
for (Extension extension : response) {

View File

@ -45,7 +45,7 @@ public class FlavorApiLiveTest extends BaseNovaApiLiveTest {
public void testListFlavors() throws Exception {
for (String zoneId : novaContext.getApi().getConfiguredZones()) {
FlavorApi api = novaContext.getApi().getFlavorApiForZone(zoneId);
Set<Resource> response = api.listFlavors();
Set<? extends Resource> response = api.listFlavors();
assert null != response;
assertTrue(response.size() >= 0);
for (Resource flavor : response) {
@ -66,7 +66,7 @@ public class FlavorApiLiveTest extends BaseNovaApiLiveTest {
public void testListFlavorsInDetail() throws Exception {
for (String zoneId : novaContext.getApi().getConfiguredZones()) {
FlavorApi api = novaContext.getApi().getFlavorApiForZone(zoneId);
Set<Flavor> response = api.listFlavorsInDetail();
Set<? extends Flavor> response = api.listFlavorsInDetail();
assert null != response;
assertTrue(response.size() >= 0);
for (Flavor flavor : response) {

View File

@ -41,7 +41,7 @@ public class ImageApiLiveTest extends BaseNovaApiLiveTest {
public void testListImages() throws Exception {
for (String zoneId : novaContext.getApi().getConfiguredZones()) {
ImageApi api = novaContext.getApi().getImageApiForZone(zoneId);
Set<Resource> response = api.listImages();
Set<? extends Resource> response = api.listImages();
assertNotNull(response);
assertTrue(response.size() >= 0);
for (Resource image : response) {
@ -58,7 +58,7 @@ public class ImageApiLiveTest extends BaseNovaApiLiveTest {
public void testListImagesInDetail() throws Exception {
for (String zoneId : novaContext.getApi().getConfiguredZones()) {
ImageApi api = novaContext.getApi().getImageApiForZone(zoneId);
Set<Image> response = api.listImagesInDetail();
Set<? extends Image> response = api.listImagesInDetail();
assertNotNull(response);
assertTrue(response.size() >= 0);
for (Image image : response) {

View File

@ -40,7 +40,7 @@ public class ServerApiLiveTest extends BaseNovaApiLiveTest {
public void testListServersInDetail() throws Exception {
for (String zoneId : novaContext.getApi().getConfiguredZones()) {
ServerApi api = novaContext.getApi().getServerApiForZone(zoneId);
Set<Resource> response = api.listServers();
Set<? extends Resource> response = api.listServers();
assert null != response;
assertTrue(response.size() >= 0);
for (Resource server : response) {

View File

@ -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;

View File

@ -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;

View File

@ -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;

View File

@ -36,7 +36,6 @@ import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;
import javax.annotation.Nullable;
import javax.ws.rs.core.MediaType;
import org.jclouds.apis.BaseViewLiveTest;
@ -48,6 +47,7 @@ import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.blobstore.domain.StorageType;
import org.jclouds.domain.Location;
import org.jclouds.http.config.JavaUrlHttpCommandExecutorServiceModule;
import org.jclouds.javax.annotation.Nullable;
import org.testng.ITestContext;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;

View File

@ -27,12 +27,11 @@ import java.util.Collections;
import java.util.List;
import java.util.logging.Logger;
import javax.annotation.Nullable;
import org.jclouds.blobstore.BlobStore;
import org.jclouds.blobstore.domain.BlobMetadata;
import org.jclouds.blobstore.domain.StorageMetadata;
import org.jclouds.domain.Location;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.util.Strings2;
import org.testng.SkipException;
import org.testng.annotations.Test;

View File

@ -205,6 +205,22 @@ public abstract class BaseTemplateBuilderLiveTest extends BaseComputeServiceCont
|| location.getParent().getIso3166Codes().containsAll(location.getIso3166Codes()) : location + " ||"
+ location.getParent();
break;
case SYSTEM:
Location systemParent = location.getParent();
// loop up to root, which must be the provider
while (systemParent.getParent() != null) {
systemParent = systemParent.getParent();
}
assertProvider(systemParent);
break;
case NETWORK:
Location networkParent = location.getParent();
// loop up to root, which must be the provider
while (networkParent.getParent() != null) {
networkParent = networkParent.getParent();
}
assertProvider(networkParent);
break;
case HOST:
Location provider2 = location.getParent().getParent().getParent();
// zone can be a direct descendant of provider

View File

@ -106,7 +106,7 @@
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>12.0</version>
<version>13.0</version>
</dependency>
<dependency>
<groupId>org.osgi</groupId>

View File

@ -86,6 +86,40 @@ public class LocationPredicates {
}
}
public static Predicate<Location> isSystem() {
return IsSystem.INSTANCE;
}
static enum IsSystem implements Predicate<Location> {
INSTANCE;
@Override
public boolean apply(Location input) {
return input.getScope() == LocationScope.SYSTEM;
}
@Override
public String toString() {
return "isSystem()";
}
}
public static Predicate<Location> isNetwork() {
return IsNetwork.INSTANCE;
}
static enum IsNetwork implements Predicate<Location> {
INSTANCE;
@Override
public boolean apply(Location input) {
return input.getScope() == LocationScope.NETWORK;
}
@Override
public String toString() {
return "isNetwork()";
}
}
public static Predicate<Location> idEquals(String id) {
return new IdEquals(id);
}

View File

@ -0,0 +1,67 @@
/**
* 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.location.suppliers.implicit;
import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.find;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.location.predicates.LocationPredicates.isNetwork;
import java.util.NoSuchElementException;
import java.util.Set;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.collect.Memoized;
import org.jclouds.domain.Location;
import org.jclouds.location.functions.ToIdAndScope;
import org.jclouds.location.suppliers.ImplicitLocationSupplier;
import com.google.common.base.Supplier;
/**
*
* @author Dies Koper
*
*/
@Singleton
public class FirstNetwork implements ImplicitLocationSupplier {
private final Supplier<Set<? extends Location>> locationsSupplier;
@Inject
FirstNetwork(@Memoized Supplier<Set<? extends Location>> locationsSupplier) {
this.locationsSupplier = checkNotNull(locationsSupplier,
"locationsSupplierSupplier");
}
@Override
public Location get() {
Set<? extends Location> locations = locationsSupplier.get();
try {
return find(locations, isNetwork());
} catch (NoSuchElementException e) {
throw new NoSuchElementException(
"none of the locations are scope NETWORK: "
+ transform(locations, ToIdAndScope.INSTANCE));
}
}
}

View File

@ -20,6 +20,8 @@ package org.jclouds.util;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.lang.reflect.WildcardType;
import com.google.common.base.Optional;
@ -35,7 +37,11 @@ public class Optionals2 {
if (optional) {
ParameterizedType futureType = ParameterizedType.class.cast(method.getGenericReturnType());
// TODO: error checking in case this is a type, not a class.
syncClass = Class.class.cast(futureType.getActualTypeArguments()[0]);
Type t = futureType.getActualTypeArguments()[0];
if (t instanceof WildcardType) {
t = ((WildcardType) t).getUpperBounds()[0];
}
syncClass = Class.class.cast(t);
} else {
syncClass = method.getReturnType();
}

View File

@ -0,0 +1,71 @@
/**
* 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.location.suppliers.implicit;
import static org.testng.Assert.assertEquals;
import java.util.NoSuchElementException;
import java.util.Set;
import org.jclouds.domain.Location;
import org.jclouds.domain.LocationBuilder;
import org.jclouds.domain.LocationScope;
import org.testng.annotations.Test;
import com.google.common.base.Supplier;
import com.google.common.base.Suppliers;
import com.google.common.collect.ImmutableSet;
/**
* Tests behavior of {@code FirstNetwork}
*
* @author Adrian Cole
* @author Dies Koper
*/
@Test(groups = "unit", testName = "FirstNetworkTest")
public class FirstNetworkTest {
Location provider = new LocationBuilder().scope(LocationScope.PROVIDER).id("servo").description("http://servo")
.build();
Location region = new LocationBuilder().scope(LocationScope.REGION).id("servo-r").description("http://r.servo")
.parent(provider).build();
Location network = new LocationBuilder().scope(LocationScope.NETWORK).id("servo-n").description("http://z.r.servo")
.parent(region).build();
@Test
public void testDidntFindNetworkThrowsNSEEWithReasonableMessage() {
Supplier<Set<? extends Location>> supplier = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(provider, region));
FirstNetwork fn = new FirstNetwork(supplier);
try {
fn.get();
assert false;
} catch (NoSuchElementException e) {
assertEquals(e.getMessage(), "none of the locations are scope NETWORK: [servo:PROVIDER, servo-r:REGION]");
}
}
@Test
public void testFirstNetwork() {
Supplier<Set<? extends Location>> supplier = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
.<Location> of(provider, region, network));
FirstNetwork fn = new FirstNetwork(supplier);
assertEquals(fn.get(), network);
}
}

View File

@ -21,13 +21,12 @@ package org.jclouds.elb;
import java.util.Set;
import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import org.jclouds.concurrent.Timeout;
import org.jclouds.elb.features.AvailabilityZoneApi;
import org.jclouds.elb.features.InstanceApi;
import org.jclouds.elb.features.LoadBalancerApi;
import org.jclouds.elb.features.PolicyApi;
import org.jclouds.elb.features.AvailabilityZoneApi;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Region;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.rest.annotations.Delegate;

View File

@ -20,13 +20,12 @@ package org.jclouds.elb;
import java.util.Set;
import javax.annotation.Nullable;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.elb.features.AvailabilityZoneAsyncApi;
import org.jclouds.elb.features.InstanceAsyncApi;
import org.jclouds.elb.features.LoadBalancerAsyncApi;
import org.jclouds.elb.features.PolicyAsyncApi;
import org.jclouds.elb.features.AvailabilityZoneAsyncApi;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.Region;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
import org.jclouds.rest.annotations.Delegate;

View File

@ -23,8 +23,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Map;
import java.util.Set;
import javax.annotation.Nullable;
import com.google.common.base.Function;
import com.google.common.base.Objects;
import com.google.common.collect.ImmutableSet;
@ -135,7 +133,7 @@ public class PolicyType {
return Maps.uniqueIndex(attributeMetadata, new Function<AttributeMetadata<?>, String>(){
@Override
public String apply(@Nullable AttributeMetadata<?> input) {
public String apply(AttributeMetadata<?> input) {
return input.getName();
}

View File

@ -22,8 +22,6 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.util.Set;
import javax.annotation.Nullable;
import org.jclouds.elb.domain.AttributeMetadata;
import org.jclouds.elb.domain.Policy;
import org.jclouds.elb.domain.PolicyType;
@ -95,7 +93,7 @@ public class PolicyApiLiveTest extends BaseELBApiLiveTest {
Iterable<String> names = Iterables.transform(response, new Function<PolicyType, String>() {
@Override
public String apply(@Nullable PolicyType input) {
public String apply(PolicyType input) {
return input.getName();
}

View File

@ -19,8 +19,6 @@
package org.jclouds.nodepool.config;
import javax.annotation.Nullable;
import org.jclouds.apis.ApiMetadata;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.config.JCloudsNativeComputeServiceAdapterContextModule;
@ -30,6 +28,7 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
import org.jclouds.domain.Location;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.nodepool.NodePoolApiMetadata;
import org.jclouds.nodepool.NodePoolComputeServiceAdapter;
import org.jclouds.nodepool.NodePoolComputeServiceContext;

View File

@ -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.
*/

View File

@ -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.
*/

View File

@ -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);

Some files were not shown because too many files have changed in this diff Show More