mirror of https://github.com/apache/jclouds.git
Issue 325: massive refactor in order to stop serializing native async http client requests
This commit is contained in:
parent
909fc0d79a
commit
34518f54ba
|
@ -49,6 +49,16 @@
|
||||||
<artifactId>jclouds-vcloud</artifactId>
|
<artifactId>jclouds-vcloud</artifactId>
|
||||||
<version>${project.version}</version>
|
<version>${project.version}</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>jclouds-bluelock</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
|
<dependency>
|
||||||
|
<groupId>${project.groupId}</groupId>
|
||||||
|
<artifactId>jclouds-terremark</artifactId>
|
||||||
|
<version>${project.version}</version>
|
||||||
|
</dependency>
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>${project.groupId}</groupId>
|
<groupId>${project.groupId}</groupId>
|
||||||
<artifactId>jclouds-gogrid</artifactId>
|
<artifactId>jclouds-gogrid</artifactId>
|
||||||
|
|
|
@ -43,7 +43,7 @@ public interface ${providerName}Client {
|
||||||
/*
|
/*
|
||||||
* Note all these delegate to methods in ${providerName}AsyncClient with a specified or inherited timeout.
|
* Note all these delegate to methods in ${providerName}AsyncClient with a specified or inherited timeout.
|
||||||
* The singatures should match those of ${providerName}AsyncClient, except the returnvals should not be
|
* The singatures should match those of ${providerName}AsyncClient, except the returnvals should not be
|
||||||
* wrapped in a ListenableFuture
|
* wrapped in a Future
|
||||||
*/
|
*/
|
||||||
|
|
||||||
String list();
|
String list();
|
||||||
|
|
|
@ -82,7 +82,7 @@ public interface AtmosStorageAsyncClient {
|
||||||
@Path("/rest/namespace")
|
@Path("/rest/namespace")
|
||||||
@ResponseParser(ParseDirectoryListFromContentAndHeaders.class)
|
@ResponseParser(ParseDirectoryListFromContentAndHeaders.class)
|
||||||
@Consumes(MediaType.TEXT_XML)
|
@Consumes(MediaType.TEXT_XML)
|
||||||
ListenableFuture<? extends BoundedSet<? extends DirectoryEntry>> listDirectories(
|
ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectories(
|
||||||
ListOptions... options);
|
ListOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,7 +93,7 @@ public interface AtmosStorageAsyncClient {
|
||||||
@ResponseParser(ParseDirectoryListFromContentAndHeaders.class)
|
@ResponseParser(ParseDirectoryListFromContentAndHeaders.class)
|
||||||
@ExceptionParser(ThrowContainerNotFoundOn404.class)
|
@ExceptionParser(ThrowContainerNotFoundOn404.class)
|
||||||
@Consumes(MediaType.TEXT_XML)
|
@Consumes(MediaType.TEXT_XML)
|
||||||
ListenableFuture<? extends BoundedSet<? extends DirectoryEntry>> listDirectory(
|
ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectory(
|
||||||
@PathParam("directoryName") String directoryName, ListOptions... options);
|
@PathParam("directoryName") String directoryName, ListOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -19,7 +19,8 @@
|
||||||
package org.jclouds.atmosonline.saas.blobstore;
|
package org.jclouds.atmosonline.saas.blobstore;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.util.concurrent.Futures.compose;
|
import static org.jclouds.concurrent.ConcurrentUtils.compose;
|
||||||
|
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -53,7 +54,6 @@ import org.jclouds.blobstore.functions.BlobToHttpGetOptions;
|
||||||
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
import org.jclouds.blobstore.internal.BaseAsyncBlobStore;
|
||||||
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
import org.jclouds.blobstore.strategy.internal.FetchBlobMetadata;
|
||||||
import org.jclouds.blobstore.util.BlobUtils;
|
import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.concurrent.ConcurrentUtils;
|
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.encryption.EncryptionService;
|
import org.jclouds.encryption.EncryptionService;
|
||||||
import org.jclouds.http.options.GetOptions;
|
import org.jclouds.http.options.GetOptions;
|
||||||
|
@ -79,15 +79,12 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
AtmosAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
AtmosAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Location defaultLocation,
|
||||||
Location defaultLocation, Set<? extends Location> locations,
|
Set<? extends Location> locations, AtmosStorageAsyncClient async, AtmosStorageClient sync,
|
||||||
|
ObjectToBlob object2Blob, ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object,
|
||||||
AtmosStorageAsyncClient async, AtmosStorageClient sync, ObjectToBlob object2Blob,
|
|
||||||
ObjectToBlobMetadata object2BlobMd, BlobToObject blob2Object,
|
|
||||||
BlobStoreListOptionsToListOptions container2ContainerListOptions,
|
BlobStoreListOptionsToListOptions container2ContainerListOptions,
|
||||||
DirectoryEntryListToResourceMetadataList container2ResourceList,
|
DirectoryEntryListToResourceMetadataList container2ResourceList, EncryptionService encryptionService,
|
||||||
EncryptionService encryptionService, BlobToHttpGetOptions blob2ObjectGetOptions,
|
BlobToHttpGetOptions blob2ObjectGetOptions, Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
|
||||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
|
|
||||||
super(context, blobUtils, service, defaultLocation, locations);
|
super(context, blobUtils, service, defaultLocation, locations);
|
||||||
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
||||||
this.sync = checkNotNull(sync, "sync");
|
this.sync = checkNotNull(sync, "sync");
|
||||||
|
@ -99,8 +96,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
|
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
|
||||||
this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd");
|
this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd");
|
||||||
this.encryptionService = checkNotNull(encryptionService, "encryptionService");
|
this.encryptionService = checkNotNull(encryptionService, "encryptionService");
|
||||||
this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider,
|
this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider, "fetchBlobMetadataProvider");
|
||||||
"fetchBlobMetadataProvider");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -108,13 +104,12 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
|
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
|
||||||
return compose(async.headFile(container + "/" + key),
|
return compose(async.headFile(container + "/" + key), new Function<AtmosObject, BlobMetadata>() {
|
||||||
new Function<AtmosObject, BlobMetadata>() {
|
@Override
|
||||||
@Override
|
public BlobMetadata apply(AtmosObject from) {
|
||||||
public BlobMetadata apply(AtmosObject from) {
|
return object2BlobMd.apply(from);
|
||||||
return object2BlobMd.apply(from);
|
}
|
||||||
}
|
}, service);
|
||||||
}, service);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -130,7 +125,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -144,7 +139,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
return null;// no etag
|
return null;// no etag
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -197,8 +192,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
* This implementation invokes {@link AtmosStorageAsyncClient#readFile}
|
* This implementation invokes {@link AtmosStorageAsyncClient#readFile}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Blob> getBlob(String container, String key,
|
public ListenableFuture<Blob> getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions options) {
|
||||||
org.jclouds.blobstore.options.GetOptions options) {
|
|
||||||
GetOptions httpOptions = blob2ObjectGetOptions.apply(options);
|
GetOptions httpOptions = blob2ObjectGetOptions.apply(options);
|
||||||
ListenableFuture<AtmosObject> returnVal = async.readFile(container + "/" + key, httpOptions);
|
ListenableFuture<AtmosObject> returnVal = async.readFile(container + "/" + key, httpOptions);
|
||||||
return compose(returnVal, object2Blob, service);
|
return compose(returnVal, object2Blob, service);
|
||||||
|
@ -208,7 +202,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
* This implementation invokes {@link AtmosStorageAsyncClient#listDirectories}
|
* This implementation invokes {@link AtmosStorageAsyncClient#listDirectories}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list() {
|
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
|
||||||
return compose(async.listDirectories(), container2ResourceList, service);
|
return compose(async.listDirectories(), container2ResourceList, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -216,16 +210,14 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
* This implementation invokes {@link AtmosStorageAsyncClient#listDirectory}
|
* This implementation invokes {@link AtmosStorageAsyncClient#listDirectory}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list(String container,
|
public ListenableFuture<PageSet<? extends StorageMetadata>> list(String container,
|
||||||
org.jclouds.blobstore.options.ListContainerOptions options) {
|
org.jclouds.blobstore.options.ListContainerOptions options) {
|
||||||
container = AtmosStorageUtils.adjustContainerIfDirOptionPresent(container, options);
|
container = AtmosStorageUtils.adjustContainerIfDirOptionPresent(container, options);
|
||||||
ListOptions nativeOptions = container2ContainerListOptions.apply(options);
|
ListOptions nativeOptions = container2ContainerListOptions.apply(options);
|
||||||
ListenableFuture<? extends BoundedSet<? extends DirectoryEntry>> returnVal = async
|
ListenableFuture<BoundedSet<? extends DirectoryEntry>> returnVal = async.listDirectory(container, nativeOptions);
|
||||||
.listDirectory(container, nativeOptions);
|
ListenableFuture<PageSet<? extends StorageMetadata>> list = compose(returnVal, container2ResourceList, service);
|
||||||
ListenableFuture<PageSet<? extends StorageMetadata>> list = compose(returnVal,
|
return (ListenableFuture<PageSet<? extends StorageMetadata>>) (options.isDetailed() ? compose(list,
|
||||||
container2ResourceList, service);
|
fetchBlobMetadataProvider.get().setContainerName(container), service) : list);
|
||||||
return options.isDetailed() ? compose(list, fetchBlobMetadataProvider.get().setContainerName(
|
|
||||||
container), service) : list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -235,7 +227,7 @@ public class AtmosAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<String> putBlob(final String container, final Blob blob) {
|
public ListenableFuture<String> putBlob(final String container, final Blob blob) {
|
||||||
return ConcurrentUtils.makeListenable(service.submit(new Callable<String>() {
|
return makeListenable(service.submit(new Callable<String>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String call() throws Exception {
|
public String call() throws Exception {
|
||||||
|
|
|
@ -26,6 +26,7 @@ import java.util.Map;
|
||||||
import java.util.concurrent.BlockingQueue;
|
import java.util.concurrent.BlockingQueue;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.SynchronousQueue;
|
import java.util.concurrent.SynchronousQueue;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -42,6 +43,7 @@ import org.jclouds.blobstore.internal.BlobRuntimeException;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
|
import org.jclouds.blobstore.strategy.ContainsValueInListStrategy;
|
||||||
import org.jclouds.blobstore.strategy.ListBlobsInContainer;
|
import org.jclouds.blobstore.strategy.ListBlobsInContainer;
|
||||||
|
import static org.jclouds.concurrent.ConcurrentUtils.*;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
|
@ -70,10 +72,8 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
|
||||||
protected Long maxTime;
|
protected Long maxTime;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private FindMD5InUserMetadata(
|
private FindMD5InUserMetadata(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
|
ObjectMD5 objectMD5, ListBlobsInContainer getAllBlobMetadata, AtmosStorageAsyncClient client) {
|
||||||
ObjectMD5 objectMD5, ListBlobsInContainer getAllBlobMetadata,
|
|
||||||
AtmosStorageAsyncClient client) {
|
|
||||||
this.objectMD5 = objectMD5;
|
this.objectMD5 = objectMD5;
|
||||||
this.getAllBlobMetadata = getAllBlobMetadata;
|
this.getAllBlobMetadata = getAllBlobMetadata;
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
@ -83,10 +83,10 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
|
||||||
public boolean execute(final String containerName, Object value, ListContainerOptions options) {
|
public boolean execute(final String containerName, Object value, ListContainerOptions options) {
|
||||||
final byte[] toSearch = objectMD5.apply(value);
|
final byte[] toSearch = objectMD5.apply(value);
|
||||||
final BlockingQueue<Boolean> queue = new SynchronousQueue<Boolean>();
|
final BlockingQueue<Boolean> queue = new SynchronousQueue<Boolean>();
|
||||||
Map<String, ListenableFuture<?>> responses = Maps.newHashMap();
|
Map<String, Future<?>> responses = Maps.newHashMap();
|
||||||
for (BlobMetadata md : getAllBlobMetadata.execute(containerName, options)) {
|
for (BlobMetadata md : getAllBlobMetadata.execute(containerName, options)) {
|
||||||
final ListenableFuture<AtmosObject> future = client.headFile(containerName + "/"
|
final ListenableFuture<AtmosObject> future = makeListenable(client.headFile(containerName
|
||||||
+ md.getName());
|
+ "/" + md.getName()), userExecutor);
|
||||||
future.addListener(new Runnable() {
|
future.addListener(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
|
@ -97,8 +97,7 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
|
||||||
queue.put(true);
|
queue.put(true);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
logger.debug("object %s has no content md5", object.getSystemMetadata()
|
logger.debug("object %s has no content md5", object.getSystemMetadata().getObjectID());
|
||||||
.getObjectID());
|
|
||||||
}
|
}
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
Throwables.propagate(e);
|
Throwables.propagate(e);
|
||||||
|
@ -109,11 +108,11 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
|
||||||
}, userExecutor);
|
}, userExecutor);
|
||||||
responses.put(md.getName(), future);
|
responses.put(md.getName(), future);
|
||||||
}
|
}
|
||||||
Map<String, Exception> exceptions = awaitCompletion(responses, userExecutor, maxTime, logger,
|
Map<String, Exception> exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, String.format(
|
||||||
String.format("searching for md5 in container %s", containerName));
|
"searching for md5 in container %s", containerName));
|
||||||
if (exceptions.size() > 0)
|
if (exceptions.size() > 0)
|
||||||
throw new BlobRuntimeException(String.format("searching for md5 in container %s: %s",
|
throw new BlobRuntimeException(String.format("searching for md5 in container %s: %s", containerName,
|
||||||
containerName, exceptions));
|
exceptions));
|
||||||
try {
|
try {
|
||||||
return queue.poll(1, TimeUnit.MICROSECONDS) != null;
|
return queue.poll(1, TimeUnit.MICROSECONDS) != null;
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
@ -121,9 +120,8 @@ public class FindMD5InUserMetadata implements ContainsValueInListStrategy {
|
||||||
return false;
|
return false;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
Throwables.propagateIfPossible(e, BlobRuntimeException.class);
|
Throwables.propagateIfPossible(e, BlobRuntimeException.class);
|
||||||
throw new BlobRuntimeException(String.format(
|
throw new BlobRuntimeException(String.format("Error searching for ETAG of value: [%s] in container:%s", value,
|
||||||
"Error searching for ETAG of value: [%s] in container:%s", value, containerName),
|
containerName), e);
|
||||||
e);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,15 +19,18 @@
|
||||||
package org.jclouds.atmosonline.saas.internal;
|
package org.jclouds.atmosonline.saas.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.util.concurrent.Futures.compose;
|
|
||||||
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
|
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
|
||||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
|
import static org.jclouds.concurrent.ConcurrentUtils.compose;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
|
import org.jclouds.atmosonline.saas.AtmosStorageAsyncClient;
|
||||||
import org.jclouds.atmosonline.saas.blobstore.functions.BlobMetadataToObject;
|
import org.jclouds.atmosonline.saas.blobstore.functions.BlobMetadataToObject;
|
||||||
import org.jclouds.atmosonline.saas.blobstore.functions.BlobToObject;
|
import org.jclouds.atmosonline.saas.blobstore.functions.BlobToObject;
|
||||||
|
@ -48,7 +51,6 @@ import org.jclouds.http.options.GetOptions;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
import com.google.common.util.concurrent.Futures;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -65,13 +67,13 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
|
||||||
private final BlobMetadataToObject blob2ObjectInfo;
|
private final BlobMetadataToObject blob2ObjectInfo;
|
||||||
private final ListOptionsToBlobStoreListOptions container2ContainerListOptions;
|
private final ListOptionsToBlobStoreListOptions container2ContainerListOptions;
|
||||||
private final ResourceMetadataListToDirectoryEntryList resource2ObjectList;
|
private final ResourceMetadataListToDirectoryEntryList resource2ObjectList;
|
||||||
|
private final ExecutorService service;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private StubAtmosStorageAsyncClient(TransientAsyncBlobStore blobStore,
|
private StubAtmosStorageAsyncClient(TransientAsyncBlobStore blobStore, AtmosObject.Factory objectProvider,
|
||||||
AtmosObject.Factory objectProvider,
|
HttpGetOptionsListToGetOptions httpGetOptionsConverter, ObjectToBlob object2Blob, BlobToObject blob2Object,
|
||||||
HttpGetOptionsListToGetOptions httpGetOptionsConverter, ObjectToBlob object2Blob,
|
BlobMetadataToObject blob2ObjectInfo, ListOptionsToBlobStoreListOptions container2ContainerListOptions,
|
||||||
BlobToObject blob2Object, BlobMetadataToObject blob2ObjectInfo,
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
|
||||||
ListOptionsToBlobStoreListOptions container2ContainerListOptions,
|
|
||||||
ResourceMetadataListToDirectoryEntryList resource2ContainerList) {
|
ResourceMetadataListToDirectoryEntryList resource2ContainerList) {
|
||||||
this.blobStore = blobStore;
|
this.blobStore = blobStore;
|
||||||
this.objectProvider = objectProvider;
|
this.objectProvider = objectProvider;
|
||||||
|
@ -82,6 +84,7 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
|
||||||
this.container2ContainerListOptions = checkNotNull(container2ContainerListOptions,
|
this.container2ContainerListOptions = checkNotNull(container2ContainerListOptions,
|
||||||
"container2ContainerListOptions");
|
"container2ContainerListOptions");
|
||||||
this.resource2ObjectList = checkNotNull(resource2ContainerList, "resource2ContainerList");
|
this.resource2ObjectList = checkNotNull(resource2ContainerList, "resource2ContainerList");
|
||||||
|
this.service = service;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<URI> createDirectory(String directoryName) {
|
public ListenableFuture<URI> createDirectory(String directoryName) {
|
||||||
|
@ -94,25 +97,23 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
|
||||||
container = directoryName;
|
container = directoryName;
|
||||||
path = null;
|
path = null;
|
||||||
}
|
}
|
||||||
return Futures.compose(blobStore.createContainerInLocation(null, container),
|
return compose(blobStore.createContainerInLocation(null, container), new Function<Boolean, URI>() {
|
||||||
new Function<Boolean, URI>() {
|
|
||||||
|
|
||||||
public URI apply(Boolean from) {
|
public URI apply(Boolean from) {
|
||||||
if (path != null) {
|
if (path != null) {
|
||||||
Blob blob = blobStore.newBlob(path + "/");
|
Blob blob = blobStore.newBlob(path + "/");
|
||||||
blob.getMetadata().setContentType("application/directory");
|
blob.getMetadata().setContentType("application/directory");
|
||||||
blob.setPayload("");
|
blob.setPayload("");
|
||||||
blobStore.putBlob(container, blob);
|
blobStore.putBlob(container, blob);
|
||||||
}
|
}
|
||||||
return URI.create("http://stub/containers/" + container);
|
return URI.create("http://stub/containers/" + container);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<URI> createFile(String parent, AtmosObject object) {
|
public ListenableFuture<URI> createFile(String parent, AtmosObject object) {
|
||||||
final String uri = "http://stub/containers/" + parent + "/"
|
final String uri = "http://stub/containers/" + parent + "/" + object.getContentMetadata().getName();
|
||||||
+ object.getContentMetadata().getName();
|
|
||||||
String file = object.getContentMetadata().getName();
|
String file = object.getContentMetadata().getName();
|
||||||
String container = parent;
|
String container = parent;
|
||||||
if (parent.indexOf('/') != -1) {
|
if (parent.indexOf('/') != -1) {
|
||||||
|
@ -128,7 +129,7 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
|
||||||
return URI.create(uri);
|
return URI.create(uri);
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<Void> deletePath(String path) {
|
public ListenableFuture<Void> deletePath(String path) {
|
||||||
|
@ -141,7 +142,7 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
}, service);
|
||||||
} else {
|
} else {
|
||||||
String container = path.substring(0, path.indexOf('/'));
|
String container = path.substring(0, path.indexOf('/'));
|
||||||
path = path.substring(path.indexOf('/') + 1);
|
path = path.substring(path.indexOf('/') + 1);
|
||||||
|
@ -159,12 +160,11 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
|
||||||
else {
|
else {
|
||||||
String container = path.substring(0, path.indexOf('/'));
|
String container = path.substring(0, path.indexOf('/'));
|
||||||
path = path.substring(path.indexOf('/') + 1);
|
path = path.substring(path.indexOf('/') + 1);
|
||||||
return compose(blobStore.blobMetadata(container, path),
|
return compose(blobStore.blobMetadata(container, path), new Function<BlobMetadata, UserMetadata>() {
|
||||||
new Function<BlobMetadata, UserMetadata>() {
|
public UserMetadata apply(BlobMetadata from) {
|
||||||
public UserMetadata apply(BlobMetadata from) {
|
return blob2ObjectInfo.apply(from).getUserMetadata();
|
||||||
return blob2ObjectInfo.apply(from).getUserMetadata();
|
}
|
||||||
}
|
}, service);
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -172,23 +172,21 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
|
||||||
String container = path.substring(0, path.indexOf('/'));
|
String container = path.substring(0, path.indexOf('/'));
|
||||||
path = path.substring(path.indexOf('/') + 1);
|
path = path.substring(path.indexOf('/') + 1);
|
||||||
try {
|
try {
|
||||||
return Futures.compose(blobStore.getBlob(container, path), blob2Object);
|
return compose(blobStore.getBlob(container, path), blob2Object, service);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return immediateFailedFuture(Throwables.getRootCause(e));
|
return immediateFailedFuture(Throwables.getRootCause(e));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<? extends BoundedSet<? extends DirectoryEntry>> listDirectories(
|
public ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectories(ListOptions... optionsList) {
|
||||||
ListOptions... optionsList) {
|
|
||||||
// org.jclouds.blobstore.options.ListOptions options = container2ContainerListOptions
|
// org.jclouds.blobstore.options.ListOptions options = container2ContainerListOptions
|
||||||
// .apply(optionsList);
|
// .apply(optionsList);
|
||||||
return Futures.compose(blobStore.list(), resource2ObjectList);
|
return compose(blobStore.list(), resource2ObjectList, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<? extends BoundedSet<? extends DirectoryEntry>> listDirectory(
|
public ListenableFuture<BoundedSet<? extends DirectoryEntry>> listDirectory(String directoryName,
|
||||||
String directoryName, ListOptions... optionsList) {
|
ListOptions... optionsList) {
|
||||||
org.jclouds.blobstore.options.ListContainerOptions options = container2ContainerListOptions
|
org.jclouds.blobstore.options.ListContainerOptions options = container2ContainerListOptions.apply(optionsList);
|
||||||
.apply(optionsList);
|
|
||||||
String container = directoryName;
|
String container = directoryName;
|
||||||
if (directoryName.indexOf('/') != -1) {
|
if (directoryName.indexOf('/') != -1) {
|
||||||
container = directoryName.substring(0, directoryName.indexOf('/'));
|
container = directoryName.substring(0, directoryName.indexOf('/'));
|
||||||
|
@ -196,7 +194,7 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
|
||||||
if (!path.equals(""))
|
if (!path.equals(""))
|
||||||
options.inDirectory(path);
|
options.inDirectory(path);
|
||||||
}
|
}
|
||||||
return compose(blobStore.list(container, options), resource2ObjectList);
|
return compose(blobStore.list(container, options), resource2ObjectList, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AtmosObject newObject() {
|
public AtmosObject newObject() {
|
||||||
|
@ -224,7 +222,7 @@ public class StubAtmosStorageAsyncClient implements AtmosStorageAsyncClient {
|
||||||
String container = path.substring(0, path.indexOf('/'));
|
String container = path.substring(0, path.indexOf('/'));
|
||||||
String blobName = path.substring(path.indexOf('/') + 1);
|
String blobName = path.substring(path.indexOf('/') + 1);
|
||||||
org.jclouds.blobstore.options.GetOptions getOptions = httpGetOptionsConverter.apply(options);
|
org.jclouds.blobstore.options.GetOptions getOptions = httpGetOptionsConverter.apply(options);
|
||||||
return Futures.compose(blobStore.getBlob(container, blobName, getOptions), blob2Object);
|
return compose(blobStore.getBlob(container, blobName, getOptions), blob2Object, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<Void> updateFile(String parent, AtmosObject object) {
|
public ListenableFuture<Void> updateFile(String parent, AtmosObject object) {
|
||||||
|
|
|
@ -18,6 +18,16 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.aws.ec2.compute.config;
|
package org.jclouds.aws.ec2.compute.config;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Iterables.concat;
|
||||||
|
import static com.google.common.collect.Iterables.filter;
|
||||||
|
import static com.google.common.collect.Iterables.find;
|
||||||
|
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||||
|
import static com.google.common.collect.Iterables.toArray;
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
import static com.google.common.collect.Maps.newLinkedHashMap;
|
||||||
|
import static com.google.common.collect.Maps.uniqueIndex;
|
||||||
|
import static com.google.common.collect.Sets.newHashSet;
|
||||||
|
import static com.google.common.collect.Sets.newLinkedHashSet;
|
||||||
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.imageIds;
|
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.imageIds;
|
||||||
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.ownedBy;
|
import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.ownedBy;
|
||||||
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
|
import static org.jclouds.aws.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
|
||||||
|
@ -26,17 +36,18 @@ import static org.jclouds.aws.ec2.util.EC2Utils.getAllRunningInstancesInRegion;
|
||||||
import static org.jclouds.aws.ec2.util.EC2Utils.parseHandle;
|
import static org.jclouds.aws.ec2.util.EC2Utils.parseHandle;
|
||||||
import static org.jclouds.compute.domain.OsFamily.CENTOS;
|
import static org.jclouds.compute.domain.OsFamily.CENTOS;
|
||||||
import static org.jclouds.compute.domain.OsFamily.UBUNTU;
|
import static org.jclouds.compute.domain.OsFamily.UBUNTU;
|
||||||
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
|
import static org.jclouds.concurrent.ConcurrentUtils.transformParallel;
|
||||||
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.Map.Entry;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
|
@ -61,6 +72,7 @@ import org.jclouds.aws.ec2.compute.functions.RegionAndIdToImage;
|
||||||
import org.jclouds.aws.ec2.compute.functions.RunningInstanceToNodeMetadata;
|
import org.jclouds.aws.ec2.compute.functions.RunningInstanceToNodeMetadata;
|
||||||
import org.jclouds.aws.ec2.compute.internal.EC2TemplateBuilderImpl;
|
import org.jclouds.aws.ec2.compute.internal.EC2TemplateBuilderImpl;
|
||||||
import org.jclouds.aws.ec2.compute.options.EC2TemplateOptions;
|
import org.jclouds.aws.ec2.compute.options.EC2TemplateOptions;
|
||||||
|
import org.jclouds.aws.ec2.compute.strategy.DescribeImagesParallel;
|
||||||
import org.jclouds.aws.ec2.compute.strategy.EC2DestroyLoadBalancerStrategy;
|
import org.jclouds.aws.ec2.compute.strategy.EC2DestroyLoadBalancerStrategy;
|
||||||
import org.jclouds.aws.ec2.compute.strategy.EC2DestroyNodeStrategy;
|
import org.jclouds.aws.ec2.compute.strategy.EC2DestroyNodeStrategy;
|
||||||
import org.jclouds.aws.ec2.compute.strategy.EC2LoadBalanceNodesStrategy;
|
import org.jclouds.aws.ec2.compute.strategy.EC2LoadBalanceNodesStrategy;
|
||||||
|
@ -68,8 +80,8 @@ import org.jclouds.aws.ec2.compute.strategy.EC2RunNodesAndAddToSetStrategy;
|
||||||
import org.jclouds.aws.ec2.domain.InstanceType;
|
import org.jclouds.aws.ec2.domain.InstanceType;
|
||||||
import org.jclouds.aws.ec2.domain.KeyPair;
|
import org.jclouds.aws.ec2.domain.KeyPair;
|
||||||
import org.jclouds.aws.ec2.domain.PlacementGroup;
|
import org.jclouds.aws.ec2.domain.PlacementGroup;
|
||||||
|
import org.jclouds.aws.ec2.domain.Reservation;
|
||||||
import org.jclouds.aws.ec2.domain.RunningInstance;
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.aws.ec2.domain.Image.ImageType;
|
|
||||||
import org.jclouds.aws.ec2.functions.RunningInstanceToStorageMappingUnix;
|
import org.jclouds.aws.ec2.functions.RunningInstanceToStorageMappingUnix;
|
||||||
import org.jclouds.aws.ec2.options.DescribeImagesOptions;
|
import org.jclouds.aws.ec2.options.DescribeImagesOptions;
|
||||||
import org.jclouds.aws.ec2.predicates.InstancePresent;
|
import org.jclouds.aws.ec2.predicates.InstancePresent;
|
||||||
|
@ -96,7 +108,6 @@ import org.jclouds.compute.strategy.ListNodesStrategy;
|
||||||
import org.jclouds.compute.strategy.LoadBalanceNodesStrategy;
|
import org.jclouds.compute.strategy.LoadBalanceNodesStrategy;
|
||||||
import org.jclouds.compute.strategy.RebootNodeStrategy;
|
import org.jclouds.compute.strategy.RebootNodeStrategy;
|
||||||
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
|
import org.jclouds.compute.strategy.RunNodesAndAddToSetStrategy;
|
||||||
import org.jclouds.concurrent.ConcurrentUtils;
|
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.domain.LocationScope;
|
import org.jclouds.domain.LocationScope;
|
||||||
import org.jclouds.domain.internal.LocationImpl;
|
import org.jclouds.domain.internal.LocationImpl;
|
||||||
|
@ -108,6 +119,7 @@ import org.jclouds.rest.internal.RestContextImpl;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
@ -115,8 +127,6 @@ import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.MapMaker;
|
import com.google.common.collect.MapMaker;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import com.google.inject.Scopes;
|
import com.google.inject.Scopes;
|
||||||
|
@ -206,13 +216,13 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
private final EC2Client client;
|
private final EC2AsyncClient client;
|
||||||
private final Map<String, URI> regionMap;
|
private final Map<String, URI> regionMap;
|
||||||
private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
|
private final RunningInstanceToNodeMetadata runningInstanceToNodeMetadata;
|
||||||
private final ExecutorService executor;
|
private final ExecutorService executor;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected EC2ListNodesStrategy(EC2Client client, @Region Map<String, URI> regionMap,
|
protected EC2ListNodesStrategy(EC2AsyncClient client, @Region Map<String, URI> regionMap,
|
||||||
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata,
|
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
@ -222,31 +232,25 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterable<? extends ComputeMetadata> list() {
|
public Set<? extends ComputeMetadata> list() {
|
||||||
return listDetailsOnNodesMatching(NodePredicates.all());
|
return listDetailsOnNodesMatching(NodePredicates.all());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) {
|
public Set<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) {
|
||||||
final Set<NodeMetadata> nodes = Sets.newHashSet();
|
Iterable<Set<? extends Reservation<? extends RunningInstance>>> reservations = transformParallel(regionMap
|
||||||
|
.keySet(), new Function<String, Future<Set<? extends Reservation<? extends RunningInstance>>>>() {
|
||||||
|
|
||||||
Map<String, ListenableFuture<?>> parallelResponses = Maps.newHashMap();
|
@Override
|
||||||
|
public Future<Set<? extends Reservation<? extends RunningInstance>>> apply(String from) {
|
||||||
|
return client.getInstanceServices().describeInstancesInRegion(from);
|
||||||
|
}
|
||||||
|
|
||||||
for (final String region : regionMap.keySet()) {
|
}, executor, null, logger, "reservations");
|
||||||
parallelResponses.put(region, ConcurrentUtils.makeListenable(executor.submit(new Callable<Void>() {
|
|
||||||
@Override
|
|
||||||
public Void call() throws Exception {
|
|
||||||
Iterables.addAll(nodes, Iterables.transform(Iterables.concat(client.getInstanceServices()
|
|
||||||
.describeInstancesInRegion(region)), runningInstanceToNodeMetadata));
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}), executor));
|
|
||||||
}
|
|
||||||
Map<String, Exception> exceptions = awaitCompletion(parallelResponses, executor, null, logger, "nodes");
|
|
||||||
|
|
||||||
if (exceptions.size() > 0)
|
Iterable<? extends RunningInstance> instances = concat(concat(reservations));
|
||||||
throw new RuntimeException(String.format("error parsing nodes in regions: %s", exceptions));
|
Iterable<? extends NodeMetadata> nodes = filter(transform(instances, runningInstanceToNodeMetadata), filter);
|
||||||
return Iterables.filter(nodes, filter);
|
return newLinkedHashSet(nodes);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -268,7 +272,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
|
||||||
String region = parts[0];
|
String region = parts[0];
|
||||||
String instanceId = parts[1];
|
String instanceId = parts[1];
|
||||||
try {
|
try {
|
||||||
RunningInstance runningInstance = Iterables.getOnlyElement(getAllRunningInstancesInRegion(client
|
RunningInstance runningInstance = getOnlyElement(getAllRunningInstancesInRegion(client
|
||||||
.getInstanceServices(), region, instanceId));
|
.getInstanceServices(), region, instanceId));
|
||||||
return runningInstanceToNodeMetadata.apply(runningInstance);
|
return runningInstanceToNodeMetadata.apply(runningInstance);
|
||||||
} catch (NoSuchElementException e) {
|
} catch (NoSuchElementException e) {
|
||||||
|
@ -305,7 +309,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
|
||||||
protected final Map<RegionAndName, KeyPair> credentialsMap(CreateUniqueKeyPair in) {
|
protected final Map<RegionAndName, KeyPair> credentialsMap(CreateUniqueKeyPair in) {
|
||||||
// doesn't seem to clear when someone issues remove(key)
|
// doesn't seem to clear when someone issues remove(key)
|
||||||
// return new MapMaker().makeComputingMap(in);
|
// return new MapMaker().makeComputingMap(in);
|
||||||
return Maps.newLinkedHashMap();
|
return newLinkedHashMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
@ -314,7 +318,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
|
||||||
protected final Map<RegionAndName, String> securityGroupMap(CreateSecurityGroupIfNeeded in) {
|
protected final Map<RegionAndName, String> securityGroupMap(CreateSecurityGroupIfNeeded in) {
|
||||||
// doesn't seem to clear when someone issues remove(key)
|
// doesn't seem to clear when someone issues remove(key)
|
||||||
// return new MapMaker().makeComputingMap(in);
|
// return new MapMaker().makeComputingMap(in);
|
||||||
return Maps.newLinkedHashMap();
|
return newLinkedHashMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
@ -323,7 +327,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
|
||||||
protected final Map<RegionAndName, String> placementGroupMap(CreatePlacementGroupIfNeeded in) {
|
protected final Map<RegionAndName, String> placementGroupMap(CreatePlacementGroupIfNeeded in) {
|
||||||
// doesn't seem to clear when someone issues remove(key)
|
// doesn't seem to clear when someone issues remove(key)
|
||||||
// return new MapMaker().makeComputingMap(in);
|
// return new MapMaker().makeComputingMap(in);
|
||||||
return Maps.newLinkedHashMap();
|
return newLinkedHashMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
@ -340,10 +344,10 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
Set<? extends Size> provideSizes(Set<? extends Location> locations, @Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis) {
|
Set<? extends Size> provideSizes(Set<? extends Location> locations, @Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis) {
|
||||||
Set<Size> sizes = Sets.newHashSet();
|
Set<Size> sizes = newHashSet();
|
||||||
for (String ccAmi : ccAmis) {
|
for (String ccAmi : ccAmis) {
|
||||||
final String region = ccAmi.split("/")[0];
|
final String region = ccAmi.split("/")[0];
|
||||||
Location location = Iterables.find(locations, new Predicate<Location>() {
|
Location location = find(locations, new Predicate<Location>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(Location input) {
|
public boolean apply(Location input) {
|
||||||
|
@ -362,11 +366,11 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
|
||||||
Set<? extends Location> provideLocations(Map<String, String> availabilityZoneToRegionMap,
|
Set<? extends Location> provideLocations(Map<String, String> availabilityZoneToRegionMap,
|
||||||
@Provider String providerName) {
|
@Provider String providerName) {
|
||||||
Location ec2 = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null);
|
Location ec2 = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null);
|
||||||
Set<Location> locations = Sets.newLinkedHashSet();
|
Set<Location> locations = newLinkedHashSet();
|
||||||
for (String region : Sets.newLinkedHashSet(availabilityZoneToRegionMap.values())) {
|
for (String region : newLinkedHashSet(availabilityZoneToRegionMap.values())) {
|
||||||
locations.add(new LocationImpl(LocationScope.REGION, region, region, ec2));
|
locations.add(new LocationImpl(LocationScope.REGION, region, region, ec2));
|
||||||
}
|
}
|
||||||
ImmutableMap<String, Location> idToLocation = Maps.uniqueIndex(locations, new Function<Location, String>() {
|
ImmutableMap<String, Location> idToLocation = uniqueIndex(locations, new Function<Location, String>() {
|
||||||
@Override
|
@Override
|
||||||
public String apply(Location from) {
|
public String apply(Location from) {
|
||||||
return from.getId();
|
return from.getId();
|
||||||
|
@ -391,7 +395,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
|
||||||
String[] amiOwners(@Named(PROPERTY_EC2_AMI_OWNERS) String amiOwners) {
|
String[] amiOwners(@Named(PROPERTY_EC2_AMI_OWNERS) String amiOwners) {
|
||||||
if (amiOwners.trim().equals(""))
|
if (amiOwners.trim().equals(""))
|
||||||
return new String[] {};
|
return new String[] {};
|
||||||
return Iterables.toArray(Splitter.on(',').split(amiOwners), String.class);
|
return toArray(Splitter.on(',').split(amiOwners), String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
@ -400,7 +404,7 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
|
||||||
String[] ccAmis(@Named(PROPERTY_EC2_CC_AMIs) String ccAmis) {
|
String[] ccAmis(@Named(PROPERTY_EC2_CC_AMIs) String ccAmis) {
|
||||||
if (ccAmis.trim().equals(""))
|
if (ccAmis.trim().equals(""))
|
||||||
return new String[] {};
|
return new String[] {};
|
||||||
return Iterables.toArray(Splitter.on(',').split(ccAmis), String.class);
|
return toArray(Splitter.on(',').split(ccAmis), String.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
@ -416,54 +420,62 @@ public class EC2ComputeServiceContextModule extends AbstractModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Map<RegionAndName, ? extends Image> provideImages(final EC2Client sync,
|
protected Map<RegionAndName, ? extends Image> provideImages(@Region Map<String, URI> regionMap,
|
||||||
@Region Map<String, URI> regionMap, final LogHolder holder, Function<ComputeMetadata, String> indexer,
|
DescribeImagesParallel describer, LogHolder holder, @Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis,
|
||||||
@Named(PROPERTY_EC2_CC_AMIs) String[] ccAmis, @Named(PROPERTY_EC2_AMI_OWNERS) final String[] amiOwners,
|
@Named(PROPERTY_EC2_AMI_OWNERS) final String[] amiOwners, final ImageParser parser,
|
||||||
final ImageParser parser, final ConcurrentMap<RegionAndName, Image> images,
|
final ConcurrentMap<RegionAndName, Image> images) throws InterruptedException, ExecutionException,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) throws InterruptedException,
|
TimeoutException {
|
||||||
ExecutionException, TimeoutException {
|
|
||||||
if (amiOwners.length == 0) {
|
if (amiOwners.length == 0) {
|
||||||
holder.logger.debug(">> no owners specified, skipping image parsing");
|
holder.logger.debug(">> no owners specified, skipping image parsing");
|
||||||
} else {
|
} else {
|
||||||
holder.logger.debug(">> providing images");
|
holder.logger.debug(">> providing images");
|
||||||
|
|
||||||
Map<String, ListenableFuture<?>> parallelResponses = Maps.newHashMap();
|
Iterable<Entry<String, DescribeImagesOptions>> queries = concat(getDescribeQueriesForOwnersInRegions(
|
||||||
final DescribeImagesOptions options;
|
regionMap, amiOwners).entrySet(), ccAmisToDescribeQueries(ccAmis).entrySet());
|
||||||
if (amiOwners.length == 1 && amiOwners[0].equals("*"))
|
|
||||||
options = new DescribeImagesOptions();
|
Iterable<? extends Image> parsedImages = filter(transform(describer.apply(queries), parser), Predicates
|
||||||
else
|
.notNull());
|
||||||
options = ownedBy(amiOwners);
|
|
||||||
for (final String region : regionMap.keySet()) {
|
images.putAll(Maps.uniqueIndex(parsedImages, new Function<Image, RegionAndName>() {
|
||||||
parallelResponses.put(region, ConcurrentUtils.makeListenable(executor.submit(new Callable<Void>() {
|
|
||||||
@Override
|
@Override
|
||||||
public Void call() throws Exception {
|
public RegionAndName apply(Image from) {
|
||||||
Set<org.jclouds.aws.ec2.domain.Image> matchingImages = sync.getAMIServices().describeImagesInRegion(
|
return new RegionAndName(from.getLocation().getId(), from.getProviderId());
|
||||||
region, options);
|
}
|
||||||
for (final org.jclouds.aws.ec2.domain.Image from : matchingImages) {
|
|
||||||
Image image = parser.apply(from);
|
}));
|
||||||
if (image != null)
|
|
||||||
images.put(new RegionAndName(region, image.getProviderId()), image);
|
|
||||||
else if (from.getImageType() == ImageType.MACHINE)
|
|
||||||
holder.logger.trace("<< image(%s) didn't parse", from.getId());
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}), executor));
|
|
||||||
}
|
|
||||||
Map<String, Exception> exceptions = awaitCompletion(parallelResponses, executor, null, holder.logger, "images");
|
|
||||||
for (String ccAmi : ccAmis) {
|
|
||||||
String region = ccAmi.split("/")[0];
|
|
||||||
org.jclouds.aws.ec2.domain.Image from = Iterables.getOnlyElement(sync.getAMIServices()
|
|
||||||
.describeImagesInRegion(region, imageIds(ccAmi.split("/")[1])));
|
|
||||||
Image image = parser.apply(from);
|
|
||||||
if (image != null)
|
|
||||||
images.put(new RegionAndName(region, image.getProviderId()), image);
|
|
||||||
}
|
|
||||||
if (exceptions.size() > 0)
|
|
||||||
throw new RuntimeException(String.format("error parsing images in regions: %s", exceptions));
|
|
||||||
|
|
||||||
holder.logger.debug("<< images(%d)", images.size());
|
holder.logger.debug("<< images(%d)", images.size());
|
||||||
}
|
}
|
||||||
return images;
|
return images;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private Map<String, DescribeImagesOptions> ccAmisToDescribeQueries(String[] ccAmis) {
|
||||||
|
Map<String, DescribeImagesOptions> queries = Maps.newLinkedHashMap();
|
||||||
|
for (String from : ccAmis) {
|
||||||
|
queries.put(from.split("/")[0], imageIds(from.split("/")[1]));
|
||||||
|
}
|
||||||
|
return queries;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, DescribeImagesOptions> getDescribeQueriesForOwnersInRegions(Map<String, URI> regionMap,
|
||||||
|
final String[] amiOwners) {
|
||||||
|
final DescribeImagesOptions options = getOptionsForOwners(amiOwners);
|
||||||
|
|
||||||
|
return Maps.transformValues(regionMap, new Function<URI, DescribeImagesOptions>() {
|
||||||
|
@Override
|
||||||
|
public DescribeImagesOptions apply(URI from) {
|
||||||
|
return options;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
private DescribeImagesOptions getOptionsForOwners(final String[] amiOwners) {
|
||||||
|
final DescribeImagesOptions options;
|
||||||
|
if (amiOwners.length == 1 && amiOwners[0].equals("*"))
|
||||||
|
options = new DescribeImagesOptions();
|
||||||
|
else
|
||||||
|
options = ownedBy(amiOwners);
|
||||||
|
return options;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -49,9 +49,9 @@ public class EC2TemplateBuilderImpl extends TemplateBuilderImpl {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected EC2TemplateBuilderImpl(Provider<Set<? extends Location>> locations, Provider<Set<? extends Image>> images,
|
protected EC2TemplateBuilderImpl(Provider<Set<? extends Location>> locations, Provider<Set<? extends Image>> images,
|
||||||
Provider<Set<? extends Size>> sizes, Location defaultLocation, Provider<TemplateOptions> optionsProvider,
|
Provider<Set<? extends Size>> sizes, Location defaultLocation, Provider<TemplateOptions> optionsProvider,
|
||||||
@Named("DEFAULT") Provider<TemplateBuilder> defaultTemplateProvider,
|
@Named("DEFAULT") Provider<TemplateBuilder> defaultTemplateProvider,
|
||||||
ConcurrentMap<RegionAndName, Image> imageMap) {
|
ConcurrentMap<RegionAndName, Image> imageMap) {
|
||||||
super(locations, images, sizes, defaultLocation, optionsProvider, defaultTemplateProvider);
|
super(locations, images, sizes, defaultLocation, optionsProvider, defaultTemplateProvider);
|
||||||
this.imageMap = imageMap;
|
this.imageMap = imageMap;
|
||||||
}
|
}
|
||||||
|
@ -80,7 +80,8 @@ public class EC2TemplateBuilderImpl extends TemplateBuilderImpl {
|
||||||
if (imageId != null) {
|
if (imageId != null) {
|
||||||
String[] regionName = imageId.split("/");
|
String[] regionName = imageId.split("/");
|
||||||
checkArgument(regionName.length == 2,
|
checkArgument(regionName.length == 2,
|
||||||
"amazon image ids must include the region. ex. us-east-1/ami-7ea24a17");
|
"amazon image ids must include the region ( ex. us-east-1/ami-7ea24a17 ) you specified: "
|
||||||
|
+ imageId);
|
||||||
RegionAndName key = new RegionAndName(regionName[0], regionName[1]);
|
RegionAndName key = new RegionAndName(regionName[0], regionName[1]);
|
||||||
try {
|
try {
|
||||||
return imageMap.get(key);
|
return imageMap.get(key);
|
||||||
|
|
|
@ -0,0 +1,79 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2009 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed 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.aws.ec2.compute.strategy;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Iterables.concat;
|
||||||
|
import static org.jclouds.concurrent.ConcurrentUtils.transformParallel;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
import java.util.Map.Entry;
|
||||||
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.aws.ec2.EC2AsyncClient;
|
||||||
|
import org.jclouds.aws.ec2.options.DescribeImagesOptions;
|
||||||
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class DescribeImagesParallel implements
|
||||||
|
Function<Iterable<Entry<String, DescribeImagesOptions>>, Iterable<? extends org.jclouds.aws.ec2.domain.Image>> {
|
||||||
|
@Resource
|
||||||
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
protected final EC2AsyncClient sync;
|
||||||
|
final ExecutorService executor;
|
||||||
|
|
||||||
|
@Inject
|
||||||
|
public DescribeImagesParallel(EC2AsyncClient sync, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
|
super();
|
||||||
|
this.sync = sync;
|
||||||
|
this.executor = executor;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Iterable<? extends org.jclouds.aws.ec2.domain.Image> apply(
|
||||||
|
Iterable<Entry<String, DescribeImagesOptions>> queries) {
|
||||||
|
return concat(transformParallel(
|
||||||
|
queries,
|
||||||
|
new Function<Entry<String, DescribeImagesOptions>, Future<Set<? extends org.jclouds.aws.ec2.domain.Image>>>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Future<Set<? extends org.jclouds.aws.ec2.domain.Image>> apply(
|
||||||
|
Entry<String, DescribeImagesOptions> from) {
|
||||||
|
return sync.getAMIServices().describeImagesInRegion(from.getKey(), from.getValue());
|
||||||
|
}
|
||||||
|
|
||||||
|
}, executor, null, logger, "amis"));
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -27,6 +27,7 @@ import static org.jclouds.aws.ec2.compute.util.EC2ComputeUtils.instanceToId;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -48,7 +49,6 @@ import org.jclouds.logging.Logger;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates futures that correlate to
|
* creates futures that correlate to
|
||||||
|
@ -56,8 +56,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class EC2RunNodesAndAddToSetStrategy implements
|
public class EC2RunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrategy {
|
||||||
RunNodesAndAddToSetStrategy {
|
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
|
@ -76,11 +75,10 @@ public class EC2RunNodesAndAddToSetStrategy implements
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
EC2RunNodesAndAddToSetStrategy(
|
EC2RunNodesAndAddToSetStrategy(
|
||||||
EC2Client client,
|
EC2Client client,
|
||||||
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions,
|
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions,
|
||||||
@Named("PRESENT") Predicate<RunningInstance> instancePresent,
|
@Named("PRESENT") Predicate<RunningInstance> instancePresent,
|
||||||
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata,
|
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata, ComputeUtils utils) {
|
||||||
ComputeUtils utils) {
|
|
||||||
this.client = client;
|
this.client = client;
|
||||||
this.instancePresent = instancePresent;
|
this.instancePresent = instancePresent;
|
||||||
this.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
|
this.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
|
||||||
|
@ -89,12 +87,11 @@ public class EC2RunNodesAndAddToSetStrategy implements
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<?, ListenableFuture<Void>> execute(String tag, int count,
|
public Map<?, Future<Void>> execute(String tag, int count, Template template, Set<NodeMetadata> goodNodes,
|
||||||
Template template, Set<NodeMetadata> goodNodes,
|
Map<NodeMetadata, Exception> badNodes) {
|
||||||
Map<NodeMetadata, Exception> badNodes) {
|
|
||||||
|
|
||||||
Reservation reservation = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(
|
Reservation<? extends RunningInstance> reservation = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(tag,
|
||||||
tag, count, template);
|
count, template);
|
||||||
|
|
||||||
Iterable<String> ids = transform(reservation, instanceToId);
|
Iterable<String> ids = transform(reservation, instanceToId);
|
||||||
|
|
||||||
|
@ -104,28 +101,25 @@ public class EC2RunNodesAndAddToSetStrategy implements
|
||||||
all(reservation, instancePresent);
|
all(reservation, instancePresent);
|
||||||
logger.debug("<< present instances(%s)", idsString);
|
logger.debug("<< present instances(%s)", idsString);
|
||||||
|
|
||||||
return utils.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(
|
return utils.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(template.getOptions(), transform(
|
||||||
template.getOptions(), transform(reservation,
|
reservation, runningInstanceToNodeMetadata), goodNodes, badNodes);
|
||||||
runningInstanceToNodeMetadata), goodNodes, badNodes);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
Reservation createKeyPairAndSecurityGroupsAsNeededThenRunInstances(
|
Reservation<? extends RunningInstance> createKeyPairAndSecurityGroupsAsNeededThenRunInstances(String tag, int count,
|
||||||
String tag, int count, Template template) {
|
Template template) {
|
||||||
String region = getRegionFromLocationOrNull(template.getLocation());
|
String region = getRegionFromLocationOrNull(template.getLocation());
|
||||||
String zone = getZoneFromLocationOrNull(template.getLocation());
|
String zone = getZoneFromLocationOrNull(template.getLocation());
|
||||||
|
|
||||||
RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions
|
RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.execute(region,
|
||||||
.execute(region, tag, template);
|
tag, template);
|
||||||
|
|
||||||
if (logger.isDebugEnabled())
|
if (logger.isDebugEnabled())
|
||||||
logger.debug(
|
logger.debug(">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", count, region, zone, template
|
||||||
">> running %d instance region(%s) zone(%s) ami(%s) params(%s)",
|
.getImage().getProviderId(), instanceOptions.buildFormParameters());
|
||||||
count, region, zone, template.getImage().getProviderId(),
|
|
||||||
instanceOptions.buildFormParameters());
|
|
||||||
|
|
||||||
return client.getInstanceServices().runInstancesInRegion(region, zone,
|
return client.getInstanceServices().runInstancesInRegion(region, zone, template.getImage().getProviderId(), 1,
|
||||||
template.getImage().getProviderId(), 1, count, instanceOptions);
|
count, instanceOptions);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -33,8 +33,8 @@ import com.google.inject.internal.Nullable;
|
||||||
* />
|
* />
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class Reservation extends LinkedHashSet<RunningInstance> implements Comparable<Reservation>,
|
public class Reservation<T extends RunningInstance> extends LinkedHashSet<T> implements Comparable<Reservation<T>>,
|
||||||
Set<RunningInstance> {
|
Set<T> {
|
||||||
|
|
||||||
/** The serialVersionUID */
|
/** The serialVersionUID */
|
||||||
private static final long serialVersionUID = -9051777593518861395L;
|
private static final long serialVersionUID = -9051777593518861395L;
|
||||||
|
@ -47,9 +47,8 @@ public class Reservation extends LinkedHashSet<RunningInstance> implements Compa
|
||||||
private final @Nullable
|
private final @Nullable
|
||||||
String reservationId;
|
String reservationId;
|
||||||
|
|
||||||
public Reservation(String region, Iterable<String> groupIds,
|
public Reservation(String region, Iterable<String> groupIds, Iterable<T> instances,
|
||||||
Iterable<RunningInstance> instances, @Nullable String ownerId,
|
@Nullable String ownerId, @Nullable String requesterId, @Nullable String reservationId) {
|
||||||
@Nullable String requesterId, @Nullable String reservationId) {
|
|
||||||
this.region = checkNotNull(region, "region");
|
this.region = checkNotNull(region, "region");
|
||||||
Iterables.addAll(this.groupIds, checkNotNull(groupIds, "groupIds"));
|
Iterables.addAll(this.groupIds, checkNotNull(groupIds, "groupIds"));
|
||||||
Iterables.addAll(this, checkNotNull(instances, "instances"));
|
Iterables.addAll(this, checkNotNull(instances, "instances"));
|
||||||
|
@ -65,7 +64,7 @@ public class Reservation extends LinkedHashSet<RunningInstance> implements Compa
|
||||||
return region;
|
return region;
|
||||||
}
|
}
|
||||||
|
|
||||||
public int compareTo(Reservation o) {
|
public int compareTo(Reservation<T> o) {
|
||||||
return (this == o) ? 0 : getReservationId().compareTo(o.getReservationId());
|
return (this == o) ? 0 : getReservationId().compareTo(o.getReservationId());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -117,7 +116,7 @@ public class Reservation extends LinkedHashSet<RunningInstance> implements Compa
|
||||||
return false;
|
return false;
|
||||||
if (getClass() != obj.getClass())
|
if (getClass() != obj.getClass())
|
||||||
return false;
|
return false;
|
||||||
Reservation other = (Reservation) obj;
|
Reservation<?> other = (Reservation<?>) obj;
|
||||||
if (groupIds == null) {
|
if (groupIds == null) {
|
||||||
if (other.groupIds != null)
|
if (other.groupIds != null)
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -32,7 +32,7 @@ import org.jclouds.aws.ec2.options.internal.BaseEC2RequestOptions;
|
||||||
* import static org.jclouds.aws.ec2.options.CreateImageOptions.Builder.*
|
* import static org.jclouds.aws.ec2.options.CreateImageOptions.Builder.*
|
||||||
* <p/>
|
* <p/>
|
||||||
* EC2Client connection = // get connection
|
* EC2Client connection = // get connection
|
||||||
* ListenableFuture<Set<ImageMetadata>> images = connection.getAMIServices().createImage(withDescription("123125").noReboot());
|
* Future<Set<ImageMetadata>> images = connection.getAMIServices().createImage(withDescription("123125").noReboot());
|
||||||
* <code>
|
* <code>
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
|
|
@ -33,7 +33,7 @@ import org.jclouds.aws.ec2.options.internal.BaseEC2RequestOptions;
|
||||||
* import static org.jclouds.aws.ec2.options.DescribeAvailabilityZonesOptions.Builder.*
|
* import static org.jclouds.aws.ec2.options.DescribeAvailabilityZonesOptions.Builder.*
|
||||||
* <p/>
|
* <p/>
|
||||||
* EC2Client connection = // get connection
|
* EC2Client connection = // get connection
|
||||||
* ListenableFuture<Set<ImageMetadata>> images = connection.getAvailabilityZoneAndRegionServices().describeAvailabilityZones(zones("us-east-1a", "us-east-1b"));
|
* Future<Set<ImageMetadata>> images = connection.getAvailabilityZoneAndRegionServices().describeAvailabilityZones(zones("us-east-1a", "us-east-1b"));
|
||||||
* <code>
|
* <code>
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
|
|
@ -34,7 +34,7 @@ import org.jclouds.aws.ec2.options.internal.BaseEC2RequestOptions;
|
||||||
* import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.*
|
* import static org.jclouds.aws.ec2.options.DescribeImagesOptions.Builder.*
|
||||||
* <p/>
|
* <p/>
|
||||||
* EC2Client connection = // get connection
|
* EC2Client connection = // get connection
|
||||||
* ListenableFuture<Set<ImageMetadata>> images = connection.getAMIServices().describeImages(executableBy("123125").imageIds(1000, 1004));
|
* Future<Set<ImageMetadata>> images = connection.getAMIServices().describeImages(executableBy("123125").imageIds(1000, 1004));
|
||||||
* <code>
|
* <code>
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
|
|
@ -34,7 +34,7 @@ import org.jclouds.aws.ec2.options.internal.BaseEC2RequestOptions;
|
||||||
* import static org.jclouds.aws.ec2.options.DescribeRegionsOptions.Builder.*
|
* import static org.jclouds.aws.ec2.options.DescribeRegionsOptions.Builder.*
|
||||||
* <p/>
|
* <p/>
|
||||||
* EC2Client connection = // get connection
|
* EC2Client connection = // get connection
|
||||||
* ListenableFuture<Set<ImageMetadata>> images = connection.getRegionsAndRegionsServices().describeRegions(regions("us-east-1a", "us-east-1b"));
|
* Future<Set<ImageMetadata>> images = connection.getRegionsAndRegionsServices().describeRegions(regions("us-east-1a", "us-east-1b"));
|
||||||
* <code>
|
* <code>
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
|
|
@ -35,7 +35,7 @@ import org.jclouds.encryption.internal.Base64;
|
||||||
* import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.*
|
* import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.*
|
||||||
* <p/>
|
* <p/>
|
||||||
* EC2Client connection = // get connection
|
* EC2Client connection = // get connection
|
||||||
* ListenableFuture<ReservationInfo> instances = connection.runInstances(executableBy("123125").imageIds(1000, 1004));
|
* Future<ReservationInfo> instances = connection.runInstances(executableBy("123125").imageIds(1000, 1004));
|
||||||
* <code>
|
* <code>
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
|
|
@ -23,6 +23,7 @@ import static org.jclouds.aws.ec2.reference.EC2Parameters.VERSION;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.ws.rs.FormParam;
|
import javax.ws.rs.FormParam;
|
||||||
|
@ -56,8 +57,6 @@ import org.jclouds.rest.annotations.VirtualHost;
|
||||||
import org.jclouds.rest.annotations.XMLResponseParser;
|
import org.jclouds.rest.annotations.XMLResponseParser;
|
||||||
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to AMI Services.
|
* Provides access to AMI Services.
|
||||||
* <p/>
|
* <p/>
|
||||||
|
@ -77,7 +76,7 @@ public interface AMIAsyncClient {
|
||||||
@FormParams(keys = ACTION, values = "DescribeImages")
|
@FormParams(keys = ACTION, values = "DescribeImages")
|
||||||
@XMLResponseParser(DescribeImagesResponseHandler.class)
|
@XMLResponseParser(DescribeImagesResponseHandler.class)
|
||||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
ListenableFuture<? extends Set<Image>> describeImagesInRegion(
|
ListenableFuture<Set<? extends Image>> describeImagesInRegion(
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region, DescribeImagesOptions... options);
|
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region, DescribeImagesOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -87,9 +86,8 @@ public interface AMIAsyncClient {
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = ACTION, values = "CreateImage")
|
@FormParams(keys = ACTION, values = "CreateImage")
|
||||||
@XMLResponseParser(ImageIdHandler.class)
|
@XMLResponseParser(ImageIdHandler.class)
|
||||||
ListenableFuture<String> createImageInRegion(
|
ListenableFuture<String> createImageInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region, @FormParam("Name") String name,
|
@FormParam("Name") String name, @FormParam("InstanceId") String instanceId, CreateImageOptions... options);
|
||||||
@FormParam("InstanceId") String instanceId, CreateImageOptions... options);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see AMIClient#deregisterImageInRegion
|
* @see AMIClient#deregisterImageInRegion
|
||||||
|
@ -97,8 +95,7 @@ public interface AMIAsyncClient {
|
||||||
@POST
|
@POST
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = ACTION, values = "DeregisterImage")
|
@FormParams(keys = ACTION, values = "DeregisterImage")
|
||||||
ListenableFuture<Void> deregisterImageInRegion(
|
ListenableFuture<Void> deregisterImageInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
|
||||||
@FormParam("ImageId") String imageId);
|
@FormParam("ImageId") String imageId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -181,7 +178,7 @@ public interface AMIAsyncClient {
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeImageAttribute", "productCodes" })
|
@FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeImageAttribute", "productCodes" })
|
||||||
@XMLResponseParser(ProductCodesHandler.class)
|
@XMLResponseParser(ProductCodesHandler.class)
|
||||||
ListenableFuture<? extends Set<String>> getProductCodesForImageInRegion(
|
ListenableFuture<Set<String>> getProductCodesForImageInRegion(
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@FormParam("ImageId") String imageId);
|
@FormParam("ImageId") String imageId);
|
||||||
|
|
||||||
|
@ -192,7 +189,7 @@ public interface AMIAsyncClient {
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeImageAttribute", "blockDeviceMapping" })
|
@FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeImageAttribute", "blockDeviceMapping" })
|
||||||
@XMLResponseParser(BlockDeviceMappingHandler.class)
|
@XMLResponseParser(BlockDeviceMappingHandler.class)
|
||||||
ListenableFuture<? extends Map<String, EbsBlockDevice>> getBlockDeviceMappingsForImageInRegion(
|
ListenableFuture<Map<String, EbsBlockDevice>> getBlockDeviceMappingsForImageInRegion(
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@FormParam("ImageId") String imageId);
|
@FormParam("ImageId") String imageId);
|
||||||
|
|
||||||
|
@ -203,8 +200,7 @@ public interface AMIAsyncClient {
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = { ACTION, "OperationType", "Attribute" }, values = { "ModifyImageAttribute", "add",
|
@FormParams(keys = { ACTION, "OperationType", "Attribute" }, values = { "ModifyImageAttribute", "add",
|
||||||
"productCodes" })
|
"productCodes" })
|
||||||
ListenableFuture<Void> addProductCodesToImageInRegion(
|
ListenableFuture<Void> addProductCodesToImageInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
|
||||||
@BinderParam(BindProductCodesToIndexedFormParams.class) Iterable<String> productCodes,
|
@BinderParam(BindProductCodesToIndexedFormParams.class) Iterable<String> productCodes,
|
||||||
@FormParam("ImageId") String imageId);
|
@FormParam("ImageId") String imageId);
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ public interface AMIClient {
|
||||||
* @see DescribeImagesOptions
|
* @see DescribeImagesOptions
|
||||||
*/
|
*/
|
||||||
@Timeout(duration = 300, timeUnit = TimeUnit.SECONDS)
|
@Timeout(duration = 300, timeUnit = TimeUnit.SECONDS)
|
||||||
Set<Image> describeImagesInRegion(@Nullable String region, DescribeImagesOptions... options);
|
Set<? extends Image> describeImagesInRegion(@Nullable String region, DescribeImagesOptions... options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the Product Codes of an image.
|
* Returns the Product Codes of an image.
|
||||||
|
|
|
@ -23,6 +23,7 @@ import static org.jclouds.aws.ec2.reference.EC2Parameters.VERSION;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.ws.rs.FormParam;
|
import javax.ws.rs.FormParam;
|
||||||
|
@ -61,8 +62,6 @@ import org.jclouds.rest.annotations.VirtualHost;
|
||||||
import org.jclouds.rest.annotations.XMLResponseParser;
|
import org.jclouds.rest.annotations.XMLResponseParser;
|
||||||
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
import org.jclouds.rest.functions.ReturnEmptySetOnNotFoundOr404;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to EC2 Instance Services via their REST API.
|
* Provides access to EC2 Instance Services via their REST API.
|
||||||
* <p/>
|
* <p/>
|
||||||
|
@ -82,7 +81,7 @@ public interface InstanceAsyncClient {
|
||||||
@FormParams(keys = ACTION, values = "DescribeInstances")
|
@FormParams(keys = ACTION, values = "DescribeInstances")
|
||||||
@XMLResponseParser(DescribeInstancesResponseHandler.class)
|
@XMLResponseParser(DescribeInstancesResponseHandler.class)
|
||||||
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
@ExceptionParser(ReturnEmptySetOnNotFoundOr404.class)
|
||||||
ListenableFuture<? extends Set<Reservation>> describeInstancesInRegion(
|
ListenableFuture<Set<? extends Reservation<? extends RunningInstance>>> describeInstancesInRegion(
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
||||||
|
|
||||||
|
@ -93,8 +92,7 @@ public interface InstanceAsyncClient {
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = ACTION, values = "RunInstances")
|
@FormParams(keys = ACTION, values = "RunInstances")
|
||||||
@XMLResponseParser(RunInstancesResponseHandler.class)
|
@XMLResponseParser(RunInstancesResponseHandler.class)
|
||||||
ListenableFuture<Reservation> runInstancesInRegion(
|
ListenableFuture<Reservation<? extends RunningInstance>> runInstancesInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
|
||||||
@Nullable @BinderParam(IfNotNullBindAvailabilityZoneToFormParam.class) String nullableAvailabilityZone,
|
@Nullable @BinderParam(IfNotNullBindAvailabilityZoneToFormParam.class) String nullableAvailabilityZone,
|
||||||
@FormParam("ImageId") String imageId, @FormParam("MinCount") int minCount,
|
@FormParam("ImageId") String imageId, @FormParam("MinCount") int minCount,
|
||||||
@FormParam("MaxCount") int maxCount, RunInstancesOptions... options);
|
@FormParam("MaxCount") int maxCount, RunInstancesOptions... options);
|
||||||
|
@ -105,8 +103,7 @@ public interface InstanceAsyncClient {
|
||||||
@POST
|
@POST
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = ACTION, values = "RebootInstances")
|
@FormParams(keys = ACTION, values = "RebootInstances")
|
||||||
ListenableFuture<Void> rebootInstancesInRegion(
|
ListenableFuture<Void> rebootInstancesInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
|
||||||
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -116,7 +113,7 @@ public interface InstanceAsyncClient {
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = ACTION, values = "TerminateInstances")
|
@FormParams(keys = ACTION, values = "TerminateInstances")
|
||||||
@XMLResponseParser(InstanceStateChangeHandler.class)
|
@XMLResponseParser(InstanceStateChangeHandler.class)
|
||||||
ListenableFuture<? extends Set<InstanceStateChange>> terminateInstancesInRegion(
|
ListenableFuture<Set<? extends InstanceStateChange>> terminateInstancesInRegion(
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
||||||
|
|
||||||
|
@ -127,7 +124,7 @@ public interface InstanceAsyncClient {
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = ACTION, values = "StopInstances")
|
@FormParams(keys = ACTION, values = "StopInstances")
|
||||||
@XMLResponseParser(InstanceStateChangeHandler.class)
|
@XMLResponseParser(InstanceStateChangeHandler.class)
|
||||||
ListenableFuture<? extends Set<InstanceStateChange>> stopInstancesInRegion(
|
ListenableFuture<Set<? extends InstanceStateChange>> stopInstancesInRegion(
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region, @FormParam("Force") boolean force,
|
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region, @FormParam("Force") boolean force,
|
||||||
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
||||||
|
|
||||||
|
@ -138,7 +135,7 @@ public interface InstanceAsyncClient {
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = ACTION, values = "StartInstances")
|
@FormParams(keys = ACTION, values = "StartInstances")
|
||||||
@XMLResponseParser(InstanceStateChangeHandler.class)
|
@XMLResponseParser(InstanceStateChangeHandler.class)
|
||||||
ListenableFuture<? extends Set<InstanceStateChange>> startInstancesInRegion(
|
ListenableFuture<Set<? extends InstanceStateChange>> startInstancesInRegion(
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
|
||||||
|
|
||||||
|
@ -182,8 +179,7 @@ public interface InstanceAsyncClient {
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "kernel" })
|
@FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "kernel" })
|
||||||
@XMLResponseParser(StringValueHandler.class)
|
@XMLResponseParser(StringValueHandler.class)
|
||||||
ListenableFuture<String> getKernelForInstanceInRegion(
|
ListenableFuture<String> getKernelForInstanceInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
|
||||||
@FormParam("InstanceId") String instanceId);
|
@FormParam("InstanceId") String instanceId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -247,8 +243,7 @@ public interface InstanceAsyncClient {
|
||||||
@POST
|
@POST
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = { ACTION, "Attribute" }, values = { "ResetInstanceAttribute", "kernel" })
|
@FormParams(keys = { ACTION, "Attribute" }, values = { "ResetInstanceAttribute", "kernel" })
|
||||||
ListenableFuture<Void> resetKernelForInstanceInRegion(
|
ListenableFuture<Void> resetKernelForInstanceInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
|
||||||
@FormParam("InstanceId") String instanceId);
|
@FormParam("InstanceId") String instanceId);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -257,8 +252,7 @@ public interface InstanceAsyncClient {
|
||||||
@POST
|
@POST
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "userData" })
|
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "userData" })
|
||||||
ListenableFuture<Void> setUserDataForInstanceInRegion(
|
ListenableFuture<Void> setUserDataForInstanceInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
|
||||||
@FormParam("InstanceId") String instanceId,
|
@FormParam("InstanceId") String instanceId,
|
||||||
@FormParam("Value") @ParamParser(ConvertUnencodedBytesToBase64EncodedString.class) byte[] unencodedData);
|
@FormParam("Value") @ParamParser(ConvertUnencodedBytesToBase64EncodedString.class) byte[] unencodedData);
|
||||||
|
|
||||||
|
@ -268,8 +262,7 @@ public interface InstanceAsyncClient {
|
||||||
@POST
|
@POST
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "ramdisk" })
|
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "ramdisk" })
|
||||||
ListenableFuture<Void> setRamdiskForInstanceInRegion(
|
ListenableFuture<Void> setRamdiskForInstanceInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
|
||||||
@FormParam("InstanceId") String instanceId, @FormParam("Value") String ramdisk);
|
@FormParam("InstanceId") String instanceId, @FormParam("Value") String ramdisk);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -278,8 +271,7 @@ public interface InstanceAsyncClient {
|
||||||
@POST
|
@POST
|
||||||
@Path("/")
|
@Path("/")
|
||||||
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "kernel" })
|
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "kernel" })
|
||||||
ListenableFuture<Void> setKernelForInstanceInRegion(
|
ListenableFuture<Void> setKernelForInstanceInRegion(@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
||||||
@EndpointParam(parser = RegionToEndpoint.class) @Nullable String region,
|
|
||||||
@FormParam("InstanceId") String instanceId, @FormParam("Value") String kernel);
|
@FormParam("InstanceId") String instanceId, @FormParam("Value") String kernel);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -61,7 +61,7 @@ public interface InstanceClient {
|
||||||
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html"
|
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html"
|
||||||
* />
|
* />
|
||||||
*/
|
*/
|
||||||
Set<Reservation> describeInstancesInRegion(@Nullable String region,
|
Set<? extends Reservation<? extends RunningInstance>> describeInstancesInRegion(@Nullable String region,
|
||||||
String... instanceIds);
|
String... instanceIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -141,7 +141,7 @@ public interface InstanceClient {
|
||||||
* />
|
* />
|
||||||
* @see RunInstancesOptions
|
* @see RunInstancesOptions
|
||||||
*/
|
*/
|
||||||
Reservation runInstancesInRegion(@Nullable String region,
|
Reservation<? extends RunningInstance> runInstancesInRegion(@Nullable String region,
|
||||||
@Nullable String nullableAvailabilityZone, String imageId,
|
@Nullable String nullableAvailabilityZone, String imageId,
|
||||||
int minCount, int maxCount, RunInstancesOptions... options);
|
int minCount, int maxCount, RunInstancesOptions... options);
|
||||||
|
|
||||||
|
@ -161,7 +161,7 @@ public interface InstanceClient {
|
||||||
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-TerminateInstances.html"
|
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-TerminateInstances.html"
|
||||||
* />
|
* />
|
||||||
*/
|
*/
|
||||||
Set<InstanceStateChange> terminateInstancesInRegion(@Nullable String region,
|
Set<? extends InstanceStateChange> terminateInstancesInRegion(@Nullable String region,
|
||||||
String... instanceIds);
|
String... instanceIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -199,7 +199,7 @@ public interface InstanceClient {
|
||||||
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StopInstances.html"
|
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StopInstances.html"
|
||||||
* />
|
* />
|
||||||
*/
|
*/
|
||||||
Set<InstanceStateChange> stopInstancesInRegion(@Nullable String region,
|
Set<? extends InstanceStateChange> stopInstancesInRegion(@Nullable String region,
|
||||||
boolean force, String... instanceIds);
|
boolean force, String... instanceIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -255,7 +255,7 @@ public interface InstanceClient {
|
||||||
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StartInstances.html"
|
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StartInstances.html"
|
||||||
* />
|
* />
|
||||||
*/
|
*/
|
||||||
Set<InstanceStateChange> startInstancesInRegion(@Nullable String region,
|
Set<? extends InstanceStateChange> startInstancesInRegion(@Nullable String region,
|
||||||
String... instanceIds);
|
String... instanceIds);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -270,11 +270,12 @@ public abstract class BaseReservationHandler<T> extends HandlerForGeneratedReque
|
||||||
currentText.append(ch, start, length);
|
currentText.append(ch, start, length);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Reservation newReservation() {
|
protected Reservation<? extends RunningInstance> newReservation() {
|
||||||
String region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest<?>) request);
|
String region = EC2Utils.findRegionInArgsOrNull((GeneratedHttpRequest<?>) request);
|
||||||
if (region == null)
|
if (region == null)
|
||||||
region = defaultRegion;
|
region = defaultRegion;
|
||||||
Reservation info = new Reservation(region, groupIds, instances, ownerId, requesterId, reservationId);
|
Reservation<? extends RunningInstance> info = new Reservation<RunningInstance>(region, groupIds, instances,
|
||||||
|
ownerId, requesterId, reservationId);
|
||||||
this.groupIds = Sets.newLinkedHashSet();
|
this.groupIds = Sets.newLinkedHashSet();
|
||||||
this.instances = Sets.newLinkedHashSet();
|
this.instances = Sets.newLinkedHashSet();
|
||||||
this.ownerId = null;
|
this.ownerId = null;
|
||||||
|
|
|
@ -24,6 +24,7 @@ import javax.inject.Inject;
|
||||||
|
|
||||||
import org.jclouds.aws.Region;
|
import org.jclouds.aws.Region;
|
||||||
import org.jclouds.aws.ec2.domain.Reservation;
|
import org.jclouds.aws.ec2.domain.Reservation;
|
||||||
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.date.DateService;
|
import org.jclouds.date.DateService;
|
||||||
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
@ -37,8 +38,8 @@ import com.google.common.collect.Sets;
|
||||||
* @see <a href="http: />
|
* @see <a href="http: />
|
||||||
*/
|
*/
|
||||||
public class DescribeInstancesResponseHandler extends
|
public class DescribeInstancesResponseHandler extends
|
||||||
BaseReservationHandler<Set<Reservation>> {
|
BaseReservationHandler<Set<Reservation<? extends RunningInstance>>> {
|
||||||
private Set<Reservation> reservations = Sets.newLinkedHashSet();
|
private Set<Reservation<? extends RunningInstance>> reservations = Sets.newLinkedHashSet();
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
DescribeInstancesResponseHandler(DateService dateService, @Region String defaultRegion) {
|
DescribeInstancesResponseHandler(DateService dateService, @Region String defaultRegion) {
|
||||||
|
@ -46,7 +47,7 @@ public class DescribeInstancesResponseHandler extends
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Reservation> getResult() {
|
public Set<Reservation<? extends RunningInstance>> getResult() {
|
||||||
return reservations;
|
return reservations;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import javax.inject.Inject;
|
||||||
|
|
||||||
import org.jclouds.aws.Region;
|
import org.jclouds.aws.Region;
|
||||||
import org.jclouds.aws.ec2.domain.Reservation;
|
import org.jclouds.aws.ec2.domain.Reservation;
|
||||||
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.date.DateService;
|
import org.jclouds.date.DateService;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -32,7 +33,7 @@ import org.jclouds.date.DateService;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
* @see <a href="http: />
|
* @see <a href="http: />
|
||||||
*/
|
*/
|
||||||
public class RunInstancesResponseHandler extends BaseReservationHandler<Reservation> {
|
public class RunInstancesResponseHandler extends BaseReservationHandler<Reservation<? extends RunningInstance>> {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
RunInstancesResponseHandler(DateService dateService, @Region String defaultRegion) {
|
RunInstancesResponseHandler(DateService dateService, @Region String defaultRegion) {
|
||||||
|
@ -40,7 +41,7 @@ public class RunInstancesResponseHandler extends BaseReservationHandler<Reservat
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Reservation getResult() {
|
public Reservation<? extends RunningInstance> getResult() {
|
||||||
return newReservation();
|
return newReservation();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -38,14 +38,14 @@ import org.jclouds.aws.s3.options.PutObjectOptions;
|
||||||
import org.jclouds.concurrent.Timeout;
|
import org.jclouds.concurrent.Timeout;
|
||||||
import org.jclouds.http.options.GetOptions;
|
import org.jclouds.http.options.GetOptions;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to S3 via their REST API.
|
* Provides access to S3 via their REST API.
|
||||||
* <p/>
|
* <p/>
|
||||||
* All commands return a ListenableFuture of the result from S3. Any exceptions incurred during
|
* All commands return a Future of the result from S3. Any exceptions incurred during
|
||||||
* processing will be wrapped in an {@link ExecutionException} as documented in
|
* processing will be wrapped in an {@link ExecutionException} as documented in
|
||||||
* {@link ListenableFuture#get()}.
|
* {@link Future#get()}.
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
* @author James Murty
|
* @author James Murty
|
||||||
|
@ -85,7 +85,7 @@ public interface S3Client {
|
||||||
* namespace of the object you are retrieving
|
* namespace of the object you are retrieving
|
||||||
* @param key
|
* @param key
|
||||||
* unique key in the s3Bucket identifying the object
|
* unique key in the s3Bucket identifying the object
|
||||||
* @return ListenableFuture reference to a fully populated S3Object including data stored in S3
|
* @return Future reference to a fully populated S3Object including data stored in S3
|
||||||
* or {@link S3Object#NOT_FOUND} if not present.
|
* or {@link S3Object#NOT_FOUND} if not present.
|
||||||
*
|
*
|
||||||
* @throws org.jclouds.http.HttpResponseException
|
* @throws org.jclouds.http.HttpResponseException
|
||||||
|
@ -231,7 +231,7 @@ public interface S3Client {
|
||||||
*
|
*
|
||||||
* @param bucketName
|
* @param bucketName
|
||||||
* namespace of the objects you wish to list
|
* namespace of the objects you wish to list
|
||||||
* @return ListenableFuture reference to a fully populated S3Bucket including metadata of the
|
* @return Future reference to a fully populated S3Bucket including metadata of the
|
||||||
* S3Objects it contains or {@link BoundedList<ObjectMetadata>#NOT_FOUND} if not present.
|
* S3Objects it contains or {@link BoundedList<ObjectMetadata>#NOT_FOUND} if not present.
|
||||||
* @see ListBucketOptions
|
* @see ListBucketOptions
|
||||||
*
|
*
|
||||||
|
|
|
@ -19,10 +19,11 @@
|
||||||
package org.jclouds.aws.s3.blobstore;
|
package org.jclouds.aws.s3.blobstore;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.util.concurrent.Futures.compose;
|
import static org.jclouds.concurrent.ConcurrentUtils.compose;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
@ -60,7 +61,6 @@ import org.jclouds.http.options.GetOptions;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -82,41 +82,34 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
S3AsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
S3AsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Location defaultLocation,
|
||||||
Location defaultLocation, Set<? extends Location> locations, S3AsyncClient async,
|
Set<? extends Location> locations, S3AsyncClient async, S3Client sync,
|
||||||
S3Client sync, BucketToResourceMetadata bucket2ResourceMd,
|
BucketToResourceMetadata bucket2ResourceMd, ContainerToBucketListOptions container2BucketListOptions,
|
||||||
ContainerToBucketListOptions container2BucketListOptions,
|
|
||||||
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,
|
BucketToResourceList bucket2ResourceList, ObjectToBlob object2Blob,
|
||||||
BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object,
|
BlobToHttpGetOptions blob2ObjectGetOptions, BlobToObject blob2Object, ObjectToBlobMetadata object2BlobMd,
|
||||||
ObjectToBlobMetadata object2BlobMd,
|
|
||||||
Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
|
Provider<FetchBlobMetadata> fetchBlobMetadataProvider) {
|
||||||
super(context, blobUtils, service, defaultLocation, locations);
|
super(context, blobUtils, service, defaultLocation, locations);
|
||||||
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
this.blob2ObjectGetOptions = checkNotNull(blob2ObjectGetOptions, "blob2ObjectGetOptions");
|
||||||
this.async = checkNotNull(async, "async");
|
this.async = checkNotNull(async, "async");
|
||||||
this.sync = checkNotNull(sync, "sync");
|
this.sync = checkNotNull(sync, "sync");
|
||||||
this.bucket2ResourceMd = checkNotNull(bucket2ResourceMd, "bucket2ResourceMd");
|
this.bucket2ResourceMd = checkNotNull(bucket2ResourceMd, "bucket2ResourceMd");
|
||||||
this.container2BucketListOptions = checkNotNull(container2BucketListOptions,
|
this.container2BucketListOptions = checkNotNull(container2BucketListOptions, "container2BucketListOptions");
|
||||||
"container2BucketListOptions");
|
|
||||||
this.bucket2ResourceList = checkNotNull(bucket2ResourceList, "bucket2ResourceList");
|
this.bucket2ResourceList = checkNotNull(bucket2ResourceList, "bucket2ResourceList");
|
||||||
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
|
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
|
||||||
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
|
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
|
||||||
this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd");
|
this.object2BlobMd = checkNotNull(object2BlobMd, "object2BlobMd");
|
||||||
this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider,
|
this.fetchBlobMetadataProvider = checkNotNull(fetchBlobMetadataProvider, "fetchBlobMetadataProvider");
|
||||||
"fetchBlobMetadataProvider");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This implementation invokes {@link S3AsyncClient#listOwnedBuckets}
|
* This implementation invokes {@link S3AsyncClient#listOwnedBuckets}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list() {
|
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
|
||||||
return compose(
|
return compose(async.listOwnedBuckets(),
|
||||||
async.listOwnedBuckets(),
|
|
||||||
new Function<Set<BucketMetadata>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
|
new Function<Set<BucketMetadata>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
|
||||||
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(
|
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(Set<BucketMetadata> from) {
|
||||||
Set<BucketMetadata> from) {
|
return new PageSetImpl<StorageMetadata>(Iterables.transform(from, bucket2ResourceMd), null);
|
||||||
return new PageSetImpl<StorageMetadata>(Iterables.transform(from,
|
|
||||||
bucket2ResourceMd), null);
|
|
||||||
}
|
}
|
||||||
}, service);
|
}, service);
|
||||||
}
|
}
|
||||||
|
@ -153,14 +146,13 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
* bucket name
|
* bucket name
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list(String container,
|
// TODO get rid of compose, as it serializes async results when the executor is single-threaded.
|
||||||
ListContainerOptions options) {
|
public ListenableFuture<PageSet<? extends StorageMetadata>> list(String container, ListContainerOptions options) {
|
||||||
ListBucketOptions httpOptions = container2BucketListOptions.apply(options);
|
ListBucketOptions httpOptions = container2BucketListOptions.apply(options);
|
||||||
ListenableFuture<ListBucketResponse> returnVal = async.listBucket(container, httpOptions);
|
ListenableFuture<ListBucketResponse> returnVal = async.listBucket(container, httpOptions);
|
||||||
ListenableFuture<PageSet<? extends StorageMetadata>> list = compose(returnVal,
|
ListenableFuture<PageSet<? extends StorageMetadata>> list = compose(returnVal, bucket2ResourceList, service);
|
||||||
bucket2ResourceList, service);
|
return (options.isDetailed()) ? compose(list, fetchBlobMetadataProvider.get().setContainerName(container),
|
||||||
return options.isDetailed() ? compose(list, fetchBlobMetadataProvider.get().setContainerName(
|
service) : list;
|
||||||
container), service) : list;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -193,15 +185,14 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
|
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
|
||||||
return compose(async.headObject(container, key),
|
return compose(async.headObject(container, key), new Function<ObjectMetadata, BlobMetadata>() {
|
||||||
new Function<ObjectMetadata, BlobMetadata>() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlobMetadata apply(ObjectMetadata from) {
|
public BlobMetadata apply(ObjectMetadata from) {
|
||||||
return object2BlobMd.apply(from);
|
return object2BlobMd.apply(from);
|
||||||
}
|
}
|
||||||
|
|
||||||
}, service);
|
}, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -213,8 +204,7 @@ public class S3AsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
* object key
|
* object key
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Blob> getBlob(String container, String key,
|
public ListenableFuture<Blob> getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions options) {
|
||||||
org.jclouds.blobstore.options.GetOptions options) {
|
|
||||||
GetOptions httpOptions = blob2ObjectGetOptions.apply(options);
|
GetOptions httpOptions = blob2ObjectGetOptions.apply(options);
|
||||||
return compose(async.getObject(container, key, httpOptions), object2Blob, service);
|
return compose(async.getObject(container, key, httpOptions), object2Blob, service);
|
||||||
}
|
}
|
||||||
|
|
|
@ -58,7 +58,7 @@ import com.google.common.collect.Multimap;
|
||||||
* <p/>
|
* <p/>
|
||||||
* // this will copy the object, provided it wasn't modified since yesterday.
|
* // this will copy the object, provided it wasn't modified since yesterday.
|
||||||
* // it will not use metadata from the source, and instead use what we pass in.
|
* // it will not use metadata from the source, and instead use what we pass in.
|
||||||
* ListenableFuture<S3Object.Metadata> object = connection.copyObject("sourceBucket", "objectName",
|
* Future<S3Object.Metadata> object = connection.copyObject("sourceBucket", "objectName",
|
||||||
* "destinationBucket", "destinationName",
|
* "destinationBucket", "destinationName",
|
||||||
* overrideMetadataWith(meta).
|
* overrideMetadataWith(meta).
|
||||||
* ifSourceModifiedSince(new Date().minusDays(1))
|
* ifSourceModifiedSince(new Date().minusDays(1))
|
||||||
|
|
|
@ -33,7 +33,7 @@ import org.jclouds.http.options.BaseHttpRequestOptions;
|
||||||
* import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.*
|
* import static org.jclouds.aws.s3.commands.options.GetBucketOptions.Builder.*
|
||||||
* <p/>
|
* <p/>
|
||||||
* S3Client connection = // get connection
|
* S3Client connection = // get connection
|
||||||
* ListenableFuture<S3Bucket> bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000));
|
* Future<S3Bucket> bucket = connection.listBucket("bucketName",withPrefix("home/users").maxKeys(1000));
|
||||||
* <code>
|
* <code>
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
|
|
@ -46,7 +46,7 @@ import com.google.common.collect.Multimap;
|
||||||
* import org.jclouds.aws.s3.S3Client;
|
* import org.jclouds.aws.s3.S3Client;
|
||||||
* <p/>
|
* <p/>
|
||||||
* S3Client connection = // get connection
|
* S3Client connection = // get connection
|
||||||
* ListenableFuture<Boolean> createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU));
|
* Future<Boolean> createdInEu = connection.putBucketIfNotExists("bucketName",createIn(EU));
|
||||||
* <code>
|
* <code>
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
|
|
@ -46,7 +46,7 @@ import static org.jclouds.aws.reference.AWSConstants.PROPERTY_HEADER_TAG;
|
||||||
* import org.jclouds.aws.s3.S3Client;
|
* import org.jclouds.aws.s3.S3Client;
|
||||||
*
|
*
|
||||||
* S3Client connection = // get connection
|
* S3Client connection = // get connection
|
||||||
* ListenableFuture<Boolean> publicly readable = connection.putObject("bucketName",new S3Object("key","value"), withAcl(CannedAccessPolicy.PUBLIC_READ));
|
* Future<Boolean> publicly readable = connection.putObject("bucketName",new S3Object("key","value"), withAcl(CannedAccessPolicy.PUBLIC_READ));
|
||||||
* <code>
|
* <code>
|
||||||
*
|
*
|
||||||
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectPUT.html?"
|
* @see <a href="http://docs.amazonwebservices.com/AmazonS3/2006-03-01/index.html?RESTObjectPUT.html?"
|
||||||
|
|
|
@ -69,8 +69,7 @@ import com.google.inject.Module;
|
||||||
/**
|
/**
|
||||||
* Follows the book Cloud Application Architectures ISBN: 978-0-596-15636-7
|
* Follows the book Cloud Application Architectures ISBN: 978-0-596-15636-7
|
||||||
* <p/>
|
* <p/>
|
||||||
* adds in functionality to boot a lamp instance:
|
* adds in functionality to boot a lamp instance: http://alestic.com/2009/06/ec2-user-data-scripts
|
||||||
* http://alestic.com/2009/06/ec2-user-data-scripts
|
|
||||||
* <p/>
|
* <p/>
|
||||||
* Generally disabled, as it incurs higher fees.
|
* Generally disabled, as it incurs higher fees.
|
||||||
*
|
*
|
||||||
|
@ -92,49 +91,38 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||||
private RetryablePredicate<RunningInstance> runningTester;
|
private RetryablePredicate<RunningInstance> runningTester;
|
||||||
|
|
||||||
@BeforeGroups(groups = { "live" })
|
@BeforeGroups(groups = { "live" })
|
||||||
public void setupClient() throws InterruptedException, ExecutionException,
|
public void setupClient() throws InterruptedException, ExecutionException, TimeoutException, IOException {
|
||||||
TimeoutException,
|
String identity = checkNotNull(System.getProperty("jclouds.test.identity"), "jclouds.test.identity");
|
||||||
IOException {
|
String credential = checkNotNull(System.getProperty("jclouds.test.credential"), "jclouds.test.credential");
|
||||||
String identity = checkNotNull(System.getProperty("jclouds.test.identity"),
|
Injector injector = new RestContextFactory().createContextBuilder("ec2", identity, credential,
|
||||||
"jclouds.test.identity");
|
ImmutableSet.<Module> of(new Log4JLoggingModule())).buildInjector();
|
||||||
String credential = checkNotNull(System.getProperty("jclouds.test.credential"),
|
|
||||||
"jclouds.test.credential");
|
|
||||||
Injector injector = new RestContextFactory().createContextBuilder(
|
|
||||||
"ec2", identity, credential, ImmutableSet.<Module> of(new Log4JLoggingModule())).buildInjector();
|
|
||||||
client = injector.getInstance(EC2Client.class);
|
client = injector.getInstance(EC2Client.class);
|
||||||
sshFactory = injector.getInstance(SshClient.Factory.class);
|
sshFactory = injector.getInstance(SshClient.Factory.class);
|
||||||
runningTester = new RetryablePredicate<RunningInstance>(
|
runningTester = new RetryablePredicate<RunningInstance>(new InstanceStateRunning(client), 180, 5,
|
||||||
new InstanceStateRunning(client), 180, 5, TimeUnit.SECONDS);
|
TimeUnit.SECONDS);
|
||||||
hasIpTester = new RetryablePredicate<RunningInstance>(
|
hasIpTester = new RetryablePredicate<RunningInstance>(new InstanceHasIpAddress(client), 180, 5, TimeUnit.SECONDS);
|
||||||
new InstanceHasIpAddress(client), 180, 5, TimeUnit.SECONDS);
|
|
||||||
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
|
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
|
||||||
socketTester = new RetryablePredicate<IPSocket>(socketOpen, 180, 1,
|
socketTester = new RetryablePredicate<IPSocket>(socketOpen, 180, 1, TimeUnit.SECONDS);
|
||||||
TimeUnit.SECONDS);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = false)
|
@Test(enabled = false)
|
||||||
void testCreateSecurityGroupIngressCidr() throws InterruptedException,
|
void testCreateSecurityGroupIngressCidr() throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
ExecutionException, TimeoutException {
|
|
||||||
securityGroupName = instancePrefix + "ingress";
|
securityGroupName = instancePrefix + "ingress";
|
||||||
|
|
||||||
try {
|
try {
|
||||||
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null,
|
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName);
|
||||||
securityGroupName);
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
}
|
}
|
||||||
|
|
||||||
client.getSecurityGroupServices().createSecurityGroupInRegion(null,
|
client.getSecurityGroupServices().createSecurityGroupInRegion(null, securityGroupName, securityGroupName);
|
||||||
securityGroupName, securityGroupName);
|
|
||||||
for (int port : new int[] { 80, 443, 22 }) {
|
for (int port : new int[] { 80, 443, 22 }) {
|
||||||
client.getSecurityGroupServices()
|
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, securityGroupName,
|
||||||
.authorizeSecurityGroupIngressInRegion(null, securityGroupName,
|
IpProtocol.TCP, port, port, "0.0.0.0/0");
|
||||||
IpProtocol.TCP, port, port, "0.0.0.0/0");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = false)
|
@Test(enabled = false)
|
||||||
void testCreateKeyPair() throws InterruptedException, ExecutionException,
|
void testCreateKeyPair() throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
TimeoutException {
|
|
||||||
String keyName = instancePrefix + "1";
|
String keyName = instancePrefix + "1";
|
||||||
try {
|
try {
|
||||||
client.getKeyPairServices().deleteKeyPairInRegion(null, keyName);
|
client.getKeyPairServices().deleteKeyPairInRegion(null, keyName);
|
||||||
|
@ -143,41 +131,37 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||||
}
|
}
|
||||||
client.getKeyPairServices().deleteKeyPairInRegion(null, keyName);
|
client.getKeyPairServices().deleteKeyPairInRegion(null, keyName);
|
||||||
|
|
||||||
keyPair = client.getKeyPairServices()
|
keyPair = client.getKeyPairServices().createKeyPairInRegion(null, keyName);
|
||||||
.createKeyPairInRegion(null, keyName);
|
|
||||||
assertNotNull(keyPair);
|
assertNotNull(keyPair);
|
||||||
assertNotNull(keyPair.getKeyMaterial());
|
assertNotNull(keyPair.getKeyMaterial());
|
||||||
assertNotNull(keyPair.getKeyFingerprint());
|
assertNotNull(keyPair.getKeyFingerprint());
|
||||||
assertEquals(keyPair.getKeyName(), keyName);
|
assertEquals(keyPair.getKeyName(), keyName);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = false, dependsOnMethods = { "testCreateKeyPair",
|
@Test(enabled = false, dependsOnMethods = { "testCreateKeyPair", "testCreateSecurityGroupIngressCidr" })
|
||||||
"testCreateSecurityGroupIngressCidr" })
|
|
||||||
public void testCreateRunningInstance() throws Exception {
|
public void testCreateRunningInstance() throws Exception {
|
||||||
String script = new ScriptBuilder() // lamp install script
|
String script = new ScriptBuilder() // lamp install script
|
||||||
.addStatement(exec("runurl run.alestic.com/apt/upgrade"))//
|
.addStatement(exec("runurl run.alestic.com/apt/upgrade"))//
|
||||||
.addStatement(exec("runurl run.alestic.com/install/lamp"))//
|
.addStatement(exec("runurl run.alestic.com/install/lamp"))//
|
||||||
.build(OsFamily.UNIX);
|
.build(OsFamily.UNIX);
|
||||||
|
|
||||||
RunningInstance instance = null;
|
RunningInstance instance = null;
|
||||||
while (instance == null) {
|
while (instance == null) {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
System.out.printf("%d: running instance%n", System
|
System.out.printf("%d: running instance%n", System.currentTimeMillis());
|
||||||
.currentTimeMillis());
|
Reservation<? extends RunningInstance> reservation = client.getInstanceServices().runInstancesInRegion(null, null, // allow
|
||||||
Reservation reservation = client.getInstanceServices()
|
// ec2
|
||||||
.runInstancesInRegion(null, null, // allow
|
// to
|
||||||
// ec2
|
// chose
|
||||||
// to
|
// an
|
||||||
// chose
|
// availability
|
||||||
// an
|
// zone
|
||||||
// availability
|
"ami-ccf615a5", // alestic ami allows auto-invoke of
|
||||||
// zone
|
// user data scripts
|
||||||
"ami-ccf615a5", // alestic ami allows auto-invoke of
|
1, // minimum instances
|
||||||
// user data scripts
|
1, // maximum instances
|
||||||
1, // minimum instances
|
asType(InstanceType.M1_SMALL) // smallest instance size
|
||||||
1, // maximum instances
|
|
||||||
asType(InstanceType.M1_SMALL) // smallest instance size
|
|
||||||
.withKeyName(keyPair.getKeyName()) // key I
|
.withKeyName(keyPair.getKeyName()) // key I
|
||||||
// created
|
// created
|
||||||
// above
|
// above
|
||||||
|
@ -203,51 +187,36 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||||
verifyInstanceProperties(script);
|
verifyInstanceProperties(script);
|
||||||
tryToChangeStuff();
|
tryToChangeStuff();
|
||||||
sshPing(instance);
|
sshPing(instance);
|
||||||
System.out.printf("%d: %s ssh connection made%n", System
|
System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instanceId);
|
||||||
.currentTimeMillis(), instanceId);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyInstanceProperties(String script) {
|
private void verifyInstanceProperties(String script) {
|
||||||
assertEquals(script, client.getInstanceServices()
|
assertEquals(script, client.getInstanceServices().getUserDataForInstanceInRegion(null, instanceId));
|
||||||
.getUserDataForInstanceInRegion(null, instanceId));
|
|
||||||
|
|
||||||
assertEquals(null, client.getInstanceServices()
|
assertEquals(null, client.getInstanceServices().getRootDeviceNameForInstanceInRegion(null, instanceId));
|
||||||
.getRootDeviceNameForInstanceInRegion(null, instanceId));
|
|
||||||
|
|
||||||
assert client.getInstanceServices().getRamdiskForInstanceInRegion(null,
|
assert client.getInstanceServices().getRamdiskForInstanceInRegion(null, instanceId).startsWith("ari-");
|
||||||
instanceId).startsWith("ari-");
|
|
||||||
|
|
||||||
assertEquals(false, client.getInstanceServices()
|
assertEquals(false, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion(null, instanceId));
|
||||||
.isApiTerminationDisabledForInstanceInRegion(null, instanceId));
|
|
||||||
|
|
||||||
assert client.getInstanceServices().getKernelForInstanceInRegion(null,
|
assert client.getInstanceServices().getKernelForInstanceInRegion(null, instanceId).startsWith("aki-");
|
||||||
instanceId).startsWith("aki-");
|
|
||||||
|
|
||||||
assertEquals(InstanceType.M1_SMALL, client.getInstanceServices()
|
assertEquals(InstanceType.M1_SMALL, client.getInstanceServices().getInstanceTypeForInstanceInRegion(null,
|
||||||
.getInstanceTypeForInstanceInRegion(null, instanceId));
|
instanceId));
|
||||||
|
|
||||||
assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client
|
assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client.getInstanceServices()
|
||||||
.getInstanceServices()
|
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, instanceId));
|
||||||
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
|
|
||||||
instanceId));
|
|
||||||
|
|
||||||
assertEquals(ImmutableMap.<String, EbsBlockDevice> of(), client
|
assertEquals(ImmutableMap.<String, EbsBlockDevice> of(), client.getInstanceServices()
|
||||||
.getInstanceServices().getBlockDeviceMappingForInstanceInRegion(
|
.getBlockDeviceMappingForInstanceInRegion(null, instanceId));
|
||||||
null, instanceId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setApiTerminationDisabledForInstanceInRegion() {
|
private void setApiTerminationDisabledForInstanceInRegion() {
|
||||||
client.getInstanceServices()
|
client.getInstanceServices().setApiTerminationDisabledForInstanceInRegion(null, instanceId, true);
|
||||||
.setApiTerminationDisabledForInstanceInRegion(null, instanceId,
|
assertEquals(true, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion(null, instanceId));
|
||||||
true);
|
client.getInstanceServices().setApiTerminationDisabledForInstanceInRegion(null, instanceId, false);
|
||||||
assertEquals(true, client.getInstanceServices()
|
assertEquals(false, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion(null, instanceId));
|
||||||
.isApiTerminationDisabledForInstanceInRegion(null, instanceId));
|
|
||||||
client.getInstanceServices()
|
|
||||||
.setApiTerminationDisabledForInstanceInRegion(null, instanceId,
|
|
||||||
false);
|
|
||||||
assertEquals(false, client.getInstanceServices()
|
|
||||||
.isApiTerminationDisabledForInstanceInRegion(null, instanceId));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryToChangeStuff() {
|
private void tryToChangeStuff() {
|
||||||
|
@ -262,8 +231,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||||
|
|
||||||
private void setUserDataForInstanceInRegion() {
|
private void setUserDataForInstanceInRegion() {
|
||||||
try {
|
try {
|
||||||
client.getInstanceServices().setUserDataForInstanceInRegion(null,
|
client.getInstanceServices().setUserDataForInstanceInRegion(null, instanceId, "test".getBytes());
|
||||||
instanceId, "test".getBytes());
|
|
||||||
assert false : "shouldn't be allowed, as instance needs to be stopped";
|
assert false : "shouldn't be allowed, as instance needs to be stopped";
|
||||||
} catch (AWSResponseException e) {
|
} catch (AWSResponseException e) {
|
||||||
assertEquals("IncorrectInstanceState", e.getError().getCode());
|
assertEquals("IncorrectInstanceState", e.getError().getCode());
|
||||||
|
@ -272,10 +240,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||||
|
|
||||||
private void setRamdiskForInstanceInRegion() {
|
private void setRamdiskForInstanceInRegion() {
|
||||||
try {
|
try {
|
||||||
String ramdisk = client.getInstanceServices()
|
String ramdisk = client.getInstanceServices().getRamdiskForInstanceInRegion(null, instanceId);
|
||||||
.getRamdiskForInstanceInRegion(null, instanceId);
|
client.getInstanceServices().setRamdiskForInstanceInRegion(null, instanceId, ramdisk);
|
||||||
client.getInstanceServices().setRamdiskForInstanceInRegion(null,
|
|
||||||
instanceId, ramdisk);
|
|
||||||
assert false : "shouldn't be allowed, as instance needs to be stopped";
|
assert false : "shouldn't be allowed, as instance needs to be stopped";
|
||||||
} catch (AWSResponseException e) {
|
} catch (AWSResponseException e) {
|
||||||
assertEquals("IncorrectInstanceState", e.getError().getCode());
|
assertEquals("IncorrectInstanceState", e.getError().getCode());
|
||||||
|
@ -284,10 +250,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||||
|
|
||||||
private void setKernelForInstanceInRegion() {
|
private void setKernelForInstanceInRegion() {
|
||||||
try {
|
try {
|
||||||
String oldKernel = client.getInstanceServices()
|
String oldKernel = client.getInstanceServices().getKernelForInstanceInRegion(null, instanceId);
|
||||||
.getKernelForInstanceInRegion(null, instanceId);
|
client.getInstanceServices().setKernelForInstanceInRegion(null, instanceId, oldKernel);
|
||||||
client.getInstanceServices().setKernelForInstanceInRegion(null,
|
|
||||||
instanceId, oldKernel);
|
|
||||||
assert false : "shouldn't be allowed, as instance needs to be stopped";
|
assert false : "shouldn't be allowed, as instance needs to be stopped";
|
||||||
} catch (AWSResponseException e) {
|
} catch (AWSResponseException e) {
|
||||||
assertEquals("IncorrectInstanceState", e.getError().getCode());
|
assertEquals("IncorrectInstanceState", e.getError().getCode());
|
||||||
|
@ -296,8 +260,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||||
|
|
||||||
private void setInstanceTypeForInstanceInRegion() {
|
private void setInstanceTypeForInstanceInRegion() {
|
||||||
try {
|
try {
|
||||||
client.getInstanceServices().setInstanceTypeForInstanceInRegion(null,
|
client.getInstanceServices().setInstanceTypeForInstanceInRegion(null, instanceId, InstanceType.C1_MEDIUM);
|
||||||
instanceId, InstanceType.C1_MEDIUM);
|
|
||||||
assert false : "shouldn't be allowed, as instance needs to be stopped";
|
assert false : "shouldn't be allowed, as instance needs to be stopped";
|
||||||
} catch (AWSResponseException e) {
|
} catch (AWSResponseException e) {
|
||||||
assertEquals("IncorrectInstanceState", e.getError().getCode());
|
assertEquals("IncorrectInstanceState", e.getError().getCode());
|
||||||
|
@ -307,8 +270,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||||
private void setBlockDeviceMappingForInstanceInRegion() {
|
private void setBlockDeviceMappingForInstanceInRegion() {
|
||||||
BlockDeviceMapping blockDeviceMapping = new BlockDeviceMapping();
|
BlockDeviceMapping blockDeviceMapping = new BlockDeviceMapping();
|
||||||
try {
|
try {
|
||||||
client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(
|
client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(null, instanceId, blockDeviceMapping);
|
||||||
null, instanceId, blockDeviceMapping);
|
|
||||||
assert false : "shouldn't be allowed, as instance needs to be ebs based-ami";
|
assert false : "shouldn't be allowed, as instance needs to be ebs based-ami";
|
||||||
} catch (AWSResponseException e) {
|
} catch (AWSResponseException e) {
|
||||||
assertEquals("InvalidParameterCombination", e.getError().getCode());
|
assertEquals("InvalidParameterCombination", e.getError().getCode());
|
||||||
|
@ -317,9 +279,8 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||||
|
|
||||||
private void setInstanceInitiatedShutdownBehaviorForInstanceInRegion() {
|
private void setInstanceInitiatedShutdownBehaviorForInstanceInRegion() {
|
||||||
try {
|
try {
|
||||||
client.getInstanceServices()
|
client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, instanceId,
|
||||||
.setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
|
InstanceInitiatedShutdownBehavior.STOP);
|
||||||
instanceId, InstanceInitiatedShutdownBehavior.STOP);
|
|
||||||
assert false : "shouldn't be allowed, as instance needs to be ebs based-ami";
|
assert false : "shouldn't be allowed, as instance needs to be ebs based-ami";
|
||||||
} catch (AWSResponseException e) {
|
} catch (AWSResponseException e) {
|
||||||
assertEquals("UnsupportedInstanceAttribute", e.getError().getCode());
|
assertEquals("UnsupportedInstanceAttribute", e.getError().getCode());
|
||||||
|
@ -327,22 +288,19 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = false, dependsOnMethods = "testCreateRunningInstance")
|
@Test(enabled = false, dependsOnMethods = "testCreateRunningInstance")
|
||||||
void testReboot() throws InterruptedException, ExecutionException,
|
void testReboot() throws InterruptedException, ExecutionException, TimeoutException, IOException {
|
||||||
TimeoutException, IOException {
|
|
||||||
RunningInstance instance = getInstance(instanceId);
|
RunningInstance instance = getInstance(instanceId);
|
||||||
System.out.printf("%d: %s rebooting instance %n", System
|
System.out.printf("%d: %s rebooting instance %n", System.currentTimeMillis(), instanceId);
|
||||||
.currentTimeMillis(), instanceId);
|
|
||||||
client.getInstanceServices().rebootInstancesInRegion(null, instanceId);
|
client.getInstanceServices().rebootInstancesInRegion(null, instanceId);
|
||||||
Thread.sleep(1000);
|
Thread.sleep(1000);
|
||||||
instance = getInstance(instanceId);
|
instance = getInstance(instanceId);
|
||||||
blockUntilWeCanSshIntoInstance(instance);
|
blockUntilWeCanSshIntoInstance(instance);
|
||||||
SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(),
|
SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(), 22), "root", keyPair.getKeyMaterial()
|
||||||
22), "root", keyPair.getKeyMaterial().getBytes());
|
.getBytes());
|
||||||
try {
|
try {
|
||||||
ssh.connect();
|
ssh.connect();
|
||||||
ExecResponse uptime = ssh.exec("uptime");
|
ExecResponse uptime = ssh.exec("uptime");
|
||||||
assert uptime.getOutput().indexOf("0 min") != -1 : "reboot didn't work: "
|
assert uptime.getOutput().indexOf("0 min") != -1 : "reboot didn't work: " + uptime;
|
||||||
+ uptime;
|
|
||||||
} finally {
|
} finally {
|
||||||
if (ssh != null)
|
if (ssh != null)
|
||||||
ssh.disconnect();
|
ssh.disconnect();
|
||||||
|
@ -350,86 +308,70 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = false, dependsOnMethods = "testReboot")
|
@Test(enabled = false, dependsOnMethods = "testReboot")
|
||||||
void testElasticIpAddress() throws InterruptedException, ExecutionException,
|
void testElasticIpAddress() throws InterruptedException, ExecutionException, TimeoutException, IOException {
|
||||||
TimeoutException, IOException {
|
address = client.getElasticIPAddressServices().allocateAddressInRegion(null);
|
||||||
address = client.getElasticIPAddressServices().allocateAddressInRegion(
|
|
||||||
null);
|
|
||||||
assertNotNull(address);
|
assertNotNull(address);
|
||||||
|
|
||||||
PublicIpInstanceIdPair compare = Iterables.getLast(client
|
PublicIpInstanceIdPair compare = Iterables.getLast(client.getElasticIPAddressServices()
|
||||||
.getElasticIPAddressServices().describeAddressesInRegion(null,
|
.describeAddressesInRegion(null, address));
|
||||||
address));
|
|
||||||
|
|
||||||
assertEquals(compare.getPublicIp(), address);
|
assertEquals(compare.getPublicIp(), address);
|
||||||
assert compare.getInstanceId() == null;
|
assert compare.getInstanceId() == null;
|
||||||
|
|
||||||
client.getElasticIPAddressServices().associateAddressInRegion(null,
|
client.getElasticIPAddressServices().associateAddressInRegion(null, address, instanceId);
|
||||||
address, instanceId);
|
|
||||||
|
|
||||||
compare = Iterables.getLast(client.getElasticIPAddressServices()
|
compare = Iterables.getLast(client.getElasticIPAddressServices().describeAddressesInRegion(null, address));
|
||||||
.describeAddressesInRegion(null, address));
|
|
||||||
|
|
||||||
assertEquals(compare.getPublicIp(), address);
|
assertEquals(compare.getPublicIp(), address);
|
||||||
assertEquals(compare.getInstanceId(), instanceId);
|
assertEquals(compare.getInstanceId(), instanceId);
|
||||||
|
|
||||||
Reservation reservation = Iterables.getOnlyElement(client
|
Reservation<? extends RunningInstance> reservation = Iterables.getOnlyElement(client.getInstanceServices()
|
||||||
.getInstanceServices().describeInstancesInRegion(null, instanceId));
|
.describeInstancesInRegion(null, instanceId));
|
||||||
|
|
||||||
assertNotNull(Iterables.getOnlyElement(reservation).getIpAddress());
|
assertNotNull(Iterables.getOnlyElement(reservation).getIpAddress());
|
||||||
assertFalse(Iterables.getOnlyElement(reservation).getIpAddress().equals(
|
assertFalse(Iterables.getOnlyElement(reservation).getIpAddress().equals(address));
|
||||||
address));
|
|
||||||
|
|
||||||
doCheckKey(address);
|
doCheckKey(address);
|
||||||
|
|
||||||
client.getElasticIPAddressServices().disassociateAddressInRegion(null,
|
client.getElasticIPAddressServices().disassociateAddressInRegion(null, address);
|
||||||
address);
|
|
||||||
|
|
||||||
compare = Iterables.getLast(client.getElasticIPAddressServices()
|
compare = Iterables.getLast(client.getElasticIPAddressServices().describeAddressesInRegion(null, address));
|
||||||
.describeAddressesInRegion(null, address));
|
|
||||||
|
|
||||||
assertEquals(compare.getPublicIp(), address);
|
assertEquals(compare.getPublicIp(), address);
|
||||||
assert compare.getInstanceId() == null;
|
assert compare.getInstanceId() == null;
|
||||||
|
|
||||||
reservation = Iterables.getOnlyElement(client.getInstanceServices()
|
reservation = Iterables.getOnlyElement(client.getInstanceServices().describeInstancesInRegion(null, instanceId));
|
||||||
.describeInstancesInRegion(null, instanceId));
|
|
||||||
// assert reservation.getRunningInstances().last().getIpAddress() == null;
|
// assert reservation.getRunningInstances().last().getIpAddress() == null;
|
||||||
// TODO
|
// TODO
|
||||||
}
|
}
|
||||||
|
|
||||||
private RunningInstance blockUntilWeCanSshIntoInstance(
|
private RunningInstance blockUntilWeCanSshIntoInstance(RunningInstance instance) throws UnknownHostException {
|
||||||
RunningInstance instance) throws UnknownHostException {
|
System.out.printf("%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance.getId());
|
||||||
System.out.printf("%d: %s awaiting instance to run %n", System
|
|
||||||
.currentTimeMillis(), instance.getId());
|
|
||||||
assert runningTester.apply(instance);
|
assert runningTester.apply(instance);
|
||||||
|
|
||||||
instance = getInstance(instance.getId());
|
instance = getInstance(instance.getId());
|
||||||
|
|
||||||
System.out.printf("%d: %s awaiting instance to have ip assigned %n",
|
System.out
|
||||||
System.currentTimeMillis(), instance.getId());
|
.printf("%d: %s awaiting instance to have ip assigned %n", System.currentTimeMillis(), instance.getId());
|
||||||
assert hasIpTester.apply(instance);
|
assert hasIpTester.apply(instance);
|
||||||
|
|
||||||
System.out.printf("%d: %s awaiting ssh service to start%n", System
|
System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(), instance.getIpAddress());
|
||||||
.currentTimeMillis(), instance.getIpAddress());
|
|
||||||
assert socketTester.apply(new IPSocket(instance.getIpAddress(), 22));
|
assert socketTester.apply(new IPSocket(instance.getIpAddress(), 22));
|
||||||
|
|
||||||
System.out.printf("%d: %s ssh service started%n", System
|
System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), instance.getDnsName());
|
||||||
.currentTimeMillis(), instance.getDnsName());
|
|
||||||
sshPing(instance);
|
sshPing(instance);
|
||||||
System.out.printf("%d: %s ssh connection made%n", System
|
System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instance.getId());
|
||||||
.currentTimeMillis(), instance.getId());
|
|
||||||
|
|
||||||
System.out.printf("%d: %s awaiting http service to start%n", System
|
System.out.printf("%d: %s awaiting http service to start%n", System.currentTimeMillis(), instance.getIpAddress());
|
||||||
.currentTimeMillis(), instance.getIpAddress());
|
|
||||||
assert socketTester.apply(new IPSocket(instance.getIpAddress(), 80));
|
assert socketTester.apply(new IPSocket(instance.getIpAddress(), 80));
|
||||||
System.out.printf("%d: %s http service started%n", System
|
System.out.printf("%d: %s http service started%n", System.currentTimeMillis(), instance.getDnsName());
|
||||||
.currentTimeMillis(), instance.getDnsName());
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private RunningInstance getInstance(String instanceId) {
|
private RunningInstance getInstance(String instanceId) {
|
||||||
// search my identity for the instance I just created
|
// search my identity for the instance I just created
|
||||||
Set<Reservation> reservations = client.getInstanceServices()
|
Set<? extends Reservation<? extends RunningInstance>> reservations = client.getInstanceServices()
|
||||||
.describeInstancesInRegion(null, instanceId); // last parameter
|
.describeInstancesInRegion(null, instanceId); // last parameter
|
||||||
// (ids) narrows the
|
// (ids) narrows the
|
||||||
// search
|
// search
|
||||||
|
|
||||||
|
@ -437,8 +379,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this tests "personality" as the file looked up was sent during instance
|
* this tests "personality" as the file looked up was sent during instance creation
|
||||||
* creation
|
|
||||||
*
|
*
|
||||||
* @throws UnknownHostException
|
* @throws UnknownHostException
|
||||||
*/
|
*/
|
||||||
|
@ -454,14 +395,12 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doCheckKey(RunningInstance newDetails)
|
private void doCheckKey(RunningInstance newDetails) throws UnknownHostException {
|
||||||
throws UnknownHostException {
|
|
||||||
doCheckKey(newDetails.getIpAddress());
|
doCheckKey(newDetails.getIpAddress());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void doCheckKey(String address) {
|
private void doCheckKey(String address) {
|
||||||
SshClient ssh = sshFactory.create(new IPSocket(address, 22), "root",
|
SshClient ssh = sshFactory.create(new IPSocket(address, 22), "root", keyPair.getKeyMaterial().getBytes());
|
||||||
keyPair.getKeyMaterial().getBytes());
|
|
||||||
try {
|
try {
|
||||||
ssh.connect();
|
ssh.connect();
|
||||||
ExecResponse hello = ssh.exec("echo hello");
|
ExecResponse hello = ssh.exec("echo hello");
|
||||||
|
@ -473,20 +412,15 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@AfterTest
|
@AfterTest
|
||||||
void cleanup() throws InterruptedException, ExecutionException,
|
void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
TimeoutException {
|
|
||||||
if (address != null)
|
if (address != null)
|
||||||
client.getElasticIPAddressServices().releaseAddressInRegion(null,
|
client.getElasticIPAddressServices().releaseAddressInRegion(null, address);
|
||||||
address);
|
|
||||||
if (instanceId != null)
|
if (instanceId != null)
|
||||||
client.getInstanceServices().terminateInstancesInRegion(null,
|
client.getInstanceServices().terminateInstancesInRegion(null, instanceId);
|
||||||
instanceId);
|
|
||||||
if (keyPair != null)
|
if (keyPair != null)
|
||||||
client.getKeyPairServices().deleteKeyPairInRegion(null,
|
client.getKeyPairServices().deleteKeyPairInRegion(null, keyPair.getKeyName());
|
||||||
keyPair.getKeyName());
|
|
||||||
if (securityGroupName != null)
|
if (securityGroupName != null)
|
||||||
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null,
|
client.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName);
|
||||||
securityGroupName);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -81,8 +81,8 @@ import com.google.inject.Module;
|
||||||
import com.google.inject.internal.ImmutableMap;
|
import com.google.inject.internal.ImmutableMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapted from the following sources: {@link http://gist.github.com/249915},
|
* Adapted from the following sources: {@link http://gist.github.com/249915}, {@link http
|
||||||
* {@link http ://www.capsunlock.net/2009/12/create-ebs-boot-ami.html}
|
* ://www.capsunlock.net/2009/12/create-ebs-boot-ami.html}
|
||||||
* <p/>
|
* <p/>
|
||||||
*
|
*
|
||||||
* Generally disabled, as it incurs higher fees.
|
* Generally disabled, as it incurs higher fees.
|
||||||
|
@ -123,7 +123,7 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
String identity = checkNotNull(System.getProperty("jclouds.test.identity"), "jclouds.test.identity");
|
String identity = checkNotNull(System.getProperty("jclouds.test.identity"), "jclouds.test.identity");
|
||||||
String credential = checkNotNull(System.getProperty("jclouds.test.credential"), "jclouds.test.credential");
|
String credential = checkNotNull(System.getProperty("jclouds.test.credential"), "jclouds.test.credential");
|
||||||
Injector injector = new RestContextFactory().createContextBuilder("ec2", identity, credential,
|
Injector injector = new RestContextFactory().createContextBuilder("ec2", identity, credential,
|
||||||
ImmutableSet.<Module> of(new Log4JLoggingModule())).buildInjector();
|
ImmutableSet.<Module> of(new Log4JLoggingModule())).buildInjector();
|
||||||
client = injector.getInstance(EC2Client.class);
|
client = injector.getInstance(EC2Client.class);
|
||||||
sshFactory = injector.getInstance(SshClient.Factory.class);
|
sshFactory = injector.getInstance(SshClient.Factory.class);
|
||||||
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
|
SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
|
||||||
|
@ -139,7 +139,7 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
attachTester = new RetryablePredicate<Attachment>(volumeAttached, 60, 1, TimeUnit.SECONDS);
|
attachTester = new RetryablePredicate<Attachment>(volumeAttached, 60, 1, TimeUnit.SECONDS);
|
||||||
|
|
||||||
runningTester = new RetryablePredicate<RunningInstance>(new InstanceStateRunning(client), 180, 5,
|
runningTester = new RetryablePredicate<RunningInstance>(new InstanceStateRunning(client), 180, 5,
|
||||||
TimeUnit.SECONDS);
|
TimeUnit.SECONDS);
|
||||||
|
|
||||||
InstanceStateStopped instanceStateStopped = injector.getInstance(InstanceStateStopped.class);
|
InstanceStateStopped instanceStateStopped = injector.getInstance(InstanceStateStopped.class);
|
||||||
stoppedTester = new RetryablePredicate<RunningInstance>(instanceStateStopped, 60, 1, TimeUnit.SECONDS);
|
stoppedTester = new RetryablePredicate<RunningInstance>(instanceStateStopped, 60, 1, TimeUnit.SECONDS);
|
||||||
|
@ -161,11 +161,11 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
|
|
||||||
client.getSecurityGroupServices().createSecurityGroupInRegion(null, securityGroupName, securityGroupName);
|
client.getSecurityGroupServices().createSecurityGroupInRegion(null, securityGroupName, securityGroupName);
|
||||||
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, securityGroupName, IpProtocol.TCP,
|
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, securityGroupName, IpProtocol.TCP,
|
||||||
80, 80, "0.0.0.0/0");
|
80, 80, "0.0.0.0/0");
|
||||||
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, securityGroupName, IpProtocol.TCP,
|
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, securityGroupName, IpProtocol.TCP,
|
||||||
443, 443, "0.0.0.0/0");
|
443, 443, "0.0.0.0/0");
|
||||||
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, securityGroupName, IpProtocol.TCP,
|
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, securityGroupName, IpProtocol.TCP,
|
||||||
22, 22, "0.0.0.0/0");
|
22, 22, "0.0.0.0/0");
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = false)
|
@Test(enabled = false)
|
||||||
|
@ -194,19 +194,20 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
while (instance == null) {
|
while (instance == null) {
|
||||||
try {
|
try {
|
||||||
System.out.printf("%d: running instance%n", System.currentTimeMillis());
|
System.out.printf("%d: running instance%n", System.currentTimeMillis());
|
||||||
Reservation reservation = client.getInstanceServices().runInstancesInRegion(null, null, // allow
|
Reservation<? extends RunningInstance> reservation = client.getInstanceServices().runInstancesInRegion(
|
||||||
// ec2
|
null, null, // allow
|
||||||
// to
|
// ec2
|
||||||
// chose
|
// to
|
||||||
// an
|
// chose
|
||||||
// availability
|
// an
|
||||||
// zone
|
// availability
|
||||||
imageId, 1, // minimum instances
|
// zone
|
||||||
1, // maximum instances
|
imageId, 1, // minimum instances
|
||||||
withKeyName(keyPair.getKeyName())// key I created above
|
1, // maximum instances
|
||||||
.asType(InstanceType.M1_SMALL)// smallest instance
|
withKeyName(keyPair.getKeyName())// key I created above
|
||||||
// size
|
.asType(InstanceType.M1_SMALL)// smallest instance
|
||||||
.withSecurityGroup(securityGroupName));// group I
|
// size
|
||||||
|
.withSecurityGroup(securityGroupName));// group I
|
||||||
// created
|
// created
|
||||||
// above
|
// above
|
||||||
instance = Iterables.getOnlyElement(reservation);
|
instance = Iterables.getOnlyElement(reservation);
|
||||||
|
@ -225,13 +226,13 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
@Test(enabled = false, dependsOnMethods = "testCreateRunningInstance")
|
@Test(enabled = false, dependsOnMethods = "testCreateRunningInstance")
|
||||||
void testCreateAndAttachVolume() {
|
void testCreateAndAttachVolume() {
|
||||||
volume = client.getElasticBlockStoreServices().createVolumeInAvailabilityZone(instance.getAvailabilityZone(),
|
volume = client.getElasticBlockStoreServices().createVolumeInAvailabilityZone(instance.getAvailabilityZone(),
|
||||||
VOLUME_SIZE);
|
VOLUME_SIZE);
|
||||||
System.out.printf("%d: %s awaiting volume to become available%n", System.currentTimeMillis(), volume.getId());
|
System.out.printf("%d: %s awaiting volume to become available%n", System.currentTimeMillis(), volume.getId());
|
||||||
|
|
||||||
assert volumeTester.apply(volume);
|
assert volumeTester.apply(volume);
|
||||||
|
|
||||||
Attachment attachment = client.getElasticBlockStoreServices().attachVolumeInRegion(instance.getRegion(),
|
Attachment attachment = client.getElasticBlockStoreServices().attachVolumeInRegion(instance.getRegion(),
|
||||||
volume.getId(), instance.getId(), "/dev/sdh");
|
volume.getId(), instance.getId(), "/dev/sdh");
|
||||||
|
|
||||||
System.out.printf("%d: %s awaiting attachment to complete%n", System.currentTimeMillis(), attachment.getId());
|
System.out.printf("%d: %s awaiting attachment to complete%n", System.currentTimeMillis(), attachment.getId());
|
||||||
|
|
||||||
|
@ -245,35 +246,35 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
void makeScript() {
|
void makeScript() {
|
||||||
|
|
||||||
mkEbsBoot = new InitBuilder(
|
mkEbsBoot = new InitBuilder(
|
||||||
"mkebsboot",// name of the script
|
"mkebsboot",// name of the script
|
||||||
"/tmp",// working directory
|
"/tmp",// working directory
|
||||||
"/tmp/logs",// location of stdout.log and stderr.log
|
"/tmp/logs",// location of stdout.log and stderr.log
|
||||||
ImmutableMap.of("imageDir", "/mnt/tmp", "ebsDevice", "/dev/sdh", "ebsMountPoint", "/mnt/ebs"),// variables
|
ImmutableMap.of("imageDir", "/mnt/tmp", "ebsDevice", "/dev/sdh", "ebsMountPoint", "/mnt/ebs"),// variables
|
||||||
// used
|
// used
|
||||||
// inside
|
// inside
|
||||||
// of
|
// of
|
||||||
// the
|
// the
|
||||||
// script
|
// script
|
||||||
"echo creating a filesystem and mounting the ebs volume",// what to
|
"echo creating a filesystem and mounting the ebs volume",// what to
|
||||||
// execute
|
// execute
|
||||||
"{md} {varl}IMAGE_DIR{varr} {varl}EBS_MOUNT_POINT{varr}",
|
"{md} {varl}IMAGE_DIR{varr} {varl}EBS_MOUNT_POINT{varr}",
|
||||||
"rm -rf {varl}IMAGE_DIR{varr}/*",
|
"rm -rf {varl}IMAGE_DIR{varr}/*",
|
||||||
"yes| mkfs -t ext3 {varl}EBS_DEVICE{varr} 2>&-",
|
"yes| mkfs -t ext3 {varl}EBS_DEVICE{varr} 2>&-",
|
||||||
"mount {varl}EBS_DEVICE{varr} {varl}EBS_MOUNT_POINT{varr}",
|
"mount {varl}EBS_DEVICE{varr} {varl}EBS_MOUNT_POINT{varr}",
|
||||||
"echo making a local working copy of the boot disk",
|
"echo making a local working copy of the boot disk",
|
||||||
"rsync -ax --exclude /ubuntu/.bash_history --exclude /home/*/.bash_history --exclude /etc/ssh/ssh_host_* --exclude /etc/ssh/moduli --exclude /etc/udev/rules.d/*persistent-net.rules --exclude /var/lib/ec2/* --exclude=/mnt/* --exclude=/proc/* --exclude=/tmp/* --exclude=/dev/log / {varl}IMAGE_DIR{varr}",
|
"rsync -ax --exclude /ubuntu/.bash_history --exclude /home/*/.bash_history --exclude /etc/ssh/ssh_host_* --exclude /etc/ssh/moduli --exclude /etc/udev/rules.d/*persistent-net.rules --exclude /var/lib/ec2/* --exclude=/mnt/* --exclude=/proc/* --exclude=/tmp/* --exclude=/dev/log / {varl}IMAGE_DIR{varr}",
|
||||||
"echo preparing the local working copy", "touch {varl}IMAGE_DIR{varr}/etc/init.d/ec2-init-user-data",
|
"echo preparing the local working copy", "touch {varl}IMAGE_DIR{varr}/etc/init.d/ec2-init-user-data",
|
||||||
"echo copying the local working copy to the ebs mount", "{cd} {varl}IMAGE_DIR{varr}",
|
"echo copying the local working copy to the ebs mount", "{cd} {varl}IMAGE_DIR{varr}",
|
||||||
"tar -cSf - * | tar xf - -C {varl}EBS_MOUNT_POINT{varr}", "echo size of ebs",
|
"tar -cSf - * | tar xf - -C {varl}EBS_MOUNT_POINT{varr}", "echo size of ebs",
|
||||||
"du -sk {varl}EBS_MOUNT_POINT{varr}", "echo size of source", "du -sk {varl}IMAGE_DIR{varr}",
|
"du -sk {varl}EBS_MOUNT_POINT{varr}", "echo size of source", "du -sk {varl}IMAGE_DIR{varr}",
|
||||||
"rm -rf {varl}IMAGE_DIR{varr}/*", "umount {varl}EBS_MOUNT_POINT{varr}", "echo " + SCRIPT_END)
|
"rm -rf {varl}IMAGE_DIR{varr}/*", "umount {varl}EBS_MOUNT_POINT{varr}", "echo " + SCRIPT_END)
|
||||||
.build(OsFamily.UNIX);
|
.build(OsFamily.UNIX);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = false, dependsOnMethods = "testCreateAndAttachVolume")
|
@Test(enabled = false, dependsOnMethods = "testCreateAndAttachVolume")
|
||||||
void testBundleInstance() {
|
void testBundleInstance() {
|
||||||
SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(), 22), "ubuntu", keyPair.getKeyMaterial()
|
SshClient ssh = sshFactory.create(new IPSocket(instance.getIpAddress(), 22), "ubuntu", keyPair.getKeyMaterial()
|
||||||
.getBytes());
|
.getBytes());
|
||||||
try {
|
try {
|
||||||
ssh.connect();
|
ssh.connect();
|
||||||
} catch (SshException e) {// try twice in case there is a network timeout
|
} catch (SshException e) {// try twice in case there is a network timeout
|
||||||
|
@ -298,7 +299,7 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
assert !output.getOutput().trim().equals("") : output;
|
assert !output.getOutput().trim().equals("") : output;
|
||||||
|
|
||||||
RetryablePredicate<String> scriptTester = new RetryablePredicate<String>(new ScriptTester(ssh, SCRIPT_END),
|
RetryablePredicate<String> scriptTester = new RetryablePredicate<String>(new ScriptTester(ssh, SCRIPT_END),
|
||||||
600, 10, TimeUnit.SECONDS);
|
600, 10, TimeUnit.SECONDS);
|
||||||
scriptTester.apply(script);
|
scriptTester.apply(script);
|
||||||
} finally {
|
} finally {
|
||||||
if (ssh != null)
|
if (ssh != null)
|
||||||
|
@ -328,7 +329,7 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
output = ssh.exec(script + " tailerr");
|
output = ssh.exec(script + " tailerr");
|
||||||
String stderr = output.getOutput().trim();
|
String stderr = output.getOutput().trim();
|
||||||
throw new RuntimeException(String.format(
|
throw new RuntimeException(String.format(
|
||||||
"script %s ended without token: stdout.log: [%s]; stderr.log: [%s]; ", script, stdout, stderr));
|
"script %s ended without token: stdout.log: [%s]; stderr.log: [%s]; ", script, stdout, stderr));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
@ -339,7 +340,7 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
@Test(enabled = false, dependsOnMethods = "testBundleInstance")
|
@Test(enabled = false, dependsOnMethods = "testBundleInstance")
|
||||||
void testAMIFromBundle() {
|
void testAMIFromBundle() {
|
||||||
volume = Iterables.getOnlyElement(client.getElasticBlockStoreServices().describeVolumesInRegion(
|
volume = Iterables.getOnlyElement(client.getElasticBlockStoreServices().describeVolumesInRegion(
|
||||||
volume.getRegion(), volume.getId()));
|
volume.getRegion(), volume.getId()));
|
||||||
if (volume.getAttachments().size() > 0) {
|
if (volume.getAttachments().size() > 0) {
|
||||||
// should be cleanly unmounted, so force is not necessary.
|
// should be cleanly unmounted, so force is not necessary.
|
||||||
client.getElasticBlockStoreServices().detachVolumeInRegion(instance.getRegion(), volume.getId(), false);
|
client.getElasticBlockStoreServices().detachVolumeInRegion(instance.getRegion(), volume.getId(), false);
|
||||||
|
@ -350,31 +351,31 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
// detach
|
// detach
|
||||||
}
|
}
|
||||||
snapshot = client.getElasticBlockStoreServices().createSnapshotInRegion(volume.getRegion(), volume.getId(),
|
snapshot = client.getElasticBlockStoreServices().createSnapshotInRegion(volume.getRegion(), volume.getId(),
|
||||||
withDescription("EBS Ubuntu Hardy"));
|
withDescription("EBS Ubuntu Hardy"));
|
||||||
|
|
||||||
System.out.printf("%d: %s awaiting snapshot to complete%n", System.currentTimeMillis(), snapshot.getId());
|
System.out.printf("%d: %s awaiting snapshot to complete%n", System.currentTimeMillis(), snapshot.getId());
|
||||||
|
|
||||||
assert snapshotTester.apply(snapshot);
|
assert snapshotTester.apply(snapshot);
|
||||||
Image image = Iterables.getOnlyElement(client.getAMIServices().describeImagesInRegion(snapshot.getRegion(),
|
Image image = Iterables.getOnlyElement(client.getAMIServices().describeImagesInRegion(snapshot.getRegion(),
|
||||||
imageIds(IMAGE_ID)));
|
imageIds(IMAGE_ID)));
|
||||||
String description = image.getDescription() == null ? "jclouds" : image.getDescription();
|
String description = image.getDescription() == null ? "jclouds" : image.getDescription();
|
||||||
|
|
||||||
System.out.printf("%d: %s creating ami from snapshot%n", System.currentTimeMillis(), snapshot.getId());
|
System.out.printf("%d: %s creating ami from snapshot%n", System.currentTimeMillis(), snapshot.getId());
|
||||||
|
|
||||||
String amiId = client.getAMIServices().registerUnixImageBackedByEbsInRegion(
|
String amiId = client.getAMIServices().registerUnixImageBackedByEbsInRegion(
|
||||||
snapshot.getRegion(),
|
snapshot.getRegion(),
|
||||||
"ebsboot-" + image.getId(),
|
"ebsboot-" + image.getId(),
|
||||||
snapshot.getId(),
|
snapshot.getId(),
|
||||||
withKernelId(image.getKernelId()).withRamdisk(image.getRamdiskId()).withDescription(description)
|
withKernelId(image.getKernelId()).withRamdisk(image.getRamdiskId()).withDescription(description)
|
||||||
.asArchitecture(Architecture.I386));
|
.asArchitecture(Architecture.I386));
|
||||||
try {
|
try {
|
||||||
ebsImage = Iterables.getOnlyElement(client.getAMIServices().describeImagesInRegion(snapshot.getRegion(),
|
ebsImage = Iterables.getOnlyElement(client.getAMIServices().describeImagesInRegion(snapshot.getRegion(),
|
||||||
imageIds(amiId)));
|
imageIds(amiId)));
|
||||||
} catch (AWSResponseException e) {
|
} catch (AWSResponseException e) {
|
||||||
// TODO add a retry handler for this HTTP code 400 and the below error
|
// TODO add a retry handler for this HTTP code 400 and the below error
|
||||||
if (e.getError().getClass().equals("InvalidAMIID.NotFound"))
|
if (e.getError().getClass().equals("InvalidAMIID.NotFound"))
|
||||||
ebsImage = Iterables.getOnlyElement(client.getAMIServices().describeImagesInRegion(snapshot.getRegion(),
|
ebsImage = Iterables.getOnlyElement(client.getAMIServices().describeImagesInRegion(snapshot.getRegion(),
|
||||||
imageIds(amiId)));
|
imageIds(amiId)));
|
||||||
else
|
else
|
||||||
throw e;
|
throw e;
|
||||||
}
|
}
|
||||||
|
@ -402,7 +403,7 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
assertEquals(ebsImage.getRootDeviceType(), RootDeviceType.EBS);
|
assertEquals(ebsImage.getRootDeviceType(), RootDeviceType.EBS);
|
||||||
assertEquals(ebsImage.getRootDeviceName(), "/dev/sda1");
|
assertEquals(ebsImage.getRootDeviceName(), "/dev/sda1");
|
||||||
assertEquals(ebsImage.getEbsBlockDevices().entrySet(), ImmutableMap.of("/dev/sda1",
|
assertEquals(ebsImage.getEbsBlockDevices().entrySet(), ImmutableMap.of("/dev/sda1",
|
||||||
new Image.EbsBlockDevice(snapshot.getId(), VOLUME_SIZE, true)).entrySet());
|
new Image.EbsBlockDevice(snapshot.getId(), VOLUME_SIZE, true)).entrySet());
|
||||||
}
|
}
|
||||||
|
|
||||||
private void tryToChangeStuff() {
|
private void tryToChangeStuff() {
|
||||||
|
@ -433,12 +434,12 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
|
|
||||||
private void setInstanceTypeForInstanceInRegion() {
|
private void setInstanceTypeForInstanceInRegion() {
|
||||||
client.getInstanceServices()
|
client.getInstanceServices()
|
||||||
.setInstanceTypeForInstanceInRegion(null, ebsInstance.getId(), InstanceType.C1_MEDIUM);
|
.setInstanceTypeForInstanceInRegion(null, ebsInstance.getId(), InstanceType.C1_MEDIUM);
|
||||||
assertEquals(InstanceType.C1_MEDIUM, client.getInstanceServices().getInstanceTypeForInstanceInRegion(null,
|
assertEquals(InstanceType.C1_MEDIUM, client.getInstanceServices().getInstanceTypeForInstanceInRegion(null,
|
||||||
ebsInstance.getId()));
|
ebsInstance.getId()));
|
||||||
client.getInstanceServices().setInstanceTypeForInstanceInRegion(null, ebsInstance.getId(), InstanceType.M1_SMALL);
|
client.getInstanceServices().setInstanceTypeForInstanceInRegion(null, ebsInstance.getId(), InstanceType.M1_SMALL);
|
||||||
assertEquals(InstanceType.M1_SMALL, client.getInstanceServices().getInstanceTypeForInstanceInRegion(null,
|
assertEquals(InstanceType.M1_SMALL, client.getInstanceServices().getInstanceTypeForInstanceInRegion(null,
|
||||||
ebsInstance.getId()));
|
ebsInstance.getId()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void setBlockDeviceMappingForInstanceInRegion() {
|
private void setBlockDeviceMappingForInstanceInRegion() {
|
||||||
|
@ -448,10 +449,10 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
blockDeviceMapping.addEbsBlockDevice("/dev/sda1", new RunningInstance.EbsBlockDevice(volumeId, false));
|
blockDeviceMapping.addEbsBlockDevice("/dev/sda1", new RunningInstance.EbsBlockDevice(volumeId, false));
|
||||||
try {
|
try {
|
||||||
client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(null, ebsInstance.getId(),
|
client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(null, ebsInstance.getId(),
|
||||||
blockDeviceMapping);
|
blockDeviceMapping);
|
||||||
|
|
||||||
Map<String, RunningInstance.EbsBlockDevice> devices = client.getInstanceServices()
|
Map<String, RunningInstance.EbsBlockDevice> devices = client.getInstanceServices()
|
||||||
.getBlockDeviceMappingForInstanceInRegion(null, ebsInstance.getId());
|
.getBlockDeviceMappingForInstanceInRegion(null, ebsInstance.getId());
|
||||||
assertEquals(devices.size(), 1);
|
assertEquals(devices.size(), 1);
|
||||||
String deviceName = Iterables.getOnlyElement(devices.keySet());
|
String deviceName = Iterables.getOnlyElement(devices.keySet());
|
||||||
RunningInstance.EbsBlockDevice device = Iterables.getOnlyElement(devices.values());
|
RunningInstance.EbsBlockDevice device = Iterables.getOnlyElement(devices.values());
|
||||||
|
@ -472,15 +473,15 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
try {
|
try {
|
||||||
|
|
||||||
client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
|
client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
|
||||||
ebsInstance.getId(), InstanceInitiatedShutdownBehavior.STOP);
|
ebsInstance.getId(), InstanceInitiatedShutdownBehavior.STOP);
|
||||||
|
|
||||||
assertEquals(InstanceInitiatedShutdownBehavior.STOP, client.getInstanceServices()
|
assertEquals(InstanceInitiatedShutdownBehavior.STOP, client.getInstanceServices()
|
||||||
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, ebsInstance.getId()));
|
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, ebsInstance.getId()));
|
||||||
client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
|
client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
|
||||||
ebsInstance.getId(), InstanceInitiatedShutdownBehavior.TERMINATE);
|
ebsInstance.getId(), InstanceInitiatedShutdownBehavior.TERMINATE);
|
||||||
|
|
||||||
assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client.getInstanceServices()
|
assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client.getInstanceServices()
|
||||||
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, ebsInstance.getId()));
|
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, ebsInstance.getId()));
|
||||||
System.out.println("OK: setInstanceInitiatedShutdownBehaviorForInstanceInRegion");
|
System.out.println("OK: setInstanceInitiatedShutdownBehaviorForInstanceInRegion");
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
System.err.println("setInstanceInitiatedShutdownBehaviorForInstanceInRegion");
|
System.err.println("setInstanceInitiatedShutdownBehaviorForInstanceInRegion");
|
||||||
|
@ -489,8 +490,7 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* this tests "personality" as the file looked up was sent during instance
|
* this tests "personality" as the file looked up was sent during instance creation
|
||||||
* creation
|
|
||||||
*
|
*
|
||||||
* @throws UnknownHostException
|
* @throws UnknownHostException
|
||||||
*/
|
*/
|
||||||
|
@ -527,8 +527,8 @@ public class EBSBootEC2ClientLiveTest {
|
||||||
assert runningTester.apply(instance);
|
assert runningTester.apply(instance);
|
||||||
|
|
||||||
// search my identity for the instance I just created
|
// search my identity for the instance I just created
|
||||||
Set<Reservation> reservations = client.getInstanceServices().describeInstancesInRegion(instance.getRegion(),
|
Set<? extends Reservation<? extends RunningInstance>> reservations = client.getInstanceServices()
|
||||||
instance.getId()); // last
|
.describeInstancesInRegion(instance.getRegion(), instance.getId()); // last
|
||||||
// parameter
|
// parameter
|
||||||
// (ids)
|
// (ids)
|
||||||
// narrows
|
// narrows
|
||||||
|
|
|
@ -43,6 +43,7 @@ import com.google.common.collect.ImmutableSet;
|
||||||
@Test(groups = "unit", testName = "ec2.RegionAndIdToImageTest")
|
@Test(groups = "unit", testName = "ec2.RegionAndIdToImageTest")
|
||||||
public class RegionAndIdToImageTest {
|
public class RegionAndIdToImageTest {
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test
|
||||||
public void testApply() {
|
public void testApply() {
|
||||||
|
|
||||||
|
@ -51,11 +52,11 @@ public class RegionAndIdToImageTest {
|
||||||
AMIClient client = createMock(AMIClient.class);
|
AMIClient client = createMock(AMIClient.class);
|
||||||
org.jclouds.aws.ec2.domain.Image ec2Image = createMock(org.jclouds.aws.ec2.domain.Image.class);
|
org.jclouds.aws.ec2.domain.Image ec2Image = createMock(org.jclouds.aws.ec2.domain.Image.class);
|
||||||
Image image = createNiceMock(Image.class);
|
Image image = createNiceMock(Image.class);
|
||||||
Set<org.jclouds.aws.ec2.domain.Image> images = ImmutableSet
|
Set<? extends org.jclouds.aws.ec2.domain.Image> images = ImmutableSet
|
||||||
.<org.jclouds.aws.ec2.domain.Image> of(ec2Image);
|
.<org.jclouds.aws.ec2.domain.Image> of(ec2Image);
|
||||||
|
|
||||||
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
|
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
|
||||||
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn(images);
|
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn((Set)images);
|
||||||
expect(parser.apply(ec2Image)).andReturn(image);
|
expect(parser.apply(ec2Image)).andReturn(image);
|
||||||
|
|
||||||
replay(caller);
|
replay(caller);
|
||||||
|
@ -74,6 +75,7 @@ public class RegionAndIdToImageTest {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test
|
||||||
public void testApplyNotFound() {
|
public void testApplyNotFound() {
|
||||||
|
|
||||||
|
@ -82,11 +84,11 @@ public class RegionAndIdToImageTest {
|
||||||
AMIClient client = createMock(AMIClient.class);
|
AMIClient client = createMock(AMIClient.class);
|
||||||
org.jclouds.aws.ec2.domain.Image ec2Image = createMock(org.jclouds.aws.ec2.domain.Image.class);
|
org.jclouds.aws.ec2.domain.Image ec2Image = createMock(org.jclouds.aws.ec2.domain.Image.class);
|
||||||
Image image = createNiceMock(Image.class);
|
Image image = createNiceMock(Image.class);
|
||||||
Set<org.jclouds.aws.ec2.domain.Image> images = ImmutableSet
|
Set<? extends org.jclouds.aws.ec2.domain.Image> images = ImmutableSet
|
||||||
.<org.jclouds.aws.ec2.domain.Image> of(ec2Image);
|
.<org.jclouds.aws.ec2.domain.Image> of(ec2Image);
|
||||||
|
|
||||||
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
|
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
|
||||||
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn(images);
|
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn((Set)images);
|
||||||
expect(parser.apply(ec2Image)).andThrow(new ResourceNotFoundException());
|
expect(parser.apply(ec2Image)).andThrow(new ResourceNotFoundException());
|
||||||
|
|
||||||
replay(caller);
|
replay(caller);
|
||||||
|
|
|
@ -58,8 +58,7 @@ import com.google.common.collect.ImmutableSet;
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit", testName = "ec2.RunningInstanceToNodeMetadataTest")
|
@Test(groups = "unit", testName = "ec2.RunningInstanceToNodeMetadataTest")
|
||||||
public class RunningInstanceToNodeMetadataTest {
|
public class RunningInstanceToNodeMetadataTest {
|
||||||
private static class ImageProvider implements
|
private static class ImageProvider implements Provider<Set<? extends org.jclouds.compute.domain.Image>> {
|
||||||
Provider<Set<? extends org.jclouds.compute.domain.Image>> {
|
|
||||||
private final Set<? extends org.jclouds.compute.domain.Image> images;
|
private final Set<? extends org.jclouds.compute.domain.Image> images;
|
||||||
|
|
||||||
private ImageProvider(org.jclouds.compute.domain.Image jcImage) {
|
private ImageProvider(org.jclouds.compute.domain.Image jcImage) {
|
||||||
|
@ -117,8 +116,8 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
replay(credentialProvider);
|
replay(credentialProvider);
|
||||||
replay(instance);
|
replay(instance);
|
||||||
|
|
||||||
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client,
|
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
|
||||||
credentialsMap, credentialProvider, new ImageProvider(jcImage), imageMap, locations,
|
credentialProvider, new ImageProvider(jcImage), imageMap, locations,
|
||||||
new RunningInstanceToStorageMappingUnix());
|
new RunningInstanceToStorageMappingUnix());
|
||||||
|
|
||||||
NodeMetadata metadata = parser.apply(instance);
|
NodeMetadata metadata = parser.apply(instance);
|
||||||
|
@ -168,8 +167,8 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
expect(jcImage.getProviderId()).andReturn("notImageId").atLeastOnce();
|
expect(jcImage.getProviderId()).andReturn("notImageId").atLeastOnce();
|
||||||
expect(instance.getRegion()).andReturn("us-east-1").atLeastOnce();
|
expect(instance.getRegion()).andReturn("us-east-1").atLeastOnce();
|
||||||
|
|
||||||
expect(imageMap.get(new RegionAndName("us-east-1", "imageId"))).andThrow(
|
expect(imageMap.get(new RegionAndName("us-east-1", "imageId"))).andThrow(new NullPointerException())
|
||||||
new NullPointerException()).atLeastOnce();
|
.atLeastOnce();
|
||||||
|
|
||||||
expect(instance.getInstanceType()).andReturn(InstanceType.C1_XLARGE).atLeastOnce();
|
expect(instance.getInstanceType()).andReturn(InstanceType.C1_XLARGE).atLeastOnce();
|
||||||
|
|
||||||
|
@ -181,8 +180,8 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
replay(credentialProvider);
|
replay(credentialProvider);
|
||||||
replay(instance);
|
replay(instance);
|
||||||
|
|
||||||
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client,
|
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
|
||||||
credentialsMap, credentialProvider, new ImageProvider(jcImage), imageMap, locations,
|
credentialProvider, new ImageProvider(jcImage), imageMap, locations,
|
||||||
new RunningInstanceToStorageMappingUnix());
|
new RunningInstanceToStorageMappingUnix());
|
||||||
|
|
||||||
NodeMetadata metadata = parser.apply(instance);
|
NodeMetadata metadata = parser.apply(instance);
|
||||||
|
@ -234,8 +233,7 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
|
|
||||||
org.jclouds.compute.domain.Image lateImage = createMock(org.jclouds.compute.domain.Image.class);
|
org.jclouds.compute.domain.Image lateImage = createMock(org.jclouds.compute.domain.Image.class);
|
||||||
|
|
||||||
expect(imageMap.get(new RegionAndName("us-east-1", "imageId"))).andReturn(lateImage)
|
expect(imageMap.get(new RegionAndName("us-east-1", "imageId"))).andReturn(lateImage).atLeastOnce();
|
||||||
.atLeastOnce();
|
|
||||||
|
|
||||||
expect(instance.getInstanceType()).andReturn(InstanceType.C1_XLARGE).atLeastOnce();
|
expect(instance.getInstanceType()).andReturn(InstanceType.C1_XLARGE).atLeastOnce();
|
||||||
|
|
||||||
|
@ -248,8 +246,8 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
replay(credentialProvider);
|
replay(credentialProvider);
|
||||||
replay(instance);
|
replay(instance);
|
||||||
|
|
||||||
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client,
|
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
|
||||||
credentialsMap, credentialProvider, new ImageProvider(jcImage), imageMap, locations,
|
credentialProvider, new ImageProvider(jcImage), imageMap, locations,
|
||||||
new RunningInstanceToStorageMappingUnix());
|
new RunningInstanceToStorageMappingUnix());
|
||||||
|
|
||||||
NodeMetadata metadata = parser.apply(instance);
|
NodeMetadata metadata = parser.apply(instance);
|
||||||
|
@ -270,8 +268,7 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test
|
||||||
public void testApplyWithNoSecurityGroupCreatesTagOfIdPrefixedByTagAndNullCredentials()
|
public void testApplyWithNoSecurityGroupCreatesTagOfIdPrefixedByTagAndNullCredentials() throws UnknownHostException {
|
||||||
throws UnknownHostException {
|
|
||||||
EC2Client client = createMock(EC2Client.class);
|
EC2Client client = createMock(EC2Client.class);
|
||||||
AMIClient amiClient = createMock(AMIClient.class);
|
AMIClient amiClient = createMock(AMIClient.class);
|
||||||
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
|
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
|
||||||
|
@ -312,8 +309,8 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
replay(credentialProvider);
|
replay(credentialProvider);
|
||||||
replay(instance);
|
replay(instance);
|
||||||
|
|
||||||
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client,
|
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
|
||||||
credentialsMap, credentialProvider, new ImageProvider(jcImage), imageMap, locations,
|
credentialProvider, new ImageProvider(jcImage), imageMap, locations,
|
||||||
new RunningInstanceToStorageMappingUnix());
|
new RunningInstanceToStorageMappingUnix());
|
||||||
|
|
||||||
NodeMetadata metadata = parser.apply(instance);
|
NodeMetadata metadata = parser.apply(instance);
|
||||||
|
@ -333,8 +330,7 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test
|
||||||
public void testApplyWithNoKeyPairCreatesTagOfParsedSecurityGroupAndNullCredentials()
|
public void testApplyWithNoKeyPairCreatesTagOfParsedSecurityGroupAndNullCredentials() throws UnknownHostException {
|
||||||
throws UnknownHostException {
|
|
||||||
EC2Client client = createMock(EC2Client.class);
|
EC2Client client = createMock(EC2Client.class);
|
||||||
AMIClient amiClient = createMock(AMIClient.class);
|
AMIClient amiClient = createMock(AMIClient.class);
|
||||||
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
|
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
|
||||||
|
@ -374,8 +370,8 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
replay(credentialProvider);
|
replay(credentialProvider);
|
||||||
replay(instance);
|
replay(instance);
|
||||||
|
|
||||||
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client,
|
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
|
||||||
credentialsMap, credentialProvider, new ImageProvider(jcImage), imageMap, locations,
|
credentialProvider, new ImageProvider(jcImage), imageMap, locations,
|
||||||
new RunningInstanceToStorageMappingUnix());
|
new RunningInstanceToStorageMappingUnix());
|
||||||
|
|
||||||
NodeMetadata metadata = parser.apply(instance);
|
NodeMetadata metadata = parser.apply(instance);
|
||||||
|
@ -395,8 +391,7 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test
|
||||||
public void testApplyWithKeyPairCreatesTagOfParsedSecurityGroupAndCredentialsBasedOnIt()
|
public void testApplyWithKeyPairCreatesTagOfParsedSecurityGroupAndCredentialsBasedOnIt() throws UnknownHostException {
|
||||||
throws UnknownHostException {
|
|
||||||
EC2Client client = createMock(EC2Client.class);
|
EC2Client client = createMock(EC2Client.class);
|
||||||
AMIClient amiClient = createMock(AMIClient.class);
|
AMIClient amiClient = createMock(AMIClient.class);
|
||||||
expect(client.getAMIServices()).andReturn(amiClient).atLeastOnce();
|
expect(client.getAMIServices()).andReturn(amiClient).atLeastOnce();
|
||||||
|
@ -429,7 +424,7 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
expect(jcImage.getLocation()).andReturn(location).atLeastOnce();
|
expect(jcImage.getLocation()).andReturn(location).atLeastOnce();
|
||||||
|
|
||||||
expect(amiClient.describeImagesInRegion(Region.US_EAST_1, imageIds("imageId"))).andReturn(
|
expect(amiClient.describeImagesInRegion(Region.US_EAST_1, imageIds("imageId"))).andReturn(
|
||||||
ImmutableSet.<Image> of(image));
|
(Set) ImmutableSet.<Image> of(image));
|
||||||
|
|
||||||
expect(credentialProvider.execute(image)).andReturn(new Credentials("user", "pass"));
|
expect(credentialProvider.execute(image)).andReturn(new Credentials("user", "pass"));
|
||||||
|
|
||||||
|
@ -448,8 +443,8 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
replay(instance);
|
replay(instance);
|
||||||
replay(jcImage);
|
replay(jcImage);
|
||||||
|
|
||||||
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client,
|
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
|
||||||
credentialsMap, credentialProvider, new ImageProvider(jcImage), imageMap, locations,
|
credentialProvider, new ImageProvider(jcImage), imageMap, locations,
|
||||||
new RunningInstanceToStorageMappingUnix());
|
new RunningInstanceToStorageMappingUnix());
|
||||||
NodeMetadata metadata = parser.apply(instance);
|
NodeMetadata metadata = parser.apply(instance);
|
||||||
|
|
||||||
|
@ -483,8 +478,7 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
Image image = createMock(Image.class);
|
Image image = createMock(Image.class);
|
||||||
|
|
||||||
expect(instance.getId()).andReturn("id").atLeastOnce();
|
expect(instance.getId()).andReturn("id").atLeastOnce();
|
||||||
expect(instance.getGroupIds()).andReturn(ImmutableSet.of("jclouds1", "jclouds2"))
|
expect(instance.getGroupIds()).andReturn(ImmutableSet.of("jclouds1", "jclouds2")).atLeastOnce();
|
||||||
.atLeastOnce();
|
|
||||||
expect(instance.getKeyName()).andReturn("jclouds#tag#us-east-1#50").atLeastOnce();
|
expect(instance.getKeyName()).andReturn("jclouds#tag#us-east-1#50").atLeastOnce();
|
||||||
expect(instance.getInstanceState()).andReturn(InstanceState.RUNNING);
|
expect(instance.getInstanceState()).andReturn(InstanceState.RUNNING);
|
||||||
expect(instance.getVirtualizationType()).andReturn("paravirtual");
|
expect(instance.getVirtualizationType()).andReturn("paravirtual");
|
||||||
|
@ -505,7 +499,7 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
expect(jcImage.getLocation()).andReturn(location).atLeastOnce();
|
expect(jcImage.getLocation()).andReturn(location).atLeastOnce();
|
||||||
|
|
||||||
expect(amiClient.describeImagesInRegion(Region.US_EAST_1, imageIds("imageId"))).andReturn(
|
expect(amiClient.describeImagesInRegion(Region.US_EAST_1, imageIds("imageId"))).andReturn(
|
||||||
ImmutableSet.<Image> of(image));
|
(Set) ImmutableSet.<Image> of(image));
|
||||||
|
|
||||||
expect(credentialProvider.execute(image)).andReturn(new Credentials("user", "pass"));
|
expect(credentialProvider.execute(image)).andReturn(new Credentials("user", "pass"));
|
||||||
|
|
||||||
|
@ -524,8 +518,8 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
replay(instance);
|
replay(instance);
|
||||||
replay(jcImage);
|
replay(jcImage);
|
||||||
|
|
||||||
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client,
|
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(client, credentialsMap,
|
||||||
credentialsMap, credentialProvider, new ImageProvider(jcImage), imageMap, locations,
|
credentialProvider, new ImageProvider(jcImage), imageMap, locations,
|
||||||
new RunningInstanceToStorageMappingUnix());
|
new RunningInstanceToStorageMappingUnix());
|
||||||
|
|
||||||
NodeMetadata metadata = parser.apply(instance);
|
NodeMetadata metadata = parser.apply(instance);
|
||||||
|
|
|
@ -60,20 +60,17 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testZoneAsALocation() {
|
public void testZoneAsALocation() {
|
||||||
assertRegionAndZoneForLocation(ZONE_AP_SOUTHEAST_1A,
|
assertRegionAndZoneForLocation(ZONE_AP_SOUTHEAST_1A, Region.AP_SOUTHEAST_1, AvailabilityZone.AP_SOUTHEAST_1A);
|
||||||
Region.AP_SOUTHEAST_1, AvailabilityZone.AP_SOUTHEAST_1A);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testRegionAsALocation() {
|
public void testRegionAsALocation() {
|
||||||
assertRegionAndZoneForLocation(REGION_AP_SOUTHEAST_1,
|
assertRegionAndZoneForLocation(REGION_AP_SOUTHEAST_1, Region.AP_SOUTHEAST_1, null);
|
||||||
Region.AP_SOUTHEAST_1, null);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// // fixtures
|
// // fixtures
|
||||||
|
|
||||||
public static Iterable<NodeMetadata> containsNodeMetadata(
|
public static Iterable<NodeMetadata> containsNodeMetadata(final NodeMetadata in) {
|
||||||
final NodeMetadata in) {
|
|
||||||
reportMatcher(new IArgumentMatcher() {
|
reportMatcher(new IArgumentMatcher() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -92,8 +89,8 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assertRegionAndZoneForLocation(Location location,
|
@SuppressWarnings("unchecked")
|
||||||
String region, String zone) {
|
private void assertRegionAndZoneForLocation(Location location, String region, String zone) {
|
||||||
String imageId = "ami1";
|
String imageId = "ami1";
|
||||||
String instanceCreatedId = "instance1";
|
String instanceCreatedId = "instance1";
|
||||||
// setup mocks
|
// setup mocks
|
||||||
|
@ -102,37 +99,28 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
||||||
InstanceClient instanceClient = createMock(InstanceClient.class);
|
InstanceClient instanceClient = createMock(InstanceClient.class);
|
||||||
RunInstancesOptions ec2Options = createMock(RunInstancesOptions.class);
|
RunInstancesOptions ec2Options = createMock(RunInstancesOptions.class);
|
||||||
RunningInstance instance = createMock(RunningInstance.class);
|
RunningInstance instance = createMock(RunningInstance.class);
|
||||||
Reservation reservation = new Reservation(region, ImmutableSet
|
Reservation<? extends RunningInstance> reservation = new Reservation<RunningInstance>(region, ImmutableSet
|
||||||
.<String> of(), ImmutableSet.<RunningInstance> of(instance),
|
.<String> of(), ImmutableSet.<RunningInstance> of(instance), "ownerId", "requesterId", "reservationId");
|
||||||
"ownerId", "requesterId", "reservationId");
|
|
||||||
NodeMetadata nodeMetadata = createMock(NodeMetadata.class);
|
NodeMetadata nodeMetadata = createMock(NodeMetadata.class);
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
expect(strategy.client.getInstanceServices()).andReturn(instanceClient)
|
expect(strategy.client.getInstanceServices()).andReturn(instanceClient).atLeastOnce();
|
||||||
.atLeastOnce();
|
|
||||||
expect(
|
expect(
|
||||||
strategy.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions
|
strategy.createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.execute(region, input.tag,
|
||||||
.execute(region, input.tag, input.template)).andReturn(
|
input.template)).andReturn(ec2Options);
|
||||||
ec2Options);
|
expect(input.template.getLocation()).andReturn(input.location).atLeastOnce();
|
||||||
expect(input.template.getLocation()).andReturn(input.location)
|
|
||||||
.atLeastOnce();
|
|
||||||
expect(input.template.getImage()).andReturn(input.image).atLeastOnce();
|
expect(input.template.getImage()).andReturn(input.image).atLeastOnce();
|
||||||
expect(input.image.getProviderId()).andReturn(imageId).atLeastOnce();
|
expect(input.image.getProviderId()).andReturn(imageId).atLeastOnce();
|
||||||
expect(
|
expect(instanceClient.runInstancesInRegion(region, zone, imageId, 1, input.count, ec2Options)).andReturn(
|
||||||
instanceClient.runInstancesInRegion(region, zone, imageId, 1,
|
(Reservation)reservation);
|
||||||
input.count, ec2Options)).andReturn(reservation);
|
|
||||||
expect(instance.getId()).andReturn(instanceCreatedId).atLeastOnce();
|
expect(instance.getId()).andReturn(instanceCreatedId).atLeastOnce();
|
||||||
expect(strategy.instancePresent.apply(instance)).andReturn(true);
|
expect(strategy.instancePresent.apply(instance)).andReturn(true);
|
||||||
expect(input.template.getOptions()).andReturn(input.options)
|
expect(input.template.getOptions()).andReturn(input.options).atLeastOnce();
|
||||||
.atLeastOnce();
|
|
||||||
|
|
||||||
expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn(
|
expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn(nodeMetadata);
|
||||||
nodeMetadata);
|
|
||||||
expect(
|
expect(
|
||||||
strategy.utils
|
strategy.utils.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(eq(input.options),
|
||||||
.runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(
|
containsNodeMetadata(nodeMetadata), eq(input.nodes), eq(input.badNodes))).andReturn(null);
|
||||||
eq(input.options), containsNodeMetadata(nodeMetadata),
|
|
||||||
eq(input.nodes), eq(input.badNodes))).andReturn(null);
|
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(instanceClient);
|
replay(instanceClient);
|
||||||
|
@ -143,8 +131,7 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
||||||
replayStrategy(strategy);
|
replayStrategy(strategy);
|
||||||
|
|
||||||
// run
|
// run
|
||||||
strategy.execute(input.tag, input.count, input.template, input.nodes,
|
strategy.execute(input.tag, input.count, input.template, input.nodes, input.badNodes);
|
||||||
input.badNodes);
|
|
||||||
|
|
||||||
// verify mocks
|
// verify mocks
|
||||||
verify(instanceClient);
|
verify(instanceClient);
|
||||||
|
@ -155,12 +142,10 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
||||||
verifyStrategy(strategy);
|
verifyStrategy(strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Location REGION_AP_SOUTHEAST_1 = new LocationImpl(
|
private static final Location REGION_AP_SOUTHEAST_1 = new LocationImpl(LocationScope.REGION, Region.AP_SOUTHEAST_1,
|
||||||
LocationScope.REGION, Region.AP_SOUTHEAST_1, Region.AP_SOUTHEAST_1,
|
Region.AP_SOUTHEAST_1, new LocationImpl(LocationScope.PROVIDER, "ec2", "ec2", null));
|
||||||
new LocationImpl(LocationScope.PROVIDER, "ec2", "ec2", null));
|
private static final Location ZONE_AP_SOUTHEAST_1A = new LocationImpl(LocationScope.ZONE,
|
||||||
private static final Location ZONE_AP_SOUTHEAST_1A = new LocationImpl(
|
AvailabilityZone.AP_SOUTHEAST_1A, AvailabilityZone.AP_SOUTHEAST_1A, REGION_AP_SOUTHEAST_1);
|
||||||
LocationScope.ZONE, AvailabilityZone.AP_SOUTHEAST_1A,
|
|
||||||
AvailabilityZone.AP_SOUTHEAST_1A, REGION_AP_SOUTHEAST_1);
|
|
||||||
|
|
||||||
// /////////////////////////////////////////////////////////////////////
|
// /////////////////////////////////////////////////////////////////////
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -213,9 +198,8 @@ public class EC2RunNodesAndAddToSetStrategyTest {
|
||||||
Predicate<RunningInstance> instanceStateRunning = createMock(Predicate.class);
|
Predicate<RunningInstance> instanceStateRunning = createMock(Predicate.class);
|
||||||
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata = createMock(RunningInstanceToNodeMetadata.class);
|
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata = createMock(RunningInstanceToNodeMetadata.class);
|
||||||
ComputeUtils utils = createMock(ComputeUtils.class);
|
ComputeUtils utils = createMock(ComputeUtils.class);
|
||||||
return new EC2RunNodesAndAddToSetStrategy(client,
|
return new EC2RunNodesAndAddToSetStrategy(client, createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions,
|
||||||
createKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions,
|
instanceStateRunning, runningInstanceToNodeMetadata, utils);
|
||||||
instanceStateRunning, runningInstanceToNodeMetadata, utils);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void replayStrategy(EC2RunNodesAndAddToSetStrategy strategy) {
|
private void replayStrategy(EC2RunNodesAndAddToSetStrategy strategy) {
|
||||||
|
|
|
@ -28,6 +28,7 @@ import org.jclouds.aws.domain.Region;
|
||||||
import org.jclouds.aws.ec2.EC2AsyncClient;
|
import org.jclouds.aws.ec2.EC2AsyncClient;
|
||||||
import org.jclouds.aws.ec2.EC2Client;
|
import org.jclouds.aws.ec2.EC2Client;
|
||||||
import org.jclouds.aws.ec2.domain.Reservation;
|
import org.jclouds.aws.ec2.domain.Reservation;
|
||||||
|
import org.jclouds.aws.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
import org.jclouds.rest.RestContextFactory;
|
import org.jclouds.rest.RestContextFactory;
|
||||||
|
@ -64,9 +65,9 @@ public class InstanceClientLiveTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
void testDescribeInstances() {
|
void testDescribeInstances() {
|
||||||
for (String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1,
|
for (String region : Lists.newArrayList(null, Region.EU_WEST_1, Region.US_EAST_1, Region.US_WEST_1,
|
||||||
Region.US_WEST_1, Region.AP_SOUTHEAST_1)) {
|
Region.AP_SOUTHEAST_1)) {
|
||||||
Set<Reservation> allResults = client.describeInstancesInRegion(region);
|
Set<? extends Reservation<? extends RunningInstance>> allResults = client.describeInstancesInRegion(region);
|
||||||
assertNotNull(allResults);
|
assertNotNull(allResults);
|
||||||
assert allResults.size() >= 0 : allResults.size();
|
assert allResults.size() >= 0 : allResults.size();
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,10 +66,10 @@ public class DescribeInstancesResponseHandlerTest extends BaseEC2HandlerTest {
|
||||||
public void testWhenRunning() throws UnknownHostException {
|
public void testWhenRunning() throws UnknownHostException {
|
||||||
|
|
||||||
InputStream is = getClass().getResourceAsStream("/ec2/describe_instances_running.xml");
|
InputStream is = getClass().getResourceAsStream("/ec2/describe_instances_running.xml");
|
||||||
Set<Reservation> contents = Sets.newLinkedHashSet();
|
Set<Reservation<? extends RunningInstance>> contents = Sets.newLinkedHashSet();
|
||||||
|
|
||||||
contents.add(new Reservation(defaultRegion, ImmutableSet.of("adriancole.ec2ingress"), ImmutableSet
|
contents.add(new Reservation<RunningInstance>(defaultRegion, ImmutableSet.of("adriancole.ec2ingress"),
|
||||||
.of(new RunningInstance(defaultRegion, ImmutableSet.of("adriancole.ec2ingress"), "0",
|
ImmutableSet.of(new RunningInstance(defaultRegion, ImmutableSet.of("adriancole.ec2ingress"), "0",
|
||||||
"ec2-174-129-81-68.compute-1.amazonaws.com", "ami-1fd73376", "i-0799056f",
|
"ec2-174-129-81-68.compute-1.amazonaws.com", "ami-1fd73376", "i-0799056f",
|
||||||
InstanceState.RUNNING, InstanceType.M1_SMALL, "174.129.81.68", "aki-a71cf9ce",
|
InstanceState.RUNNING, InstanceType.M1_SMALL, "174.129.81.68", "aki-a71cf9ce",
|
||||||
"adriancole.ec21", dateService.iso8601DateParse("2009-11-09T03:00:34.000Z"), false,
|
"adriancole.ec21", dateService.iso8601DateParse("2009-11-09T03:00:34.000Z"), false,
|
||||||
|
@ -78,7 +78,7 @@ public class DescribeInstancesResponseHandlerTest extends BaseEC2HandlerTest {
|
||||||
RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of())),
|
RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of())),
|
||||||
"993194456877", null, "r-a3c508cb"));
|
"993194456877", null, "r-a3c508cb"));
|
||||||
|
|
||||||
Set<Reservation> result = getReservations(is);
|
Set<Reservation<? extends RunningInstance>> result = getReservations(is);
|
||||||
|
|
||||||
assertEquals(result, contents);
|
assertEquals(result, contents);
|
||||||
}
|
}
|
||||||
|
@ -86,23 +86,25 @@ public class DescribeInstancesResponseHandlerTest extends BaseEC2HandlerTest {
|
||||||
public void testApplyInputStream() {
|
public void testApplyInputStream() {
|
||||||
|
|
||||||
InputStream is = getClass().getResourceAsStream("/ec2/describe_instances.xml");
|
InputStream is = getClass().getResourceAsStream("/ec2/describe_instances.xml");
|
||||||
Set<Reservation> contents = Sets.newLinkedHashSet();
|
Set<Reservation<? extends RunningInstance>> contents = Sets.newLinkedHashSet();
|
||||||
|
|
||||||
contents.add(new Reservation(defaultRegion, ImmutableSet.of("default"), ImmutableSet.of(new RunningInstance(
|
contents.add(new Reservation<RunningInstance>(defaultRegion, ImmutableSet.of("default"), ImmutableSet.of(
|
||||||
defaultRegion, ImmutableSet.of("default"), "23", "ec2-72-44-33-4.compute-1.amazonaws.com",
|
new RunningInstance(defaultRegion, ImmutableSet.of("default"), "23",
|
||||||
"ami-6ea54007", "i-28a64341", InstanceState.RUNNING, InstanceType.M1_LARGE, (String) null,
|
"ec2-72-44-33-4.compute-1.amazonaws.com", "ami-6ea54007", "i-28a64341", InstanceState.RUNNING,
|
||||||
"aki-ba3adfd3", "example-key-name", dateService.iso8601DateParse("2007-08-07T11:54:42.000Z"), false,
|
InstanceType.M1_LARGE, (String) null, "aki-ba3adfd3", "example-key-name", dateService
|
||||||
AvailabilityZone.US_EAST_1B, null, "paravirtual", null, "10-251-50-132.ec2.internal", null, ImmutableSet
|
.iso8601DateParse("2007-08-07T11:54:42.000Z"), false, AvailabilityZone.US_EAST_1B,
|
||||||
.of("774F4FF8"), "ari-badbad00", null, null, null, RootDeviceType.INSTANCE_STORE, null,
|
null, "paravirtual", null, "10-251-50-132.ec2.internal", null, ImmutableSet.of("774F4FF8"),
|
||||||
ImmutableMap.<String, EbsBlockDevice> of()), new RunningInstance(defaultRegion, ImmutableSet
|
"ari-badbad00", null, null, null, RootDeviceType.INSTANCE_STORE, null, ImmutableMap
|
||||||
.of("default"), "23", "ec2-72-44-33-6.compute-1.amazonaws.com", "ami-6ea54007", "i-28a64435",
|
.<String, EbsBlockDevice> of()), new RunningInstance(defaultRegion, ImmutableSet
|
||||||
InstanceState.RUNNING, InstanceType.M1_LARGE, (String) null, "aki-ba3adfd3", "example-key-name",
|
.of("default"), "23", "ec2-72-44-33-6.compute-1.amazonaws.com", "ami-6ea54007", "i-28a64435",
|
||||||
dateService.iso8601DateParse("2007-08-07T11:54:42.000Z"), false, AvailabilityZone.US_EAST_1B, null,
|
InstanceState.RUNNING, InstanceType.M1_LARGE, (String) null, "aki-ba3adfd3",
|
||||||
"paravirtual", null, "10-251-50-134.ec2.internal", null, ImmutableSet.of("774F4FF8"), "ari-badbad00",
|
"example-key-name", dateService.iso8601DateParse("2007-08-07T11:54:42.000Z"), false,
|
||||||
null, null, null, RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of())),
|
AvailabilityZone.US_EAST_1B, null, "paravirtual", null, "10-251-50-134.ec2.internal", null,
|
||||||
"UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", null, "r-44a5402d"));
|
ImmutableSet.of("774F4FF8"), "ari-badbad00", null, null, null, RootDeviceType.INSTANCE_STORE,
|
||||||
|
null, ImmutableMap.<String, EbsBlockDevice> of())), "UYY3TLBUXIEON5NQVUUX6OMPWBZIQNFM", null,
|
||||||
|
"r-44a5402d"));
|
||||||
|
|
||||||
Set<Reservation> result = getReservations(is);
|
Set<Reservation<? extends RunningInstance>> result = getReservations(is);
|
||||||
|
|
||||||
assertEquals(result, contents);
|
assertEquals(result, contents);
|
||||||
}
|
}
|
||||||
|
@ -112,17 +114,17 @@ public class DescribeInstancesResponseHandlerTest extends BaseEC2HandlerTest {
|
||||||
public void testApplyInputStreamEuc() {
|
public void testApplyInputStreamEuc() {
|
||||||
|
|
||||||
InputStream is = getClass().getResourceAsStream("/ec2/describe_instances_euc.xml");
|
InputStream is = getClass().getResourceAsStream("/ec2/describe_instances_euc.xml");
|
||||||
Set<Reservation> contents = Sets.newLinkedHashSet();
|
Set<Reservation<? extends RunningInstance>> contents = Sets.newLinkedHashSet();
|
||||||
|
|
||||||
contents.add(new Reservation(defaultRegion, ImmutableSet.of("default"), ImmutableSet.of(new RunningInstance(
|
contents.add(new Reservation<RunningInstance>(defaultRegion, ImmutableSet.of("default"), ImmutableSet
|
||||||
defaultRegion, ImmutableSet.of("jclouds#euc"), "1", null, "emi-9ACB1363", "i-3FFA0762",
|
.of(new RunningInstance(defaultRegion, ImmutableSet.of("jclouds#euc"), "1", null, "emi-9ACB1363",
|
||||||
InstanceState.SHUTTING_DOWN, InstanceType.M1_LARGE, null, "eki-6CBD12F2", "jclouds#euc-17", dateService
|
"i-3FFA0762", InstanceState.SHUTTING_DOWN, InstanceType.M1_LARGE, null, "eki-6CBD12F2",
|
||||||
.iso8601DateParse("2010-06-16T03:06:19.000Z"), false, "open", null, "paravirtual", null,
|
"jclouds#euc-17", dateService.iso8601DateParse("2010-06-16T03:06:19.000Z"), false, "open",
|
||||||
"10.7.0.179", null, ImmutableSet.<String> of(), "eri-A97113E4", null, null, null,
|
null, "paravirtual", null, "10.7.0.179", null, ImmutableSet.<String> of(), "eri-A97113E4",
|
||||||
RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of())), "jclouds", null,
|
null, null, null, RootDeviceType.INSTANCE_STORE, null, ImmutableMap
|
||||||
"r-4D2A08AD"));
|
.<String, EbsBlockDevice> of())), "jclouds", null, "r-4D2A08AD"));
|
||||||
|
|
||||||
Set<Reservation> result = getReservations(is);
|
Set<Reservation<? extends RunningInstance>> result = getReservations(is);
|
||||||
|
|
||||||
assertEquals(result, contents);
|
assertEquals(result, contents);
|
||||||
}
|
}
|
||||||
|
@ -130,29 +132,30 @@ public class DescribeInstancesResponseHandlerTest extends BaseEC2HandlerTest {
|
||||||
public void testEBS() throws UnknownHostException {
|
public void testEBS() throws UnknownHostException {
|
||||||
|
|
||||||
InputStream is = getClass().getResourceAsStream("/ec2/describe_instances_ebs.xml");
|
InputStream is = getClass().getResourceAsStream("/ec2/describe_instances_ebs.xml");
|
||||||
Set<Reservation> contents = Sets.newLinkedHashSet();
|
Set<Reservation<? extends RunningInstance>> contents = Sets.newLinkedHashSet();
|
||||||
|
|
||||||
contents.add(new Reservation(defaultRegion, ImmutableSet.of("adriancole.ec2ebsingress"), ImmutableSet
|
contents.add(new Reservation<RunningInstance>(defaultRegion, ImmutableSet.of("adriancole.ec2ebsingress"),
|
||||||
.of(new RunningInstance(defaultRegion, ImmutableSet.of("adriancole.ec2ebsingress"), "0",
|
ImmutableSet.of(new RunningInstance(defaultRegion, ImmutableSet.of("adriancole.ec2ebsingress"), "0",
|
||||||
"ec2-75-101-203-146.compute-1.amazonaws.com", "ami-849875ed", "i-e564438d",
|
"ec2-75-101-203-146.compute-1.amazonaws.com", "ami-849875ed", "i-e564438d",
|
||||||
InstanceState.RUNNING, InstanceType.M1_SMALL, "75.101.203.146", "aki-a71cf9ce",
|
InstanceState.RUNNING, InstanceType.M1_SMALL, "75.101.203.146", "aki-a71cf9ce",
|
||||||
"adriancole.ec2ebs1", dateService.iso8601DateParse("2009-12-30T04:06:23.000Z"), false,
|
"adriancole.ec2ebs1", dateService.iso8601DateParse("2009-12-30T04:06:23.000Z"), false,
|
||||||
AvailabilityZone.US_EAST_1B, "placement","hvm", null, "domU-12-31-39-09-CE-53.compute-1.internal",
|
AvailabilityZone.US_EAST_1B, "placement", "hvm", null,
|
||||||
"10.210.209.157", ImmutableSet.<String> of(), "ari-a51cf9cc", null, null, null,
|
"domU-12-31-39-09-CE-53.compute-1.internal", "10.210.209.157", ImmutableSet.<String> of(),
|
||||||
RootDeviceType.EBS, "/dev/sda1", ImmutableMap.<String, EbsBlockDevice> of("/dev/sda1",
|
"ari-a51cf9cc", null, null, null, RootDeviceType.EBS, "/dev/sda1", ImmutableMap
|
||||||
new EbsBlockDevice("vol-dc6ca8b5", Attachment.Status.ATTACHED, dateService
|
.<String, EbsBlockDevice> of("/dev/sda1", new EbsBlockDevice("vol-dc6ca8b5",
|
||||||
.iso8601DateParse("2009-12-30T04:06:29.000Z"), true)))), "993194456877",
|
Attachment.Status.ATTACHED, dateService
|
||||||
null, "r-596dd731"));
|
.iso8601DateParse("2009-12-30T04:06:29.000Z"), true)))),
|
||||||
|
"993194456877", null, "r-596dd731"));
|
||||||
|
|
||||||
Set<Reservation> result = getReservations(is);
|
Set<Reservation<? extends RunningInstance>> result = getReservations(is);
|
||||||
|
|
||||||
assertEquals(result, contents);
|
assertEquals(result, contents);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Set<Reservation> getReservations(InputStream is) {
|
private Set<Reservation<? extends RunningInstance>> getReservations(InputStream is) {
|
||||||
DescribeInstancesResponseHandler handler = injector.getInstance(DescribeInstancesResponseHandler.class);
|
DescribeInstancesResponseHandler handler = injector.getInstance(DescribeInstancesResponseHandler.class);
|
||||||
addDefaultRegionToHandler(handler);
|
addDefaultRegionToHandler(handler);
|
||||||
Set<Reservation> result = factory.create(handler).parse(is);
|
Set<Reservation<? extends RunningInstance>> result = factory.create(handler).parse(is);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -64,28 +64,29 @@ public class RunInstancesResponseHandlerTest extends BaseEC2HandlerTest {
|
||||||
|
|
||||||
InputStream is = getClass().getResourceAsStream("/ec2/run_instances.xml");
|
InputStream is = getClass().getResourceAsStream("/ec2/run_instances.xml");
|
||||||
|
|
||||||
Reservation expected = new Reservation(defaultRegion, ImmutableSet.of("default"), ImmutableSet.of(
|
Reservation<? extends RunningInstance> expected = new Reservation<RunningInstance>(defaultRegion, ImmutableSet
|
||||||
new RunningInstance(defaultRegion, ImmutableSet.of("default"), "0", null, "ami-60a54009", "i-2ba64342",
|
.of("default"), ImmutableSet.of(new RunningInstance(defaultRegion, ImmutableSet.of("default"), "0",
|
||||||
InstanceState.PENDING, InstanceType.M1_SMALL, (String) null, null, "example-key-name",
|
null, "ami-60a54009", "i-2ba64342", InstanceState.PENDING, InstanceType.M1_SMALL, (String) null, null,
|
||||||
dateService.iso8601DateParse("2007-08-07T11:51:50.000Z"), true, AvailabilityZone.US_EAST_1B,
|
"example-key-name", dateService.iso8601DateParse("2007-08-07T11:51:50.000Z"), true,
|
||||||
null, "paravirtual", null, (String) null, null, Sets.<String> newLinkedHashSet(), null, null,
|
AvailabilityZone.US_EAST_1B, null, "paravirtual", null, (String) null, null, Sets
|
||||||
null, null, RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of()),
|
.<String> newLinkedHashSet(), null, null, null, null, RootDeviceType.INSTANCE_STORE, null,
|
||||||
new RunningInstance(defaultRegion, ImmutableSet.of("default"), "1", null, "ami-60a54009", "i-2bc64242",
|
ImmutableMap.<String, EbsBlockDevice> of()), new RunningInstance(defaultRegion, ImmutableSet
|
||||||
InstanceState.PENDING, InstanceType.M1_SMALL, (String) null, null, "example-key-name",
|
.of("default"), "1", null, "ami-60a54009", "i-2bc64242", InstanceState.PENDING, InstanceType.M1_SMALL,
|
||||||
dateService.iso8601DateParse("2007-08-07T11:51:50.000Z"), true, AvailabilityZone.US_EAST_1B,
|
(String) null, null, "example-key-name", dateService.iso8601DateParse("2007-08-07T11:51:50.000Z"), true,
|
||||||
null, "paravirtual", null, (String) null, null, Sets.<String> newLinkedHashSet(), null, null,
|
AvailabilityZone.US_EAST_1B, null, "paravirtual", null, (String) null, null, Sets
|
||||||
null, null, RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of()),
|
.<String> newLinkedHashSet(), null, null, null, null, RootDeviceType.INSTANCE_STORE, null,
|
||||||
new RunningInstance(defaultRegion, ImmutableSet.of("default"), "2", null, "ami-60a54009", "i-2be64332",
|
ImmutableMap.<String, EbsBlockDevice> of()), new RunningInstance(defaultRegion, ImmutableSet
|
||||||
InstanceState.PENDING, InstanceType.M1_SMALL, (String) null, null, "example-key-name",
|
.of("default"), "2", null, "ami-60a54009", "i-2be64332", InstanceState.PENDING, InstanceType.M1_SMALL,
|
||||||
dateService.iso8601DateParse("2007-08-07T11:51:50.000Z"), true, AvailabilityZone.US_EAST_1B,
|
(String) null, null, "example-key-name", dateService.iso8601DateParse("2007-08-07T11:51:50.000Z"), true,
|
||||||
null, "paravirtual", null, (String) null, null, Sets.<String> newLinkedHashSet(), null, null,
|
AvailabilityZone.US_EAST_1B, null, "paravirtual", null, (String) null, null, Sets
|
||||||
null, null, RootDeviceType.INSTANCE_STORE, null, ImmutableMap.<String, EbsBlockDevice> of())
|
.<String> newLinkedHashSet(), null, null, null, null, RootDeviceType.INSTANCE_STORE, null,
|
||||||
|
ImmutableMap.<String, EbsBlockDevice> of())
|
||||||
|
|
||||||
), "AIDADH4IGTRXXKCD", null, "r-47a5402e");
|
), "AIDADH4IGTRXXKCD", null, "r-47a5402e");
|
||||||
|
|
||||||
RunInstancesResponseHandler handler = injector.getInstance(RunInstancesResponseHandler.class);
|
RunInstancesResponseHandler handler = injector.getInstance(RunInstancesResponseHandler.class);
|
||||||
addDefaultRegionToHandler(handler);
|
addDefaultRegionToHandler(handler);
|
||||||
Reservation result = factory.create(handler).parse(is);
|
Reservation<? extends RunningInstance> result = factory.create(handler).parse(is);
|
||||||
assertEquals(result, expected);
|
assertEquals(result, expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -19,9 +19,9 @@
|
||||||
package org.jclouds.aws.s3.internal;
|
package org.jclouds.aws.s3.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.util.concurrent.Futures.compose;
|
|
||||||
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
|
import static com.google.common.util.concurrent.Futures.immediateFailedFuture;
|
||||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
||||||
|
import static org.jclouds.concurrent.ConcurrentUtils.compose;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -67,7 +67,6 @@ import org.jclouds.blobstore.domain.BlobMetadata;
|
||||||
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
import org.jclouds.blobstore.domain.MutableBlobMetadata;
|
||||||
import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions;
|
import org.jclouds.blobstore.functions.HttpGetOptionsListToGetOptions;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.concurrent.ConcurrentUtils;
|
|
||||||
import org.jclouds.date.DateService;
|
import org.jclouds.date.DateService;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.domain.LocationScope;
|
import org.jclouds.domain.LocationScope;
|
||||||
|
@ -97,20 +96,19 @@ public class StubS3AsyncClient implements S3AsyncClient {
|
||||||
private final BlobToObjectMetadata blob2ObjectMetadata;
|
private final BlobToObjectMetadata blob2ObjectMetadata;
|
||||||
private final BucketToContainerListOptions bucket2ContainerListOptions;
|
private final BucketToContainerListOptions bucket2ContainerListOptions;
|
||||||
private final ResourceToBucketList resource2BucketList;
|
private final ResourceToBucketList resource2BucketList;
|
||||||
private final ExecutorService executorService;
|
|
||||||
private final ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs;
|
private final ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs;
|
||||||
private final ConcurrentMap<String, Location> containerToLocation;
|
private final ConcurrentMap<String, Location> containerToLocation;
|
||||||
|
private final ExecutorService service;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
private StubS3AsyncClient(TransientAsyncBlobStore blobStore,
|
private StubS3AsyncClient(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
|
||||||
ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
|
TransientAsyncBlobStore blobStore, ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
|
||||||
ConcurrentMap<String, Location> containerToLocation, DateService dateService,
|
ConcurrentMap<String, Location> containerToLocation, DateService dateService,
|
||||||
S3Object.Factory objectProvider, Blob.Factory blobProvider,
|
S3Object.Factory objectProvider, Blob.Factory blobProvider,
|
||||||
HttpGetOptionsListToGetOptions httpGetOptionsConverter, ObjectToBlob object2Blob,
|
HttpGetOptionsListToGetOptions httpGetOptionsConverter, ObjectToBlob object2Blob, BlobToObject blob2Object,
|
||||||
BlobToObject blob2Object, BlobToObjectMetadata blob2ObjectMetadata,
|
BlobToObjectMetadata blob2ObjectMetadata, BucketToContainerListOptions bucket2ContainerListOptions,
|
||||||
BucketToContainerListOptions bucket2ContainerListOptions,
|
ResourceToBucketList resource2BucketList) {
|
||||||
ResourceToBucketList resource2BucketList,
|
this.service = service;
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executorService) {
|
|
||||||
this.containerToBlobs = containerToBlobs;
|
this.containerToBlobs = containerToBlobs;
|
||||||
this.containerToLocation = containerToLocation;
|
this.containerToLocation = containerToLocation;
|
||||||
this.blobStore = blobStore;
|
this.blobStore = blobStore;
|
||||||
|
@ -121,10 +119,8 @@ public class StubS3AsyncClient implements S3AsyncClient {
|
||||||
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
|
this.object2Blob = checkNotNull(object2Blob, "object2Blob");
|
||||||
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
|
this.blob2Object = checkNotNull(blob2Object, "blob2Object");
|
||||||
this.blob2ObjectMetadata = checkNotNull(blob2ObjectMetadata, "blob2ObjectMetadata");
|
this.blob2ObjectMetadata = checkNotNull(blob2ObjectMetadata, "blob2ObjectMetadata");
|
||||||
this.bucket2ContainerListOptions = checkNotNull(bucket2ContainerListOptions,
|
this.bucket2ContainerListOptions = checkNotNull(bucket2ContainerListOptions, "bucket2ContainerListOptions");
|
||||||
"bucket2ContainerListOptions");
|
|
||||||
this.resource2BucketList = checkNotNull(resource2BucketList, "resource2BucketList");
|
this.resource2BucketList = checkNotNull(resource2BucketList, "resource2BucketList");
|
||||||
this.executorService = checkNotNull(executorService, "executorService");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public static final String TEST_ACL_ID = "1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c";
|
public static final String TEST_ACL_ID = "1a405254c932b52e5b5caaa88186bc431a1bacb9ece631f835daddaf0c47677c";
|
||||||
|
@ -141,24 +137,19 @@ public class StubS3AsyncClient implements S3AsyncClient {
|
||||||
public ListenableFuture<Boolean> putBucketInRegion(@Nullable String region, String name,
|
public ListenableFuture<Boolean> putBucketInRegion(@Nullable String region, String name,
|
||||||
PutBucketOptions... optionsList) {
|
PutBucketOptions... optionsList) {
|
||||||
region = region == null ? Region.US_STANDARD : region;
|
region = region == null ? Region.US_STANDARD : region;
|
||||||
final PutBucketOptions options = (optionsList.length == 0) ? new PutBucketOptions()
|
final PutBucketOptions options = (optionsList.length == 0) ? new PutBucketOptions() : optionsList[0];
|
||||||
: optionsList[0];
|
|
||||||
keyToAcl.put(name, options.getAcl());
|
keyToAcl.put(name, options.getAcl());
|
||||||
return blobStore.createContainerInLocation(new LocationImpl(LocationScope.REGION, region,
|
return blobStore.createContainerInLocation(new LocationImpl(LocationScope.REGION, region, region, null), name);
|
||||||
region, null), name);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<ListBucketResponse> listBucket(final String name,
|
public ListenableFuture<ListBucketResponse> listBucket(final String name, ListBucketOptions... optionsList) {
|
||||||
ListBucketOptions... optionsList) {
|
|
||||||
ListContainerOptions options = bucket2ContainerListOptions.apply(optionsList);
|
ListContainerOptions options = bucket2ContainerListOptions.apply(optionsList);
|
||||||
return compose(blobStore.list(name, options), resource2BucketList);
|
return compose(blobStore.list(name, options), resource2BucketList, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<ObjectMetadata> copyObject(final String sourceBucket,
|
public ListenableFuture<ObjectMetadata> copyObject(final String sourceBucket, final String sourceObject,
|
||||||
final String sourceObject, final String destinationBucket,
|
final String destinationBucket, final String destinationObject, CopyObjectOptions... nullableOptions) {
|
||||||
final String destinationObject, CopyObjectOptions... nullableOptions) {
|
final CopyObjectOptions options = (nullableOptions.length == 0) ? new CopyObjectOptions() : nullableOptions[0];
|
||||||
final CopyObjectOptions options = (nullableOptions.length == 0) ? new CopyObjectOptions()
|
|
||||||
: nullableOptions[0];
|
|
||||||
ConcurrentMap<String, Blob> source = containerToBlobs.get(sourceBucket);
|
ConcurrentMap<String, Blob> source = containerToBlobs.get(sourceBucket);
|
||||||
ConcurrentMap<String, Blob> dest = containerToBlobs.get(destinationBucket);
|
ConcurrentMap<String, Blob> dest = containerToBlobs.get(destinationBucket);
|
||||||
if (source.containsKey(sourceObject)) {
|
if (source.containsKey(sourceObject)) {
|
||||||
|
@ -183,8 +174,7 @@ public class StubS3AsyncClient implements S3AsyncClient {
|
||||||
return immediateFailedFuture(TransientAsyncBlobStore.returnResponseException(412));
|
return immediateFailedFuture(TransientAsyncBlobStore.returnResponseException(412));
|
||||||
}
|
}
|
||||||
Blob sourceS3 = source.get(sourceObject);
|
Blob sourceS3 = source.get(sourceObject);
|
||||||
MutableBlobMetadata newMd = TransientAsyncBlobStore.copy(sourceS3.getMetadata(),
|
MutableBlobMetadata newMd = TransientAsyncBlobStore.copy(sourceS3.getMetadata(), destinationObject);
|
||||||
destinationObject);
|
|
||||||
if (options.getAcl() != null)
|
if (options.getAcl() != null)
|
||||||
keyToAcl.put(destinationBucket + "/" + destinationObject, options.getAcl());
|
keyToAcl.put(destinationBucket + "/" + destinationObject, options.getAcl());
|
||||||
|
|
||||||
|
@ -192,17 +182,15 @@ public class StubS3AsyncClient implements S3AsyncClient {
|
||||||
Blob newBlob = blobProvider.create(newMd);
|
Blob newBlob = blobProvider.create(newMd);
|
||||||
newBlob.setPayload(sourceS3.getPayload());
|
newBlob.setPayload(sourceS3.getPayload());
|
||||||
dest.put(destinationObject, newBlob);
|
dest.put(destinationObject, newBlob);
|
||||||
return immediateFuture((ObjectMetadata) blob2ObjectMetadata.apply(TransientAsyncBlobStore
|
return immediateFuture((ObjectMetadata) blob2ObjectMetadata.apply(TransientAsyncBlobStore.copy(newMd)));
|
||||||
.copy(newMd)));
|
|
||||||
}
|
}
|
||||||
return immediateFailedFuture(new KeyNotFoundException(sourceBucket, sourceObject,
|
return immediateFailedFuture(new KeyNotFoundException(sourceBucket, sourceObject, sourceBucket + "/"
|
||||||
sourceBucket + "/" + sourceObject));
|
+ sourceObject));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<String> putObject(final String bucketName, final S3Object object,
|
public ListenableFuture<String> putObject(final String bucketName, final S3Object object,
|
||||||
PutObjectOptions... nullableOptions) {
|
PutObjectOptions... nullableOptions) {
|
||||||
final PutObjectOptions options = (nullableOptions.length == 0) ? new PutObjectOptions()
|
final PutObjectOptions options = (nullableOptions.length == 0) ? new PutObjectOptions() : nullableOptions[0];
|
||||||
: nullableOptions[0];
|
|
||||||
if (options.getAcl() != null)
|
if (options.getAcl() != null)
|
||||||
keyToAcl.put(bucketName + "/" + object.getMetadata().getKey(), options.getAcl());
|
keyToAcl.put(bucketName + "/" + object.getMetadata().getKey(), options.getAcl());
|
||||||
return blobStore.putBlob(bucketName, object2Blob.apply(object));
|
return blobStore.putBlob(bucketName, object2Blob.apply(object));
|
||||||
|
@ -214,12 +202,10 @@ public class StubS3AsyncClient implements S3AsyncClient {
|
||||||
if (aclObj instanceof AccessControlList) {
|
if (aclObj instanceof AccessControlList) {
|
||||||
acl = (AccessControlList) aclObj;
|
acl = (AccessControlList) aclObj;
|
||||||
} else if (aclObj instanceof CannedAccessPolicy) {
|
} else if (aclObj instanceof CannedAccessPolicy) {
|
||||||
acl = AccessControlList.fromCannedAccessPolicy((CannedAccessPolicy) aclObj,
|
acl = AccessControlList.fromCannedAccessPolicy((CannedAccessPolicy) aclObj, DEFAULT_OWNER_ID);
|
||||||
DEFAULT_OWNER_ID);
|
|
||||||
} else if (aclObj == null) {
|
} else if (aclObj == null) {
|
||||||
// Default to private access policy
|
// Default to private access policy
|
||||||
acl = AccessControlList.fromCannedAccessPolicy(CannedAccessPolicy.PRIVATE,
|
acl = AccessControlList.fromCannedAccessPolicy(CannedAccessPolicy.PRIVATE, DEFAULT_OWNER_ID);
|
||||||
DEFAULT_OWNER_ID);
|
|
||||||
}
|
}
|
||||||
return acl;
|
return acl;
|
||||||
}
|
}
|
||||||
|
@ -228,8 +214,7 @@ public class StubS3AsyncClient implements S3AsyncClient {
|
||||||
return immediateFuture(getACLforS3Item(bucket));
|
return immediateFuture(getACLforS3Item(bucket));
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<AccessControlList> getObjectACL(final String bucket,
|
public ListenableFuture<AccessControlList> getObjectACL(final String bucket, final String objectKey) {
|
||||||
final String objectKey) {
|
|
||||||
return immediateFuture(getACLforS3Item(bucket + "/" + objectKey));
|
return immediateFuture(getACLforS3Item(bucket + "/" + objectKey));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,8 +233,7 @@ public class StubS3AsyncClient implements S3AsyncClient {
|
||||||
for (Grant grant : acl.getGrants()) {
|
for (Grant grant : acl.getGrants()) {
|
||||||
if (grant.getGrantee() instanceof EmailAddressGrantee) {
|
if (grant.getGrantee() instanceof EmailAddressGrantee) {
|
||||||
EmailAddressGrantee emailGrantee = (EmailAddressGrantee) grant.getGrantee();
|
EmailAddressGrantee emailGrantee = (EmailAddressGrantee) grant.getGrantee();
|
||||||
String id = emailGrantee.getEmailAddress().equals(TEST_ACL_EMAIL) ? TEST_ACL_ID : acl
|
String id = emailGrantee.getEmailAddress().equals(TEST_ACL_EMAIL) ? TEST_ACL_ID : acl.getOwner().getId();
|
||||||
.getOwner().getId();
|
|
||||||
grant.setGrantee(new CanonicalUserGrantee(id, acl.getOwner().getDisplayName()));
|
grant.setGrantee(new CanonicalUserGrantee(id, acl.getOwner().getDisplayName()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -286,20 +270,18 @@ public class StubS3AsyncClient implements S3AsyncClient {
|
||||||
return blobStore.removeBlob(bucketName, key);
|
return blobStore.removeBlob(bucketName, key);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<S3Object> getObject(final String bucketName, final String key,
|
public ListenableFuture<S3Object> getObject(final String bucketName, final String key, final GetOptions... options) {
|
||||||
final GetOptions... options) {
|
|
||||||
org.jclouds.blobstore.options.GetOptions getOptions = httpGetOptionsConverter.apply(options);
|
org.jclouds.blobstore.options.GetOptions getOptions = httpGetOptionsConverter.apply(options);
|
||||||
return compose(blobStore.getBlob(bucketName, key, getOptions), blob2Object);
|
return compose(blobStore.getBlob(bucketName, key, getOptions), blob2Object, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<ObjectMetadata> headObject(String bucketName, String key) {
|
public ListenableFuture<ObjectMetadata> headObject(String bucketName, String key) {
|
||||||
return compose(ConcurrentUtils.makeListenable(blobStore.blobMetadata(bucketName, key),
|
return compose(blobStore.blobMetadata(bucketName, key), new Function<BlobMetadata, ObjectMetadata>() {
|
||||||
executorService), new Function<BlobMetadata, ObjectMetadata>() {
|
|
||||||
@Override
|
@Override
|
||||||
public ObjectMetadata apply(BlobMetadata from) {
|
public ObjectMetadata apply(BlobMetadata from) {
|
||||||
return blob2ObjectMetadata.apply(from);
|
return blob2ObjectMetadata.apply(from);
|
||||||
}
|
}
|
||||||
});
|
}, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<? extends Set<BucketMetadata>> listOwnedBuckets() {
|
public ListenableFuture<? extends Set<BucketMetadata>> listOwnedBuckets() {
|
||||||
|
|
|
@ -72,8 +72,8 @@ public class MainApp {
|
||||||
String name = args[3];
|
String name = args[3];
|
||||||
|
|
||||||
// Init
|
// Init
|
||||||
RestContext<EC2Client, EC2AsyncClient> context = new RestContextFactory().createContext(
|
RestContext<EC2Client, EC2AsyncClient> context = new RestContextFactory().createContext("ec2", accesskeyid,
|
||||||
"ec2", accesskeyid, secretkey);
|
secretkey);
|
||||||
|
|
||||||
// Get a synchronous client
|
// Get a synchronous client
|
||||||
EC2Client client = context.getApi();
|
EC2Client client = context.getApi();
|
||||||
|
@ -107,8 +107,7 @@ public class MainApp {
|
||||||
try {
|
try {
|
||||||
String id = findInstanceByKeyName(client, name).getId();
|
String id = findInstanceByKeyName(client, name).getId();
|
||||||
System.out.printf("%d: %s terminating instance%n", System.currentTimeMillis(), id);
|
System.out.printf("%d: %s terminating instance%n", System.currentTimeMillis(), id);
|
||||||
client.getInstanceServices().terminateInstancesInRegion(null,
|
client.getInstanceServices().terminateInstancesInRegion(null, findInstanceByKeyName(client, name).getId());
|
||||||
findInstanceByKeyName(client, name).getId());
|
|
||||||
} catch (NoSuchElementException e) {
|
} catch (NoSuchElementException e) {
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
|
@ -129,8 +128,8 @@ public class MainApp {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RunningInstance createSecurityGroupKeyPairAndInstance(EC2Client client,
|
private static RunningInstance createSecurityGroupKeyPairAndInstance(EC2Client client, String name)
|
||||||
String name) throws TimeoutException {
|
throws TimeoutException {
|
||||||
// create a new security group
|
// create a new security group
|
||||||
createSecurityGroupAndAuthorizePorts(client, name);
|
createSecurityGroupAndAuthorizePorts(client, name);
|
||||||
|
|
||||||
|
@ -145,8 +144,8 @@ public class MainApp {
|
||||||
System.out.printf("%d: creating security group: %s%n", System.currentTimeMillis(), name);
|
System.out.printf("%d: creating security group: %s%n", System.currentTimeMillis(), name);
|
||||||
client.getSecurityGroupServices().createSecurityGroupInRegion(null, name, name);
|
client.getSecurityGroupServices().createSecurityGroupInRegion(null, name, name);
|
||||||
for (int port : new int[] { 80, 8080, 443, 22 }) {
|
for (int port : new int[] { 80, 8080, 443, 22 }) {
|
||||||
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, name,
|
client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, name, IpProtocol.TCP, port,
|
||||||
IpProtocol.TCP, port, port, "0.0.0.0/0");
|
port, "0.0.0.0/0");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,7 +162,7 @@ public class MainApp {
|
||||||
.build(OsFamily.UNIX);
|
.build(OsFamily.UNIX);
|
||||||
|
|
||||||
System.out.printf("%d: running instance%n", System.currentTimeMillis());
|
System.out.printf("%d: running instance%n", System.currentTimeMillis());
|
||||||
Reservation reservation = client.getInstanceServices().runInstancesInRegion(null, null, // allow
|
Reservation<? extends RunningInstance> reservation = client.getInstanceServices().runInstancesInRegion(null, null, // allow
|
||||||
// ec2
|
// ec2
|
||||||
// to
|
// to
|
||||||
// chose
|
// chose
|
||||||
|
@ -182,43 +181,38 @@ public class MainApp {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static RunningInstance blockUntilInstanceRunning(EC2Client client, RunningInstance instance)
|
static RunningInstance blockUntilInstanceRunning(EC2Client client, RunningInstance instance) throws TimeoutException {
|
||||||
throws TimeoutException {
|
|
||||||
// create utilities that wait for the instance to finish
|
// create utilities that wait for the instance to finish
|
||||||
RetryablePredicate<RunningInstance> runningTester = new RetryablePredicate<RunningInstance>(
|
RetryablePredicate<RunningInstance> runningTester = new RetryablePredicate<RunningInstance>(
|
||||||
new InstanceStateRunning(client), 180, 5, TimeUnit.SECONDS);
|
new InstanceStateRunning(client), 180, 5, TimeUnit.SECONDS);
|
||||||
|
|
||||||
System.out.printf("%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance
|
System.out.printf("%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance.getId());
|
||||||
.getId());
|
|
||||||
if (!runningTester.apply(instance))
|
if (!runningTester.apply(instance))
|
||||||
throw new TimeoutException("timeout waiting for instance to run: " + instance.getId());
|
throw new TimeoutException("timeout waiting for instance to run: " + instance.getId());
|
||||||
|
|
||||||
instance = findInstanceById(client, instance.getId());
|
instance = findInstanceById(client, instance.getId());
|
||||||
|
|
||||||
RetryablePredicate<IPSocket> socketTester = new RetryablePredicate<IPSocket>(
|
RetryablePredicate<IPSocket> socketTester = new RetryablePredicate<IPSocket>(new InetSocketAddressConnect(), 300,
|
||||||
new InetSocketAddressConnect(), 300, 1, TimeUnit.SECONDS);
|
1, TimeUnit.SECONDS);
|
||||||
System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(),
|
System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(), instance.getIpAddress());
|
||||||
instance.getIpAddress());
|
|
||||||
if (!socketTester.apply(new IPSocket(instance.getIpAddress(), 22)))
|
if (!socketTester.apply(new IPSocket(instance.getIpAddress(), 22)))
|
||||||
throw new TimeoutException("timeout waiting for ssh to start: " + instance.getIpAddress());
|
throw new TimeoutException("timeout waiting for ssh to start: " + instance.getIpAddress());
|
||||||
|
|
||||||
System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), instance
|
System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), instance.getIpAddress());
|
||||||
.getIpAddress());
|
|
||||||
|
|
||||||
System.out.printf("%d: %s awaiting http service to start%n", System.currentTimeMillis(),
|
System.out.printf("%d: %s awaiting http service to start%n", System.currentTimeMillis(), instance.getIpAddress());
|
||||||
instance.getIpAddress());
|
|
||||||
if (!socketTester.apply(new IPSocket(instance.getIpAddress(), 80)))
|
if (!socketTester.apply(new IPSocket(instance.getIpAddress(), 80)))
|
||||||
throw new TimeoutException("timeout waiting for http to start: " + instance.getIpAddress());
|
throw new TimeoutException("timeout waiting for http to start: " + instance.getIpAddress());
|
||||||
|
|
||||||
System.out.printf("%d: %s http service started%n", System.currentTimeMillis(), instance
|
System.out.printf("%d: %s http service started%n", System.currentTimeMillis(), instance.getIpAddress());
|
||||||
.getIpAddress());
|
|
||||||
return instance;
|
return instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static RunningInstance findInstanceById(EC2Client client, String instanceId) {
|
private static RunningInstance findInstanceById(EC2Client client, String instanceId) {
|
||||||
// search my account for the instance I just created
|
// search my account for the instance I just created
|
||||||
Set<Reservation> reservations = client.getInstanceServices().describeInstancesInRegion(null,
|
Set<? extends Reservation<? extends RunningInstance>> reservations = client.getInstanceServices()
|
||||||
instanceId); // last parameter (ids) narrows the search
|
.describeInstancesInRegion(null, instanceId); // last parameter (ids) narrows the
|
||||||
|
// search
|
||||||
|
|
||||||
// since we refined by instanceId there should only be one instance
|
// since we refined by instanceId there should only be one instance
|
||||||
return Iterables.getOnlyElement(Iterables.getOnlyElement(reservations));
|
return Iterables.getOnlyElement(Iterables.getOnlyElement(reservations));
|
||||||
|
@ -226,11 +220,12 @@ public class MainApp {
|
||||||
|
|
||||||
private static RunningInstance findInstanceByKeyName(EC2Client client, final String keyName) {
|
private static RunningInstance findInstanceByKeyName(EC2Client client, final String keyName) {
|
||||||
// search my account for the instance I just created
|
// search my account for the instance I just created
|
||||||
Set<Reservation> reservations = client.getInstanceServices().describeInstancesInRegion(null);
|
Set<? extends Reservation<? extends RunningInstance>> reservations = client.getInstanceServices()
|
||||||
|
.describeInstancesInRegion(null);
|
||||||
|
|
||||||
// extract all the instances from all reservations
|
// extract all the instances from all reservations
|
||||||
Set<RunningInstance> allInstances = Sets.newHashSet();
|
Set<RunningInstance> allInstances = Sets.newHashSet();
|
||||||
for (Reservation reservation : reservations) {
|
for (Reservation<? extends RunningInstance> reservation : reservations) {
|
||||||
allInstances.addAll(reservation);
|
allInstances.addAll(reservation);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -239,8 +234,7 @@ public class MainApp {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(RunningInstance input) {
|
public boolean apply(RunningInstance input) {
|
||||||
return input.getKeyName().equals(keyName)
|
return input.getKeyName().equals(keyName) && input.getInstanceState() != InstanceState.TERMINATED;
|
||||||
&& input.getInstanceState() != InstanceState.TERMINATED;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.aws.sqs;
|
package org.jclouds.aws.sqs;
|
||||||
|
|
||||||
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
|
import static org.jclouds.concurrent.ConcurrentUtils.sameThreadExecutor;
|
||||||
import static org.jclouds.aws.sqs.options.ListQueuesOptions.Builder.queuePrefix;
|
import static org.jclouds.aws.sqs.options.ListQueuesOptions.Builder.queuePrefix;
|
||||||
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
|
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
|
||||||
|
|
||||||
|
@ -38,7 +38,7 @@ import org.jclouds.rest.RestContextFactory;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import java.util.concurrent.Future;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -133,7 +133,7 @@ public class SpeedTest {
|
||||||
queue.getName());
|
queue.getName());
|
||||||
|
|
||||||
// fire off all the messages for the test
|
// fire off all the messages for the test
|
||||||
Map<QueueMessage, ListenableFuture<byte[]>> responses = Maps.newHashMap();
|
Map<QueueMessage, Future<byte[]>> responses = Maps.newHashMap();
|
||||||
for (int i = 0; i < messageCount; i++) {
|
for (int i = 0; i < messageCount; i++) {
|
||||||
responses.put(new QueueMessage(queue, message), context.getAsyncApi().sendMessage(
|
responses.put(new QueueMessage(queue, message), context.getAsyncApi().sendMessage(
|
||||||
queue, message));
|
queue, message));
|
||||||
|
|
|
@ -68,7 +68,7 @@ public class JCloudsS3Service extends S3Service {
|
||||||
* @param awsCredentials
|
* @param awsCredentials
|
||||||
* - credentials to access S3
|
* - credentials to access S3
|
||||||
* @param modules
|
* @param modules
|
||||||
* - Module that configures a ListenableFutureHttpClient, if not specified, default is
|
* - Module that configures a FutureHttpClient, if not specified, default is
|
||||||
* URLFetchServiceClientModule
|
* URLFetchServiceClientModule
|
||||||
* @throws S3ServiceException
|
* @throws S3ServiceException
|
||||||
*/
|
*/
|
||||||
|
|
|
@ -33,14 +33,14 @@ import org.jclouds.blobstore.ContainerNotFoundException;
|
||||||
import org.jclouds.concurrent.Timeout;
|
import org.jclouds.concurrent.Timeout;
|
||||||
import org.jclouds.http.options.GetOptions;
|
import org.jclouds.http.options.GetOptions;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to Azure Blob via their REST API.
|
* Provides access to Azure Blob via their REST API.
|
||||||
* <p/>
|
* <p/>
|
||||||
* All commands return a ListenableFuture of the result from Azure Blob. Any exceptions incurred
|
* All commands return a Future of the result from Azure Blob. Any exceptions incurred
|
||||||
* during processing will be wrapped in an {@link ExecutionException} as documented in
|
* during processing will be wrapped in an {@link ExecutionException} as documented in
|
||||||
* {@link ListenableFuture#get()}.
|
* {@link Future#get()}.
|
||||||
*
|
*
|
||||||
* @see <a href="http://msdn.microsoft.com/en-us/library/dd135733.aspx" />
|
* @see <a href="http://msdn.microsoft.com/en-us/library/dd135733.aspx" />
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
|
|
@ -19,11 +19,12 @@
|
||||||
package org.jclouds.azure.storage.blob.blobstore;
|
package org.jclouds.azure.storage.blob.blobstore;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.util.concurrent.Futures.compose;
|
import static org.jclouds.concurrent.ConcurrentUtils.compose;
|
||||||
import static org.jclouds.azure.storage.options.ListOptions.Builder.includeMetadata;
|
import static org.jclouds.azure.storage.options.ListOptions.Builder.includeMetadata;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
@ -58,7 +59,6 @@ import org.jclouds.http.options.GetOptions;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -76,21 +76,19 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
AzureAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
AzureAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Location defaultLocation,
|
||||||
Location defaultLocation, Set<? extends Location> locations,
|
Set<? extends Location> locations, AzureBlobAsyncClient async,
|
||||||
|
ContainerToResourceMetadata container2ResourceMd,
|
||||||
AzureBlobAsyncClient async, ContainerToResourceMetadata container2ResourceMd,
|
|
||||||
ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions,
|
ListOptionsToListBlobsOptions blobStore2AzureContainerListOptions,
|
||||||
ListBlobsResponseToResourceList azure2BlobStoreResourceList,
|
ListBlobsResponseToResourceList azure2BlobStoreResourceList, AzureBlobToBlob azureBlob2Blob,
|
||||||
AzureBlobToBlob azureBlob2Blob, BlobToAzureBlob blob2AzureBlob,
|
BlobToAzureBlob blob2AzureBlob, BlobPropertiesToBlobMetadata blob2BlobMd,
|
||||||
BlobPropertiesToBlobMetadata blob2BlobMd, BlobToHttpGetOptions blob2ObjectGetOptions) {
|
BlobToHttpGetOptions blob2ObjectGetOptions) {
|
||||||
super(context, blobUtils, service, defaultLocation, locations);
|
super(context, blobUtils, service, defaultLocation, locations);
|
||||||
this.async = checkNotNull(async, "async");
|
this.async = checkNotNull(async, "async");
|
||||||
this.container2ResourceMd = checkNotNull(container2ResourceMd, "container2ResourceMd");
|
this.container2ResourceMd = checkNotNull(container2ResourceMd, "container2ResourceMd");
|
||||||
this.blobStore2AzureContainerListOptions = checkNotNull(blobStore2AzureContainerListOptions,
|
this.blobStore2AzureContainerListOptions = checkNotNull(blobStore2AzureContainerListOptions,
|
||||||
"blobStore2AzureContainerListOptions");
|
"blobStore2AzureContainerListOptions");
|
||||||
this.azure2BlobStoreResourceList = checkNotNull(azure2BlobStoreResourceList,
|
this.azure2BlobStoreResourceList = checkNotNull(azure2BlobStoreResourceList, "azure2BlobStoreResourceList");
|
||||||
"azure2BlobStoreResourceList");
|
|
||||||
this.azureBlob2Blob = checkNotNull(azureBlob2Blob, "azureBlob2Blob");
|
this.azureBlob2Blob = checkNotNull(azureBlob2Blob, "azureBlob2Blob");
|
||||||
this.blob2AzureBlob = checkNotNull(blob2AzureBlob, "blob2AzureBlob");
|
this.blob2AzureBlob = checkNotNull(blob2AzureBlob, "blob2AzureBlob");
|
||||||
this.blob2BlobMd = checkNotNull(blob2BlobMd, "blob2BlobMd");
|
this.blob2BlobMd = checkNotNull(blob2BlobMd, "blob2BlobMd");
|
||||||
|
@ -102,14 +100,14 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
* {@link org.jclouds.azure.storage.options.ListOptions#includeMetadata} option.
|
* {@link org.jclouds.azure.storage.options.ListOptions#includeMetadata} option.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<? extends org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>> list() {
|
public ListenableFuture<org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>> list() {
|
||||||
return compose(
|
return compose(
|
||||||
async.listContainers(includeMetadata()),
|
async.listContainers(includeMetadata()),
|
||||||
new Function<BoundedSet<ContainerProperties>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
|
new Function<BoundedSet<ContainerProperties>, org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata>>() {
|
||||||
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(
|
public org.jclouds.blobstore.domain.PageSet<? extends StorageMetadata> apply(
|
||||||
BoundedSet<ContainerProperties> from) {
|
BoundedSet<ContainerProperties> from) {
|
||||||
return new PageSetImpl<StorageMetadata>(Iterables.transform(from,
|
return new PageSetImpl<StorageMetadata>(Iterables.transform(from, container2ResourceMd), from
|
||||||
container2ResourceMd), from.getNextMarker());
|
.getNextMarker());
|
||||||
}
|
}
|
||||||
}, service);
|
}, service);
|
||||||
}
|
}
|
||||||
|
@ -145,11 +143,9 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
* container name
|
* container name
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list(String container,
|
public ListenableFuture<PageSet<? extends StorageMetadata>> list(String container, ListContainerOptions options) {
|
||||||
ListContainerOptions options) {
|
|
||||||
ListBlobsOptions azureOptions = blobStore2AzureContainerListOptions.apply(options);
|
ListBlobsOptions azureOptions = blobStore2AzureContainerListOptions.apply(options);
|
||||||
ListenableFuture<ListBlobsResponse> returnVal = async.listBlobs(container, azureOptions
|
ListenableFuture<ListBlobsResponse> returnVal = async.listBlobs(container, azureOptions.includeMetadata());
|
||||||
.includeMetadata());
|
|
||||||
return compose(returnVal, azure2BlobStoreResourceList, service);
|
return compose(returnVal, azure2BlobStoreResourceList, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -173,8 +169,7 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
* blob key
|
* blob key
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Blob> getBlob(String container, String key,
|
public ListenableFuture<Blob> getBlob(String container, String key, org.jclouds.blobstore.options.GetOptions options) {
|
||||||
org.jclouds.blobstore.options.GetOptions options) {
|
|
||||||
GetOptions azureOptions = blob2ObjectGetOptions.apply(options);
|
GetOptions azureOptions = blob2ObjectGetOptions.apply(options);
|
||||||
ListenableFuture<AzureBlob> returnVal = async.getBlob(container, key, azureOptions);
|
ListenableFuture<AzureBlob> returnVal = async.getBlob(container, key, azureOptions);
|
||||||
return compose(returnVal, azureBlob2Blob, service);
|
return compose(returnVal, azureBlob2Blob, service);
|
||||||
|
@ -229,15 +224,14 @@ public class AzureAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
|
public ListenableFuture<BlobMetadata> blobMetadata(String container, String key) {
|
||||||
return compose(async.getBlobProperties(container, key),
|
return compose(async.getBlobProperties(container, key), new Function<BlobProperties, BlobMetadata>() {
|
||||||
new Function<BlobProperties, BlobMetadata>() {
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public BlobMetadata apply(BlobProperties from) {
|
public BlobMetadata apply(BlobProperties from) {
|
||||||
return blob2BlobMd.apply(from);
|
return blob2BlobMd.apply(from);
|
||||||
}
|
}
|
||||||
|
|
||||||
}, service);
|
}, service);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -32,7 +32,7 @@ import org.jclouds.azure.storage.queue.options.PutMessageOptions;
|
||||||
import org.jclouds.concurrent.Timeout;
|
import org.jclouds.concurrent.Timeout;
|
||||||
import org.jclouds.http.HttpResponseException;
|
import org.jclouds.http.HttpResponseException;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides access to Azure Queue via their REST API.
|
* Provides access to Azure Queue via their REST API.
|
||||||
|
@ -47,9 +47,9 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||||
* If you need to store messages larger than 8 KB, you can store message data as a blob or in a
|
* If you need to store messages larger than 8 KB, you can store message data as a blob or in a
|
||||||
* table, and then store a reference to the data as a message in a queue.
|
* table, and then store a reference to the data as a message in a queue.
|
||||||
* <p/>
|
* <p/>
|
||||||
* All commands return a ListenableFuture of the result from Azure Queue. Any exceptions incurred
|
* All commands return a Future of the result from Azure Queue. Any exceptions incurred
|
||||||
* during processing will be wrapped in an {@link ExecutionException} as documented in
|
* during processing will be wrapped in an {@link ExecutionException} as documented in
|
||||||
* {@link ListenableFuture#get()}.
|
* {@link Future#get()}.
|
||||||
*
|
*
|
||||||
* @see AzureQueueAsyncClient
|
* @see AzureQueueAsyncClient
|
||||||
* @see <a href="http://msdn.microsoft.com/en-us/library/dd135733.aspx" />
|
* @see <a href="http://msdn.microsoft.com/en-us/library/dd135733.aspx" />
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
package org.jclouds.blobstore;
|
package org.jclouds.blobstore;
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
|
||||||
|
@ -30,8 +31,6 @@ import org.jclouds.blobstore.options.GetOptions;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Provides hooks needed to run a blob store asynchronously
|
* Provides hooks needed to run a blob store asynchronously
|
||||||
*
|
*
|
||||||
|
@ -51,12 +50,12 @@ public interface AsyncBlobStore {
|
||||||
/**
|
/**
|
||||||
* @see BlobStore#listAssignableLocations
|
* @see BlobStore#listAssignableLocations
|
||||||
*/
|
*/
|
||||||
ListenableFuture<? extends Set<? extends Location>> listAssignableLocations();
|
ListenableFuture<Set<? extends Location>> listAssignableLocations();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see BlobStore#list
|
* @see BlobStore#list
|
||||||
*/
|
*/
|
||||||
ListenableFuture<? extends PageSet<? extends StorageMetadata>> list();
|
ListenableFuture<PageSet<? extends StorageMetadata>> list();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see BlobStore#containerExists
|
* @see BlobStore#containerExists
|
||||||
|
@ -71,13 +70,12 @@ public interface AsyncBlobStore {
|
||||||
/**
|
/**
|
||||||
* @see BlobStore#list(String)
|
* @see BlobStore#list(String)
|
||||||
*/
|
*/
|
||||||
ListenableFuture<? extends PageSet<? extends StorageMetadata>> list(String container);
|
ListenableFuture<PageSet<? extends StorageMetadata>> list(String container);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see BlobStore#list(String, ListContainerOptions)
|
* @see BlobStore#list(String, ListContainerOptions)
|
||||||
*/
|
*/
|
||||||
ListenableFuture<? extends PageSet<? extends StorageMetadata>> list(String container,
|
ListenableFuture<PageSet<? extends StorageMetadata>> list(String container, ListContainerOptions options);
|
||||||
ListContainerOptions options);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see BlobStore#clearContainer(String)
|
* @see BlobStore#clearContainer(String)
|
||||||
|
@ -127,12 +125,12 @@ public interface AsyncBlobStore {
|
||||||
/**
|
/**
|
||||||
* @see BlobStore#getBlob(String, String)
|
* @see BlobStore#getBlob(String, String)
|
||||||
*/
|
*/
|
||||||
ListenableFuture<? extends Blob> getBlob(String container, String key);
|
ListenableFuture<Blob> getBlob(String container, String key);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see BlobStore#getBlob(String, String, GetOptions)
|
* @see BlobStore#getBlob(String, String, GetOptions)
|
||||||
*/
|
*/
|
||||||
ListenableFuture<? extends Blob> getBlob(String container, String key, GetOptions options);
|
ListenableFuture<Blob> getBlob(String container, String key, GetOptions options);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see BlobStore#removeBlob
|
* @see BlobStore#removeBlob
|
||||||
|
|
|
@ -93,6 +93,7 @@ import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Multimaps;
|
import com.google.common.collect.Multimaps;
|
||||||
import com.google.common.io.Closeables;
|
import com.google.common.io.Closeables;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.inject.internal.Nullable;
|
import com.google.inject.internal.Nullable;
|
||||||
|
|
||||||
|
@ -114,13 +115,12 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected TransientAsyncBlobStore(BlobStoreContext context, DateService dateService,
|
protected TransientAsyncBlobStore(BlobStoreContext context, DateService dateService,
|
||||||
EncryptionService encryptionService,
|
EncryptionService encryptionService, ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
|
||||||
ConcurrentMap<String, ConcurrentMap<String, Blob>> containerToBlobs,
|
|
||||||
ConcurrentMap<String, Location> containerToLocation,
|
ConcurrentMap<String, Location> containerToLocation,
|
||||||
HttpGetOptionsListToGetOptions httpGetOptionsConverter,
|
HttpGetOptionsListToGetOptions httpGetOptionsConverter,
|
||||||
IfDirectoryReturnNameStrategy ifDirectoryReturnName, Blob.Factory blobFactory,
|
IfDirectoryReturnNameStrategy ifDirectoryReturnName, Blob.Factory blobFactory, BlobUtils blobUtils,
|
||||||
BlobUtils blobUtils, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Location defaultLocation,
|
||||||
Location defaultLocation, Set<Location> locations) {
|
Set<Location> locations) {
|
||||||
super(context, blobUtils, service, defaultLocation, locations);
|
super(context, blobUtils, service, defaultLocation, locations);
|
||||||
this.blobFactory = blobFactory;
|
this.blobFactory = blobFactory;
|
||||||
this.dateService = dateService;
|
this.dateService = dateService;
|
||||||
|
@ -137,8 +137,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
* default maxResults is 1000
|
* default maxResults is 1000
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list(
|
public ListenableFuture<PageSet<? extends StorageMetadata>> list(final String container, ListContainerOptions options) {
|
||||||
final String container, ListContainerOptions options) {
|
|
||||||
final Map<String, Blob> realContents = getContainerToBlobs().get(container);
|
final Map<String, Blob> realContents = getContainerToBlobs().get(container);
|
||||||
|
|
||||||
if (realContents == null)
|
if (realContents == null)
|
||||||
|
@ -148,10 +147,9 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
new Function<String, StorageMetadata>() {
|
new Function<String, StorageMetadata>() {
|
||||||
public StorageMetadata apply(String key) {
|
public StorageMetadata apply(String key) {
|
||||||
Blob oldBlob = realContents.get(key);
|
Blob oldBlob = realContents.get(key);
|
||||||
checkState(oldBlob != null, "blob " + key
|
checkState(oldBlob != null, "blob " + key + " is not present although it was in the list of "
|
||||||
+ " is not present although it was in the list of " + container);
|
+ container);
|
||||||
checkState(oldBlob.getMetadata() != null, "blob " + container + "/" + key
|
checkState(oldBlob.getMetadata() != null, "blob " + container + "/" + key + " has no metadata");
|
||||||
+ " has no metadata");
|
|
||||||
MutableBlobMetadata md = copy(oldBlob.getMetadata());
|
MutableBlobMetadata md = copy(oldBlob.getMetadata());
|
||||||
String directoryName = ifDirectoryReturnName.execute(md);
|
String directoryName = ifDirectoryReturnName.execute(md);
|
||||||
if (directoryName != null) {
|
if (directoryName != null) {
|
||||||
|
@ -198,13 +196,11 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
final String delimiter = options.isRecursive() ? null : "/";
|
final String delimiter = options.isRecursive() ? null : "/";
|
||||||
if (delimiter != null) {
|
if (delimiter != null) {
|
||||||
SortedSet<String> commonPrefixes = null;
|
SortedSet<String> commonPrefixes = null;
|
||||||
Iterable<String> iterable = transform(contents, new CommonPrefixes(prefix != null ? prefix
|
Iterable<String> iterable = transform(contents, new CommonPrefixes(prefix != null ? prefix : null, delimiter));
|
||||||
: null, delimiter));
|
|
||||||
commonPrefixes = iterable != null ? newTreeSet(iterable) : new TreeSet<String>();
|
commonPrefixes = iterable != null ? newTreeSet(iterable) : new TreeSet<String>();
|
||||||
commonPrefixes.remove(CommonPrefixes.NO_PREFIX);
|
commonPrefixes.remove(CommonPrefixes.NO_PREFIX);
|
||||||
|
|
||||||
contents = newTreeSet(filter(contents, new DelimiterFilter(prefix != null ? prefix : null,
|
contents = newTreeSet(filter(contents, new DelimiterFilter(prefix != null ? prefix : null, delimiter)));
|
||||||
delimiter)));
|
|
||||||
|
|
||||||
Iterables.<StorageMetadata> addAll(contents, transform(commonPrefixes,
|
Iterables.<StorageMetadata> addAll(contents, transform(commonPrefixes,
|
||||||
new Function<String, StorageMetadata>() {
|
new Function<String, StorageMetadata>() {
|
||||||
|
@ -224,13 +220,14 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return immediateFuture(new PageSetImpl<StorageMetadata>(contents, marker));
|
return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(contents,
|
||||||
|
marker));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private ContainerNotFoundException cnfe(final String name) {
|
private ContainerNotFoundException cnfe(final String name) {
|
||||||
return new ContainerNotFoundException(name, String.format("container %s not in %s", name,
|
return new ContainerNotFoundException(name, String.format("container %s not in %s", name, getContainerToBlobs()
|
||||||
getContainerToBlobs().keySet()));
|
.keySet()));
|
||||||
}
|
}
|
||||||
|
|
||||||
public static MutableBlobMetadata copy(MutableBlobMetadata in) {
|
public static MutableBlobMetadata copy(MutableBlobMetadata in) {
|
||||||
|
@ -318,17 +315,17 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list() {
|
public ListenableFuture<PageSet<? extends StorageMetadata>> list() {
|
||||||
return immediateFuture(new PageSetImpl<StorageMetadata>(transform(getContainerToBlobs()
|
return Futures.<PageSet<? extends StorageMetadata>> immediateFuture(new PageSetImpl<StorageMetadata>(transform(
|
||||||
.keySet(), new Function<String, StorageMetadata>() {
|
getContainerToBlobs().keySet(), new Function<String, StorageMetadata>() {
|
||||||
public StorageMetadata apply(String name) {
|
public StorageMetadata apply(String name) {
|
||||||
MutableStorageMetadata cmd = create();
|
MutableStorageMetadata cmd = create();
|
||||||
cmd.setName(name);
|
cmd.setName(name);
|
||||||
cmd.setType(StorageType.CONTAINER);
|
cmd.setType(StorageType.CONTAINER);
|
||||||
cmd.setLocation(getContainerToLocation().get(name));
|
cmd.setLocation(getContainerToLocation().get(name));
|
||||||
return cmd;
|
return cmd;
|
||||||
}
|
}
|
||||||
}), null));
|
}), null));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected MutableStorageMetadata create() {
|
protected MutableStorageMetadata create() {
|
||||||
|
@ -339,8 +336,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Boolean> createContainerInLocation(final Location location,
|
public ListenableFuture<Boolean> createContainerInLocation(final Location location, final String name) {
|
||||||
final String name) {
|
|
||||||
if (!getContainerToBlobs().containsKey(name)) {
|
if (!getContainerToBlobs().containsKey(name)) {
|
||||||
getContainerToBlobs().put(name, new ConcurrentHashMap<String, Blob>());
|
getContainerToBlobs().put(name, new ConcurrentHashMap<String, Blob>());
|
||||||
getContainerToLocation().put(name, location != null ? location : defaultLocation);
|
getContainerToLocation().put(name, location != null ? location : defaultLocation);
|
||||||
|
@ -407,8 +403,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T extends Comparable<?>> SortedSet<T> firstSliceOfSize(Iterable<T> elements,
|
public static <T extends Comparable<?>> SortedSet<T> firstSliceOfSize(Iterable<T> elements, int size) {
|
||||||
int size) {
|
|
||||||
List<List<T>> slices = partition(newArrayList(elements), size);
|
List<List<T>> slices = partition(newArrayList(elements), size);
|
||||||
return newTreeSet(slices.get(0));
|
return newTreeSet(slices.get(0));
|
||||||
}
|
}
|
||||||
|
@ -463,15 +458,12 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
new RuntimeException("containerName not found: " + containerName);
|
new RuntimeException("containerName not found: " + containerName);
|
||||||
}
|
}
|
||||||
|
|
||||||
ByteArrayPayload payload = (object.getPayload() instanceof ByteArrayPayload) ? ByteArrayPayload.class
|
ByteArrayPayload payload = (object.getPayload() instanceof ByteArrayPayload) ? ByteArrayPayload.class.cast(object
|
||||||
.cast(object.getPayload())
|
.getPayload()) : null;
|
||||||
: null;
|
|
||||||
if (payload == null)
|
if (payload == null)
|
||||||
payload = (object.getPayload() instanceof DelegatingPayload) ? (DelegatingPayload.class
|
payload = (object.getPayload() instanceof DelegatingPayload) ? (DelegatingPayload.class.cast(
|
||||||
.cast(object.getPayload()).getDelegate() instanceof ByteArrayPayload) ? ByteArrayPayload.class
|
object.getPayload()).getDelegate() instanceof ByteArrayPayload) ? ByteArrayPayload.class
|
||||||
.cast(DelegatingPayload.class.cast(object.getPayload()).getDelegate())
|
.cast(DelegatingPayload.class.cast(object.getPayload()).getDelegate()) : null : null;
|
||||||
: null
|
|
||||||
: null;
|
|
||||||
if (payload == null || !(payload instanceof ByteArrayPayload)) {
|
if (payload == null || !(payload instanceof ByteArrayPayload)) {
|
||||||
InputStream input = object.getPayload().getInput();
|
InputStream input = object.getPayload().getInput();
|
||||||
try {
|
try {
|
||||||
|
@ -483,8 +475,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (payload.getContentMD5() == null)
|
if (payload.getContentMD5() == null)
|
||||||
payload = (ByteArrayPayload) encryptionService
|
payload = (ByteArrayPayload) encryptionService.generateMD5BufferingIfNotRepeatable(payload);
|
||||||
.generateMD5BufferingIfNotRepeatable(payload);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Blob blob = blobFactory.create(copy(object.getMetadata()));
|
Blob blob = blobFactory.create(copy(object.getMetadata()));
|
||||||
|
@ -525,8 +516,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<? extends Blob> getBlob(final String containerName, final String key,
|
public ListenableFuture<Blob> getBlob(final String containerName, final String key, GetOptions options) {
|
||||||
GetOptions options) {
|
|
||||||
if (!getContainerToBlobs().containsKey(containerName))
|
if (!getContainerToBlobs().containsKey(containerName))
|
||||||
return immediateFailedFuture(cnfe(containerName));
|
return immediateFailedFuture(cnfe(containerName));
|
||||||
Map<String, Blob> realContents = getContainerToBlobs().get(containerName);
|
Map<String, Blob> realContents = getContainerToBlobs().get(containerName);
|
||||||
|
@ -547,9 +537,8 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
Date modifiedSince = options.getIfModifiedSince();
|
Date modifiedSince = options.getIfModifiedSince();
|
||||||
if (object.getMetadata().getLastModified().before(modifiedSince)) {
|
if (object.getMetadata().getLastModified().before(modifiedSince)) {
|
||||||
HttpResponse response = new HttpResponse(304, null, null);
|
HttpResponse response = new HttpResponse(304, null, null);
|
||||||
return immediateFailedFuture(new HttpResponseException(String.format(
|
return immediateFailedFuture(new HttpResponseException(String.format("%1$s is before %2$s", object
|
||||||
"%1$s is before %2$s", object.getMetadata().getLastModified(), modifiedSince),
|
.getMetadata().getLastModified(), modifiedSince), null, response));
|
||||||
null, response));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -557,9 +546,8 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
Date unmodifiedSince = options.getIfUnmodifiedSince();
|
Date unmodifiedSince = options.getIfUnmodifiedSince();
|
||||||
if (object.getMetadata().getLastModified().after(unmodifiedSince)) {
|
if (object.getMetadata().getLastModified().after(unmodifiedSince)) {
|
||||||
HttpResponse response = new HttpResponse(412, null, null);
|
HttpResponse response = new HttpResponse(412, null, null);
|
||||||
return immediateFailedFuture(new HttpResponseException(
|
return immediateFailedFuture(new HttpResponseException(String.format("%1$s is after %2$s", object
|
||||||
String.format("%1$s is after %2$s", object.getMetadata().getLastModified(),
|
.getMetadata().getLastModified(), unmodifiedSince), null, response));
|
||||||
unmodifiedSince), null, response));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Blob returnVal = copyBlob(object);
|
Blob returnVal = copyBlob(object);
|
||||||
|
@ -586,8 +574,7 @@ public class TransientAsyncBlobStore extends BaseAsyncBlobStore {
|
||||||
int length = (last < data.length) ? last + 1 : data.length - offset;
|
int length = (last < data.length) ? last + 1 : data.length - offset;
|
||||||
out.write(data, offset, length);
|
out.write(data, offset, length);
|
||||||
} else {
|
} else {
|
||||||
return immediateFailedFuture(new IllegalArgumentException(
|
return immediateFailedFuture(new IllegalArgumentException("first and last were null!"));
|
||||||
"first and last were null!"));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,10 +19,7 @@
|
||||||
package org.jclouds.blobstore.internal;
|
package org.jclouds.blobstore.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.util.concurrent.Futures.chain;
|
|
||||||
import static com.google.common.util.concurrent.Futures.immediateFuture;
|
|
||||||
import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
|
import static org.jclouds.blobstore.options.ListContainerOptions.Builder.recursive;
|
||||||
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
|
|
||||||
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
|
@ -41,11 +38,12 @@ import org.jclouds.blobstore.domain.StorageMetadata;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.blobstore.util.BlobUtils;
|
import org.jclouds.blobstore.util.BlobUtils;
|
||||||
import org.jclouds.blobstore.util.internal.BlobUtilsImpl;
|
import org.jclouds.blobstore.util.internal.BlobUtilsImpl;
|
||||||
|
import static org.jclouds.concurrent.ConcurrentUtils.*;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.util.Utils;
|
import org.jclouds.util.Utils;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,8 +60,8 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected BaseAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
protected BaseAsyncBlobStore(BlobStoreContext context, BlobUtils blobUtils,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service, Location defaultLocation,
|
||||||
Location defaultLocation, Set<? extends Location> locations) {
|
Set<? extends Location> locations) {
|
||||||
this.context = checkNotNull(context, "context");
|
this.context = checkNotNull(context, "context");
|
||||||
this.blobUtils = checkNotNull(blobUtils, "blobUtils");
|
this.blobUtils = checkNotNull(blobUtils, "blobUtils");
|
||||||
this.service = checkNotNull(service, "service");
|
this.service = checkNotNull(service, "service");
|
||||||
|
@ -92,7 +90,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
|
||||||
* container name
|
* container name
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<? extends PageSet<? extends StorageMetadata>> list(String container) {
|
public ListenableFuture<PageSet<? extends StorageMetadata>> list(String container) {
|
||||||
return this.list(container, org.jclouds.blobstore.options.ListContainerOptions.NONE);
|
return this.list(container, org.jclouds.blobstore.options.ListContainerOptions.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -115,8 +113,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
|
||||||
* container name
|
* container name
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Long> countBlobs(final String containerName,
|
public ListenableFuture<Long> countBlobs(final String containerName, final ListContainerOptions options) {
|
||||||
final ListContainerOptions options) {
|
|
||||||
return makeListenable(service.submit(new Callable<Long>() {
|
return makeListenable(service.submit(new Callable<Long>() {
|
||||||
public Long call() throws Exception {
|
public Long call() throws Exception {
|
||||||
return blobUtils.countBlobs(containerName, options);
|
return blobUtils.countBlobs(containerName, options);
|
||||||
|
@ -144,8 +141,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
|
||||||
* container name
|
* container name
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<Void> clearContainer(final String containerName,
|
public ListenableFuture<Void> clearContainer(final String containerName, final ListContainerOptions options) {
|
||||||
final ListContainerOptions options) {
|
|
||||||
return makeListenable(service.submit(new Callable<Void>() {
|
return makeListenable(service.submit(new Callable<Void>() {
|
||||||
|
|
||||||
public Void call() throws Exception {
|
public Void call() throws Exception {
|
||||||
|
@ -182,8 +178,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
|
||||||
* @param directory
|
* @param directory
|
||||||
* virtual path
|
* virtual path
|
||||||
*/
|
*/
|
||||||
public ListenableFuture<Boolean> directoryExists(final String containerName,
|
public ListenableFuture<Boolean> directoryExists(final String containerName, final String directory) {
|
||||||
final String directory) {
|
|
||||||
return makeListenable(service.submit(new Callable<Boolean>() {
|
return makeListenable(service.submit(new Callable<Boolean>() {
|
||||||
|
|
||||||
public Boolean call() throws Exception {
|
public Boolean call() throws Exception {
|
||||||
|
@ -204,18 +199,13 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
|
||||||
|
|
||||||
public ListenableFuture<Void> createDirectory(final String containerName, final String directory) {
|
public ListenableFuture<Void> createDirectory(final String containerName, final String directory) {
|
||||||
|
|
||||||
return chain(directoryExists(containerName, directory),
|
return blobUtils.directoryExists(containerName, directory) ? Futures.immediateFuture((Void) null)
|
||||||
new Function<Boolean, ListenableFuture<Void>>() {
|
: makeListenable(service.submit(new Callable<Void>() {
|
||||||
|
public Void call() throws Exception {
|
||||||
@Override
|
blobUtils.createDirectory(containerName, directory);
|
||||||
public ListenableFuture<Void> apply(Boolean from) {
|
return null;
|
||||||
if (!from) {
|
|
||||||
blobUtils.createDirectory(containerName, directory);
|
|
||||||
}
|
|
||||||
return immediateFuture(null);
|
|
||||||
}
|
}
|
||||||
|
}), service);
|
||||||
}, service);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -228,7 +218,7 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
|
||||||
* blob key
|
* blob key
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<? extends Blob> getBlob(String container, String key) {
|
public ListenableFuture<Blob> getBlob(String container, String key) {
|
||||||
return getBlob(container, key, org.jclouds.blobstore.options.GetOptions.NONE);
|
return getBlob(container, key, org.jclouds.blobstore.options.GetOptions.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -271,8 +261,8 @@ public abstract class BaseAsyncBlobStore implements AsyncBlobStore {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ListenableFuture<? extends Set<? extends Location>> listAssignableLocations() {
|
public ListenableFuture<Set<? extends Location>> listAssignableLocations() {
|
||||||
return immediateFuture(locations);
|
return Futures.<Set<? extends Location>> immediateFuture(locations);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected abstract boolean deleteAndVerifyContainerGone(String container);
|
protected abstract boolean deleteAndVerifyContainerGone(String container);
|
||||||
|
|
|
@ -160,8 +160,8 @@ public abstract class BaseBlobMap<V> implements ListableMap<String, V> {
|
||||||
return (int) blobstore.countBlobs(containerName, options);
|
return (int) blobstore.countBlobs(containerName, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Set<? extends Blob> getAllBlobs() {
|
protected Iterable<Blob> getAllBlobs() {
|
||||||
Set<? extends Blob> returnVal = getAllBlobs.execute(containerName, options);
|
Iterable<Blob> returnVal = getAllBlobs.execute(containerName, options);
|
||||||
if (options != null) {
|
if (options != null) {
|
||||||
for (Blob from : returnVal)
|
for (Blob from : returnVal)
|
||||||
stripPrefix(from);
|
stripPrefix(from);
|
||||||
|
|
|
@ -33,6 +33,8 @@ import org.jclouds.blobstore.strategy.GetBlobsInListStrategy;
|
||||||
import org.jclouds.blobstore.strategy.PutBlobsStrategy;
|
import org.jclouds.blobstore.strategy.PutBlobsStrategy;
|
||||||
import org.jclouds.blobstore.strategy.internal.ListContainerAndRecurseThroughFolders;
|
import org.jclouds.blobstore.strategy.internal.ListContainerAndRecurseThroughFolders;
|
||||||
|
|
||||||
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Map representation of a live connection to a Blob Service.
|
* Map representation of a live connection to a Blob Service.
|
||||||
*
|
*
|
||||||
|
@ -46,10 +48,8 @@ public class BlobMapImpl extends BaseBlobMap<Blob> implements BlobMap {
|
||||||
@Inject
|
@Inject
|
||||||
public BlobMapImpl(BlobStore blobstore, GetBlobsInListStrategy getAllBlobs,
|
public BlobMapImpl(BlobStore blobstore, GetBlobsInListStrategy getAllBlobs,
|
||||||
ContainsValueInListStrategy containsValueStrategy, PutBlobsStrategy putBlobsStrategy,
|
ContainsValueInListStrategy containsValueStrategy, PutBlobsStrategy putBlobsStrategy,
|
||||||
ListContainerAndRecurseThroughFolders listStrategy, String containerName,
|
ListContainerAndRecurseThroughFolders listStrategy, String containerName, ListContainerOptions options) {
|
||||||
ListContainerOptions options) {
|
super(blobstore, getAllBlobs, containsValueStrategy, putBlobsStrategy, listStrategy, containerName, options);
|
||||||
super(blobstore, getAllBlobs, containsValueStrategy, putBlobsStrategy, listStrategy,
|
|
||||||
containerName, options);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -89,10 +89,9 @@ public class BlobMapImpl extends BaseBlobMap<Blob> implements BlobMap {
|
||||||
return old;
|
return old;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Blob> values() {
|
public Collection<Blob> values() {
|
||||||
return (Collection<Blob>) getAllBlobs.execute(containerName, options);
|
return Sets.newLinkedHashSet(getAllBlobs.execute(containerName, options));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -37,7 +37,7 @@ import java.util.List;
|
||||||
*
|
*
|
||||||
*
|
*
|
||||||
* // this will get the first megabyte of an object, provided it wasn't modified since yesterday
|
* // this will get the first megabyte of an object, provided it wasn't modified since yesterday
|
||||||
* ListenableFuture<S3Object> object = client.get("objectName",range(0,1024).ifUnmodifiedSince(new Date().minusDays(1)));
|
* Future<S3Object> object = client.get("objectName",range(0,1024).ifUnmodifiedSince(new Date().minusDays(1)));
|
||||||
* <code>
|
* <code>
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
|
|
@ -31,7 +31,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
* import static org.jclouds.blobstore.options.ListContainerOptions.Builder.*
|
* import static org.jclouds.blobstore.options.ListContainerOptions.Builder.*
|
||||||
* <p/>
|
* <p/>
|
||||||
* BlobStore connection = // get connection
|
* BlobStore connection = // get connection
|
||||||
* ListenableFuture<ListResponse<ResourceMetadata>> list = connection.list("container",inDirectory("home/users").maxResults(1000));
|
* Future<ListResponse<ResourceMetadata>> list = connection.list("container",inDirectory("home/users").maxResults(1000));
|
||||||
* <code>
|
* <code>
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
|
|
@ -30,7 +30,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
* import static org.jclouds.blobstore.options.ListOptions.Builder.*
|
* import static org.jclouds.blobstore.options.ListOptions.Builder.*
|
||||||
* <p/>
|
* <p/>
|
||||||
* BlobStore connection = // get connection
|
* BlobStore connection = // get connection
|
||||||
* ListenableFuture<BoundedSortedSet<ResourceMetadata>> list = connection.list(maxResults(1000));
|
* Future<BoundedSortedSet<ResourceMetadata>> list = connection.list(maxResults(1000));
|
||||||
* <code>
|
* <code>
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.blobstore.strategy;
|
package org.jclouds.blobstore.strategy;
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.jclouds.blobstore.domain.Blob;
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.blobstore.strategy.internal.GetAllBlobsInListAndRetryOnFailure;
|
import org.jclouds.blobstore.strategy.internal.GetAllBlobsInListAndRetryOnFailure;
|
||||||
|
@ -34,6 +32,6 @@ import com.google.inject.ImplementedBy;
|
||||||
@ImplementedBy(GetAllBlobsInListAndRetryOnFailure.class)
|
@ImplementedBy(GetAllBlobsInListAndRetryOnFailure.class)
|
||||||
public interface GetBlobsInListStrategy {
|
public interface GetBlobsInListStrategy {
|
||||||
|
|
||||||
Set<? extends Blob> execute(String containerName, ListContainerOptions options);
|
Iterable<Blob> execute(String containerName, ListContainerOptions options);
|
||||||
|
|
||||||
}
|
}
|
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.blobstore.strategy;
|
package org.jclouds.blobstore.strategy;
|
||||||
|
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.blobstore.strategy.internal.ListContainerAndRecurseThroughFolders;
|
import org.jclouds.blobstore.strategy.internal.ListContainerAndRecurseThroughFolders;
|
||||||
|
@ -32,6 +34,6 @@ import com.google.inject.ImplementedBy;
|
||||||
@ImplementedBy(ListContainerAndRecurseThroughFolders.class)
|
@ImplementedBy(ListContainerAndRecurseThroughFolders.class)
|
||||||
public interface ListBlobsInContainer {
|
public interface ListBlobsInContainer {
|
||||||
|
|
||||||
Iterable<? extends BlobMetadata> execute(String containerName, ListContainerOptions options);
|
Set<? extends BlobMetadata> execute(String containerName, ListContainerOptions options);
|
||||||
|
|
||||||
}
|
}
|
|
@ -43,7 +43,7 @@ import org.jclouds.logging.Logger;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import java.util.concurrent.Future;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -93,7 +93,7 @@ public class DeleteAllKeysInList implements ClearListStrategy, ClearContainerStr
|
||||||
Map<StorageMetadata, Exception> exceptions = Maps.newHashMap();
|
Map<StorageMetadata, Exception> exceptions = Maps.newHashMap();
|
||||||
Iterable<? extends StorageMetadata> toDelete = getResourcesToDelete(containerName, options);
|
Iterable<? extends StorageMetadata> toDelete = getResourcesToDelete(containerName, options);
|
||||||
for (int i = 0; i < 3; i++) { // TODO parameterize
|
for (int i = 0; i < 3; i++) { // TODO parameterize
|
||||||
Map<StorageMetadata, ListenableFuture<?>> responses = Maps.newHashMap();
|
Map<StorageMetadata, Future<?>> responses = Maps.newHashMap();
|
||||||
try {
|
try {
|
||||||
for (final StorageMetadata md : toDelete) {
|
for (final StorageMetadata md : toDelete) {
|
||||||
String fullPath = parentIsFolder(options, md) ? options.getDir() + "/"
|
String fullPath = parentIsFolder(options, md) ? options.getDir() + "/"
|
||||||
|
|
|
@ -19,13 +19,10 @@
|
||||||
package org.jclouds.blobstore.strategy.internal;
|
package org.jclouds.blobstore.strategy.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
|
import static org.jclouds.concurrent.ConcurrentUtils.transformParallel;
|
||||||
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.annotation.concurrent.NotThreadSafe;
|
import javax.annotation.concurrent.NotThreadSafe;
|
||||||
|
@ -33,20 +30,18 @@ import javax.inject.Named;
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.blobstore.AsyncBlobStore;
|
import org.jclouds.blobstore.AsyncBlobStore;
|
||||||
|
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||||
import org.jclouds.blobstore.domain.PageSet;
|
import org.jclouds.blobstore.domain.PageSet;
|
||||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||||
import org.jclouds.blobstore.domain.StorageType;
|
import org.jclouds.blobstore.domain.StorageType;
|
||||||
import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
import org.jclouds.blobstore.domain.internal.PageSetImpl;
|
||||||
import org.jclouds.blobstore.internal.BlobRuntimeException;
|
|
||||||
import org.jclouds.blobstore.reference.BlobStoreConstants;
|
import org.jclouds.blobstore.reference.BlobStoreConstants;
|
||||||
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -55,8 +50,7 @@ import com.google.inject.Inject;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@NotThreadSafe
|
@NotThreadSafe
|
||||||
public class FetchBlobMetadata implements
|
public class FetchBlobMetadata implements Function<PageSet<? extends StorageMetadata>, PageSet<? extends StorageMetadata>> {
|
||||||
Function<PageSet<? extends StorageMetadata>, PageSet<? extends StorageMetadata>> {
|
|
||||||
|
|
||||||
protected final BackoffLimitedRetryHandler retryHandler;
|
protected final BackoffLimitedRetryHandler retryHandler;
|
||||||
protected final AsyncBlobStore ablobstore;
|
protected final AsyncBlobStore ablobstore;
|
||||||
|
@ -74,8 +68,8 @@ public class FetchBlobMetadata implements
|
||||||
protected Long maxTime;
|
protected Long maxTime;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
FetchBlobMetadata(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
|
FetchBlobMetadata(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, AsyncBlobStore ablobstore,
|
||||||
AsyncBlobStore ablobstore, BackoffLimitedRetryHandler retryHandler) {
|
BackoffLimitedRetryHandler retryHandler) {
|
||||||
this.userExecutor = userExecutor;
|
this.userExecutor = userExecutor;
|
||||||
this.ablobstore = ablobstore;
|
this.ablobstore = ablobstore;
|
||||||
this.retryHandler = retryHandler;
|
this.retryHandler = retryHandler;
|
||||||
|
@ -88,35 +82,23 @@ public class FetchBlobMetadata implements
|
||||||
|
|
||||||
public PageSet<? extends StorageMetadata> apply(PageSet<? extends StorageMetadata> in) {
|
public PageSet<? extends StorageMetadata> apply(PageSet<? extends StorageMetadata> in) {
|
||||||
checkState(container != null, "container name should be initialized");
|
checkState(container != null, "container name should be initialized");
|
||||||
Map<? extends StorageMetadata, Exception> exceptions = Maps.newHashMap();
|
|
||||||
final Set<StorageMetadata> metadata = Sets.newHashSet();
|
Iterable<BlobMetadata> returnv = transformParallel(Iterables.filter(in, new Predicate<StorageMetadata>() {
|
||||||
Map<StorageMetadata, ListenableFuture<?>> responses = Maps.newHashMap();
|
|
||||||
for (StorageMetadata md : in) {
|
@Override
|
||||||
if (md.getType() == StorageType.BLOB) {
|
public boolean apply(StorageMetadata input) {
|
||||||
final ListenableFuture<? extends StorageMetadata> future = ablobstore.blobMetadata(
|
return input.getType() == StorageType.BLOB;
|
||||||
container, md.getName());
|
|
||||||
future.addListener(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
metadata.add(future.get());
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Throwables.propagate(e);
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
Throwables.propagate(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, sameThreadExecutor());
|
|
||||||
responses.put(md, future);
|
|
||||||
} else {
|
|
||||||
metadata.add(md);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, String.format(
|
}), new Function<StorageMetadata, Future<BlobMetadata>>() {
|
||||||
"getting metadata from containerName: %s", container));
|
|
||||||
if (exceptions.size() > 0)
|
@Override
|
||||||
throw new BlobRuntimeException(String.format("errors getting from container %s: %s",
|
public Future<BlobMetadata> apply(StorageMetadata from) {
|
||||||
container, exceptions));
|
return ablobstore.blobMetadata(container, from.getName());
|
||||||
return new PageSetImpl<StorageMetadata>(metadata, in.getNextMarker());
|
}
|
||||||
|
|
||||||
|
}, userExecutor, maxTime, logger, String.format("getting metadata from containerName: %s", container));
|
||||||
|
|
||||||
|
return new PageSetImpl<BlobMetadata>(returnv, in.getNextMarker());
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -18,13 +18,10 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.blobstore.strategy.internal;
|
package org.jclouds.blobstore.strategy.internal;
|
||||||
|
|
||||||
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
|
import static org.jclouds.concurrent.ConcurrentUtils.transformParallel;
|
||||||
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
@ -34,7 +31,6 @@ import org.jclouds.Constants;
|
||||||
import org.jclouds.blobstore.AsyncBlobStore;
|
import org.jclouds.blobstore.AsyncBlobStore;
|
||||||
import org.jclouds.blobstore.domain.Blob;
|
import org.jclouds.blobstore.domain.Blob;
|
||||||
import org.jclouds.blobstore.domain.BlobMetadata;
|
import org.jclouds.blobstore.domain.BlobMetadata;
|
||||||
import org.jclouds.blobstore.internal.BlobRuntimeException;
|
|
||||||
import org.jclouds.blobstore.options.ListContainerOptions;
|
import org.jclouds.blobstore.options.ListContainerOptions;
|
||||||
import org.jclouds.blobstore.reference.BlobStoreConstants;
|
import org.jclouds.blobstore.reference.BlobStoreConstants;
|
||||||
import org.jclouds.blobstore.strategy.GetBlobsInListStrategy;
|
import org.jclouds.blobstore.strategy.GetBlobsInListStrategy;
|
||||||
|
@ -42,10 +38,7 @@ import org.jclouds.blobstore.strategy.ListBlobsInContainer;
|
||||||
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.collect.Maps;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -72,52 +65,24 @@ public class GetAllBlobsInListAndRetryOnFailure implements GetBlobsInListStrateg
|
||||||
protected Long maxTime;
|
protected Long maxTime;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
GetAllBlobsInListAndRetryOnFailure(
|
GetAllBlobsInListAndRetryOnFailure(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor,
|
ListBlobsInContainer getAllBlobMetadata, AsyncBlobStore ablobstore, BackoffLimitedRetryHandler retryHandler) {
|
||||||
ListBlobsInContainer getAllBlobMetadata, AsyncBlobStore ablobstore,
|
|
||||||
BackoffLimitedRetryHandler retryHandler) {
|
|
||||||
this.userExecutor = userExecutor;
|
this.userExecutor = userExecutor;
|
||||||
this.ablobstore = ablobstore;
|
this.ablobstore = ablobstore;
|
||||||
this.getAllBlobMetadata = getAllBlobMetadata;
|
this.getAllBlobMetadata = getAllBlobMetadata;
|
||||||
this.retryHandler = retryHandler;
|
this.retryHandler = retryHandler;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Set<? extends Blob> execute(String container, ListContainerOptions options) {
|
public Iterable<Blob> execute(final String container, ListContainerOptions options) {
|
||||||
Map<BlobMetadata, Exception> exceptions = Maps.newHashMap();
|
Iterable<? extends BlobMetadata> list = getAllBlobMetadata.execute(container, options);
|
||||||
final Set<Blob> objects = Sets.newHashSet();
|
return transformParallel(list, new Function<BlobMetadata, Future<Blob>>() {
|
||||||
Iterable<? extends BlobMetadata> toGet = getAllBlobMetadata.execute(container, options);
|
|
||||||
for (int i = 0; i < 3; i++) {
|
@Override
|
||||||
Map<BlobMetadata, ListenableFuture<?>> responses = Maps.newHashMap();
|
public Future<Blob> apply(BlobMetadata from) {
|
||||||
for (BlobMetadata md : toGet) {
|
return ablobstore.getBlob(container, from.getName());
|
||||||
final ListenableFuture<? extends Blob> future = ablobstore.getBlob(container, md
|
|
||||||
.getName());
|
|
||||||
future.addListener(new Runnable() {
|
|
||||||
@Override
|
|
||||||
public void run() {
|
|
||||||
try {
|
|
||||||
objects.add(future.get());
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
Throwables.propagate(e);
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
Throwables.propagate(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, sameThreadExecutor());
|
|
||||||
responses.put(md, future);
|
|
||||||
}
|
}
|
||||||
exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, String.format(
|
|
||||||
"getting from containerName: %s", container));
|
}, userExecutor, maxTime, logger, String.format("getting from containerName: %s", container), retryHandler, 3);
|
||||||
if (exceptions.size() > 0) {
|
|
||||||
toGet = exceptions.keySet();
|
|
||||||
retryHandler.imposeBackoffExponentialDelay(i + 1, String.format("blob %s/%s not found",
|
|
||||||
container, toGet));
|
|
||||||
} else {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if (exceptions.size() > 0)
|
|
||||||
throw new BlobRuntimeException(String.format("errors getting from container %s: %s",
|
|
||||||
container, exceptions));
|
|
||||||
return objects;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -18,7 +18,14 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.blobstore.strategy.internal;
|
package org.jclouds.blobstore.strategy.internal;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Iterables.concat;
|
||||||
|
import static com.google.common.collect.Iterables.filter;
|
||||||
|
import static com.google.common.collect.Iterables.transform;
|
||||||
|
import static com.google.common.collect.Lists.newArrayList;
|
||||||
|
import static com.google.common.collect.Sets.newLinkedHashSet;
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
@ -31,9 +38,6 @@ import org.jclouds.blobstore.strategy.ListContainerStrategy;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import com.google.common.collect.Lists;
|
|
||||||
import com.google.common.collect.Sets;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -52,22 +56,20 @@ public class ListContainerAndRecurseThroughFolders implements ListBlobsInContain
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterable<? extends BlobMetadata> execute(final String containerName,
|
public Set<? extends BlobMetadata> execute(final String containerName, final ListContainerOptions options) {
|
||||||
final ListContainerOptions options) {
|
final List<Iterable<? extends BlobMetadata>> lists = newArrayList();
|
||||||
final List<Iterable<? extends BlobMetadata>> lists = Lists.newArrayList();
|
|
||||||
Iterable<? extends StorageMetadata> pwdList = lister.execute(containerName, options);
|
Iterable<? extends StorageMetadata> pwdList = lister.execute(containerName, options);
|
||||||
for (StorageMetadata md : Iterables.filter(pwdList, new Predicate<StorageMetadata>() {
|
for (StorageMetadata md : filter(pwdList, new Predicate<StorageMetadata>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(StorageMetadata input) {
|
public boolean apply(StorageMetadata input) {
|
||||||
return (input.getType() == StorageType.FOLDER || input.getType() == StorageType.RELATIVE_PATH)
|
return (input.getType() == StorageType.FOLDER || input.getType() == StorageType.RELATIVE_PATH)
|
||||||
&& options.isRecursive();
|
&& options.isRecursive();
|
||||||
}
|
}
|
||||||
})) {
|
})) {
|
||||||
String directory = (options.getDir() != null) ? options.getDir() + "/" + md.getName() : md
|
String directory = (options.getDir() != null) ? options.getDir() + "/" + md.getName() : md.getName();
|
||||||
.getName();
|
|
||||||
lists.add(execute(containerName, options.clone().inDirectory(directory)));
|
lists.add(execute(containerName, options.clone().inDirectory(directory)));
|
||||||
}
|
}
|
||||||
lists.add(Iterables.transform(Iterables.filter(pwdList, new Predicate<StorageMetadata>() {
|
lists.add(transform(filter(pwdList, new Predicate<StorageMetadata>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(StorageMetadata input) {
|
public boolean apply(StorageMetadata input) {
|
||||||
return input.getType() == StorageType.BLOB;
|
return input.getType() == StorageType.BLOB;
|
||||||
|
@ -78,6 +80,6 @@ public class ListContainerAndRecurseThroughFolders implements ListBlobsInContain
|
||||||
return (BlobMetadata) from;
|
return (BlobMetadata) from;
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
return Sets.newHashSet(Iterables.concat(lists));
|
return newLinkedHashSet(concat(lists));
|
||||||
}
|
}
|
||||||
}
|
}
|
|
@ -38,7 +38,7 @@ import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import java.util.concurrent.Future;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -92,7 +92,7 @@ public class MarkersDeleteDirectoryStrategy implements DeleteDirectoryStrategy {
|
||||||
for (String suffix : BlobStoreConstants.DIRECTORY_SUFFIXES) {
|
for (String suffix : BlobStoreConstants.DIRECTORY_SUFFIXES) {
|
||||||
names.add(directory + suffix);
|
names.add(directory + suffix);
|
||||||
}
|
}
|
||||||
Map<String, ListenableFuture<?>> responses = Maps.newHashMap();
|
Map<String, Future<?>> responses = Maps.newHashMap();
|
||||||
for (String name : names) {
|
for (String name : names) {
|
||||||
responses.put(name, ablobstore.removeBlob(containerName, name));
|
responses.put(name, ablobstore.removeBlob(containerName, name));
|
||||||
}
|
}
|
||||||
|
|
|
@ -36,7 +36,7 @@ import org.jclouds.blobstore.strategy.PutBlobsStrategy;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import java.util.concurrent.Future;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,7 +67,7 @@ public class PutBlobsStrategyImpl implements PutBlobsStrategy {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void execute(String containerName, Iterable<? extends Blob> blobs) {
|
public void execute(String containerName, Iterable<? extends Blob> blobs) {
|
||||||
Map<Blob, ListenableFuture<?>> responses = Maps.newHashMap();
|
Map<Blob, Future<?>> responses = Maps.newHashMap();
|
||||||
for (Blob blob : blobs) {
|
for (Blob blob : blobs) {
|
||||||
responses.put(blob, ablobstore.putBlob(containerName, blob));
|
responses.put(blob, ablobstore.putBlob(containerName, blob));
|
||||||
}
|
}
|
||||||
|
|
|
@ -38,6 +38,7 @@ import java.io.UnsupportedEncodingException;
|
||||||
import java.security.NoSuchAlgorithmException;
|
import java.security.NoSuchAlgorithmException;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
import java.util.zip.GZIPInputStream;
|
import java.util.zip.GZIPInputStream;
|
||||||
|
|
||||||
import javax.ws.rs.core.MediaType;
|
import javax.ws.rs.core.MediaType;
|
||||||
|
@ -48,6 +49,7 @@ import org.jclouds.blobstore.domain.BlobMetadata;
|
||||||
import org.jclouds.blobstore.domain.PageSet;
|
import org.jclouds.blobstore.domain.PageSet;
|
||||||
import org.jclouds.blobstore.domain.StorageMetadata;
|
import org.jclouds.blobstore.domain.StorageMetadata;
|
||||||
import org.jclouds.blobstore.domain.StorageType;
|
import org.jclouds.blobstore.domain.StorageType;
|
||||||
|
import static org.jclouds.concurrent.ConcurrentUtils.*;
|
||||||
import org.jclouds.encryption.EncryptionService;
|
import org.jclouds.encryption.EncryptionService;
|
||||||
import org.jclouds.encryption.internal.JCEEncryptionService;
|
import org.jclouds.encryption.internal.JCEEncryptionService;
|
||||||
import org.jclouds.http.BaseJettyTest;
|
import org.jclouds.http.BaseJettyTest;
|
||||||
|
@ -68,8 +70,6 @@ import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.io.ByteStreams;
|
import com.google.common.io.ByteStreams;
|
||||||
import com.google.common.io.InputSupplier;
|
import com.google.common.io.InputSupplier;
|
||||||
import com.google.common.util.concurrent.Futures;
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -90,7 +90,7 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static InputSupplier<InputStream> getTestDataSupplier() throws IOException {
|
public static InputSupplier<InputStream> getTestDataSupplier() throws IOException {
|
||||||
byte[] oneConstitution = ByteStreams.toByteArray(new GZIPInputStream(BaseJettyTest.class
|
byte[] oneConstitution = ByteStreams.toByteArray(new GZIPInputStream(BaseJettyTest.class
|
||||||
.getResourceAsStream("/const.txt.gz")));
|
.getResourceAsStream("/const.txt.gz")));
|
||||||
InputSupplier<ByteArrayInputStream> constitutionSupplier = ByteStreams.newInputStreamSupplier(oneConstitution);
|
InputSupplier<ByteArrayInputStream> constitutionSupplier = ByteStreams.newInputStreamSupplier(oneConstitution);
|
||||||
|
|
||||||
InputSupplier<InputStream> temp = ByteStreams.join(constitutionSupplier);
|
InputSupplier<InputStream> temp = ByteStreams.join(constitutionSupplier);
|
||||||
|
@ -108,23 +108,23 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
String key = "constitution.txt";
|
String key = "constitution.txt";
|
||||||
|
|
||||||
uploadConstitution(containerName, key);
|
uploadConstitution(containerName, key);
|
||||||
Map<Integer, ListenableFuture<?>> responses = Maps.newHashMap();
|
Map<Integer, Future<?>> responses = Maps.newHashMap();
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
|
|
||||||
responses.put(i, Futures.compose(context.getAsyncBlobStore().getBlob(containerName, key),
|
responses.put(i, compose(context.getAsyncBlobStore().getBlob(containerName, key),
|
||||||
new Function<Blob, Void>() {
|
new Function<Blob, Void>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Void apply(Blob from) {
|
public Void apply(Blob from) {
|
||||||
assertEquals(context.utils().encryption().md5(from.getPayload().getInput()),
|
assertEquals(context.utils().encryption().md5(from.getPayload().getInput()),
|
||||||
oneHundredOneConstitutionsMD5);
|
oneHundredOneConstitutionsMD5);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
}));
|
}, this.exec));
|
||||||
}
|
}
|
||||||
Map<Integer, Exception> exceptions = awaitCompletion(responses, exec, 30000l, Logger.CONSOLE,
|
Map<Integer, Exception> exceptions = awaitCompletion(responses, exec, 30000l, Logger.CONSOLE,
|
||||||
"get constitution");
|
"get constitution");
|
||||||
assert exceptions.size() == 0 : exceptions;
|
assert exceptions.size() == 0 : exceptions;
|
||||||
|
|
||||||
} finally {
|
} finally {
|
||||||
|
@ -349,8 +349,8 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
|
|
||||||
@DataProvider(name = "delete")
|
@DataProvider(name = "delete")
|
||||||
public Object[][] createData() {
|
public Object[][] createData() {
|
||||||
return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" },
|
return new Object[][] { { "normal" }, { "sp ace" }, { "qu?stion" }, { "unic₪de" }, { "path/foo" }, { "colon:" },
|
||||||
{ "colon:" }, { "asteri*k" }, { "quote\"" }, { "{great<r}" }, { "lesst>en" }, { "p|pe" } };
|
{ "asteri*k" }, { "quote\"" }, { "{great<r}" }, { "lesst>en" }, { "p|pe" } };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(groups = { "integration", "live" }, dataProvider = "delete")
|
@Test(groups = { "integration", "live" }, dataProvider = "delete")
|
||||||
|
@ -367,17 +367,17 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
|
|
||||||
private void assertContainerEmptyDeleting(String containerName, String key) {
|
private void assertContainerEmptyDeleting(String containerName, String key) {
|
||||||
Iterable<? extends StorageMetadata> listing = Iterables.filter(context.getBlobStore().list(containerName),
|
Iterable<? extends StorageMetadata> listing = Iterables.filter(context.getBlobStore().list(containerName),
|
||||||
new Predicate<StorageMetadata>() {
|
new Predicate<StorageMetadata>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(StorageMetadata input) {
|
public boolean apply(StorageMetadata input) {
|
||||||
return input.getType() == StorageType.BLOB;
|
return input.getType() == StorageType.BLOB;
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
assertEquals(Iterables.size(listing), 0, String.format(
|
assertEquals(Iterables.size(listing), 0, String.format(
|
||||||
"deleting %s, we still have %s blobs left in container %s, using encoding %s", key,
|
"deleting %s, we still have %s blobs left in container %s, using encoding %s", key, Iterables
|
||||||
Iterables.size(listing), containerName, LOCAL_ENCODING));
|
.size(listing), containerName, LOCAL_ENCODING));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(groups = { "integration", "live" })
|
@Test(groups = { "integration", "live" })
|
||||||
|
@ -397,13 +397,13 @@ public class BaseBlobIntegrationTest extends BaseBlobStoreIntegrationTest {
|
||||||
String realObject = Utils.toStringAndClose(new FileInputStream("pom.xml"));
|
String realObject = Utils.toStringAndClose(new FileInputStream("pom.xml"));
|
||||||
|
|
||||||
return new Object[][] { { "file", "text/xml", new File("pom.xml"), realObject },
|
return new Object[][] { { "file", "text/xml", new File("pom.xml"), realObject },
|
||||||
{ "string", "text/xml", realObject, realObject },
|
{ "string", "text/xml", realObject, realObject },
|
||||||
{ "bytes", "application/octet-stream", realObject.getBytes(), realObject } };
|
{ "bytes", "application/octet-stream", realObject.getBytes(), realObject } };
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(groups = { "integration", "live" }, dataProvider = "putTests")
|
@Test(groups = { "integration", "live" }, dataProvider = "putTests")
|
||||||
public void testPutObject(String key, String type, Object content, Object realObject) throws InterruptedException,
|
public void testPutObject(String key, String type, Object content, Object realObject) throws InterruptedException,
|
||||||
IOException {
|
IOException {
|
||||||
Blob blob = context.getBlobStore().newBlob(key);
|
Blob blob = context.getBlobStore().newBlob(key);
|
||||||
blob.getMetadata().setContentType(type);
|
blob.getMetadata().setContentType(type);
|
||||||
blob.setPayload(Payloads.newPayload(content));
|
blob.setPayload(Payloads.newPayload(content));
|
||||||
|
|
|
@ -56,21 +56,17 @@ import com.google.common.io.Files;
|
||||||
|
|
||||||
public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegrationTest {
|
public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegrationTest {
|
||||||
|
|
||||||
public abstract void testPutAll() throws InterruptedException, ExecutionException,
|
public abstract void testPutAll() throws InterruptedException, ExecutionException, TimeoutException;
|
||||||
TimeoutException;
|
|
||||||
|
|
||||||
public abstract void testEntrySet() throws IOException, InterruptedException,
|
public abstract void testEntrySet() throws IOException, InterruptedException, ExecutionException, TimeoutException;
|
||||||
ExecutionException, TimeoutException;
|
|
||||||
|
|
||||||
public abstract void testValues() throws IOException, InterruptedException, ExecutionException,
|
public abstract void testValues() throws IOException, InterruptedException, ExecutionException, TimeoutException;
|
||||||
TimeoutException;
|
|
||||||
|
|
||||||
protected Map<String, byte[]> fiveBytes = Maps.transformValues(fiveStrings,
|
protected Map<String, byte[]> fiveBytes = Maps.transformValues(fiveStrings, new Function<String, byte[]>() {
|
||||||
new Function<String, byte[]>() {
|
public byte[] apply(String from) {
|
||||||
public byte[] apply(String from) {
|
return from.getBytes();
|
||||||
return from.getBytes();
|
}
|
||||||
}
|
});
|
||||||
});
|
|
||||||
protected Map<String, InputStream> fiveInputs;
|
protected Map<String, InputStream> fiveInputs;
|
||||||
protected Map<String, File> fiveFiles;
|
protected Map<String, File> fiveFiles;
|
||||||
String tmpDirectory;
|
String tmpDirectory;
|
||||||
|
@ -86,13 +82,13 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
|
||||||
|
|
||||||
@BeforeClass(groups = { "integration", "live" })
|
@BeforeClass(groups = { "integration", "live" })
|
||||||
@Parameters( { "basedir" })
|
@Parameters( { "basedir" })
|
||||||
protected void setUpTempDir(@Optional String basedir) throws InterruptedException,
|
protected void setUpTempDir(@Optional String basedir) throws InterruptedException, ExecutionException,
|
||||||
ExecutionException, FileNotFoundException, IOException, TimeoutException {
|
FileNotFoundException, IOException, TimeoutException {
|
||||||
if (basedir == null) {
|
if (basedir == null) {
|
||||||
basedir = System.getProperty("java.io.tmpdir");
|
basedir = System.getProperty("java.io.tmpdir");
|
||||||
}
|
}
|
||||||
tmpDirectory = basedir + File.separator + "target" + File.separator + "testFiles"
|
tmpDirectory = basedir + File.separator + "target" + File.separator + "testFiles" + File.separator
|
||||||
+ File.separator + getClass().getSimpleName();
|
+ getClass().getSimpleName();
|
||||||
new File(tmpDirectory).mkdirs();
|
new File(tmpDirectory).mkdirs();
|
||||||
fiveFiles = Maps.newHashMap();
|
fiveFiles = Maps.newHashMap();
|
||||||
for (Entry<String, String> entry : fiveStrings.entrySet()) {
|
for (Entry<String, String> entry : fiveStrings.entrySet()) {
|
||||||
|
@ -123,8 +119,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(groups = { "integration", "live" })
|
@Test(groups = { "integration", "live" })
|
||||||
public abstract void testRemove() throws IOException, InterruptedException, ExecutionException,
|
public abstract void testRemove() throws IOException, InterruptedException, ExecutionException, TimeoutException;
|
||||||
TimeoutException;
|
|
||||||
|
|
||||||
@Test(groups = { "integration", "live" })
|
@Test(groups = { "integration", "live" })
|
||||||
public void testKeySet() throws InterruptedException, ExecutionException, TimeoutException {
|
public void testKeySet() throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
|
@ -140,8 +135,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void addTenObjectsUnderPrefix(String containerName, String prefix)
|
protected void addTenObjectsUnderPrefix(String containerName, String prefix) throws InterruptedException {
|
||||||
throws InterruptedException {
|
|
||||||
for (int i = 0; i < 10; i++) {
|
for (int i = 0; i < 10; i++) {
|
||||||
Blob blob = context.getBlobStore().newBlob(prefix + "/" + i);
|
Blob blob = context.getBlobStore().newBlob(prefix + "/" + i);
|
||||||
blob.setPayload(i + "content");
|
blob.setPayload(i + "content");
|
||||||
|
@ -160,14 +154,12 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
|
||||||
@Test(groups = { "integration", "live" })
|
@Test(groups = { "integration", "live" })
|
||||||
public void testDirectory() throws InterruptedException, UnsupportedEncodingException {
|
public void testDirectory() throws InterruptedException, UnsupportedEncodingException {
|
||||||
String containerName = getContainerName();
|
String containerName = getContainerName();
|
||||||
|
String directory = "apps";
|
||||||
|
Map<String, V> rootMap = createMap(context, containerName);
|
||||||
|
Map<String, V> rootRecursiveMap = createMap(context, containerName, recursive());
|
||||||
|
Map<String, V> inDirectoryMap = createMap(context, containerName, inDirectory(directory));
|
||||||
|
Map<String, V> inDirectoryRecursiveMap = createMap(context, containerName, inDirectory(directory).recursive());
|
||||||
try {
|
try {
|
||||||
String directory = "apps";
|
|
||||||
|
|
||||||
Map<String, V> rootMap = createMap(context, containerName);
|
|
||||||
Map<String, V> rootRecursiveMap = createMap(context, containerName, recursive());
|
|
||||||
Map<String, V> inDirectoryMap = createMap(context, containerName, inDirectory(directory));
|
|
||||||
Map<String, V> inDirectoryRecursiveMap = createMap(context, containerName, inDirectory(
|
|
||||||
directory).recursive());
|
|
||||||
|
|
||||||
context.getBlobStore().createDirectory(containerName, directory);
|
context.getBlobStore().createDirectory(containerName, directory);
|
||||||
addTenObjectsUnderRoot(containerName);
|
addTenObjectsUnderRoot(containerName);
|
||||||
|
@ -206,24 +198,22 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertConsistencyAwareKeySetEquals(final Map<String, V> map,
|
protected void assertConsistencyAwareKeySetEquals(final Map<String, V> map, final Set<String> expected)
|
||||||
final Set<String> expected) throws InterruptedException {
|
throws InterruptedException {
|
||||||
assertConsistencyAware(new Runnable() {
|
assertConsistencyAware(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
Set<String> toMatch = map.keySet();
|
Set<String> toMatch = map.keySet();
|
||||||
Set<String> shouldBeEmpty = Sets.difference(expected, toMatch);
|
Set<String> shouldBeEmpty = Sets.difference(expected, toMatch);
|
||||||
assert shouldBeEmpty.size() == 0 : "toMatch has less keys than expected. missing: "
|
assert shouldBeEmpty.size() == 0 : "toMatch has less keys than expected. missing: " + shouldBeEmpty;
|
||||||
+ shouldBeEmpty;
|
|
||||||
shouldBeEmpty = Sets.difference(toMatch, expected);
|
shouldBeEmpty = Sets.difference(toMatch, expected);
|
||||||
assert shouldBeEmpty.size() == 0 : "toMatch has more keys than expected. extras: "
|
assert shouldBeEmpty.size() == 0 : "toMatch has more keys than expected. extras: " + shouldBeEmpty;
|
||||||
+ shouldBeEmpty;
|
|
||||||
assertEquals(Sets.newTreeSet(toMatch), Sets.newTreeSet(expected));
|
assertEquals(Sets.newTreeSet(toMatch), Sets.newTreeSet(expected));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertConsistencyAwareRemoveEquals(final Map<String, V> map, final String key,
|
protected void assertConsistencyAwareRemoveEquals(final Map<String, V> map, final String key, final Object equals)
|
||||||
final Object equals) throws InterruptedException {
|
throws InterruptedException {
|
||||||
assertConsistencyAware(new Runnable() {
|
assertConsistencyAware(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
assertEquals(map.remove(key), equals);
|
assertEquals(map.remove(key), equals);
|
||||||
|
@ -231,8 +221,8 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertConsistencyAwareGetEquals(final Map<String, V> map, final String key,
|
protected void assertConsistencyAwareGetEquals(final Map<String, V> map, final String key, final Object equals)
|
||||||
final Object equals) throws InterruptedException {
|
throws InterruptedException {
|
||||||
assertConsistencyAware(new Runnable() {
|
assertConsistencyAware(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
assertEquals(map.get(key), equals);
|
assertEquals(map.get(key), equals);
|
||||||
|
@ -240,8 +230,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertConsistencyAwareKeySize(final Map<String, V> map, final int size)
|
protected void assertConsistencyAwareKeySize(final Map<String, V> map, final int size) throws InterruptedException {
|
||||||
throws InterruptedException {
|
|
||||||
assertConsistencyAware(new Runnable() {
|
assertConsistencyAware(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
assertEquals(map.keySet().size(), size);
|
assertEquals(map.keySet().size(), size);
|
||||||
|
@ -275,8 +264,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertConsistencyAwareContainsKey(final Map<String, V> map)
|
protected void assertConsistencyAwareContainsKey(final Map<String, V> map) throws InterruptedException {
|
||||||
throws InterruptedException {
|
|
||||||
assertConsistencyAware(new Runnable() {
|
assertConsistencyAware(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
assert map.containsKey("one");
|
assert map.containsKey("one");
|
||||||
|
@ -284,8 +272,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertConsistencyAwareDoesntContainKey(final Map<String, V> map)
|
protected void assertConsistencyAwareDoesntContainKey(final Map<String, V> map) throws InterruptedException {
|
||||||
throws InterruptedException {
|
|
||||||
assertConsistencyAware(new Runnable() {
|
assertConsistencyAware(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
assert !map.containsKey("one");
|
assert !map.containsKey("one");
|
||||||
|
@ -306,8 +293,7 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertConsistencyAwareNotEmpty(final Map<String, V> map)
|
protected void assertConsistencyAwareNotEmpty(final Map<String, V> map) throws InterruptedException {
|
||||||
throws InterruptedException {
|
|
||||||
assertConsistencyAware(new Runnable() {
|
assertConsistencyAware(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
assert !map.isEmpty();
|
assert !map.isEmpty();
|
||||||
|
@ -323,18 +309,16 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
abstract protected void putStringWithMD5(Map<String, V> map, String key, String value)
|
abstract protected void putStringWithMD5(Map<String, V> map, String key, String value) throws InterruptedException,
|
||||||
throws InterruptedException, ExecutionException, TimeoutException;
|
ExecutionException, TimeoutException;
|
||||||
|
|
||||||
protected void fourLeftRemovingOne(Map<String, V> map) throws InterruptedException {
|
protected void fourLeftRemovingOne(Map<String, V> map) throws InterruptedException {
|
||||||
map.remove("one");
|
map.remove("one");
|
||||||
assertConsistencyAwareMapSize(map, 4);
|
assertConsistencyAwareMapSize(map, 4);
|
||||||
assertConsistencyAwareKeySetEquals(map, new TreeSet<String>(ImmutableSet.of("two", "three",
|
assertConsistencyAwareKeySetEquals(map, new TreeSet<String>(ImmutableSet.of("two", "three", "four", "five")));
|
||||||
"four", "five")));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertConsistencyAwareMapSize(final Map<String, V> map, final int size)
|
protected void assertConsistencyAwareMapSize(final Map<String, V> map, final int size) throws InterruptedException {
|
||||||
throws InterruptedException {
|
|
||||||
assertConsistencyAware(new Runnable() {
|
assertConsistencyAware(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
assertEquals(map.size(), size);
|
assertEquals(map.size(), size);
|
||||||
|
@ -343,12 +327,10 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(groups = { "integration", "live" })
|
@Test(groups = { "integration", "live" })
|
||||||
public abstract void testPut() throws IOException, InterruptedException, ExecutionException,
|
public abstract void testPut() throws IOException, InterruptedException, ExecutionException, TimeoutException;
|
||||||
TimeoutException;
|
|
||||||
|
|
||||||
@Test(groups = { "integration", "live" })
|
@Test(groups = { "integration", "live" })
|
||||||
public void testListContainer() throws InterruptedException, ExecutionException,
|
public void testListContainer() throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
TimeoutException {
|
|
||||||
String containerNameName = getContainerName();
|
String containerNameName = getContainerName();
|
||||||
try {
|
try {
|
||||||
ListableMap<?, ?> map = (ListableMap<?, ?>) createMap(context, containerNameName);
|
ListableMap<?, ?> map = (ListableMap<?, ?>) createMap(context, containerNameName);
|
||||||
|
@ -358,8 +340,8 @@ public abstract class BaseMapIntegrationTest<V> extends BaseBlobStoreIntegration
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void assertConsistencyAwareListContainer(final ListableMap<?, ?> map,
|
protected void assertConsistencyAwareListContainer(final ListableMap<?, ?> map, final String containerNameName)
|
||||||
final String containerNameName) throws InterruptedException {
|
throws InterruptedException {
|
||||||
assertConsistencyAware(new Runnable() {
|
assertConsistencyAware(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
assertTrue(Iterables.size(map.list()) >= 0);
|
assertTrue(Iterables.size(map.list()) >= 0);
|
||||||
|
|
|
@ -40,7 +40,7 @@ public interface BoxDotNetClient {
|
||||||
/*
|
/*
|
||||||
* Note all these delegate to methods in BoxDotNetAsyncClient with a specified or inherited timeout.
|
* Note all these delegate to methods in BoxDotNetAsyncClient with a specified or inherited timeout.
|
||||||
* The singatures should match those of BoxDotNetAsyncClient, except the returnvals should not be
|
* The singatures should match those of BoxDotNetAsyncClient, except the returnvals should not be
|
||||||
* wrapped in a ListenableFuture
|
* wrapped in a Future
|
||||||
*/
|
*/
|
||||||
|
|
||||||
String list();
|
String list();
|
||||||
|
|
|
@ -1,7 +1,5 @@
|
||||||
package org.jclouds.chef;
|
package org.jclouds.chef;
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.jclouds.chef.domain.Node;
|
import org.jclouds.chef.domain.Node;
|
||||||
import org.jclouds.chef.internal.BaseChefService;
|
import org.jclouds.chef.internal.BaseChefService;
|
||||||
|
|
||||||
|
@ -26,11 +24,11 @@ public interface ChefService {
|
||||||
|
|
||||||
void deleteAllClientsAndNodesInList(Iterable<String> names);
|
void deleteAllClientsAndNodesInList(Iterable<String> names);
|
||||||
|
|
||||||
Set<Node> getNodes();
|
Iterable<? extends Node> getNodes();
|
||||||
|
|
||||||
Set<Node> getNodesWithNamesMatching(Predicate<String> nodeNameSelector);
|
Iterable<? extends Node> getNodesWithNamesMatching(Predicate<String> nodeNameSelector);
|
||||||
|
|
||||||
Set<Node> getNodesNamed(Iterable<String> names);
|
Iterable<? extends Node> getNodesNamed(Iterable<String> names);
|
||||||
|
|
||||||
void updateAutomaticAttributesOnNode(String nodeName);
|
void updateAutomaticAttributesOnNode(String nodeName);
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,8 +2,6 @@ package org.jclouds.chef.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
@ -72,17 +70,17 @@ public class BaseChefService implements ChefService {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Node> getNodes() {
|
public Iterable<? extends Node> getNodes() {
|
||||||
return getNodes.execute();
|
return getNodes.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Node> getNodesWithNamesMatching(Predicate<String> nodeNameSelector) {
|
public Iterable<? extends Node> getNodesWithNamesMatching(Predicate<String> nodeNameSelector) {
|
||||||
return getNodes.execute(nodeNameSelector);
|
return getNodes.execute(nodeNameSelector);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Node> getNodesNamed(Iterable<String> names) {
|
public Iterable<? extends Node> getNodesNamed(Iterable<String> names) {
|
||||||
return getNodes.execute(names);
|
return getNodes.execute(names);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.chef.strategy;
|
package org.jclouds.chef.strategy;
|
||||||
|
|
||||||
import java.util.Set;
|
|
||||||
|
|
||||||
import org.jclouds.chef.domain.Node;
|
import org.jclouds.chef.domain.Node;
|
||||||
import org.jclouds.chef.strategy.internal.GetNodesImpl;
|
import org.jclouds.chef.strategy.internal.GetNodesImpl;
|
||||||
|
|
||||||
|
@ -34,9 +32,9 @@ import com.google.inject.ImplementedBy;
|
||||||
@ImplementedBy(GetNodesImpl.class)
|
@ImplementedBy(GetNodesImpl.class)
|
||||||
public interface GetNodes {
|
public interface GetNodes {
|
||||||
|
|
||||||
Set<Node> execute();
|
Iterable<? extends Node> execute();
|
||||||
|
|
||||||
Set<Node> execute(Predicate<String> nodeNameSelector);
|
Iterable<? extends Node> execute(Predicate<String> nodeNameSelector);
|
||||||
|
|
||||||
Set<Node> execute(Iterable<String> toGet);
|
Iterable<? extends Node> execute(Iterable<String> toGet);
|
||||||
}
|
}
|
|
@ -68,7 +68,7 @@ public class CleanupStaleNodesAndClientsImpl implements CleanupStaleNodesAndClie
|
||||||
final Calendar expired = Calendar.getInstance();
|
final Calendar expired = Calendar.getInstance();
|
||||||
expired.setTime(new Date());
|
expired.setTime(new Date());
|
||||||
expired.add(Calendar.SECOND, -secondsStale);
|
expired.add(Calendar.SECOND, -secondsStale);
|
||||||
Iterable<Node> staleNodes = filter(getAllNodes.execute(new Predicate<String>() {
|
Iterable<? extends Node> staleNodes = filter(getAllNodes.execute(new Predicate<String>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(String input) {
|
public boolean apply(String input) {
|
||||||
|
|
|
@ -35,7 +35,7 @@ import org.jclouds.chef.reference.ChefConstants;
|
||||||
import org.jclouds.chef.strategy.DeleteAllClientsAndNodesInList;
|
import org.jclouds.chef.strategy.DeleteAllClientsAndNodesInList;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import java.util.concurrent.Future;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -68,7 +68,7 @@ public class DeleteAllClientsAndNodesInListImpl implements DeleteAllClientsAndNo
|
||||||
@Override
|
@Override
|
||||||
public void execute(Iterable<String> names) {
|
public void execute(Iterable<String> names) {
|
||||||
Map<String, Exception> exceptions = newHashMap();
|
Map<String, Exception> exceptions = newHashMap();
|
||||||
Map<String, ListenableFuture<?>> responses = newHashMap();
|
Map<String, Future<?>> responses = newHashMap();
|
||||||
for (String name : names) {
|
for (String name : names) {
|
||||||
responses.put(name, chefAsyncClient.deleteClient(name));
|
responses.put(name, chefAsyncClient.deleteClient(name));
|
||||||
responses.put(name, chefAsyncClient.deleteNode(name));
|
responses.put(name, chefAsyncClient.deleteNode(name));
|
||||||
|
|
|
@ -18,17 +18,11 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.chef.strategy.internal;
|
package org.jclouds.chef.strategy.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Throwables.propagate;
|
|
||||||
import static com.google.common.collect.Iterables.filter;
|
import static com.google.common.collect.Iterables.filter;
|
||||||
import static com.google.common.collect.Maps.newHashMap;
|
import static org.jclouds.concurrent.ConcurrentUtils.transformParallel;
|
||||||
import static com.google.common.collect.Sets.newHashSet;
|
|
||||||
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
|
|
||||||
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
@ -42,8 +36,8 @@ import org.jclouds.chef.reference.ChefConstants;
|
||||||
import org.jclouds.chef.strategy.GetNodes;
|
import org.jclouds.chef.strategy.GetNodes;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,46 +61,33 @@ public class GetNodesImpl implements GetNodes {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
GetNodesImpl(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, ChefClient getAllNode,
|
GetNodesImpl(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userExecutor, ChefClient getAllNode,
|
||||||
ChefAsyncClient ablobstore) {
|
ChefAsyncClient ablobstore) {
|
||||||
this.userExecutor = userExecutor;
|
this.userExecutor = userExecutor;
|
||||||
this.chefAsyncClient = ablobstore;
|
this.chefAsyncClient = ablobstore;
|
||||||
this.chefClient = getAllNode;
|
this.chefClient = getAllNode;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Node> execute() {
|
public Iterable<? extends Node> execute() {
|
||||||
return execute(chefClient.listNodes());
|
return execute(chefClient.listNodes());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Node> execute(Predicate<String> nodeNameSelector) {
|
public Iterable<? extends Node> execute(Predicate<String> nodeNameSelector) {
|
||||||
return execute(filter(chefClient.listNodes(), nodeNameSelector));
|
return execute(filter(chefClient.listNodes(), nodeNameSelector));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Node> execute(Iterable<String> toGet) {
|
public Iterable<? extends Node> execute(Iterable<String> toGet) {
|
||||||
Map<String, Exception> exceptions = newHashMap();
|
return transformParallel(toGet, new Function<String, Future<Node>>() {
|
||||||
final Set<Node> nodes = newHashSet();
|
|
||||||
Map<String, ListenableFuture<?>> responses = newHashMap();
|
@Override
|
||||||
for (String nodeName : toGet) {
|
public Future<Node> apply(String from) {
|
||||||
final ListenableFuture<? extends Node> future = chefAsyncClient.getNode(nodeName);
|
return chefAsyncClient.getNode(from);
|
||||||
future.addListener(new Runnable() {
|
}
|
||||||
@Override
|
|
||||||
public void run() {
|
}, userExecutor, maxTime, logger, "getting nodes");
|
||||||
try {
|
|
||||||
nodes.add(future.get());
|
|
||||||
} catch (InterruptedException e) {
|
|
||||||
propagate(e);
|
|
||||||
} catch (ExecutionException e) {
|
|
||||||
propagate(e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}, sameThreadExecutor());
|
|
||||||
responses.put(nodeName, future);
|
|
||||||
}
|
|
||||||
exceptions = awaitCompletion(responses, userExecutor, maxTime, logger, String.format("getting nodes: %s", toGet));
|
|
||||||
if (exceptions.size() > 0)
|
|
||||||
throw new RuntimeException(String.format("errors getting nodes: %s: %s", toGet, exceptions));
|
|
||||||
return nodes;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -23,6 +23,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.chef.strategy.internal;
|
package org.jclouds.chef.strategy.internal;
|
||||||
|
|
||||||
|
import static com.google.common.collect.Iterables.size;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -69,24 +70,24 @@ public class GetNodesImplLiveTest extends BaseChefStrategyLiveTest {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExecute() {
|
public void testExecute() {
|
||||||
assert strategy.execute().size() > 0;
|
assert size(strategy.execute()) > 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExecutePredicateOfString() {
|
public void testExecutePredicateOfString() {
|
||||||
assertEquals(strategy.execute(new Predicate<String>() {
|
assertEquals(size(strategy.execute(new Predicate<String>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(String input) {
|
public boolean apply(String input) {
|
||||||
return input.startsWith(prefix);
|
return input.startsWith(prefix);
|
||||||
}
|
}
|
||||||
|
|
||||||
}).size(), 2);
|
})), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExecuteIterableOfString() {
|
public void testExecuteIterableOfString() {
|
||||||
assertEquals(strategy.execute(ImmutableSet.of(prefix, prefix + 1)).size(), 2);
|
assertEquals(size(strategy.execute(ImmutableSet.of(prefix, prefix + 1))), 2);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -27,7 +27,6 @@ import static org.jclouds.chef.reference.ChefConstants.CHEF_NODE;
|
||||||
import static org.jclouds.chef.reference.ChefConstants.CHEF_ROLE;
|
import static org.jclouds.chef.reference.ChefConstants.CHEF_ROLE;
|
||||||
import static org.jclouds.chef.reference.ChefConstants.CHEF_SERVICE_CLIENT;
|
import static org.jclouds.chef.reference.ChefConstants.CHEF_SERVICE_CLIENT;
|
||||||
|
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
@ -41,18 +40,18 @@ import org.jclouds.chef.ChefClient;
|
||||||
import org.jclouds.chef.ChefContext;
|
import org.jclouds.chef.ChefContext;
|
||||||
import org.jclouds.chef.ChefService;
|
import org.jclouds.chef.ChefService;
|
||||||
import org.jclouds.chef.reference.ChefConstants;
|
import org.jclouds.chef.reference.ChefConstants;
|
||||||
|
import org.jclouds.chef.servlet.functions.InitParamsToProperties;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.logging.jdk.JDKLogger;
|
import org.jclouds.logging.jdk.JDKLogger;
|
||||||
import org.jclouds.rest.RestContextFactory;
|
import org.jclouds.rest.RestContextFactory;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Registers a new node in Chef and binds its name to
|
* Registers a new node in Chef and binds its name to {@link ChefConstants.CHEF_NODE}, its role to
|
||||||
* {@link ChefConstants.CHEF_NODE}, its role to {@link ChefConstants.CHEF_ROLE}
|
* {@link ChefConstants.CHEF_ROLE} and the {@link ChefService} for the client to
|
||||||
* and the {@link ChefService} for the client to
|
* {@link ChefConstants.CHEF_SERVICE_CLIENT} upon initialized. Deletes the node and client when the
|
||||||
* {@link ChefConstants.CHEF_SERVICE_CLIENT} upon initialized. Deletes the node
|
* context is destroyed.
|
||||||
* and client when the context is destroyed.
|
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
|
@ -60,18 +59,11 @@ public class ChefRegistrationListener implements ServletContextListener {
|
||||||
|
|
||||||
private Logger logger = new JDKLogger.JDKLoggerFactory().getLogger(ChefRegistrationListener.class.getName());
|
private Logger logger = new JDKLogger.JDKLoggerFactory().getLogger(ChefRegistrationListener.class.getName());
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
|
||||||
@Override
|
@Override
|
||||||
public void contextInitialized(ServletContextEvent servletContextEvent) {
|
public void contextInitialized(ServletContextEvent servletContextEvent) {
|
||||||
try {
|
try {
|
||||||
logger.debug("starting initialization");
|
logger.debug("starting initialization");
|
||||||
Properties overrides = new Properties();
|
Properties overrides = InitParamsToProperties.INSTANCE.apply(servletContextEvent);
|
||||||
Enumeration<String> e = servletContextEvent.getServletContext().getInitParameterNames();
|
|
||||||
while (e.hasMoreElements()) {
|
|
||||||
String propertyName = e.nextElement();
|
|
||||||
overrides.setProperty(propertyName, servletContextEvent.getServletContext().getInitParameter(propertyName));
|
|
||||||
|
|
||||||
}
|
|
||||||
String role = getInitParam(servletContextEvent, CHEF_ROLE);
|
String role = getInitParam(servletContextEvent, CHEF_ROLE);
|
||||||
|
|
||||||
logger.trace("creating validator connection");
|
logger.trace("creating validator connection");
|
||||||
|
@ -105,8 +97,8 @@ public class ChefRegistrationListener implements ServletContextListener {
|
||||||
}
|
}
|
||||||
|
|
||||||
private String findNextClientAndNodeName(ChefService validatorService, String prefix) {
|
private String findNextClientAndNodeName(ChefService validatorService, String prefix) {
|
||||||
ListenableFuture<Set<String>> nodes = validatorService.getContext().getAsyncApi().listNodes();
|
Future<Set<String>> nodes = validatorService.getContext().getAsyncApi().listNodes();
|
||||||
ListenableFuture<Set<String>> clients = validatorService.getContext().getAsyncApi().listClients();
|
Future<Set<String>> clients = validatorService.getContext().getAsyncApi().listClients();
|
||||||
try {
|
try {
|
||||||
String nodeName;
|
String nodeName;
|
||||||
Set<String> names = newHashSet(concat(nodes.get(), clients.get()));
|
Set<String> names = newHashSet(concat(nodes.get(), clients.get()));
|
||||||
|
@ -156,7 +148,7 @@ public class ChefRegistrationListener implements ServletContextListener {
|
||||||
|
|
||||||
private ChefService createService(Properties props) {
|
private ChefService createService(Properties props) {
|
||||||
return ((ChefContext) new RestContextFactory().<ChefClient, ChefAsyncClient> createContext("chef", props))
|
return ((ChefContext) new RestContextFactory().<ChefClient, ChefAsyncClient> createContext("chef", props))
|
||||||
.getChefService();
|
.getChefService();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static String getInitParam(ServletContextEvent servletContextEvent, String name) {
|
private static String getInitParam(ServletContextEvent servletContextEvent, String name) {
|
||||||
|
|
|
@ -0,0 +1,47 @@
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
|
||||||
|
*
|
||||||
|
* ====================================================================
|
||||||
|
* Licensed 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.chef.servlet.functions;
|
||||||
|
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Singleton
|
||||||
|
public class InitParamsToProperties implements Function<ServletContextEvent, Properties> {
|
||||||
|
|
||||||
|
public static final InitParamsToProperties INSTANCE = new InitParamsToProperties();
|
||||||
|
|
||||||
|
public Properties apply(ServletContextEvent servletContextEvent) {
|
||||||
|
Properties overrides = new Properties();
|
||||||
|
Enumeration<?> e = servletContextEvent.getServletContext().getInitParameterNames();
|
||||||
|
while (e.hasMoreElements()) {
|
||||||
|
String propertyName = e.nextElement().toString();
|
||||||
|
overrides.setProperty(propertyName, servletContextEvent.getServletContext().getInitParameter(propertyName));
|
||||||
|
}
|
||||||
|
return overrides;
|
||||||
|
}
|
||||||
|
}
|
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.compute.domain;
|
package org.jclouds.compute.domain;
|
||||||
|
|
||||||
|
import java.util.NoSuchElementException;
|
||||||
|
|
||||||
import org.jclouds.compute.internal.TemplateBuilderImpl;
|
import org.jclouds.compute.internal.TemplateBuilderImpl;
|
||||||
import org.jclouds.compute.options.TemplateOptions;
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
|
|
||||||
|
@ -73,6 +75,9 @@ public interface TemplateBuilder {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Configure this template to start in a specific location
|
* Configure this template to start in a specific location
|
||||||
|
*
|
||||||
|
* @throws NoSuchElementException
|
||||||
|
* if location matches the id specified
|
||||||
*/
|
*/
|
||||||
TemplateBuilder locationId(String locationId);
|
TemplateBuilder locationId(String locationId);
|
||||||
|
|
||||||
|
|
|
@ -27,12 +27,13 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static org.jclouds.compute.util.ComputeServiceUtils.installNewCredentials;
|
import static org.jclouds.compute.util.ComputeServiceUtils.installNewCredentials;
|
||||||
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
|
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
|
||||||
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
|
import static org.jclouds.concurrent.ConcurrentUtils.transformParallel;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
@ -75,7 +76,7 @@ import com.google.common.base.Predicates;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -106,13 +107,14 @@ public class BaseComputeService implements ComputeService {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected BaseComputeService(ComputeServiceContext context, Provider<Set<? extends Image>> images,
|
protected BaseComputeService(ComputeServiceContext context, Provider<Set<? extends Image>> images,
|
||||||
Provider<Set<? extends Size>> sizes, Provider<Set<? extends Location>> locations,
|
Provider<Set<? extends Size>> sizes, Provider<Set<? extends Location>> locations,
|
||||||
ListNodesStrategy listNodesStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
|
ListNodesStrategy listNodesStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy,
|
||||||
RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
|
RunNodesAndAddToSetStrategy runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy,
|
||||||
DestroyNodeStrategy destroyNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
|
DestroyNodeStrategy destroyNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider,
|
||||||
Provider<TemplateOptions> templateOptionsProvider, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
|
Provider<TemplateOptions> templateOptionsProvider,
|
||||||
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated, ComputeUtils utils,
|
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated, ComputeUtils utils,
|
||||||
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
this.context = checkNotNull(context, "context");
|
this.context = checkNotNull(context, "context");
|
||||||
this.images = checkNotNull(images, "images");
|
this.images = checkNotNull(images, "images");
|
||||||
this.sizes = checkNotNull(sizes, "sizes");
|
this.sizes = checkNotNull(sizes, "sizes");
|
||||||
|
@ -143,16 +145,15 @@ public class BaseComputeService implements ComputeService {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends NodeMetadata> runNodesWithTag(String tag, int count, Template template)
|
public Set<? extends NodeMetadata> runNodesWithTag(String tag, int count, Template template)
|
||||||
throws RunNodesException {
|
throws RunNodesException {
|
||||||
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
|
checkArgument(tag.indexOf('-') == -1, "tag cannot contain hyphens");
|
||||||
checkNotNull(template.getLocation(), "location");
|
checkNotNull(template.getLocation(), "location");
|
||||||
logger.debug(">> running %d node%s tag(%s) location(%s) image(%s) size(%s) options(%s)", count, count > 1 ? "s"
|
logger.debug(">> running %d node%s tag(%s) location(%s) image(%s) size(%s) options(%s)", count, count > 1 ? "s"
|
||||||
: "", tag, template.getLocation().getId(), template.getImage().getProviderId(), template.getSize()
|
: "", tag, template.getLocation().getId(), template.getImage().getProviderId(), template.getSize()
|
||||||
.getProviderId(), template.getOptions());
|
.getProviderId(), template.getOptions());
|
||||||
Set<NodeMetadata> nodes = Sets.newHashSet();
|
Set<NodeMetadata> nodes = Sets.newHashSet();
|
||||||
Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap();
|
Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap();
|
||||||
Map<?, ListenableFuture<Void>> responses = runNodesAndAddToSetStrategy.execute(tag, count, template, nodes,
|
Map<?, Future<Void>> responses = runNodesAndAddToSetStrategy.execute(tag, count, template, nodes, badNodes);
|
||||||
badNodes);
|
|
||||||
Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger, "starting nodes");
|
Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger, "starting nodes");
|
||||||
if (executionExceptions.size() > 0 || badNodes.size() > 0) {
|
if (executionExceptions.size() > 0 || badNodes.size() > 0) {
|
||||||
throw new RunNodesException(tag, count, template, nodes, executionExceptions, badNodes);
|
throw new RunNodesException(tag, count, template, nodes, executionExceptions, badNodes);
|
||||||
|
@ -165,7 +166,7 @@ public class BaseComputeService implements ComputeService {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends NodeMetadata> runNodesWithTag(String tag, int count, TemplateOptions templateOptions)
|
public Set<? extends NodeMetadata> runNodesWithTag(String tag, int count, TemplateOptions templateOptions)
|
||||||
throws RunNodesException {
|
throws RunNodesException {
|
||||||
return runNodesWithTag(tag, count, templateBuilder().any().options(templateOptions).build());
|
return runNodesWithTag(tag, count, templateBuilder().any().options(templateOptions).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -195,21 +196,26 @@ public class BaseComputeService implements ComputeService {
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
|
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
|
||||||
logger.debug(">> destroying nodes matching(%s)", filter);
|
logger.debug(">> destroying nodes matching(%s)", filter);
|
||||||
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
|
Set<NodeMetadata> set = Sets.newLinkedHashSet(transformParallel(nodesMatchingFilterAndNotTerminated(filter),
|
||||||
final Set<NodeMetadata> destroyedNodes = Sets.newLinkedHashSet();
|
new Function<NodeMetadata, Future<NodeMetadata>>() {
|
||||||
for (final NodeMetadata node : nodesMatchingFilterAndNotTerminated(filter)) {
|
|
||||||
responses.put(node, makeListenable(executor.submit(new Callable<Void>() {
|
// TODO make an async interface instead of re-wrapping
|
||||||
@Override
|
@Override
|
||||||
public Void call() throws Exception {
|
public Future<NodeMetadata> apply(final NodeMetadata from) {
|
||||||
destroyNode(node.getId());
|
return executor.submit(new Callable<NodeMetadata>() {
|
||||||
destroyedNodes.add(node);
|
|
||||||
return null;
|
@Override
|
||||||
}
|
public NodeMetadata call() throws Exception {
|
||||||
}), executor));
|
destroyNode(from.getId());
|
||||||
}
|
return from;
|
||||||
awaitCompletion(responses, executor, null, logger, "destroying nodes");
|
}
|
||||||
logger.debug("<< destroyed");
|
|
||||||
return destroyedNodes;
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
}, executor, null, logger, "destroying nodes"));
|
||||||
|
logger.debug("<< destroyed(%d)", set.size());
|
||||||
|
return set;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Iterable<? extends NodeMetadata> nodesMatchingFilterAndNotTerminated(Predicate<NodeMetadata> filter) {
|
private Iterable<? extends NodeMetadata> nodesMatchingFilterAndNotTerminated(Predicate<NodeMetadata> filter) {
|
||||||
|
@ -220,9 +226,9 @@ public class BaseComputeService implements ComputeService {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends ComputeMetadata> listNodes() {
|
public Set<ComputeMetadata> listNodes() {
|
||||||
logger.debug(">> listing nodes");
|
logger.debug(">> listing nodes");
|
||||||
Set<? extends ComputeMetadata> set = Sets.newLinkedHashSet(listNodesStrategy.list());
|
Set<ComputeMetadata> set = Sets.newLinkedHashSet(listNodesStrategy.list());
|
||||||
logger.debug("<< list(%d)", set.size());
|
logger.debug("<< list(%d)", set.size());
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
@ -234,7 +240,7 @@ public class BaseComputeService implements ComputeService {
|
||||||
public Set<? extends NodeMetadata> listNodesDetailsMatching(Predicate<ComputeMetadata> filter) {
|
public Set<? extends NodeMetadata> listNodesDetailsMatching(Predicate<ComputeMetadata> filter) {
|
||||||
checkNotNull(filter, "filter");
|
checkNotNull(filter, "filter");
|
||||||
logger.debug(">> listing node details matching(%s)", filter);
|
logger.debug(">> listing node details matching(%s)", filter);
|
||||||
Set<? extends NodeMetadata> set = Sets.newLinkedHashSet(listNodesStrategy.listDetailsOnNodesMatching(filter));
|
Set<NodeMetadata> set = Sets.newLinkedHashSet(listNodesStrategy.listDetailsOnNodesMatching(filter));
|
||||||
logger.debug("<< list(%d)", set.size());
|
logger.debug("<< list(%d)", set.size());
|
||||||
return set;
|
return set;
|
||||||
}
|
}
|
||||||
|
@ -298,18 +304,15 @@ public class BaseComputeService implements ComputeService {
|
||||||
@Override
|
@Override
|
||||||
public void rebootNodesMatching(Predicate<NodeMetadata> filter) {
|
public void rebootNodesMatching(Predicate<NodeMetadata> filter) {
|
||||||
logger.debug(">> rebooting nodes matching(%s)", filter);
|
logger.debug(">> rebooting nodes matching(%s)", filter);
|
||||||
|
transformParallel(nodesMatchingFilterAndNotTerminated(filter), new Function<NodeMetadata, Future<Void>>() {
|
||||||
|
// TODO use native async
|
||||||
|
@Override
|
||||||
|
public Future<Void> apply(NodeMetadata from) {
|
||||||
|
rebootNode(from.getId());
|
||||||
|
return Futures.immediateFuture(null);
|
||||||
|
}
|
||||||
|
|
||||||
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
|
}, executor, null, logger, "rebooting nodes");
|
||||||
for (final NodeMetadata node : nodesMatchingFilterAndNotTerminated(filter)) {
|
|
||||||
responses.put(node, makeListenable(executor.submit(new Callable<Void>() {
|
|
||||||
@Override
|
|
||||||
public Void call() throws Exception {
|
|
||||||
rebootNode(node.getId());
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}), executor));
|
|
||||||
}
|
|
||||||
awaitCompletion(responses, executor, null, logger, "rebooting nodes");
|
|
||||||
logger.debug("<< rebooted");
|
logger.debug("<< rebooted");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -317,8 +320,8 @@ public class BaseComputeService implements ComputeService {
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
|
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript)
|
||||||
Payload runScript) throws RunScriptOnNodesException {
|
throws RunScriptOnNodesException {
|
||||||
return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE);
|
return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -327,19 +330,19 @@ public class BaseComputeService implements ComputeService {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
|
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
|
||||||
final Payload runScript, @Nullable final RunScriptOptions options) throws RunScriptOnNodesException {
|
final Payload runScript, @Nullable final RunScriptOptions options) throws RunScriptOnNodesException {
|
||||||
Iterable<? extends NodeMetadata> nodes = verifyParametersAndListNodes(filter, runScript,
|
Iterable<NodeMetadata> nodes = verifyParametersAndListNodes(filter, runScript, (options != null) ? options
|
||||||
(options != null) ? options : RunScriptOptions.NONE);
|
: RunScriptOptions.NONE);
|
||||||
|
|
||||||
final Map<NodeMetadata, ExecResponse> execs = Maps.newHashMap();
|
final Map<NodeMetadata, ExecResponse> execs = Maps.newHashMap();
|
||||||
|
|
||||||
final Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap();
|
final Map<NodeMetadata, Exception> badNodes = Maps.newLinkedHashMap();
|
||||||
|
|
||||||
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
|
Map<NodeMetadata, Future<Void>> responses = Maps.newHashMap();
|
||||||
|
|
||||||
for (final NodeMetadata node : nodes) {
|
for (final NodeMetadata node : nodes) {
|
||||||
|
|
||||||
responses.put(node, makeListenable(executor.submit(new Callable<Void>() {
|
responses.put(node, executor.submit(new Callable<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public Void call() throws Exception {
|
public Void call() throws Exception {
|
||||||
try {
|
try {
|
||||||
|
@ -363,7 +366,7 @@ public class BaseComputeService implements ComputeService {
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}), executor));
|
}));
|
||||||
|
|
||||||
}
|
}
|
||||||
Map<?, Exception> exceptions = awaitCompletion(responses, executor, null, logger, "starting nodes");
|
Map<?, Exception> exceptions = awaitCompletion(responses, executor, null, logger, "starting nodes");
|
||||||
|
@ -374,14 +377,14 @@ public class BaseComputeService implements ComputeService {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private Iterable<? extends NodeMetadata> verifyParametersAndListNodes(Predicate<NodeMetadata> filter,
|
private Iterable<NodeMetadata> verifyParametersAndListNodes(Predicate<NodeMetadata> filter, Payload runScript,
|
||||||
Payload runScript, final RunScriptOptions options) {
|
final RunScriptOptions options) {
|
||||||
checkNotNull(filter, "Filter must be provided");
|
checkNotNull(filter, "Filter must be provided");
|
||||||
checkNotNull(runScript, "The script (represented by bytes array - use \"script\".getBytes() must be provided");
|
checkNotNull(runScript, "The script (represented by bytes array - use \"script\".getBytes() must be provided");
|
||||||
checkNotNull(options, "options");
|
checkNotNull(options, "options");
|
||||||
|
|
||||||
Iterable<? extends NodeMetadata> nodes = Iterables.filter(detailsOnAllNodes(), filter);
|
Iterable<? extends NodeMetadata> nodes = Iterables.filter(detailsOnAllNodes(), filter);
|
||||||
|
// TODO parallel
|
||||||
return Iterables.transform(nodes, new Function<NodeMetadata, NodeMetadata>() {
|
return Iterables.transform(nodes, new Function<NodeMetadata, NodeMetadata>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -396,17 +399,17 @@ public class BaseComputeService implements ComputeService {
|
||||||
// don't override
|
// don't override
|
||||||
checkNotNull(node.getCredentials(), "If the default credentials need to be used, they can't be null");
|
checkNotNull(node.getCredentials(), "If the default credentials need to be used, they can't be null");
|
||||||
checkNotNull(node.getCredentials().identity, "Account name for ssh authentication must be "
|
checkNotNull(node.getCredentials().identity, "Account name for ssh authentication must be "
|
||||||
+ "specified. Try passing RunScriptOptions with new credentials");
|
+ "specified. Try passing RunScriptOptions with new credentials");
|
||||||
checkNotNull(node.getCredentials().credential, "Key or password for ssh authentication must be "
|
checkNotNull(node.getCredentials().credential, "Key or password for ssh authentication must be "
|
||||||
+ "specified. Try passing RunScriptOptions with new credentials");
|
+ "specified. Try passing RunScriptOptions with new credentials");
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Iterable<? extends NodeMetadata> detailsOnAllNodes() {
|
private Set<? extends NodeMetadata> detailsOnAllNodes() {
|
||||||
return listNodesStrategy.listDetailsOnNodesMatching(NodePredicates.all());
|
return Sets.newLinkedHashSet(listNodesStrategy.listDetailsOnNodesMatching(NodePredicates.all()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -21,7 +21,6 @@ package org.jclouds.compute.internal;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Predicates.and;
|
import static com.google.common.base.Predicates.and;
|
||||||
import static com.google.common.collect.Iterables.filter;
|
import static com.google.common.collect.Iterables.filter;
|
||||||
import static com.google.common.collect.Iterables.find;
|
|
||||||
import static com.google.common.collect.Lists.newArrayList;
|
import static com.google.common.collect.Lists.newArrayList;
|
||||||
import static org.jclouds.util.Utils.multiMax;
|
import static org.jclouds.util.Utils.multiMax;
|
||||||
|
|
||||||
|
@ -79,7 +78,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected Architecture arch;
|
protected Architecture arch;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected String locationId;
|
protected Location location;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
protected String imageId;
|
protected String imageId;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
@ -105,8 +104,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected TemplateBuilderImpl(Provider<Set<? extends Location>> locations, Provider<Set<? extends Image>> images,
|
protected TemplateBuilderImpl(Provider<Set<? extends Location>> locations, Provider<Set<? extends Image>> images,
|
||||||
Provider<Set<? extends Size>> sizes, Location defaultLocation, Provider<TemplateOptions> optionsProvider,
|
Provider<Set<? extends Size>> sizes, Location defaultLocation, Provider<TemplateOptions> optionsProvider,
|
||||||
@Named("DEFAULT") Provider<TemplateBuilder> defaultTemplateProvider) {
|
@Named("DEFAULT") Provider<TemplateBuilder> defaultTemplateProvider) {
|
||||||
this.locations = locations;
|
this.locations = locations;
|
||||||
this.images = images;
|
this.images = images;
|
||||||
this.sizes = sizes;
|
this.sizes = sizes;
|
||||||
|
@ -115,12 +114,20 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
this.defaultTemplateProvider = defaultTemplateProvider;
|
this.defaultTemplateProvider = defaultTemplateProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If the current location id is null, then we don't care where to launch a node.
|
||||||
|
*
|
||||||
|
* If the input location is null, then the data isn't location sensitive
|
||||||
|
*
|
||||||
|
* If the input location is a parent of the specified location, then we are ok.
|
||||||
|
*/
|
||||||
private final Predicate<ComputeMetadata> locationPredicate = new Predicate<ComputeMetadata>() {
|
private final Predicate<ComputeMetadata> locationPredicate = new Predicate<ComputeMetadata>() {
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(ComputeMetadata input) {
|
public boolean apply(ComputeMetadata input) {
|
||||||
boolean returnVal = true;
|
boolean returnVal = true;
|
||||||
if (locationId != null && input.getLocation() != null)
|
if (location != null && input.getLocation() != null)
|
||||||
returnVal = locationId.equals(input.getLocation().getId());
|
returnVal = location.equals(input.getLocation()) || location.getParent() != null
|
||||||
|
&& location.getParent().equals(input.getLocation());
|
||||||
return returnVal;
|
return returnVal;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
@ -172,7 +179,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
returnVal = false;
|
returnVal = false;
|
||||||
else
|
else
|
||||||
returnVal = input.getOsDescription().contains(osDescription)
|
returnVal = input.getOsDescription().contains(osDescription)
|
||||||
|| input.getOsDescription().matches(osDescription);
|
|| input.getOsDescription().matches(osDescription);
|
||||||
}
|
}
|
||||||
return returnVal;
|
return returnVal;
|
||||||
}
|
}
|
||||||
|
@ -212,8 +219,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
returnVal = false;
|
returnVal = false;
|
||||||
else
|
else
|
||||||
returnVal = input.getDescription().equals(imageDescription)
|
returnVal = input.getDescription().equals(imageDescription)
|
||||||
|| input.getDescription().contains(imageDescription)
|
|| input.getDescription().contains(imageDescription)
|
||||||
|| input.getDescription().matches(imageDescription);
|
|| input.getDescription().matches(imageDescription);
|
||||||
}
|
}
|
||||||
return returnVal;
|
return returnVal;
|
||||||
}
|
}
|
||||||
|
@ -247,12 +254,12 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
private final Predicate<Size> sizePredicate = and(sizeIdPredicate, locationPredicate, sizeCoresPredicate,
|
private final Predicate<Size> sizePredicate = and(sizeIdPredicate, locationPredicate, sizeCoresPredicate,
|
||||||
sizeRamPredicate);
|
sizeRamPredicate);
|
||||||
|
|
||||||
static final Ordering<Size> DEFAULT_SIZE_ORDERING = new Ordering<Size>() {
|
static final Ordering<Size> DEFAULT_SIZE_ORDERING = new Ordering<Size>() {
|
||||||
public int compare(Size left, Size right) {
|
public int compare(Size left, Size right) {
|
||||||
return ComparisonChain.start().compare(left.getCores(), right.getCores()).compare(left.getRam(),
|
return ComparisonChain.start().compare(left.getCores(), right.getCores()).compare(left.getRam(),
|
||||||
right.getRam()).compare(left.getDisk(), right.getDisk()).result();
|
right.getRam()).compare(left.getDisk(), right.getDisk()).result();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
static final Ordering<Size> BY_CORES_ORDERING = new Ordering<Size>() {
|
static final Ordering<Size> BY_CORES_ORDERING = new Ordering<Size>() {
|
||||||
|
@ -263,10 +270,10 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
static final Ordering<Image> DEFAULT_IMAGE_ORDERING = new Ordering<Image>() {
|
static final Ordering<Image> DEFAULT_IMAGE_ORDERING = new Ordering<Image>() {
|
||||||
public int compare(Image left, Image right) {
|
public int compare(Image left, Image right) {
|
||||||
return ComparisonChain.start().compare(left.getName(), right.getName(),
|
return ComparisonChain.start().compare(left.getName(), right.getName(),
|
||||||
Ordering.<String> natural().nullsLast()).compare(left.getVersion(), right.getVersion(),
|
Ordering.<String> natural().nullsLast()).compare(left.getVersion(), right.getVersion(),
|
||||||
Ordering.<String> natural().nullsLast()).compare(left.getOsDescription(), right.getOsDescription(),
|
Ordering.<String> natural().nullsLast()).compare(left.getOsDescription(), right.getOsDescription(),
|
||||||
Ordering.<String> natural().nullsLast()).compare(left.getArchitecture(), right.getArchitecture())
|
Ordering.<String> natural().nullsLast()).compare(left.getArchitecture(), right.getArchitecture())
|
||||||
.result();
|
.result();
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -286,7 +293,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
@Override
|
@Override
|
||||||
public TemplateBuilder fromSize(Size size) {
|
public TemplateBuilder fromSize(Size size) {
|
||||||
if (size.getLocation() != null)
|
if (size.getLocation() != null)
|
||||||
this.locationId = size.getLocation().getId();
|
this.location = size.getLocation();
|
||||||
this.minCores = size.getCores();
|
this.minCores = size.getCores();
|
||||||
this.minRam = size.getRam();
|
this.minRam = size.getRam();
|
||||||
return this;
|
return this;
|
||||||
|
@ -298,7 +305,7 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
@Override
|
@Override
|
||||||
public TemplateBuilder fromImage(Image image) {
|
public TemplateBuilder fromImage(Image image) {
|
||||||
if (image.getLocation() != null)
|
if (image.getLocation() != null)
|
||||||
this.locationId = image.getLocation().getId();
|
this.location = image.getLocation();
|
||||||
if (image.getOsFamily() != null)
|
if (image.getOsFamily() != null)
|
||||||
this.os = image.getOsFamily();
|
this.os = image.getOsFamily();
|
||||||
if (image.getName() != null)
|
if (image.getName() != null)
|
||||||
|
@ -346,7 +353,14 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public TemplateBuilder locationId(final String locationId) {
|
public TemplateBuilder locationId(final String locationId) {
|
||||||
this.locationId = locationId;
|
this.location = Iterables.find(locations.get(), new Predicate<Location>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean apply(Location input) {
|
||||||
|
return input.getId().equals(locationId);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,12 +393,11 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
defaultTemplate.options(options);
|
defaultTemplate.options(options);
|
||||||
return defaultTemplate.build();
|
return defaultTemplate.build();
|
||||||
}
|
}
|
||||||
if (locationId == null)
|
if (location == null)
|
||||||
locationId = defaultLocation.getId();
|
location = defaultLocation;
|
||||||
if (options == null)
|
if (options == null)
|
||||||
options = optionsProvider.get();
|
options = optionsProvider.get();
|
||||||
logger.debug(">> searching params(%s)", this);
|
logger.debug(">> searching params(%s)", this);
|
||||||
Location location = resolveLocation();
|
|
||||||
Size size = resolveSize(sizeSorter(), getImages());
|
Size size = resolveSize(sizeSorter(), getImages());
|
||||||
Image image = resolveImage(size);
|
Image image = resolveImage(size);
|
||||||
logger.debug("<< matched image(%s)", image);
|
logger.debug("<< matched image(%s)", image);
|
||||||
|
@ -394,19 +407,6 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
return new TemplateImpl(image, size, location, options);
|
return new TemplateImpl(image, size, location, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Location resolveLocation() {
|
|
||||||
Location location = find(locations.get(), new Predicate<Location>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public boolean apply(Location input) {
|
|
||||||
return input.getId().equals(locationId);
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
logger.debug("<< matched location(%s)", location);
|
|
||||||
return location;
|
|
||||||
}
|
|
||||||
|
|
||||||
protected Size resolveSize(Ordering<Size> sizeOrdering, final Iterable<? extends Image> images) {
|
protected Size resolveSize(Ordering<Size> sizeOrdering, final Iterable<? extends Image> images) {
|
||||||
Size size;
|
Size size;
|
||||||
try {
|
try {
|
||||||
|
@ -429,7 +429,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
});
|
});
|
||||||
size = sizeOrdering.max(filter(sizesThatAreCompatibleWithOurImages, sizePredicate));
|
size = sizeOrdering.max(filter(sizesThatAreCompatibleWithOurImages, sizePredicate));
|
||||||
} catch (NoSuchElementException exception) {
|
} catch (NoSuchElementException exception) {
|
||||||
throw new NoSuchElementException("size didn't match: " + toString() + "\n" + sizes.get());
|
throw new NoSuchElementException("sizes don't support any images: " + toString() + "\n" + sizes.get() + "\n"
|
||||||
|
+ images);
|
||||||
}
|
}
|
||||||
logger.debug("<< matched size(%s)", size);
|
logger.debug("<< matched size(%s)", size);
|
||||||
return size;
|
return size;
|
||||||
|
@ -468,7 +469,8 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
logger.trace("<< best images(%s)", maxImages);
|
logger.trace("<< best images(%s)", maxImages);
|
||||||
return maxImages.get(maxImages.size() - 1);
|
return maxImages.get(maxImages.size() - 1);
|
||||||
} catch (NoSuchElementException exception) {
|
} catch (NoSuchElementException exception) {
|
||||||
throw new NoSuchElementException("image didn't match: " + toString() + "\n" + getImages());
|
Set<? extends Image> images = getImages();
|
||||||
|
throw new NoSuchElementException("image didn't match: " + toString() + "\n" + images);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -608,9 +610,9 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
boolean nothingChangedExceptOptions() {
|
boolean nothingChangedExceptOptions() {
|
||||||
return os == null && arch == null && locationId == null && imageId == null && sizeId == null
|
return os == null && arch == null && location == null && imageId == null && sizeId == null
|
||||||
&& osDescription == null && imageVersion == null && imageName == null && imageDescription == null
|
&& osDescription == null && imageVersion == null && imageName == null && imageDescription == null
|
||||||
&& minCores == 0 && minRam == 0 && !biggest && !fastest;
|
&& minCores == 0 && minRam == 0 && !biggest && !fastest;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -624,9 +626,9 @@ public class TemplateBuilderImpl implements TemplateBuilder {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[arch=" + arch + ", biggest=" + biggest + ", fastest=" + fastest + ", imageName=" + imageName
|
return "[arch=" + arch + ", biggest=" + biggest + ", fastest=" + fastest + ", imageName=" + imageName
|
||||||
+ ", imageDescription=" + imageDescription + ", imageId=" + imageId + ", imageVersion=" + imageVersion
|
+ ", imageDescription=" + imageDescription + ", imageId=" + imageId + ", imageVersion=" + imageVersion
|
||||||
+ ", location=" + locationId + ", minCores=" + minCores + ", minRam=" + minRam + ", os=" + os
|
+ ", location=" + location + ", minCores=" + minCores + ", minRam=" + minRam + ", os=" + os
|
||||||
+ ", osDescription=" + osDescription + ", sizeId=" + sizeId + "]";
|
+ ", osDescription=" + osDescription + ", sizeId=" + sizeId + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -26,7 +26,7 @@ import org.jclouds.compute.domain.NodeMetadata;
|
||||||
import org.jclouds.compute.domain.Template;
|
import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.compute.strategy.impl.EncodeTagIntoNameRunNodesAndAddToSetStrategy;
|
import org.jclouds.compute.strategy.impl.EncodeTagIntoNameRunNodesAndAddToSetStrategy;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import java.util.concurrent.Future;
|
||||||
import com.google.inject.ImplementedBy;
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -37,6 +37,6 @@ import com.google.inject.ImplementedBy;
|
||||||
@ImplementedBy(EncodeTagIntoNameRunNodesAndAddToSetStrategy.class)
|
@ImplementedBy(EncodeTagIntoNameRunNodesAndAddToSetStrategy.class)
|
||||||
public interface RunNodesAndAddToSetStrategy {
|
public interface RunNodesAndAddToSetStrategy {
|
||||||
|
|
||||||
Map<?, ListenableFuture<Void>> execute(String tag, int count, Template template,
|
Map<?, Future<Void>> execute(String tag, int count, Template template,
|
||||||
Set<NodeMetadata> nodes, Map<NodeMetadata, Exception> badNodes);
|
Set<NodeMetadata> nodes, Map<NodeMetadata, Exception> badNodes);
|
||||||
}
|
}
|
|
@ -19,13 +19,12 @@
|
||||||
|
|
||||||
package org.jclouds.compute.strategy.impl;
|
package org.jclouds.compute.strategy.impl;
|
||||||
|
|
||||||
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
|
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -47,7 +46,6 @@ import com.google.common.base.Predicate;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* creates futures that correlate to
|
* creates futures that correlate to
|
||||||
|
@ -55,8 +53,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements
|
public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements RunNodesAndAddToSetStrategy {
|
||||||
RunNodesAndAddToSetStrategy {
|
|
||||||
@Resource
|
@Resource
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
@ -67,12 +64,9 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements
|
||||||
protected final ExecutorService executor;
|
protected final ExecutorService executor;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected EncodeTagIntoNameRunNodesAndAddToSetStrategy(
|
protected EncodeTagIntoNameRunNodesAndAddToSetStrategy(AddNodeWithTagStrategy addNodeWithTagStrategy,
|
||||||
AddNodeWithTagStrategy addNodeWithTagStrategy,
|
ListNodesStrategy listNodesStrategy, @Named("NAMING_CONVENTION") String nodeNamingConvention,
|
||||||
ListNodesStrategy listNodesStrategy,
|
ComputeUtils utils, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
@Named("NAMING_CONVENTION") String nodeNamingConvention,
|
|
||||||
ComputeUtils utils,
|
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
|
||||||
this.addNodeWithTagStrategy = addNodeWithTagStrategy;
|
this.addNodeWithTagStrategy = addNodeWithTagStrategy;
|
||||||
this.listNodesStrategy = listNodesStrategy;
|
this.listNodesStrategy = listNodesStrategy;
|
||||||
this.nodeNamingConvention = nodeNamingConvention;
|
this.nodeNamingConvention = nodeNamingConvention;
|
||||||
|
@ -81,51 +75,43 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This implementation gets a list of acceptable node names to encode the tag
|
* This implementation gets a list of acceptable node names to encode the tag into, then it
|
||||||
* into, then it simultaneously runs the nodes and applies options to them.
|
* simultaneously runs the nodes and applies options to them.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Map<?, ListenableFuture<Void>> execute(final String tag,
|
public Map<?, Future<Void>> execute(final String tag, final int count, final Template template,
|
||||||
final int count, final Template template,
|
final Set<NodeMetadata> nodes, final Map<NodeMetadata, Exception> badNodes) {
|
||||||
final Set<NodeMetadata> nodes,
|
Map<String, Future<Void>> responses = Maps.newHashMap();
|
||||||
final Map<NodeMetadata, Exception> badNodes) {
|
|
||||||
Map<String, ListenableFuture<Void>> responses = Maps.newHashMap();
|
|
||||||
for (final String name : getNextNames(tag, template, count)) {
|
for (final String name : getNextNames(tag, template, count)) {
|
||||||
responses.put(name, makeListenable(executor
|
responses.put(name, executor.submit(new Callable<Void>() {
|
||||||
.submit(new Callable<Void>() {
|
@Override
|
||||||
@Override
|
public Void call() throws Exception {
|
||||||
public Void call() throws Exception {
|
NodeMetadata node = null;
|
||||||
NodeMetadata node = null;
|
logger.debug(">> starting node(%s) tag(%s)", name, tag);
|
||||||
logger.debug(">> starting node(%s) tag(%s)", name, tag);
|
node = addNodeWithTagStrategy.execute(tag, name, template);
|
||||||
node = addNodeWithTagStrategy.execute(tag, name, template);
|
logger.debug("<< %s node(%s)", node.getState(), node.getId());
|
||||||
logger.debug("<< %s node(%s)", node.getState(), node
|
utils.runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(node, badNodes, nodes,
|
||||||
.getId());
|
template.getOptions()).call();
|
||||||
utils
|
return null;
|
||||||
.runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(
|
}
|
||||||
node, badNodes, nodes, template.getOptions())
|
}));
|
||||||
.call();
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}), executor));
|
|
||||||
}
|
}
|
||||||
return responses;
|
return responses;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Find the next node names that can be used. These will be derived from the
|
* Find the next node names that can be used. These will be derived from the tag and the
|
||||||
* tag and the template. We will pre-allocate a specified quantity, and
|
* template. We will pre-allocate a specified quantity, and attempt to verify that there is no
|
||||||
* attempt to verify that there is no name conflict with the current service.
|
* name conflict with the current service.
|
||||||
*
|
*
|
||||||
* @param tag
|
* @param tag
|
||||||
* @param count
|
* @param count
|
||||||
* @param template
|
* @param template
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
protected Set<String> getNextNames(final String tag,
|
protected Set<String> getNextNames(final String tag, final Template template, int count) {
|
||||||
final Template template, int count) {
|
|
||||||
Set<String> names = Sets.newHashSet();
|
Set<String> names = Sets.newHashSet();
|
||||||
Iterable<? extends ComputeMetadata> currentNodes = listNodesStrategy
|
Iterable<? extends ComputeMetadata> currentNodes = listNodesStrategy.list();
|
||||||
.list();
|
|
||||||
int maxTries = 100;
|
int maxTries = 100;
|
||||||
int currentTries = 0;
|
int currentTries = 0;
|
||||||
while (names.size() < count && currentTries++ < maxTries) {
|
while (names.size() < count && currentTries++ < maxTries) {
|
||||||
|
@ -145,16 +131,14 @@ public class EncodeTagIntoNameRunNodesAndAddToSetStrategy implements
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get a name using a random mechanism that still ties all nodes in a tag
|
* Get a name using a random mechanism that still ties all nodes in a tag together.
|
||||||
* together.
|
|
||||||
*
|
*
|
||||||
* This implementation will pass the tag and a hex formatted random number to
|
* This implementation will pass the tag and a hex formatted random number to the configured
|
||||||
* the configured naming convention.
|
* naming convention.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
protected String getNextName(final String tag, final Template template) {
|
protected String getNextName(final String tag, final Template template) {
|
||||||
return String.format(nodeNamingConvention, tag, Integer
|
return String.format(nodeNamingConvention, tag, Integer.toHexString(new SecureRandom().nextInt(4095)));
|
||||||
.toHexString(new SecureRandom().nextInt(4095)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -180,12 +180,12 @@ public class StubComputeServiceContextModule extends AbstractModule {
|
||||||
private NodeState state;
|
private NodeState state;
|
||||||
private final ExecutorService service;
|
private final ExecutorService service;
|
||||||
|
|
||||||
public StubNodeMetadata(String providerId, String name, String id, Location location,
|
public StubNodeMetadata(String providerId, String name, String id, Location location, URI uri,
|
||||||
URI uri, Map<String, String> userMetadata, String tag, Image image, NodeState state,
|
Map<String, String> userMetadata, String tag, Image image, NodeState state,
|
||||||
Iterable<String> publicAddresses, Iterable<String> privateAddresses,
|
Iterable<String> publicAddresses, Iterable<String> privateAddresses, Map<String, String> extra,
|
||||||
Map<String, String> extra, Credentials credentials, ExecutorService service) {
|
Credentials credentials, ExecutorService service) {
|
||||||
super(providerId, name, id, location, uri, userMetadata, tag, image, state,
|
super(providerId, name, id, location, uri, userMetadata, tag, image, state, publicAddresses, privateAddresses,
|
||||||
publicAddresses, privateAddresses, extra, credentials);
|
extra, credentials);
|
||||||
this.setState(state, 0);
|
this.setState(state, 0);
|
||||||
this.service = service;
|
this.service = service;
|
||||||
}
|
}
|
||||||
|
@ -227,12 +227,10 @@ public class StubComputeServiceContextModule extends AbstractModule {
|
||||||
private final String passwordPrefix;
|
private final String passwordPrefix;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public StubAddNodeWithTagStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes,
|
public StubAddNodeWithTagStrategy(ConcurrentMap<Integer, StubNodeMetadata> nodes, Location location,
|
||||||
Location location, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService service,
|
||||||
@Named("NODE_ID") Provider<Integer> idProvider,
|
@Named("NODE_ID") Provider<Integer> idProvider, @Named("PUBLIC_IP_PREFIX") String publicIpPrefix,
|
||||||
@Named("PUBLIC_IP_PREFIX") String publicIpPrefix,
|
@Named("PRIVATE_IP_PREFIX") String privateIpPrefix, @Named("PASSWORD_PREFIX") String passwordPrefix) {
|
||||||
@Named("PRIVATE_IP_PREFIX") String privateIpPrefix,
|
|
||||||
@Named("PASSWORD_PREFIX") String passwordPrefix) {
|
|
||||||
this.nodes = nodes;
|
this.nodes = nodes;
|
||||||
this.location = location;
|
this.location = location;
|
||||||
this.service = Executors.newCachedThreadPool();
|
this.service = Executors.newCachedThreadPool();
|
||||||
|
@ -244,14 +242,12 @@ public class StubComputeServiceContextModule extends AbstractModule {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public NodeMetadata execute(String tag, String name, Template template) {
|
public NodeMetadata execute(String tag, String name, Template template) {
|
||||||
checkArgument(location.equals(template.getLocation()), "invalid location: "
|
checkArgument(location.equals(template.getLocation()), "invalid location: " + template.getLocation());
|
||||||
+ template.getLocation());
|
|
||||||
int id = idProvider.get();
|
int id = idProvider.get();
|
||||||
StubNodeMetadata node = new StubNodeMetadata(id + "", name, id + "", location, null,
|
StubNodeMetadata node = new StubNodeMetadata(id + "", name, id + "", location, null, ImmutableMap
|
||||||
ImmutableMap.<String, String> of(), tag, template.getImage(), NodeState.PENDING,
|
.<String, String> of(), tag, template.getImage(), NodeState.PENDING, ImmutableSet
|
||||||
ImmutableSet.<String> of(publicIpPrefix + id), ImmutableSet
|
.<String> of(publicIpPrefix + id), ImmutableSet.<String> of(privateIpPrefix + id), ImmutableMap
|
||||||
.<String> of(privateIpPrefix + id), ImmutableMap.<String, String> of(),
|
.<String, String> of(), new Credentials("root", passwordPrefix + id), service);
|
||||||
new Credentials("root", passwordPrefix + id), service);
|
|
||||||
nodes.put(id, node);
|
nodes.put(id, node);
|
||||||
node.setState(NodeState.RUNNING, 100);
|
node.setState(NodeState.RUNNING, 100);
|
||||||
return node;
|
return node;
|
||||||
|
@ -289,8 +285,7 @@ public class StubComputeServiceContextModule extends AbstractModule {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(
|
public Iterable<? extends NodeMetadata> listDetailsOnNodesMatching(Predicate<ComputeMetadata> filter) {
|
||||||
Predicate<ComputeMetadata> filter) {
|
|
||||||
return Iterables.filter(nodes.values(), filter);
|
return Iterables.filter(nodes.values(), filter);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -363,18 +358,16 @@ public class StubComputeServiceContextModule extends AbstractModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Set<? extends Size> provideSizes() {
|
protected Set<? extends Size> provideSizes() {
|
||||||
return ImmutableSet.of(new StubSize("small", 1, 1740, 160, ImmutableSet
|
return ImmutableSet.<Size> of(new StubSize("small", 1, 1740, 160, ImmutableSet.of(Architecture.X86_32)),
|
||||||
.of(Architecture.X86_32)), new StubSize("medium", 4, 7680, 850, ImmutableSet
|
new StubSize("medium", 4, 7680, 850, ImmutableSet.of(Architecture.X86_64)), new StubSize("large", 8,
|
||||||
.of(Architecture.X86_64)), new StubSize("large", 8, 15360, 1690, ImmutableSet
|
15360, 1690, ImmutableSet.of(Architecture.X86_64)));
|
||||||
.of(Architecture.X86_64)));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class StubSize extends org.jclouds.compute.domain.internal.SizeImpl {
|
private static class StubSize extends org.jclouds.compute.domain.internal.SizeImpl {
|
||||||
/** The serialVersionUID */
|
/** The serialVersionUID */
|
||||||
private static final long serialVersionUID = -1842135761654973637L;
|
private static final long serialVersionUID = -1842135761654973637L;
|
||||||
|
|
||||||
StubSize(String type, int cores, int ram, int disk,
|
StubSize(String type, int cores, int ram, int disk, Iterable<Architecture> supportedArchitectures) {
|
||||||
Iterable<Architecture> supportedArchitectures) {
|
|
||||||
super(type, type, type, null, null, ImmutableMap.<String, String> of(), cores, ram, disk,
|
super(type, type, type, null, null, ImmutableMap.<String, String> of(), cores, ram, disk,
|
||||||
architectureIn(supportedArchitectures));
|
architectureIn(supportedArchitectures));
|
||||||
}
|
}
|
||||||
|
@ -383,22 +376,23 @@ public class StubComputeServiceContextModule extends AbstractModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Set<? extends Image> provideImages(Location defaultLocation) {
|
protected Set<? extends Image> provideImages(Location defaultLocation) {
|
||||||
return ImmutableSet.of(new ImageImpl("1", OsFamily.UBUNTU.name(), "1", defaultLocation, null,
|
String parentId = defaultLocation.getParent().getId();
|
||||||
ImmutableMap.<String, String> of(), "stub ubuntu 32", "", OsFamily.UBUNTU,
|
return ImmutableSet.<Image> of(new ImageImpl("1", OsFamily.UBUNTU.name(), parentId + "/1", defaultLocation
|
||||||
"ubuntu 64", Architecture.X86_64, new Credentials("root", null)), new ImageImpl("2",
|
.getParent(), null, ImmutableMap.<String, String> of(), "stub ubuntu 32", "", OsFamily.UBUNTU,
|
||||||
OsFamily.UBUNTU.name(), "2", defaultLocation, null, ImmutableMap
|
"ubuntu 64", Architecture.X86_64, new Credentials("root", null)), new ImageImpl("2", OsFamily.UBUNTU
|
||||||
.<String, String> of(), "stub ubuntu 64", "", OsFamily.UBUNTU, "ubuntu 64",
|
.name(), parentId + "/2", defaultLocation.getParent(), null, ImmutableMap.<String, String> of(),
|
||||||
Architecture.X86_64, new Credentials("root", null)), new ImageImpl("3",
|
"stub ubuntu 64", "", OsFamily.UBUNTU, "ubuntu 64", Architecture.X86_64, new Credentials("root", null)),
|
||||||
OsFamily.CENTOS.name(), "3", defaultLocation, null, ImmutableMap
|
new ImageImpl("3", OsFamily.CENTOS.name(), parentId + "/3", defaultLocation.getParent(), null,
|
||||||
.<String, String> of(), "stub centos 64", "", OsFamily.CENTOS, "centos 64",
|
ImmutableMap.<String, String> of(), "stub centos 64", "", OsFamily.CENTOS, "centos 64",
|
||||||
Architecture.X86_64, new Credentials("root", null)));
|
Architecture.X86_64, new Credentials("root", null)));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
Location getLocation(@org.jclouds.rest.annotations.Provider String providerName) {
|
Location getLocation(@org.jclouds.rest.annotations.Provider String providerName) {
|
||||||
Location provider = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null);
|
Location provider = new LocationImpl(LocationScope.PROVIDER, providerName, providerName, null);
|
||||||
return new LocationImpl(LocationScope.ZONE, providerName, providerName, provider);
|
Location region = new LocationImpl(LocationScope.REGION, providerName+"region", providerName+"region", provider);
|
||||||
|
return new LocationImpl(LocationScope.ZONE, providerName+"zone", providerName+"zone", region);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -23,7 +23,6 @@ import static com.google.common.base.Preconditions.checkState;
|
||||||
import static org.jclouds.compute.util.ComputeServiceUtils.installNewCredentials;
|
import static org.jclouds.compute.util.ComputeServiceUtils.installNewCredentials;
|
||||||
import static org.jclouds.compute.util.ComputeServiceUtils.isKeyAuth;
|
import static org.jclouds.compute.util.ComputeServiceUtils.isKeyAuth;
|
||||||
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
|
import static org.jclouds.concurrent.ConcurrentUtils.awaitCompletion;
|
||||||
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
|
|
||||||
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -31,6 +30,7 @@ import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
@ -49,7 +49,6 @@ import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
|
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
|
||||||
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
|
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
|
||||||
import org.jclouds.compute.util.ComputeServiceUtils.SshCallable;
|
import org.jclouds.compute.util.ComputeServiceUtils.SshCallable;
|
||||||
import org.jclouds.concurrent.ConcurrentUtils;
|
|
||||||
import org.jclouds.io.Payload;
|
import org.jclouds.io.Payload;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.net.IPSocket;
|
import org.jclouds.net.IPSocket;
|
||||||
|
@ -61,7 +60,6 @@ import com.google.common.base.Throwables;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -84,9 +82,10 @@ public class ComputeUtils {
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ComputeUtils(Predicate<IPSocket> socketTester,
|
public ComputeUtils(Predicate<IPSocket> socketTester,
|
||||||
@Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning, GetNodeMetadataStrategy getNode,
|
@Named("SCRIPT_COMPLETE") Predicate<CommandUsingClient> runScriptNotRunning,
|
||||||
Timeouts timeouts, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
|
GetNodeMetadataStrategy getNode, Timeouts timeouts,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
|
||||||
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
this.nodeRunning = nodeRunning;
|
this.nodeRunning = nodeRunning;
|
||||||
this.timeouts = timeouts;
|
this.timeouts = timeouts;
|
||||||
this.getNode = getNode;
|
this.getNode = getNode;
|
||||||
|
@ -95,19 +94,20 @@ public class ComputeUtils {
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<?, ListenableFuture<Void>> runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(
|
public Map<?, Future<Void>> runOptionsOnNodesAndAddToGoodSetOrPutExceptionIntoBadMap(final TemplateOptions options,
|
||||||
final TemplateOptions options, Iterable<NodeMetadata> runningNodes, final Set<NodeMetadata> goodNodes,
|
Iterable<NodeMetadata> runningNodes, final Set<NodeMetadata> goodNodes,
|
||||||
final Map<NodeMetadata, Exception> badNodes) {
|
final Map<NodeMetadata, Exception> badNodes) {
|
||||||
Map<NodeMetadata, ListenableFuture<Void>> responses = Maps.newHashMap();
|
Map<NodeMetadata, Future<Void>> responses = Maps.newHashMap();
|
||||||
for (final NodeMetadata node : runningNodes) {
|
for (final NodeMetadata node : runningNodes) {
|
||||||
responses.put(node, makeListenable(executor.submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(
|
responses.put(node, executor.submit(runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(node, badNodes,
|
||||||
node, badNodes, goodNodes, options)), executor));
|
goodNodes, options)));
|
||||||
}
|
}
|
||||||
return responses;
|
return responses;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Callable<Void> runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(final NodeMetadata node,
|
public Callable<Void> runOptionsOnNodeAndAddToGoodSetOrPutExceptionIntoBadMap(final NodeMetadata node,
|
||||||
final Map<NodeMetadata, Exception> badNodes, final Set<NodeMetadata> goodNodes, final TemplateOptions options) {
|
final Map<NodeMetadata, Exception> badNodes, final Set<NodeMetadata> goodNodes,
|
||||||
|
final TemplateOptions options) {
|
||||||
return new Callable<Void>() {
|
return new Callable<Void>() {
|
||||||
@Override
|
@Override
|
||||||
public Void call() throws Exception {
|
public Void call() throws Exception {
|
||||||
|
@ -117,7 +117,7 @@ public class ComputeUtils {
|
||||||
goodNodes.add(node1);
|
goodNodes.add(node1);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.error(e, "<< problem applying options to node(%s): ", node.getId(), Throwables.getRootCause(e)
|
logger.error(e, "<< problem applying options to node(%s): ", node.getId(), Throwables.getRootCause(e)
|
||||||
.getMessage());
|
.getMessage());
|
||||||
badNodes.put(node, e);
|
badNodes.put(node, e);
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
@ -133,8 +133,8 @@ public class ComputeUtils {
|
||||||
node = installNewCredentials(getNode.execute(node.getId()), node.getCredentials());
|
node = installNewCredentials(getNode.execute(node.getId()), node.getCredentials());
|
||||||
else
|
else
|
||||||
throw new IllegalStateException(String.format(
|
throw new IllegalStateException(String.format(
|
||||||
"node didn't achieve the state running on node %s within %d seconds, final state: %s", node.getId(),
|
"node didn't achieve the state running on node %s within %d seconds, final state: %s", node.getId(),
|
||||||
timeouts.nodeRunning / 1000, node.getState()));
|
timeouts.nodeRunning / 1000, node.getState()));
|
||||||
|
|
||||||
List<SshCallable<?>> callables = Lists.newArrayList();
|
List<SshCallable<?>> callables = Lists.newArrayList();
|
||||||
if (options.getRunScript() != null) {
|
if (options.getRunScript() != null) {
|
||||||
|
@ -148,13 +148,13 @@ public class ComputeUtils {
|
||||||
// fail.
|
// fail.
|
||||||
if (callables.size() > 0 || options.getPrivateKey() != null) {
|
if (callables.size() > 0 || options.getPrivateKey() != null) {
|
||||||
runCallablesOnNode(node, callables, options.getPrivateKey() != null ? installKeyOnNode(node, options
|
runCallablesOnNode(node, callables, options.getPrivateKey() != null ? installKeyOnNode(node, options
|
||||||
.getPrivateKey()) : null);
|
.getPrivateKey()) : null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.getPort() > 0) {
|
if (options.getPort() > 0) {
|
||||||
checkNodeHasPublicIps(node);
|
checkNodeHasPublicIps(node);
|
||||||
blockUntilPortIsListeningOnPublicIp(options.getPort(), options.getSeconds(), Iterables.get(node
|
blockUntilPortIsListeningOnPublicIp(options.getPort(), options.getSeconds(), Iterables.get(node
|
||||||
.getPublicAddresses(), 0));
|
.getPublicAddresses(), 0));
|
||||||
}
|
}
|
||||||
return node;
|
return node;
|
||||||
}
|
}
|
||||||
|
@ -190,11 +190,12 @@ public class ComputeUtils {
|
||||||
return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script, false);
|
return new RunScriptOnNode(runScriptNotRunning, node, scriptName, script, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Map<SshCallable<?>, ?> runCallablesOnNode(NodeMetadata node, Iterable<? extends SshCallable<?>> parallel,
|
public Map<SshCallable<?>, ?> runCallablesOnNode(NodeMetadata node, Iterable<SshCallable<?>> parallel,
|
||||||
@Nullable SshCallable<?> last) {
|
@Nullable SshCallable<?> last) {
|
||||||
checkState(this.sshFactory != null, "runScript requested, but no SshModule configured");
|
checkState(this.sshFactory != null, "runScript requested, but no SshModule configured");
|
||||||
checkNodeHasPublicIps(node);
|
checkNodeHasPublicIps(node);
|
||||||
checkNotNull(node.getCredentials().credential, "credentials.key for node " + node.getId());
|
checkNotNull(node.getCredentials(), "credentials for node " + node.getId());
|
||||||
|
checkNotNull(node.getCredentials().credential, "credentials.credential for node " + node.getId());
|
||||||
SshClient ssh = createSshClientOncePortIsListeningOnNode(node);
|
SshClient ssh = createSshClientOncePortIsListeningOnNode(node);
|
||||||
try {
|
try {
|
||||||
ssh.connect();
|
ssh.connect();
|
||||||
|
@ -205,8 +206,8 @@ public class ComputeUtils {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<SshCallable<?>, ?> runTasksUsingSshClient(Iterable<? extends SshCallable<?>> parallel,
|
private Map<SshCallable<?>, ?> runTasksUsingSshClient(Iterable<SshCallable<?>> parallel, SshCallable<?> last,
|
||||||
SshCallable<?> last, SshClient ssh) {
|
SshClient ssh) {
|
||||||
Map<SshCallable<?>, Object> responses = Maps.newHashMap();
|
Map<SshCallable<?>, Object> responses = Maps.newHashMap();
|
||||||
if (Iterables.size(parallel) > 0) {
|
if (Iterables.size(parallel) > 0) {
|
||||||
responses.putAll(runCallablesUsingSshClient(parallel, ssh));
|
responses.putAll(runCallablesUsingSshClient(parallel, ssh));
|
||||||
|
@ -226,18 +227,18 @@ public class ComputeUtils {
|
||||||
IPSocket socket = new IPSocket(Iterables.get(node.getPublicAddresses(), 0), 22);
|
IPSocket socket = new IPSocket(Iterables.get(node.getPublicAddresses(), 0), 22);
|
||||||
socketTester.apply(socket);
|
socketTester.apply(socket);
|
||||||
SshClient ssh = isKeyAuth(node) ? sshFactory.create(socket, node.getCredentials().identity,
|
SshClient ssh = isKeyAuth(node) ? sshFactory.create(socket, node.getCredentials().identity,
|
||||||
node.getCredentials().credential.getBytes()) : sshFactory.create(socket, node.getCredentials().identity,
|
node.getCredentials().credential.getBytes()) : sshFactory.create(socket, node.getCredentials().identity,
|
||||||
node.getCredentials().credential);
|
node.getCredentials().credential);
|
||||||
return ssh;
|
return ssh;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<SshCallable<?>, Object> runCallablesUsingSshClient(Iterable<? extends SshCallable<?>> parallel,
|
// TODO refactor
|
||||||
SshClient ssh) {
|
private Map<SshCallable<?>, Object> runCallablesUsingSshClient(Iterable<SshCallable<?>> parallel, SshClient ssh) {
|
||||||
Map<SshCallable<?>, ListenableFuture<?>> parallelResponses = Maps.newHashMap();
|
Map<SshCallable<?>, Future<?>> parallelResponses = Maps.newHashMap();
|
||||||
|
|
||||||
for (SshCallable<?> callable : parallel) {
|
for (SshCallable<?> callable : parallel) {
|
||||||
callable.setConnection(ssh, logger);
|
callable.setConnection(ssh, logger);
|
||||||
parallelResponses.put(callable, ConcurrentUtils.makeListenable(executor.submit(callable), executor));
|
parallelResponses.put(callable, executor.submit(callable));
|
||||||
}
|
}
|
||||||
|
|
||||||
Map<SshCallable<?>, Exception> exceptions = awaitCompletion(parallelResponses, executor, null, logger, "ssh");
|
Map<SshCallable<?>, Exception> exceptions = awaitCompletion(parallelResponses, executor, null, logger, "ssh");
|
||||||
|
@ -248,9 +249,9 @@ public class ComputeUtils {
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <T> Map<SshCallable<?>, T> transform(Map<SshCallable<?>, ListenableFuture<?>> responses) {
|
public <T> Map<SshCallable<?>, T> transform(Map<SshCallable<?>, Future<?>> responses) {
|
||||||
Map<SshCallable<?>, T> actualResponses = Maps.newHashMap();
|
Map<SshCallable<?>, T> actualResponses = Maps.newHashMap();
|
||||||
for (Map.Entry<SshCallable<?>, ListenableFuture<?>> entry : responses.entrySet()) {
|
for (Map.Entry<SshCallable<?>, Future<?>> entry : responses.entrySet()) {
|
||||||
try {
|
try {
|
||||||
actualResponses.put(entry.getKey(), (T) entry.getValue().get());
|
actualResponses.put(entry.getKey(), (T) entry.getValue().get());
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
|
|
@ -26,7 +26,7 @@ import static com.google.common.collect.Iterables.concat;
|
||||||
import static com.google.common.collect.Iterables.get;
|
import static com.google.common.collect.Iterables.get;
|
||||||
import static com.google.common.collect.Iterables.getOnlyElement;
|
import static com.google.common.collect.Iterables.getOnlyElement;
|
||||||
import static com.google.common.collect.Sets.filter;
|
import static com.google.common.collect.Sets.filter;
|
||||||
import static com.google.common.collect.Sets.newHashSet;
|
import static com.google.common.collect.Sets.newLinkedHashSet;
|
||||||
import static com.google.common.collect.Sets.newTreeSet;
|
import static com.google.common.collect.Sets.newTreeSet;
|
||||||
import static org.jclouds.compute.options.RunScriptOptions.Builder.overrideCredentialsWith;
|
import static org.jclouds.compute.options.RunScriptOptions.Builder.overrideCredentialsWith;
|
||||||
import static org.jclouds.compute.predicates.NodePredicates.TERMINATED;
|
import static org.jclouds.compute.predicates.NodePredicates.TERMINATED;
|
||||||
|
@ -137,7 +137,7 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
String secret = Files.toString(new File(secretKeyFile), Charsets.UTF_8);
|
String secret = Files.toString(new File(secretKeyFile), Charsets.UTF_8);
|
||||||
assert secret.startsWith("-----BEGIN RSA PRIVATE KEY-----") : "invalid key:\n" + secret;
|
assert secret.startsWith("-----BEGIN RSA PRIVATE KEY-----") : "invalid key:\n" + secret;
|
||||||
return ImmutableMap.<String, String> of("private", secret, "public", Files.toString(new File(secretKeyFile
|
return ImmutableMap.<String, String> of("private", secret, "public", Files.toString(new File(secretKeyFile
|
||||||
+ ".pub"), Charsets.UTF_8));
|
+ ".pub"), Charsets.UTF_8));
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void setupCredentials() {
|
protected void setupCredentials() {
|
||||||
|
@ -153,7 +153,7 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
if (context != null)
|
if (context != null)
|
||||||
context.close();
|
context.close();
|
||||||
context = new ComputeServiceContextFactory().createContext(provider, identity, credential, ImmutableSet.of(
|
context = new ComputeServiceContextFactory().createContext(provider, identity, credential, ImmutableSet.of(
|
||||||
new Log4JLoggingModule(), getSshModule()));
|
new Log4JLoggingModule(), getSshModule()));
|
||||||
client = context.getComputeService();
|
client = context.getComputeService();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -170,7 +170,7 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
@Test(enabled = true, expectedExceptions = AuthorizationException.class)
|
@Test(enabled = true, expectedExceptions = AuthorizationException.class)
|
||||||
public void testCorrectAuthException() throws Exception {
|
public void testCorrectAuthException() throws Exception {
|
||||||
new ComputeServiceContextFactory().createContext(provider, "MOMMA", "MIA",
|
new ComputeServiceContextFactory().createContext(provider, "MOMMA", "MIA",
|
||||||
ImmutableSet.<Module> of(new Log4JLoggingModule())).close();
|
ImmutableSet.<Module> of(new Log4JLoggingModule())).close();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = true, dependsOnMethods = "testCorrectAuthException")
|
@Test(enabled = true, dependsOnMethods = "testCorrectAuthException")
|
||||||
|
@ -197,13 +197,13 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
try {
|
try {
|
||||||
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, options);
|
Set<? extends NodeMetadata> nodes = client.runNodesWithTag(tag, 1, options);
|
||||||
Credentials good = nodes.iterator().next().getCredentials();
|
Credentials good = nodes.iterator().next().getCredentials();
|
||||||
assert good.identity != null;
|
assert good.identity != null : nodes;
|
||||||
assert good.credential != null;
|
assert good.credential != null : nodes;
|
||||||
|
|
||||||
Image image = get(nodes, 0).getImage();
|
Image image = get(nodes, 0).getImage();
|
||||||
try {
|
try {
|
||||||
Map<? extends NodeMetadata, ExecResponse> responses = runScriptWithCreds(tag, image.getOsFamily(),
|
Map<? extends NodeMetadata, ExecResponse> responses = runScriptWithCreds(tag, image.getOsFamily(),
|
||||||
new Credentials(good.identity, "romeo"));
|
new Credentials(good.identity, "romeo"));
|
||||||
assert false : "shouldn't pass with a bad password\n" + responses;
|
assert false : "shouldn't pass with a bad password\n" + responses;
|
||||||
} catch (RunScriptOnNodesException e) {
|
} catch (RunScriptOnNodesException e) {
|
||||||
assert getRootCause(e).getMessage().contains("Auth fail") : e;
|
assert getRootCause(e).getMessage().contains("Auth fail") : e;
|
||||||
|
@ -237,8 +237,8 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
template = buildTemplate(client.templateBuilder());
|
template = buildTemplate(client.templateBuilder());
|
||||||
|
|
||||||
template.getOptions().installPrivateKey(newStringPayload(keyPair.get("private"))).authorizePublicKey(
|
template.getOptions().installPrivateKey(newStringPayload(keyPair.get("private"))).authorizePublicKey(
|
||||||
newStringPayload(keyPair.get("public"))).runScript(
|
newStringPayload(keyPair.get("public"))).runScript(
|
||||||
newStringPayload(buildScript(template.getImage().getOsFamily())));
|
newStringPayload(buildScript(template.getImage().getOsFamily())));
|
||||||
try {
|
try {
|
||||||
nodes = newTreeSet(client.runNodesWithTag(tag, 2, template));
|
nodes = newTreeSet(client.runNodesWithTag(tag, 2, template));
|
||||||
} catch (RunNodesException e) {
|
} catch (RunNodesException e) {
|
||||||
|
@ -281,10 +281,10 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(final String tag, OsFamily osFamily,
|
protected Map<? extends NodeMetadata, ExecResponse> runScriptWithCreds(final String tag, OsFamily osFamily,
|
||||||
Credentials creds) throws RunScriptOnNodesException {
|
Credentials creds) throws RunScriptOnNodesException {
|
||||||
try {
|
try {
|
||||||
return client.runScriptOnNodesMatching(runningWithTag(tag), newStringPayload(buildScript(osFamily)),
|
return client.runScriptOnNodesMatching(runningWithTag(tag), newStringPayload(buildScript(osFamily)),
|
||||||
overrideCredentialsWith(creds));
|
overrideCredentialsWith(creds));
|
||||||
} catch (SshException e) {
|
} catch (SshException e) {
|
||||||
if (getRootCause(e).getMessage().contains("Auth fail")) {
|
if (getRootCause(e).getMessage().contains("Auth fail")) {
|
||||||
// System.err.printf("bad credentials: %s:%s for %s%n",
|
// System.err.printf("bad credentials: %s:%s for %s%n",
|
||||||
|
@ -317,38 +317,39 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
|
|
||||||
public static String buildScript(OsFamily osFamily) {
|
public static String buildScript(OsFamily osFamily) {
|
||||||
switch (osFamily) {
|
switch (osFamily) {
|
||||||
case UBUNTU:
|
case UBUNTU:
|
||||||
return new StringBuilder()//
|
return new StringBuilder()//
|
||||||
.append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")//
|
.append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")//
|
||||||
.append("cp /etc/apt/sources.list /etc/apt/sources.list.old\n")//
|
.append("cp /etc/apt/sources.list /etc/apt/sources.list.old\n")//
|
||||||
.append(
|
.append(
|
||||||
"sed 's~us.archive.ubuntu.com~mirror.anl.gov/pub~g' /etc/apt/sources.list.old >/etc/apt/sources.list\n")//
|
"sed 's~us.archive.ubuntu.com~mirror.anl.gov/pub~g' /etc/apt/sources.list.old >/etc/apt/sources.list\n")//
|
||||||
.append("apt-get update\n")//
|
.append("apt-get update\n")//
|
||||||
.append("apt-get install -f -y --force-yes openjdk-6-jdk\n")//
|
.append("apt-get install -f -y --force-yes openjdk-6-jdk\n")//
|
||||||
.append("wget -qO/usr/bin/runurl run.alestic.com/runurl\n")//
|
.append("wget -qO/usr/bin/runurl run.alestic.com/runurl\n")//
|
||||||
.append("chmod 755 /usr/bin/runurl\n")//
|
.append("chmod 755 /usr/bin/runurl\n")//
|
||||||
.toString();
|
.toString();
|
||||||
case CENTOS:
|
case CENTOS:
|
||||||
case RHEL:
|
case RHEL:
|
||||||
return new StringBuilder()
|
return new StringBuilder()
|
||||||
.append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")
|
.append("echo nameserver 208.67.222.222 >> /etc/resolv.conf\n")
|
||||||
.append("echo \"[jdkrepo]\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
|
.append("echo \"[jdkrepo]\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
|
||||||
.append("echo \"name=jdkrepository\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
|
.append("echo \"name=jdkrepository\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
|
||||||
.append(
|
.append(
|
||||||
"echo \"baseurl=http://ec2-us-east-mirror.rightscale.com/epel/5/i386/\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
|
"echo \"baseurl=http://ec2-us-east-mirror.rightscale.com/epel/5/i386/\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
|
||||||
.append("echo \"enabled=1\" >> /etc/yum.repos.d/CentOS-Base.repo\n").append(
|
.append("echo \"enabled=1\" >> /etc/yum.repos.d/CentOS-Base.repo\n")
|
||||||
"yum --nogpgcheck -y install java-1.6.0-openjdk\n").append(
|
.append("yum --nogpgcheck -y install java-1.6.0-openjdk\n")
|
||||||
"echo \"export PATH=\\\"/usr/lib/jvm/jre-1.6.0-openjdk/bin/:\\$PATH\\\"\" >> /root/.bashrc\n")
|
.append(
|
||||||
.toString();
|
"echo \"export PATH=\\\"/usr/lib/jvm/jre-1.6.0-openjdk/bin/:\\$PATH\\\"\" >> /root/.bashrc\n")
|
||||||
default:
|
.toString();
|
||||||
throw new IllegalArgumentException(osFamily.toString());
|
default:
|
||||||
|
throw new IllegalArgumentException(osFamily.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired")
|
@Test(enabled = true, dependsOnMethods = "testCreateAnotherNodeWithANewContextToEnsureSharedMemIsntRequired")
|
||||||
public void testGet() throws Exception {
|
public void testGet() throws Exception {
|
||||||
Set<? extends NodeMetadata> metadataSet = newHashSet(filter(client.listNodesDetailsMatching(all()), and(
|
Set<? extends NodeMetadata> nodes = client.listNodesDetailsMatching(all());
|
||||||
withTag(tag), not(TERMINATED))));
|
Set<? extends NodeMetadata> metadataSet = newLinkedHashSet(filter(nodes, and(withTag(tag), not(TERMINATED))));
|
||||||
for (NodeMetadata node : nodes) {
|
for (NodeMetadata node : nodes) {
|
||||||
metadataSet.remove(node);
|
metadataSet.remove(node);
|
||||||
NodeMetadata metadata = client.getNodeMetadata(node.getId());
|
NodeMetadata metadata = client.getNodeMetadata(node.getId());
|
||||||
|
@ -365,7 +366,7 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
|
|
||||||
protected void assertNodeZero(Set<? extends NodeMetadata> metadataSet) {
|
protected void assertNodeZero(Set<? extends NodeMetadata> metadataSet) {
|
||||||
assert metadataSet.size() == 0 : String.format("nodes left in set: [%s] which didn't match set: [%s]",
|
assert metadataSet.size() == 0 : String.format("nodes left in set: [%s] which didn't match set: [%s]",
|
||||||
metadataSet, nodes);
|
metadataSet, nodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(enabled = true, dependsOnMethods = "testGet")
|
@Test(enabled = true, dependsOnMethods = "testGet")
|
||||||
|
@ -426,26 +427,26 @@ public abstract class BaseComputeServiceLiveTest {
|
||||||
assert location != location.getParent() : location;
|
assert location != location.getParent() : location;
|
||||||
assert location.getScope() != null : location;
|
assert location.getScope() != null : location;
|
||||||
switch (location.getScope()) {
|
switch (location.getScope()) {
|
||||||
case PROVIDER:
|
case PROVIDER:
|
||||||
assertProvider(location);
|
assertProvider(location);
|
||||||
break;
|
break;
|
||||||
case REGION:
|
case REGION:
|
||||||
assertProvider(location.getParent());
|
assertProvider(location.getParent());
|
||||||
break;
|
break;
|
||||||
case ZONE:
|
case ZONE:
|
||||||
Location provider = location.getParent().getParent();
|
Location provider = location.getParent().getParent();
|
||||||
// zone can be a direct descendant of provider
|
// zone can be a direct descendant of provider
|
||||||
if (provider == null)
|
if (provider == null)
|
||||||
provider = location.getParent();
|
provider = location.getParent();
|
||||||
assertProvider(provider);
|
assertProvider(provider);
|
||||||
break;
|
break;
|
||||||
case HOST:
|
case HOST:
|
||||||
Location provider2 = location.getParent().getParent().getParent();
|
Location provider2 = location.getParent().getParent().getParent();
|
||||||
// zone can be a direct descendant of provider
|
// zone can be a direct descendant of provider
|
||||||
if (provider2 == null)
|
if (provider2 == null)
|
||||||
provider2 = location.getParent().getParent();
|
provider2 = location.getParent().getParent();
|
||||||
assertProvider(provider2);
|
assertProvider(provider2);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@ import java.io.IOException;
|
||||||
import java.io.Serializable;
|
import java.io.Serializable;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ConcurrentMap;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import org.easymock.IArgumentMatcher;
|
import org.easymock.IArgumentMatcher;
|
||||||
import org.jclouds.compute.domain.Architecture;
|
import org.jclouds.compute.domain.Architecture;
|
||||||
|
@ -86,7 +88,7 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
Template defaultTemplate = client.templateBuilder().build();
|
Template defaultTemplate = client.templateBuilder().build();
|
||||||
assertEquals(defaultTemplate.getImage().getArchitecture(), Architecture.X86_64);
|
assertEquals(defaultTemplate.getImage().getArchitecture(), Architecture.X86_64);
|
||||||
assertEquals(defaultTemplate.getImage().getOsFamily(), OsFamily.UBUNTU);
|
assertEquals(defaultTemplate.getImage().getOsFamily(), OsFamily.UBUNTU);
|
||||||
assertEquals(defaultTemplate.getLocation().getId(), provider);
|
assertEquals(defaultTemplate.getLocation().getId(), provider + "zone");
|
||||||
assertEquals(defaultTemplate.getSize().getCores(), 4.0d);
|
assertEquals(defaultTemplate.getSize().getCores(), 4.0d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -109,17 +111,17 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
expect(open.apply(new IPSocket("144.175.1.4", 22))).andReturn(true);
|
expect(open.apply(new IPSocket("144.175.1.4", 22))).andReturn(true);
|
||||||
|
|
||||||
expect(
|
expect(
|
||||||
factory.create(eq(new IPSocket("144.175.1.1", 22)), eq("root"), aryEq(keyPair.get("private")
|
factory.create(eq(new IPSocket("144.175.1.1", 22)), eq("root"), aryEq(keyPair.get("private")
|
||||||
.getBytes()))).andReturn(client1).atLeastOnce();
|
.getBytes()))).andReturn(client1).atLeastOnce();
|
||||||
expect(
|
expect(
|
||||||
factory.create(eq(new IPSocket("144.175.1.2", 22)), eq("root"), aryEq(keyPair.get("private")
|
factory.create(eq(new IPSocket("144.175.1.2", 22)), eq("root"), aryEq(keyPair.get("private")
|
||||||
.getBytes()))).andReturn(client2).atLeastOnce();
|
.getBytes()))).andReturn(client2).atLeastOnce();
|
||||||
expect(
|
expect(
|
||||||
factory.create(eq(new IPSocket("144.175.1.3", 22)), eq("root"), aryEq(keyPair.get("private")
|
factory.create(eq(new IPSocket("144.175.1.3", 22)), eq("root"), aryEq(keyPair.get("private")
|
||||||
.getBytes()))).andReturn(client3).atLeastOnce();
|
.getBytes()))).andReturn(client3).atLeastOnce();
|
||||||
expect(
|
expect(
|
||||||
factory.create(eq(new IPSocket("144.175.1.4", 22)), eq("root"), aryEq(keyPair.get("private")
|
factory.create(eq(new IPSocket("144.175.1.4", 22)), eq("root"), aryEq(keyPair.get("private")
|
||||||
.getBytes()))).andReturn(client4).atLeastOnce();
|
.getBytes()))).andReturn(client4).atLeastOnce();
|
||||||
|
|
||||||
helloAndJava(client1);
|
helloAndJava(client1);
|
||||||
helloAndJava(client2);
|
helloAndJava(client2);
|
||||||
|
@ -163,20 +165,20 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
SshClient client4 = createMock(SshClient.class);
|
SshClient client4 = createMock(SshClient.class);
|
||||||
|
|
||||||
expect(factory.create(new IPSocket("144.175.1.1", 22), "root", "romeo")).andThrow(
|
expect(factory.create(new IPSocket("144.175.1.1", 22), "root", "romeo")).andThrow(
|
||||||
new SshException("Auth fail"));
|
new SshException("Auth fail"));
|
||||||
expect(factory.create(new IPSocket("144.175.1.1", 22), "root", "password1")).andReturn(client1)
|
expect(factory.create(new IPSocket("144.175.1.1", 22), "root", "password1")).andReturn(client1)
|
||||||
.atLeastOnce();
|
.atLeastOnce();
|
||||||
|
|
||||||
client1.connect();
|
client1.connect();
|
||||||
runScript(client1, "computeserv", 1);
|
runScript(client1, "computeserv", 1);
|
||||||
client1.disconnect();
|
client1.disconnect();
|
||||||
|
|
||||||
expect(factory.create(new IPSocket("144.175.1.2", 22), "root", "password2")).andReturn(client2)
|
expect(factory.create(new IPSocket("144.175.1.2", 22), "root", "password2")).andReturn(client2)
|
||||||
.atLeastOnce();
|
.atLeastOnce();
|
||||||
expect(factory.create(new IPSocket("144.175.1.3", 22), "root", "password3")).andReturn(client3)
|
expect(factory.create(new IPSocket("144.175.1.3", 22), "root", "password3")).andReturn(client3)
|
||||||
.atLeastOnce();
|
.atLeastOnce();
|
||||||
expect(factory.create(new IPSocket("144.175.1.4", 22), "root", "password4")).andReturn(client4)
|
expect(factory.create(new IPSocket("144.175.1.4", 22), "root", "password4")).andReturn(client4)
|
||||||
.atLeastOnce();
|
.atLeastOnce();
|
||||||
|
|
||||||
runScriptAndInstallSsh(client2, "runscript", 2);
|
runScriptAndInstallSsh(client2, "runscript", 2);
|
||||||
runScriptAndInstallSsh(client3, "runscript", 3);
|
runScriptAndInstallSsh(client3, "runscript", 3);
|
||||||
|
@ -240,9 +242,9 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
|
|
||||||
public static String initScript(String scriptName, String script) {
|
public static String initScript(String scriptName, String script) {
|
||||||
return new InitBuilder(scriptName, "/tmp/" + scriptName, "/tmp/" + scriptName,
|
return new InitBuilder(scriptName, "/tmp/" + scriptName, "/tmp/" + scriptName,
|
||||||
ImmutableMap.<String, String> of(), Iterables.toArray(Splitter.on("\n").split(
|
ImmutableMap.<String, String> of(), Iterables.toArray(Splitter.on("\n").split(
|
||||||
new String(checkNotNull(script, "script"))), String.class))
|
new String(checkNotNull(script, "script"))), String.class))
|
||||||
.build(org.jclouds.scriptbuilder.domain.OsFamily.UNIX);
|
.build(org.jclouds.scriptbuilder.domain.OsFamily.UNIX);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Payload payloadEq(String value) {
|
public static Payload payloadEq(String value) {
|
||||||
|
@ -253,7 +255,7 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
public void testAssignability() throws Exception {
|
public void testAssignability() throws Exception {
|
||||||
@SuppressWarnings("unused")
|
@SuppressWarnings("unused")
|
||||||
RestContext<ConcurrentMap<Integer, StubNodeMetadata>, ConcurrentMap<Integer, StubNodeMetadata>> stubContext = new ComputeServiceContextFactory()
|
RestContext<ConcurrentMap<Integer, StubNodeMetadata>, ConcurrentMap<Integer, StubNodeMetadata>> stubContext = new ComputeServiceContextFactory()
|
||||||
.createContext(provider, identity, credential).getProviderSpecificContext();
|
.createContext(provider, identity, credential).getProviderSpecificContext();
|
||||||
}
|
}
|
||||||
|
|
||||||
private static class PayloadEquals implements IArgumentMatcher, Serializable {
|
private static class PayloadEquals implements IArgumentMatcher, Serializable {
|
||||||
|
@ -303,7 +305,7 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
return false;
|
return false;
|
||||||
PayloadEquals other = (PayloadEquals) o;
|
PayloadEquals other = (PayloadEquals) o;
|
||||||
return this.expected == null && other.expected == null || this.expected != null
|
return this.expected == null && other.expected == null || this.expected != null
|
||||||
&& this.expected.equals(other.expected);
|
&& this.expected.equals(other.expected);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -361,4 +363,9 @@ public class StubComputeServiceIntegrationTest extends BaseComputeServiceLiveTes
|
||||||
super.testTemplateMatch();
|
super.testTemplateMatch();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
|
super.cleanup();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -59,12 +59,12 @@ public class TemplateBuilderImplTest {
|
||||||
Image image2 = createMock(Image.class);
|
Image image2 = createMock(Image.class);
|
||||||
|
|
||||||
Size size = new SizeImpl("sizeId", null, "sizeId", defaultLocation, null, ImmutableMap.<String, String> of(),
|
Size size = new SizeImpl("sizeId", null, "sizeId", defaultLocation, null, ImmutableMap.<String, String> of(),
|
||||||
1.0, 0, 0, ImagePredicates.any());
|
1.0, 0, 0, ImagePredicates.any());
|
||||||
|
|
||||||
Provider<Set<? extends Location>> locations = Providers.<Set<? extends Location>> of(ImmutableSet
|
Provider<Set<? extends Location>> locations = Providers.<Set<? extends Location>> of(ImmutableSet
|
||||||
.<Location> of(defaultLocation));
|
.<Location> of(defaultLocation));
|
||||||
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
|
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
|
||||||
.<Image> of(image, image2));
|
.<Image> of(image, image2));
|
||||||
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of(size));
|
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of(size));
|
||||||
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
|
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
|
||||||
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
||||||
|
@ -87,7 +87,7 @@ public class TemplateBuilderImplTest {
|
||||||
replay(templateBuilderProvider);
|
replay(templateBuilderProvider);
|
||||||
|
|
||||||
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
||||||
templateBuilderProvider);
|
templateBuilderProvider);
|
||||||
|
|
||||||
assertEquals(template.resolveImage(size), image2);
|
assertEquals(template.resolveImage(size), image2);
|
||||||
|
|
||||||
|
@ -107,18 +107,17 @@ public class TemplateBuilderImplTest {
|
||||||
Image image2 = createMock(Image.class);
|
Image image2 = createMock(Image.class);
|
||||||
|
|
||||||
Size size = new SizeImpl("sizeId", null, "sizeId", defaultLocation, null, ImmutableMap.<String, String> of(),
|
Size size = new SizeImpl("sizeId", null, "sizeId", defaultLocation, null, ImmutableMap.<String, String> of(),
|
||||||
1.0, 0, 0, ImagePredicates.any());
|
1.0, 0, 0, ImagePredicates.any());
|
||||||
|
|
||||||
Provider<Set<? extends Location>> locations = Providers.<Set<? extends Location>> of(ImmutableSet
|
Provider<Set<? extends Location>> locations = Providers.<Set<? extends Location>> of(ImmutableSet
|
||||||
.<Location> of(defaultLocation));
|
.<Location> of(defaultLocation));
|
||||||
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
|
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet
|
||||||
.<Image> of(image, image2));
|
.<Image> of(image, image2));
|
||||||
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of(size));
|
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of(size));
|
||||||
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
|
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
|
||||||
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
||||||
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
|
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
|
||||||
|
|
||||||
expect(defaultLocation.getId()).andReturn("locationId").atLeastOnce();
|
|
||||||
expect(optionsProvider.get()).andReturn(new TemplateOptions());
|
expect(optionsProvider.get()).andReturn(new TemplateOptions());
|
||||||
|
|
||||||
expect(image.getLocation()).andReturn(defaultLocation).atLeastOnce();
|
expect(image.getLocation()).andReturn(defaultLocation).atLeastOnce();
|
||||||
|
@ -135,7 +134,7 @@ public class TemplateBuilderImplTest {
|
||||||
replay(templateBuilderProvider);
|
replay(templateBuilderProvider);
|
||||||
|
|
||||||
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
||||||
templateBuilderProvider);
|
templateBuilderProvider);
|
||||||
|
|
||||||
assertEquals(template.smallest().architecture(Architecture.X86_32).build().getImage(), image);
|
assertEquals(template.smallest().architecture(Architecture.X86_32).build().getImage(), image);
|
||||||
|
|
||||||
|
@ -153,17 +152,16 @@ public class TemplateBuilderImplTest {
|
||||||
Location defaultLocation = createMock(Location.class);
|
Location defaultLocation = createMock(Location.class);
|
||||||
Image image = createMock(Image.class);
|
Image image = createMock(Image.class);
|
||||||
Size size = new SizeImpl("sizeId", null, "sizeId", defaultLocation, null, ImmutableMap.<String, String> of(), 0,
|
Size size = new SizeImpl("sizeId", null, "sizeId", defaultLocation, null, ImmutableMap.<String, String> of(), 0,
|
||||||
0, 0, ImagePredicates.idEquals("imageId"));
|
0, 0, ImagePredicates.idEquals("imageId"));
|
||||||
|
|
||||||
Provider<Set<? extends Location>> locations = Providers.<Set<? extends Location>> of(ImmutableSet
|
Provider<Set<? extends Location>> locations = Providers.<Set<? extends Location>> of(ImmutableSet
|
||||||
.<Location> of(defaultLocation));
|
.<Location> of(defaultLocation));
|
||||||
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of(image));
|
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of(image));
|
||||||
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of(size));
|
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of(size));
|
||||||
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
|
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
|
||||||
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
||||||
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
|
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
|
||||||
|
|
||||||
expect(defaultLocation.getId()).andReturn("locationId").atLeastOnce();
|
|
||||||
expect(optionsProvider.get()).andReturn(new TemplateOptions());
|
expect(optionsProvider.get()).andReturn(new TemplateOptions());
|
||||||
expect(image.getId()).andReturn("imageId").atLeastOnce();
|
expect(image.getId()).andReturn("imageId").atLeastOnce();
|
||||||
expect(image.getLocation()).andReturn(defaultLocation).atLeastOnce();
|
expect(image.getLocation()).andReturn(defaultLocation).atLeastOnce();
|
||||||
|
@ -181,7 +179,7 @@ public class TemplateBuilderImplTest {
|
||||||
replay(templateBuilderProvider);
|
replay(templateBuilderProvider);
|
||||||
|
|
||||||
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
||||||
templateBuilderProvider);
|
templateBuilderProvider);
|
||||||
|
|
||||||
template.imageId("imageId").build();
|
template.imageId("imageId").build();
|
||||||
|
|
||||||
|
@ -198,17 +196,16 @@ public class TemplateBuilderImplTest {
|
||||||
Location defaultLocation = createMock(Location.class);
|
Location defaultLocation = createMock(Location.class);
|
||||||
Image image = createMock(Image.class);
|
Image image = createMock(Image.class);
|
||||||
Size size = new SizeImpl("sizeId", null, "sizeId", defaultLocation, null, ImmutableMap.<String, String> of(), 0,
|
Size size = new SizeImpl("sizeId", null, "sizeId", defaultLocation, null, ImmutableMap.<String, String> of(), 0,
|
||||||
0, 0, ImagePredicates.idEquals("imageId"));
|
0, 0, ImagePredicates.idEquals("imageId"));
|
||||||
|
|
||||||
Provider<Set<? extends Location>> locations = Providers.<Set<? extends Location>> of(ImmutableSet
|
Provider<Set<? extends Location>> locations = Providers.<Set<? extends Location>> of(ImmutableSet
|
||||||
.<Location> of(defaultLocation));
|
.<Location> of(defaultLocation));
|
||||||
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of(image));
|
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of(image));
|
||||||
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of(size));
|
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of(size));
|
||||||
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
|
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
|
||||||
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
||||||
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
|
TemplateBuilder defaultTemplate = createMock(TemplateBuilder.class);
|
||||||
|
|
||||||
expect(defaultLocation.getId()).andReturn("locationId").atLeastOnce();
|
|
||||||
expect(optionsProvider.get()).andReturn(new TemplateOptions());
|
expect(optionsProvider.get()).andReturn(new TemplateOptions());
|
||||||
expect(image.getId()).andReturn("notImageId").atLeastOnce();
|
expect(image.getId()).andReturn("notImageId").atLeastOnce();
|
||||||
|
|
||||||
|
@ -219,7 +216,7 @@ public class TemplateBuilderImplTest {
|
||||||
replay(templateBuilderProvider);
|
replay(templateBuilderProvider);
|
||||||
|
|
||||||
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
||||||
templateBuilderProvider);
|
templateBuilderProvider);
|
||||||
try {
|
try {
|
||||||
template.imageId("notImageId").build();
|
template.imageId("notImageId").build();
|
||||||
assert false;
|
assert false;
|
||||||
|
@ -239,7 +236,7 @@ public class TemplateBuilderImplTest {
|
||||||
TemplateOptions from = provideTemplateOptions();
|
TemplateOptions from = provideTemplateOptions();
|
||||||
|
|
||||||
Provider<Set<? extends Location>> locations = Providers
|
Provider<Set<? extends Location>> locations = Providers
|
||||||
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
|
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
|
||||||
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of());
|
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of());
|
||||||
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of());
|
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of());
|
||||||
Location defaultLocation = createMock(Location.class);
|
Location defaultLocation = createMock(Location.class);
|
||||||
|
@ -258,7 +255,7 @@ public class TemplateBuilderImplTest {
|
||||||
replay(templateBuilderProvider);
|
replay(templateBuilderProvider);
|
||||||
|
|
||||||
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
||||||
templateBuilderProvider);
|
templateBuilderProvider);
|
||||||
|
|
||||||
template.options(options).build();
|
template.options(options).build();
|
||||||
|
|
||||||
|
@ -273,7 +270,7 @@ public class TemplateBuilderImplTest {
|
||||||
public void testNothingUsesDefaultTemplateBuilder() {
|
public void testNothingUsesDefaultTemplateBuilder() {
|
||||||
|
|
||||||
Provider<Set<? extends Location>> locations = Providers
|
Provider<Set<? extends Location>> locations = Providers
|
||||||
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
|
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
|
||||||
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of());
|
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of());
|
||||||
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of());
|
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of());
|
||||||
|
|
||||||
|
@ -291,7 +288,7 @@ public class TemplateBuilderImplTest {
|
||||||
replay(templateBuilderProvider);
|
replay(templateBuilderProvider);
|
||||||
|
|
||||||
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
||||||
templateBuilderProvider);
|
templateBuilderProvider);
|
||||||
|
|
||||||
template.build();
|
template.build();
|
||||||
|
|
||||||
|
@ -302,10 +299,10 @@ public class TemplateBuilderImplTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected TemplateBuilderImpl createTemplateBuilder(Provider<Set<? extends Location>> locations,
|
protected TemplateBuilderImpl createTemplateBuilder(Provider<Set<? extends Location>> locations,
|
||||||
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes, Location defaultLocation,
|
Provider<Set<? extends Image>> images, Provider<Set<? extends Size>> sizes, Location defaultLocation,
|
||||||
Provider<TemplateOptions> optionsProvider, Provider<TemplateBuilder> templateBuilderProvider) {
|
Provider<TemplateOptions> optionsProvider, Provider<TemplateBuilder> templateBuilderProvider) {
|
||||||
TemplateBuilderImpl template = new TemplateBuilderImpl(locations, images, sizes, defaultLocation,
|
TemplateBuilderImpl template = new TemplateBuilderImpl(locations, images, sizes, defaultLocation,
|
||||||
optionsProvider, templateBuilderProvider);
|
optionsProvider, templateBuilderProvider);
|
||||||
return template;
|
return template;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -313,7 +310,7 @@ public class TemplateBuilderImplTest {
|
||||||
@Test
|
@Test
|
||||||
public void testSuppliedLocationWithNoOptions() {
|
public void testSuppliedLocationWithNoOptions() {
|
||||||
Provider<Set<? extends Location>> locations = Providers
|
Provider<Set<? extends Location>> locations = Providers
|
||||||
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
|
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
|
||||||
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of());
|
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of());
|
||||||
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of());
|
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of());
|
||||||
Location defaultLocation = createMock(Location.class);
|
Location defaultLocation = createMock(Location.class);
|
||||||
|
@ -321,15 +318,13 @@ public class TemplateBuilderImplTest {
|
||||||
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
||||||
TemplateOptions defaultOptions = createMock(TemplateOptions.class);
|
TemplateOptions defaultOptions = createMock(TemplateOptions.class);
|
||||||
|
|
||||||
expect(optionsProvider.get()).andReturn(defaultOptions);
|
|
||||||
|
|
||||||
replay(defaultOptions);
|
replay(defaultOptions);
|
||||||
replay(defaultLocation);
|
replay(defaultLocation);
|
||||||
replay(optionsProvider);
|
replay(optionsProvider);
|
||||||
replay(templateBuilderProvider);
|
replay(templateBuilderProvider);
|
||||||
|
|
||||||
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
||||||
templateBuilderProvider);
|
templateBuilderProvider);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
template.imageId("foo").locationId("location").build();
|
template.imageId("foo").locationId("location").build();
|
||||||
|
@ -350,7 +345,7 @@ public class TemplateBuilderImplTest {
|
||||||
TemplateOptions from = provideTemplateOptions();
|
TemplateOptions from = provideTemplateOptions();
|
||||||
|
|
||||||
Provider<Set<? extends Location>> locations = Providers
|
Provider<Set<? extends Location>> locations = Providers
|
||||||
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
|
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
|
||||||
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of());
|
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of());
|
||||||
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of());
|
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of());
|
||||||
Location defaultLocation = createMock(Location.class);
|
Location defaultLocation = createMock(Location.class);
|
||||||
|
@ -364,7 +359,7 @@ public class TemplateBuilderImplTest {
|
||||||
replay(templateBuilderProvider);
|
replay(templateBuilderProvider);
|
||||||
|
|
||||||
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
||||||
templateBuilderProvider);
|
templateBuilderProvider);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
template.imageId("foo").options(provideTemplateOptions()).locationId("location").build();
|
template.imageId("foo").options(provideTemplateOptions()).locationId("location").build();
|
||||||
|
@ -382,7 +377,7 @@ public class TemplateBuilderImplTest {
|
||||||
@Test
|
@Test
|
||||||
public void testDefaultLocationWithNoOptionsNoSuchElement() {
|
public void testDefaultLocationWithNoOptionsNoSuchElement() {
|
||||||
Provider<Set<? extends Location>> locations = Providers
|
Provider<Set<? extends Location>> locations = Providers
|
||||||
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
|
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
|
||||||
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of());
|
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of());
|
||||||
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of());
|
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of());
|
||||||
Location defaultLocation = createMock(Location.class);
|
Location defaultLocation = createMock(Location.class);
|
||||||
|
@ -390,7 +385,6 @@ public class TemplateBuilderImplTest {
|
||||||
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
||||||
TemplateOptions defaultOptions = createMock(TemplateOptions.class);
|
TemplateOptions defaultOptions = createMock(TemplateOptions.class);
|
||||||
|
|
||||||
expect(defaultLocation.getId()).andReturn("foo");
|
|
||||||
expect(optionsProvider.get()).andReturn(defaultOptions);
|
expect(optionsProvider.get()).andReturn(defaultOptions);
|
||||||
|
|
||||||
replay(defaultOptions);
|
replay(defaultOptions);
|
||||||
|
@ -399,10 +393,10 @@ public class TemplateBuilderImplTest {
|
||||||
replay(templateBuilderProvider);
|
replay(templateBuilderProvider);
|
||||||
|
|
||||||
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
||||||
templateBuilderProvider);
|
templateBuilderProvider);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
template.imageId("foo").build();
|
template.imageId("region/ami").build();
|
||||||
assert false;
|
assert false;
|
||||||
} catch (NoSuchElementException e) {
|
} catch (NoSuchElementException e) {
|
||||||
|
|
||||||
|
@ -422,7 +416,7 @@ public class TemplateBuilderImplTest {
|
||||||
@Test
|
@Test
|
||||||
public void testDefaultLocationWithOptions() {
|
public void testDefaultLocationWithOptions() {
|
||||||
Provider<Set<? extends Location>> locations = Providers
|
Provider<Set<? extends Location>> locations = Providers
|
||||||
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
|
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
|
||||||
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of());
|
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of());
|
||||||
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of());
|
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of());
|
||||||
Location defaultLocation = createMock(Location.class);
|
Location defaultLocation = createMock(Location.class);
|
||||||
|
@ -430,28 +424,19 @@ public class TemplateBuilderImplTest {
|
||||||
TemplateOptions from = provideTemplateOptions();
|
TemplateOptions from = provideTemplateOptions();
|
||||||
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
||||||
|
|
||||||
expect(defaultLocation.getId()).andReturn("foo");
|
|
||||||
// expect(defaultLocation.getId()).andReturn("foo");
|
|
||||||
expect(optionsProvider.get()).andReturn(from);
|
expect(optionsProvider.get()).andReturn(from);
|
||||||
// expect(optionsProvider.get()).andReturn(provideTemplateOptions());
|
|
||||||
|
|
||||||
expect(from.getInboundPorts()).andReturn(new int[] { 22 });
|
expect(from.getInboundPorts()).andReturn(new int[] { 22 });
|
||||||
// expect(from.getRunScript()).andReturn(null);
|
|
||||||
// expect(from.getPrivateKey()).andReturn(null);
|
|
||||||
// expect(from.getPublicKey()).andReturn(null);
|
|
||||||
// expect(from.getPort()).andReturn(null);
|
|
||||||
// expect(from.isIncludeMetadata()).andReturn(false);
|
|
||||||
// expect(from.shouldBlockUntilRunning()).andReturn(true);
|
|
||||||
|
|
||||||
replay(defaultLocation);
|
replay(defaultLocation);
|
||||||
replay(optionsProvider);
|
replay(optionsProvider);
|
||||||
replay(templateBuilderProvider);
|
replay(templateBuilderProvider);
|
||||||
|
|
||||||
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
||||||
templateBuilderProvider);
|
templateBuilderProvider);
|
||||||
|
|
||||||
try {
|
try {
|
||||||
template.imageId("foo").options(provideTemplateOptions()).build();
|
template.imageId("region/ami").options(provideTemplateOptions()).build();
|
||||||
assert false;
|
assert false;
|
||||||
} catch (NoSuchElementException e) {
|
} catch (NoSuchElementException e) {
|
||||||
|
|
||||||
|
@ -466,7 +451,7 @@ public class TemplateBuilderImplTest {
|
||||||
@Test
|
@Test
|
||||||
public void testImageIdNullsEverythingElse() {
|
public void testImageIdNullsEverythingElse() {
|
||||||
Provider<Set<? extends Location>> locations = Providers
|
Provider<Set<? extends Location>> locations = Providers
|
||||||
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
|
.<Set<? extends Location>> of(ImmutableSet.<Location> of());
|
||||||
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of());
|
Provider<Set<? extends Image>> images = Providers.<Set<? extends Image>> of(ImmutableSet.<Image> of());
|
||||||
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of());
|
Provider<Set<? extends Size>> sizes = Providers.<Set<? extends Size>> of(ImmutableSet.<Size> of());
|
||||||
Location defaultLocation = createMock(Location.class);
|
Location defaultLocation = createMock(Location.class);
|
||||||
|
@ -478,7 +463,7 @@ public class TemplateBuilderImplTest {
|
||||||
replay(templateBuilderProvider);
|
replay(templateBuilderProvider);
|
||||||
|
|
||||||
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
TemplateBuilderImpl template = createTemplateBuilder(locations, images, sizes, defaultLocation, optionsProvider,
|
||||||
templateBuilderProvider);
|
templateBuilderProvider);
|
||||||
|
|
||||||
template.architecture(Architecture.X86_32);
|
template.architecture(Architecture.X86_32);
|
||||||
template.imageDescriptionMatches("imageDescriptionMatches");
|
template.imageDescriptionMatches("imageDescriptionMatches");
|
||||||
|
|
|
@ -18,41 +18,111 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.concurrent;
|
package org.jclouds.concurrent;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
import static com.google.common.collect.Maps.newHashMap;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.concurrent.AbstractExecutorService;
|
||||||
import java.util.concurrent.CancellationException;
|
import java.util.concurrent.CancellationException;
|
||||||
import java.util.concurrent.CountDownLatch;
|
import java.util.concurrent.CountDownLatch;
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Future;
|
import java.util.concurrent.Future;
|
||||||
|
import java.util.concurrent.RejectedExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
import java.util.concurrent.ThreadPoolExecutor.CallerRunsPolicy;
|
||||||
import java.util.concurrent.atomic.AtomicBoolean;
|
import java.util.concurrent.atomic.AtomicBoolean;
|
||||||
import java.util.concurrent.atomic.AtomicInteger;
|
import java.util.concurrent.atomic.AtomicInteger;
|
||||||
|
import java.util.concurrent.locks.Condition;
|
||||||
|
import java.util.concurrent.locks.Lock;
|
||||||
|
import java.util.concurrent.locks.ReentrantLock;
|
||||||
|
|
||||||
import javax.annotation.Nullable;
|
import javax.annotation.Nullable;
|
||||||
|
import javax.annotation.Resource;
|
||||||
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
|
import org.jclouds.http.handlers.BackoffLimitedRetryHandler;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.collect.ForwardingObject;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.util.concurrent.ExecutionList;
|
import com.google.common.util.concurrent.ExecutionList;
|
||||||
import com.google.common.util.concurrent.ForwardingFuture;
|
import com.google.common.util.concurrent.ForwardingFuture;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
import com.google.common.util.concurrent.MoreExecutors;
|
||||||
|
import com.google.inject.Inject;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adapt things missing from Guava.
|
* Adapt things from Guava.
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class ConcurrentUtils {
|
public class ConcurrentUtils {
|
||||||
|
@Resource
|
||||||
|
private static Logger logger = Logger.CONSOLE;
|
||||||
|
|
||||||
public static <T> Map<T, Exception> awaitCompletion(Map<T, ? extends ListenableFuture<?>> responses,
|
@Inject(optional = true)
|
||||||
ExecutorService executor, @Nullable Long maxTime, final Logger logger, final String logPrefix) {
|
@Named(Constants.PROPERTY_MAX_RETRIES)
|
||||||
|
private static int maxRetries = 5;
|
||||||
|
|
||||||
|
@Inject(optional = true)
|
||||||
|
private static BackoffLimitedRetryHandler retryHandler = BackoffLimitedRetryHandler.INSTANCE;
|
||||||
|
|
||||||
|
public static <F, T> Iterable<T> transformParallel(final Iterable<F> fromIterable,
|
||||||
|
final Function<? super F, Future<T>> function) {
|
||||||
|
return transformParallel(fromIterable, function, sameThreadExecutor(), null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <F, T> Iterable<T> transformParallel(final Iterable<F> fromIterable,
|
||||||
|
final Function<? super F, Future<T>> function, ExecutorService exec, @Nullable Long maxTime) {
|
||||||
|
return transformParallel(fromIterable, function, exec, maxTime, logger, "transforming");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <F, T> Iterable<T> transformParallel(final Iterable<F> fromIterable,
|
||||||
|
final Function<? super F, Future<T>> function, ExecutorService exec, @Nullable Long maxTime, Logger logger,
|
||||||
|
String logPrefix) {
|
||||||
|
return transformParallel(fromIterable, function, exec, maxTime, logger, logPrefix, retryHandler, maxRetries);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <F, T> Iterable<T> transformParallel(Iterable<F> fromIterable,
|
||||||
|
Function<? super F, Future<T>> function, ExecutorService exec, @Nullable Long maxTime, Logger logger,
|
||||||
|
String logPrefix, BackoffLimitedRetryHandler retryHandler, int maxRetries) {
|
||||||
|
Map<F, Exception> exceptions = newHashMap();
|
||||||
|
Map<F, Future<T>> responses = newHashMap();
|
||||||
|
for (int i = 0; i < maxRetries; i++) {
|
||||||
|
|
||||||
|
for (F from : fromIterable) {
|
||||||
|
responses.put(from, function.apply(from));
|
||||||
|
}
|
||||||
|
exceptions = awaitCompletion(responses, exec, maxTime, logger, logPrefix);
|
||||||
|
if (exceptions.size() > 0) {
|
||||||
|
fromIterable = exceptions.keySet();
|
||||||
|
retryHandler.imposeBackoffExponentialDelay(i + 1, String.format("error %s: %s: %s", logPrefix,
|
||||||
|
fromIterable, exceptions));
|
||||||
|
} else {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (exceptions.size() > 0)
|
||||||
|
throw new RuntimeException(String.format("error %s: %s: %s", logPrefix, fromIterable, exceptions));
|
||||||
|
|
||||||
|
return unwrap(responses.values());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static <T> Map<T, Exception> awaitCompletion(Map<T, ? extends Future<?>> responses, ExecutorService exec,
|
||||||
|
@Nullable Long maxTime, final Logger logger, final String logPrefix) {
|
||||||
if (responses.size() == 0)
|
if (responses.size() == 0)
|
||||||
return ImmutableMap.of();
|
return ImmutableMap.of();
|
||||||
final int total = responses.size();
|
final int total = responses.size();
|
||||||
|
@ -61,8 +131,8 @@ public class ConcurrentUtils {
|
||||||
final AtomicInteger errors = new AtomicInteger(0);
|
final AtomicInteger errors = new AtomicInteger(0);
|
||||||
final long start = System.currentTimeMillis();
|
final long start = System.currentTimeMillis();
|
||||||
final Map<T, Exception> errorMap = Maps.newHashMap();
|
final Map<T, Exception> errorMap = Maps.newHashMap();
|
||||||
for (final Entry<T, ? extends ListenableFuture<?>> future : responses.entrySet()) {
|
for (final java.util.Map.Entry<T, ? extends Future<?>> future : responses.entrySet()) {
|
||||||
future.getValue().addListener(new Runnable() {
|
makeListenable(future.getValue(), exec).addListener(new Runnable() {
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
future.getValue().get();
|
future.getValue().get();
|
||||||
|
@ -74,7 +144,7 @@ public class ConcurrentUtils {
|
||||||
}
|
}
|
||||||
doneSignal.countDown();
|
doneSignal.countDown();
|
||||||
}
|
}
|
||||||
}, executor);
|
}, exec);
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
if (maxTime != null)
|
if (maxTime != null)
|
||||||
|
@ -99,6 +169,22 @@ public class ConcurrentUtils {
|
||||||
return errorMap;
|
return errorMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static <T> Iterable<T> unwrap(Iterable<Future<T>> values) {
|
||||||
|
return Iterables.transform(values, new Function<Future<T>, T>() {
|
||||||
|
@Override
|
||||||
|
public T apply(Future<T> from) {
|
||||||
|
try {
|
||||||
|
return from.get();
|
||||||
|
} catch (InterruptedException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
}
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
private static void logException(Logger logger, String logPrefix, int total, int complete, int errors, long start,
|
private static void logException(Logger logger, String logPrefix, int total, int complete, int errors, long start,
|
||||||
Exception e) {
|
Exception e) {
|
||||||
String message = message(logPrefix, total, complete, errors, start);
|
String message = message(logPrefix, total, complete, errors, start);
|
||||||
|
@ -123,49 +209,55 @@ public class ConcurrentUtils {
|
||||||
if (future instanceof ListenableFuture<?>) {
|
if (future instanceof ListenableFuture<?>) {
|
||||||
return (ListenableFuture<T>) future;
|
return (ListenableFuture<T>) future;
|
||||||
}
|
}
|
||||||
return new ListenableFutureAdapter<T>(executorService, future);
|
return ListenableFutureAdapter.create(future, executorService);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Just like {@code Futures#ListenableFutureAdapter} except that we pass in an executorService.
|
* Just like {@code Futures#compose} except that we check the type of the executorService before
|
||||||
* <p/>
|
* creating the Future. If we are single threaded, invoke the function lazy as opposed to
|
||||||
* Temporary hack until http://code.google.com/p/guava-libraries/issues/detail?id=317 is fixed.
|
* chaining, so that we don't invoke get() early.
|
||||||
*/
|
*/
|
||||||
private static class ListenableFutureAdapter<T> extends ForwardingFuture<T> implements ListenableFuture<T> {
|
public static <I, O> ListenableFuture<O> compose(Future<I> future, final Function<? super I, ? extends O> function,
|
||||||
|
ExecutorService executorService) {
|
||||||
|
if (future instanceof ListenableFutureAdapter<?>) {
|
||||||
|
ListenableFutureAdapter<I> lf = (ListenableFutureAdapter<I>) future;
|
||||||
|
if (lf.futureListener.executor.getClass().isAnnotationPresent(SingleThreaded.class))
|
||||||
|
return LazyListenableFutureFunctionAdapter.create(((ListenableFutureAdapter<I>) future).futureListener,
|
||||||
|
function);
|
||||||
|
else
|
||||||
|
return Futures.compose(lf, function, executorService);
|
||||||
|
} else if (executorService.getClass().isAnnotationPresent(SingleThreaded.class)) {
|
||||||
|
return LazyListenableFutureFunctionAdapter.create(future, function, executorService);
|
||||||
|
} else {
|
||||||
|
return Futures.compose(makeListenable(future, executorService), function, executorService);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private final Executor adapterExecutor;
|
public static class FutureListener<T> {
|
||||||
|
private final Future<T> future;
|
||||||
// The execution list to hold our listeners.
|
private final ExecutorService executor;
|
||||||
private final ExecutionList executionList = new ExecutionList();
|
private final ExecutionList executionList = new ExecutionList();
|
||||||
|
|
||||||
// This allows us to only start up a thread waiting on the delegate future
|
|
||||||
// when the first listener is added.
|
|
||||||
private final AtomicBoolean hasListeners = new AtomicBoolean(false);
|
private final AtomicBoolean hasListeners = new AtomicBoolean(false);
|
||||||
|
|
||||||
// The delegate future.
|
static <T> FutureListener<T> create(Future<T> future, ExecutorService executor) {
|
||||||
private final Future<T> delegate;
|
return new FutureListener<T>(future, executor);
|
||||||
|
|
||||||
ListenableFutureAdapter(ExecutorService executorService, final Future<T> delegate) {
|
|
||||||
this.adapterExecutor = executorService;
|
|
||||||
this.delegate = delegate;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
private FutureListener(Future<T> future, ExecutorService executor) {
|
||||||
protected Future<T> delegate() {
|
this.future = checkNotNull(future, "future");
|
||||||
return delegate;
|
this.executor = checkNotNull(executor, "executor");
|
||||||
}
|
}
|
||||||
|
|
||||||
/* @Override */
|
|
||||||
public void addListener(Runnable listener, Executor exec) {
|
public void addListener(Runnable listener, Executor exec) {
|
||||||
|
|
||||||
// When a listener is first added, we run a task that will wait for
|
// When a listener is first added, we run a task that will wait for
|
||||||
// the delegate to finish, and when it is done will run the listeners.
|
// the future to finish, and when it is done will run the listeners.
|
||||||
if (!hasListeners.get() && hasListeners.compareAndSet(false, true)) {
|
if (!hasListeners.get() && hasListeners.compareAndSet(false, true)) {
|
||||||
adapterExecutor.execute(new Runnable() {
|
executor.execute(new Runnable() {
|
||||||
/* @Override */
|
/* @Override */
|
||||||
public void run() {
|
public void run() {
|
||||||
try {
|
try {
|
||||||
delegate.get();
|
future.get();
|
||||||
} catch (CancellationException e) {
|
} catch (CancellationException e) {
|
||||||
// The task was cancelled, so it is done, run the listeners.
|
// The task was cancelled, so it is done, run the listeners.
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
@ -181,5 +273,289 @@ public class ConcurrentUtils {
|
||||||
}
|
}
|
||||||
executionList.add(listener, exec);
|
executionList.add(listener, exec);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Future<T> getFuture() {
|
||||||
|
return future;
|
||||||
|
}
|
||||||
|
|
||||||
|
ExecutorService getExecutor() {
|
||||||
|
return executor;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static class ListenableFutureAdapter<T> extends ForwardingFuture<T> implements ListenableFuture<T> {
|
||||||
|
private final FutureListener<T> futureListener;
|
||||||
|
|
||||||
|
static <T> ListenableFutureAdapter<T> create(Future<T> future, ExecutorService executor) {
|
||||||
|
return new ListenableFutureAdapter<T>(future, executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ListenableFutureAdapter(Future<T> future, ExecutorService executor) {
|
||||||
|
this.futureListener = FutureListener.create(future, executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Future<T> delegate() {
|
||||||
|
return futureListener.getFuture();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addListener(Runnable listener, Executor exec) {
|
||||||
|
futureListener.addListener(listener, exec);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static class LazyListenableFutureFunctionAdapter<I, O> extends ForwardingObject implements
|
||||||
|
ListenableFuture<O> {
|
||||||
|
private final FutureListener<I> futureListener;
|
||||||
|
private final Function<? super I, ? extends O> function;
|
||||||
|
|
||||||
|
static <I, O> LazyListenableFutureFunctionAdapter<I, O> create(Future<I> future,
|
||||||
|
Function<? super I, ? extends O> function, ExecutorService executor) {
|
||||||
|
return new LazyListenableFutureFunctionAdapter<I, O>(future, function, executor);
|
||||||
|
}
|
||||||
|
|
||||||
|
static <I, O> LazyListenableFutureFunctionAdapter<I, O> create(FutureListener<I> futureListener,
|
||||||
|
Function<? super I, ? extends O> function) {
|
||||||
|
return new LazyListenableFutureFunctionAdapter<I, O>(futureListener, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LazyListenableFutureFunctionAdapter(Future<I> future, Function<? super I, ? extends O> function,
|
||||||
|
ExecutorService executor) {
|
||||||
|
this(FutureListener.create(future, executor), function);
|
||||||
|
}
|
||||||
|
|
||||||
|
private LazyListenableFutureFunctionAdapter(FutureListener<I> futureListener,
|
||||||
|
Function<? super I, ? extends O> function) {
|
||||||
|
this.futureListener = checkNotNull(futureListener, "futureListener");
|
||||||
|
this.function = checkNotNull(function, "function");
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Concurrency detail:
|
||||||
|
*
|
||||||
|
* <p>To preserve the idempotency of calls to this.get(*) calls to the function are only
|
||||||
|
* applied once. A lock is required to prevent multiple applications of the function. The
|
||||||
|
* calls to future.get(*) are performed outside the lock, as is required to prevent calls to
|
||||||
|
* get(long, TimeUnit) to persist beyond their timeout.
|
||||||
|
*
|
||||||
|
* <p>Calls to future.get(*) on every call to this.get(*) also provide the cancellation
|
||||||
|
* behavior for this.
|
||||||
|
*
|
||||||
|
* <p>(Consider: in thread A, call get(), in thread B call get(long, TimeUnit). Thread B may
|
||||||
|
* have to wait for Thread A to finish, which would be unacceptable.)
|
||||||
|
*
|
||||||
|
* <p>Note that each call to Future<O>.get(*) results in a call to Future<I>.get(*), but the
|
||||||
|
* function is only applied once, so Future<I>.get(*) is assumed to be idempotent.
|
||||||
|
*/
|
||||||
|
|
||||||
|
private final Object lock = new Object();
|
||||||
|
private boolean set = false;
|
||||||
|
private O value = null;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public O get() throws InterruptedException, ExecutionException {
|
||||||
|
return apply(futureListener.getFuture().get());
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public O get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
|
return apply(futureListener.getFuture().get(timeout, unit));
|
||||||
|
}
|
||||||
|
|
||||||
|
private O apply(I raw) {
|
||||||
|
synchronized (lock) {
|
||||||
|
if (!set) {
|
||||||
|
value = function.apply(raw);
|
||||||
|
set = true;
|
||||||
|
}
|
||||||
|
return value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||||
|
return futureListener.getFuture().cancel(mayInterruptIfRunning);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isCancelled() {
|
||||||
|
return futureListener.getFuture().isCancelled();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isDone() {
|
||||||
|
return futureListener.getFuture().isDone();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void addListener(Runnable listener, Executor exec) {
|
||||||
|
futureListener.addListener(listener, exec);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected Object delegate() {
|
||||||
|
return futureListener.getFuture();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Taken from {@link MoreExecutors#sameThreadExecutor} as it was hidden and therefore incapable
|
||||||
|
* of instanceof checks.
|
||||||
|
*
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* Creates an executor service that runs each task in the thread that invokes {@code
|
||||||
|
* execute/submit}, as in {@link CallerRunsPolicy} This applies both to individually submitted
|
||||||
|
* tasks and to collections of tasks submitted via {@code invokeAll} or {@code invokeAny}. In the
|
||||||
|
* latter case, tasks will run serially on the calling thread. Tasks are run to completion before
|
||||||
|
* a {@code Future} is returned to the caller (unless the executor has been shutdown).
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* Although all tasks are immediately executed in the thread that submitted the task, this
|
||||||
|
* {@code ExecutorService} imposes a small locking overhead on each task submission in order to
|
||||||
|
* implement shutdown and termination behavior.
|
||||||
|
*
|
||||||
|
* <p>
|
||||||
|
* The implementation deviates from the {@code ExecutorService} specification with regards to the
|
||||||
|
* {@code shutdownNow} method. First, "best-effort" with regards to canceling running tasks is
|
||||||
|
* implemented as "no-effort". No interrupts or other attempts are made to stop threads executing
|
||||||
|
* tasks. Second, the returned list will always be empty, as any submitted task is considered to
|
||||||
|
* have started execution. This applies also to tasks given to {@code invokeAll} or {@code
|
||||||
|
* invokeAny} which are pending serial execution, even the subset of the tasks that have not yet
|
||||||
|
* started execution. It is unclear from the {@code ExecutorService} specification if these
|
||||||
|
* should be included, and it's much easier to implement the interpretation that they not be.
|
||||||
|
* Finally, a call to {@code shutdown} or {@code shutdownNow} may result in concurrent calls to
|
||||||
|
* {@code invokeAll/invokeAny} throwing RejectedExecutionException, although a subset of the
|
||||||
|
* tasks may already have been executed.
|
||||||
|
*/
|
||||||
|
public static ExecutorService sameThreadExecutor() {
|
||||||
|
return new SameThreadExecutorService();
|
||||||
|
}
|
||||||
|
|
||||||
|
// See sameThreadExecutor javadoc for behavioral notes.
|
||||||
|
@SingleThreaded
|
||||||
|
public static class SameThreadExecutorService extends AbstractExecutorService {
|
||||||
|
/**
|
||||||
|
* Lock used whenever accessing the state variables (runningTasks, shutdown,
|
||||||
|
* terminationCondition) of the executor
|
||||||
|
*/
|
||||||
|
private final Lock lock = new ReentrantLock();
|
||||||
|
|
||||||
|
/** Signaled after the executor is shutdown and running tasks are done */
|
||||||
|
private final Condition termination = lock.newCondition();
|
||||||
|
|
||||||
|
private SameThreadExecutorService() {
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Conceptually, these two variables describe the executor being in one of three states: -
|
||||||
|
* Active: shutdown == false - Shutdown: runningTasks > 0 and shutdown == true - Terminated:
|
||||||
|
* runningTasks == 0 and shutdown == true
|
||||||
|
*/
|
||||||
|
private int runningTasks = 0;
|
||||||
|
private boolean shutdown = false;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void execute(Runnable command) {
|
||||||
|
startTask();
|
||||||
|
try {
|
||||||
|
command.run();
|
||||||
|
} finally {
|
||||||
|
endTask();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isShutdown() {
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
return shutdown;
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void shutdown() {
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
shutdown = true;
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// See sameThreadExecutor javadoc for unusual behavior of this method.
|
||||||
|
@Override
|
||||||
|
public List<Runnable> shutdownNow() {
|
||||||
|
shutdown();
|
||||||
|
return Collections.emptyList();
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean isTerminated() {
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
return shutdown && runningTasks == 0;
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public boolean awaitTermination(long timeout, TimeUnit unit) throws InterruptedException {
|
||||||
|
long nanos = unit.toNanos(timeout);
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
for (;;) {
|
||||||
|
if (isTerminated()) {
|
||||||
|
return true;
|
||||||
|
} else if (nanos <= 0) {
|
||||||
|
return false;
|
||||||
|
} else {
|
||||||
|
nanos = termination.awaitNanos(nanos);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the executor has been shut down and increments the running task count.
|
||||||
|
*
|
||||||
|
* @throws RejectedExecutionException
|
||||||
|
* if the executor has been previously shutdown
|
||||||
|
*/
|
||||||
|
private void startTask() {
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
if (isShutdown()) {
|
||||||
|
throw new RejectedExecutionException("Executor already shutdown");
|
||||||
|
}
|
||||||
|
runningTasks++;
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Decrements the running task count.
|
||||||
|
*/
|
||||||
|
private void endTask() {
|
||||||
|
lock.lock();
|
||||||
|
try {
|
||||||
|
runningTasks--;
|
||||||
|
if (isTerminated()) {
|
||||||
|
termination.signalAll();
|
||||||
|
}
|
||||||
|
} finally {
|
||||||
|
lock.unlock();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.concurrent;
|
package org.jclouds.concurrent;
|
||||||
|
|
||||||
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.Executor;
|
import java.util.concurrent.Executor;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -27,30 +29,35 @@ import com.google.common.base.Function;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Transforms the result of a future as soon as it is available.
|
* Transforms the exceptions in a future upon get
|
||||||
*
|
*
|
||||||
* Temporarily here until the following is resolved: <a
|
* Temporarily here until the following is resolved: <a
|
||||||
* href="http://code.google.com/p/guava-libraries/issues/detail?id=310"> guava issue 310</a>
|
* href="http://code.google.com/p/guava-libraries/issues/detail?id=310"> guava issue 310</a>
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class FutureExceptionParser<T> implements ListenableFuture<T> {
|
public class ExceptionParsingListenableFuture<T> implements ListenableFuture<T> {
|
||||||
|
|
||||||
private final ListenableFuture<T> delegate;
|
private final ListenableFuture<T> future;
|
||||||
private final Function<Exception, T> function;
|
private final Function<Exception, T> function;
|
||||||
|
|
||||||
public FutureExceptionParser(ListenableFuture<T> delegate, Function<Exception, T> function) {
|
public static <T> ExceptionParsingListenableFuture<T> create(ListenableFuture<T> future,
|
||||||
this.delegate = delegate;
|
Function<Exception, T> function) {
|
||||||
this.function = function;
|
return new ExceptionParsingListenableFuture<T>(future, function);
|
||||||
|
}
|
||||||
|
|
||||||
|
public ExceptionParsingListenableFuture(ListenableFuture<T> future, Function<Exception, T> function) {
|
||||||
|
this.future = checkNotNull(future);
|
||||||
|
this.function = checkNotNull(function);
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean cancel(boolean mayInterruptIfRunning) {
|
public boolean cancel(boolean mayInterruptIfRunning) {
|
||||||
return delegate.cancel(mayInterruptIfRunning);
|
return future.cancel(mayInterruptIfRunning);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T get() throws InterruptedException, ExecutionException {
|
public T get() throws InterruptedException, ExecutionException {
|
||||||
try {
|
try {
|
||||||
return delegate.get();
|
return future.get();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return attemptConvert(e);
|
return attemptConvert(e);
|
||||||
}
|
}
|
||||||
|
@ -60,26 +67,24 @@ public class FutureExceptionParser<T> implements ListenableFuture<T> {
|
||||||
return function.apply(e instanceof ExecutionException ? (Exception) e.getCause() : e);
|
return function.apply(e instanceof ExecutionException ? (Exception) e.getCause() : e);
|
||||||
}
|
}
|
||||||
|
|
||||||
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException,
|
public T get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
|
||||||
TimeoutException {
|
|
||||||
try {
|
try {
|
||||||
return delegate.get(timeout, unit);
|
return future.get(timeout, unit);
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return attemptConvert(e);
|
return attemptConvert(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isCancelled() {
|
public boolean isCancelled() {
|
||||||
return delegate.isCancelled();
|
return future.isCancelled();
|
||||||
}
|
}
|
||||||
|
|
||||||
public boolean isDone() {
|
public boolean isDone() {
|
||||||
return delegate.isDone();
|
return future.isDone();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void addListener(Runnable listener, Executor exec) {
|
public void addListener(Runnable listener, Executor exec) {
|
||||||
delegate.addListener(listener, exec);
|
future.addListener(listener, exec);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -18,13 +18,12 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.concurrent;
|
package org.jclouds.concurrent;
|
||||||
|
|
||||||
|
import static com.google.common.base.Throwables.propagate;
|
||||||
|
import static org.jclouds.util.Utils.getFirstThrowableOfType;
|
||||||
|
|
||||||
import java.util.concurrent.TimeoutException;
|
import java.util.concurrent.TimeoutException;
|
||||||
|
|
||||||
import org.jclouds.util.Utils;
|
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Throwables;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -44,15 +43,15 @@ public class RetryOnTimeOutExceptionSupplier<T> implements Supplier<T> {
|
||||||
ex = null;
|
ex = null;
|
||||||
return delegate.get();
|
return delegate.get();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
if ((ex = Utils.getFirstThrowableOfType(e, TimeoutException.class)) != null)
|
if ((ex = getFirstThrowableOfType(e, TimeoutException.class)) != null)
|
||||||
continue;
|
continue;
|
||||||
Throwables.propagate(e);
|
propagate(e);
|
||||||
assert false;
|
assert false;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ex != null)
|
if (ex != null)
|
||||||
Throwables.propagate(ex);
|
propagate(ex);
|
||||||
assert false;
|
assert false;
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
|
@ -32,6 +32,8 @@ import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
|
import static org.jclouds.concurrent.ConcurrentUtils.*;
|
||||||
|
import org.jclouds.concurrent.SingleThreaded;
|
||||||
import org.jclouds.lifecycle.Closer;
|
import org.jclouds.lifecycle.Closer;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
@ -65,8 +67,7 @@ public class ExecutorServiceModule extends AbstractModule {
|
||||||
public void close() throws IOException {
|
public void close() throws IOException {
|
||||||
List<Runnable> runnables = service.shutdownNow();
|
List<Runnable> runnables = service.shutdownNow();
|
||||||
if (runnables.size() > 0)
|
if (runnables.size() > 0)
|
||||||
logger.warn("when shutting down executor %s, runnables outstanding: %s", service,
|
logger.warn("when shutting down executor %s, runnables outstanding: %s", service, runnables);
|
||||||
runnables);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -74,11 +75,22 @@ public class ExecutorServiceModule extends AbstractModule {
|
||||||
private final ExecutorService ioExecutorFromConstructor;
|
private final ExecutorService ioExecutorFromConstructor;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ExecutorServiceModule(
|
public ExecutorServiceModule(@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads,
|
|
||||||
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioThreads) {
|
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioThreads) {
|
||||||
this.userExecutorFromConstructor = userThreads;
|
this.userExecutorFromConstructor = checkNotGuavaSameThreadExecutor(userThreads);
|
||||||
this.ioExecutorFromConstructor = ioThreads;
|
this.ioExecutorFromConstructor = checkNotGuavaSameThreadExecutor(ioThreads);
|
||||||
|
}
|
||||||
|
|
||||||
|
private ExecutorService checkNotGuavaSameThreadExecutor(ExecutorService executor) {
|
||||||
|
// we detect behavior based on the class
|
||||||
|
if (executor != null && !(executor.getClass().isAnnotationPresent(SingleThreaded.class))
|
||||||
|
&& executor.getClass().getSimpleName().indexOf("SameThread") != -1) {
|
||||||
|
Logger.CONSOLE.warn(
|
||||||
|
"please switch from %s to %s or annotate your same threaded executor with @SingleThreaded", executor
|
||||||
|
.getClass().getName(), SameThreadExecutorService.class.getName());
|
||||||
|
return sameThreadExecutor();
|
||||||
|
}
|
||||||
|
return executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ExecutorServiceModule() {
|
public ExecutorServiceModule() {
|
||||||
|
@ -92,8 +104,7 @@ public class ExecutorServiceModule extends AbstractModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@Named(Constants.PROPERTY_USER_THREADS)
|
@Named(Constants.PROPERTY_USER_THREADS)
|
||||||
ExecutorService provideExecutorService(@Named(Constants.PROPERTY_USER_THREADS) int count,
|
ExecutorService provideExecutorService(@Named(Constants.PROPERTY_USER_THREADS) int count, Closer closer) {
|
||||||
Closer closer) {
|
|
||||||
if (userExecutorFromConstructor != null)
|
if (userExecutorFromConstructor != null)
|
||||||
return shutdownOnClose(userExecutorFromConstructor, closer);
|
return shutdownOnClose(userExecutorFromConstructor, closer);
|
||||||
return shutdownOnClose(newThreadPoolNamed("user thread %d", count), closer);
|
return shutdownOnClose(newThreadPoolNamed("user thread %d", count), closer);
|
||||||
|
@ -102,8 +113,7 @@ public class ExecutorServiceModule extends AbstractModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@Named(Constants.PROPERTY_IO_WORKER_THREADS)
|
@Named(Constants.PROPERTY_IO_WORKER_THREADS)
|
||||||
ExecutorService provideIOExecutor(@Named(Constants.PROPERTY_IO_WORKER_THREADS) int count,
|
ExecutorService provideIOExecutor(@Named(Constants.PROPERTY_IO_WORKER_THREADS) int count, Closer closer) {
|
||||||
Closer closer) {
|
|
||||||
if (ioExecutorFromConstructor != null)
|
if (ioExecutorFromConstructor != null)
|
||||||
return shutdownOnClose(ioExecutorFromConstructor, closer);
|
return shutdownOnClose(ioExecutorFromConstructor, closer);
|
||||||
return shutdownOnClose(newThreadPoolNamed("i/o thread %d", count), closer);
|
return shutdownOnClose(newThreadPoolNamed("i/o thread %d", count), closer);
|
||||||
|
@ -117,20 +127,19 @@ public class ExecutorServiceModule extends AbstractModule {
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static ExecutorService newCachedThreadPoolNamed(String name) {
|
static ExecutorService newCachedThreadPoolNamed(String name) {
|
||||||
return Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat(name)
|
return Executors.newCachedThreadPool(new ThreadFactoryBuilder().setNameFormat(name).setThreadFactory(
|
||||||
.setThreadFactory(Executors.defaultThreadFactory()).build());
|
Executors.defaultThreadFactory()).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static ExecutorService newThreadPoolNamed(String name, int maxCount) {
|
static ExecutorService newThreadPoolNamed(String name, int maxCount) {
|
||||||
return maxCount == 0 ? newCachedThreadPoolNamed(name) : newScalingThreadPoolNamed(name,
|
return maxCount == 0 ? newCachedThreadPoolNamed(name) : newScalingThreadPoolNamed(name, maxCount);
|
||||||
maxCount);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
static ExecutorService newScalingThreadPoolNamed(String name, int maxCount) {
|
static ExecutorService newScalingThreadPoolNamed(String name, int maxCount) {
|
||||||
return newScalingThreadPool(1, maxCount, 60L * 1000, new ThreadFactoryBuilder()
|
return newScalingThreadPool(1, maxCount, 60L * 1000, new ThreadFactoryBuilder().setNameFormat(name)
|
||||||
.setNameFormat(name).setThreadFactory(Executors.defaultThreadFactory()).build());
|
.setThreadFactory(Executors.defaultThreadFactory()).build());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -18,7 +18,7 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.http;
|
package org.jclouds.http;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Capable of invoking http commands.
|
* Capable of invoking http commands.
|
||||||
|
@ -33,7 +33,7 @@ public interface HttpCommandExecutorService {
|
||||||
*
|
*
|
||||||
* @param command
|
* @param command
|
||||||
* that generates requests
|
* that generates requests
|
||||||
* @return {@link ListenableFuture} containing the response from the {@code endpoint}
|
* @return {@link Future} containing the response from the {@code endpoint}
|
||||||
*/
|
*/
|
||||||
ListenableFuture<HttpResponse> submit(HttpCommand command);
|
Future<HttpResponse> submit(HttpCommand command);
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,7 +20,7 @@ package org.jclouds.http;
|
||||||
|
|
||||||
import java.util.concurrent.SynchronousQueue;
|
import java.util.concurrent.SynchronousQueue;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Used for passing objects for response processing
|
* Used for passing objects for response processing
|
||||||
|
@ -32,11 +32,11 @@ public class HttpCommandRendezvous<T> {
|
||||||
private final HttpCommand command;
|
private final HttpCommand command;
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private final SynchronousQueue rendezvous;
|
private final SynchronousQueue rendezvous;
|
||||||
private final ListenableFuture<T> future;
|
private final Future<T> future;
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public HttpCommandRendezvous(HttpCommand command, SynchronousQueue rendezvous,
|
public HttpCommandRendezvous(HttpCommand command, SynchronousQueue rendezvous,
|
||||||
ListenableFuture<T> future) {
|
Future<T> future) {
|
||||||
this.command = command;
|
this.command = command;
|
||||||
this.rendezvous = rendezvous;
|
this.rendezvous = rendezvous;
|
||||||
this.future = future;
|
this.future = future;
|
||||||
|
@ -53,14 +53,14 @@ public class HttpCommandRendezvous<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void cancel() {
|
public void cancel() {
|
||||||
getListenableFuture().cancel(true);
|
getFuture().cancel(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
public HttpCommand getCommand() {
|
public HttpCommand getCommand() {
|
||||||
return command;
|
return command;
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<T> getListenableFuture() {
|
public Future<T> getFuture() {
|
||||||
return future;
|
return future;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,6 +18,8 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.http;
|
package org.jclouds.http;
|
||||||
|
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
|
||||||
|
@ -30,7 +32,7 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||||
public interface TransformingHttpCommandExecutorService {
|
public interface TransformingHttpCommandExecutorService {
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Submits the command and transforms the result before requested via {@link ListenableFuture#get()}.
|
* Submits the command and transforms the result before requested via {@link Future#get()}.
|
||||||
*
|
*
|
||||||
* @param <T>
|
* @param <T>
|
||||||
* type that is required from the value.
|
* type that is required from the value.
|
||||||
|
|
|
@ -18,10 +18,13 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.http;
|
package org.jclouds.http;
|
||||||
|
|
||||||
import static com.google.common.util.concurrent.Futures.compose;
|
import java.util.concurrent.ExecutorService;
|
||||||
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Named;
|
||||||
|
|
||||||
|
import org.jclouds.Constants;
|
||||||
|
import static org.jclouds.concurrent.ConcurrentUtils.*;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
@ -32,21 +35,22 @@ import com.google.common.util.concurrent.ListenableFuture;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class TransformingHttpCommandExecutorServiceImpl implements
|
public class TransformingHttpCommandExecutorServiceImpl implements TransformingHttpCommandExecutorService {
|
||||||
TransformingHttpCommandExecutorService {
|
|
||||||
private final HttpCommandExecutorService client;
|
private final HttpCommandExecutorService client;
|
||||||
|
private final ExecutorService userThreads;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public TransformingHttpCommandExecutorServiceImpl(HttpCommandExecutorService client) {
|
public TransformingHttpCommandExecutorServiceImpl(HttpCommandExecutorService client,
|
||||||
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService userThreads) {
|
||||||
this.client = client;
|
this.client = client;
|
||||||
|
this.userThreads = userThreads;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* {@inheritDoc}
|
* {@inheritDoc}
|
||||||
*/
|
*/
|
||||||
public <T> ListenableFuture<T> submit(HttpCommand command,
|
public <T> ListenableFuture<T> submit(HttpCommand command, Function<HttpResponse, T> responseTransformer) {
|
||||||
Function<HttpResponse, T> responseTransformer) {
|
return compose(client.submit(command), responseTransformer, userThreads);
|
||||||
return compose(client.submit(command), responseTransformer, sameThreadExecutor());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -79,6 +79,9 @@ import com.google.inject.Inject;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class BackoffLimitedRetryHandler implements HttpRetryHandler, IOExceptionRetryHandler {
|
public class BackoffLimitedRetryHandler implements HttpRetryHandler, IOExceptionRetryHandler {
|
||||||
|
|
||||||
|
public static BackoffLimitedRetryHandler INSTANCE = new BackoffLimitedRetryHandler();
|
||||||
|
|
||||||
@Inject(optional = true)
|
@Inject(optional = true)
|
||||||
@Named(Constants.PROPERTY_MAX_RETRIES)
|
@Named(Constants.PROPERTY_MAX_RETRIES)
|
||||||
private int retryCountLimit = 5;
|
private int retryCountLimit = 5;
|
||||||
|
@ -102,13 +105,11 @@ public class BackoffLimitedRetryHandler implements HttpRetryHandler, IOException
|
||||||
logger.warn("Cannot retry after server error, command is not replayable: %1$s", command);
|
logger.warn("Cannot retry after server error, command is not replayable: %1$s", command);
|
||||||
return false;
|
return false;
|
||||||
} else if (command.getFailureCount() > retryCountLimit) {
|
} else if (command.getFailureCount() > retryCountLimit) {
|
||||||
logger.warn(
|
logger.warn("Cannot retry after server error, command has exceeded retry limit %1$d: %2$s", retryCountLimit,
|
||||||
"Cannot retry after server error, command has exceeded retry limit %1$d: %2$s",
|
command);
|
||||||
retryCountLimit, command);
|
|
||||||
return false;
|
return false;
|
||||||
} else {
|
} else {
|
||||||
imposeBackoffExponentialDelay(command.getFailureCount(), "server error: "
|
imposeBackoffExponentialDelay(command.getFailureCount(), "server error: " + command.toString());
|
||||||
+ command.toString());
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -117,11 +118,9 @@ public class BackoffLimitedRetryHandler implements HttpRetryHandler, IOException
|
||||||
imposeBackoffExponentialDelay(50L, 2, failureCount, retryCountLimit, commandDescription);
|
imposeBackoffExponentialDelay(50L, 2, failureCount, retryCountLimit, commandDescription);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void imposeBackoffExponentialDelay(long period, int pow, int failureCount, int max,
|
public void imposeBackoffExponentialDelay(long period, int pow, int failureCount, int max, String commandDescription) {
|
||||||
String commandDescription) {
|
|
||||||
long delayMs = (long) (period * Math.pow(failureCount, pow));
|
long delayMs = (long) (period * Math.pow(failureCount, pow));
|
||||||
logger.debug("Retry %d/%d: delaying for %d ms: %s", failureCount, retryCountLimit, delayMs,
|
logger.debug("Retry %d/%d: delaying for %d ms: %s", failureCount, retryCountLimit, delayMs, commandDescription);
|
||||||
commandDescription);
|
|
||||||
try {
|
try {
|
||||||
Thread.sleep(delayMs);
|
Thread.sleep(delayMs);
|
||||||
} catch (InterruptedException e) {
|
} catch (InterruptedException e) {
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
package org.jclouds.http.internal;
|
package org.jclouds.http.internal;
|
||||||
|
|
||||||
import static com.google.common.io.ByteStreams.copy;
|
import static com.google.common.io.ByteStreams.copy;
|
||||||
import static org.jclouds.concurrent.ConcurrentUtils.makeListenable;
|
|
||||||
import static org.jclouds.http.HttpUtils.checkRequestHasContentLengthOrChunkedEncoding;
|
import static org.jclouds.http.HttpUtils.checkRequestHasContentLengthOrChunkedEncoding;
|
||||||
import static org.jclouds.http.HttpUtils.wirePayloadIfEnabled;
|
import static org.jclouds.http.HttpUtils.wirePayloadIfEnabled;
|
||||||
import static org.jclouds.util.Utils.getFirstThrowableOfType;
|
import static org.jclouds.util.Utils.getFirstThrowableOfType;
|
||||||
|
@ -29,6 +28,7 @@ import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
|
import java.util.concurrent.Future;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -49,7 +49,6 @@ import org.jclouds.http.handlers.DelegatingRetryHandler;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.io.NullOutputStream;
|
import com.google.common.io.NullOutputStream;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -74,9 +73,9 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected BaseHttpCommandExecutorService(HttpUtils utils, EncryptionService encryptionService,
|
protected BaseHttpCommandExecutorService(HttpUtils utils, EncryptionService encryptionService,
|
||||||
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioWorkerExecutor,
|
@Named(Constants.PROPERTY_IO_WORKER_THREADS) ExecutorService ioWorkerExecutor,
|
||||||
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
|
DelegatingRetryHandler retryHandler, IOExceptionRetryHandler ioRetryHandler,
|
||||||
DelegatingErrorHandler errorHandler, HttpWire wire) {
|
DelegatingErrorHandler errorHandler, HttpWire wire) {
|
||||||
this.utils = utils;
|
this.utils = utils;
|
||||||
this.encryptionService = encryptionService;
|
this.encryptionService = encryptionService;
|
||||||
this.retryHandler = retryHandler;
|
this.retryHandler = retryHandler;
|
||||||
|
@ -123,11 +122,12 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public ListenableFuture<HttpResponse> submit(HttpCommand command) {
|
public Future<HttpResponse> submit(HttpCommand command) {
|
||||||
HttpRequest request = command.getRequest();
|
HttpRequest request = command.getRequest();
|
||||||
checkRequestHasContentLengthOrChunkedEncoding(request,
|
checkRequestHasContentLengthOrChunkedEncoding(request,
|
||||||
"if the request has a payload, it must be set to chunked encoding or specify a content length: " + request);
|
"if the request has a payload, it must be set to chunked encoding or specify a content length: "
|
||||||
return makeListenable(ioWorkerExecutor.submit(new HttpResponseCallable(command)), ioWorkerExecutor);
|
+ request);
|
||||||
|
return ioWorkerExecutor.submit(new HttpResponseCallable(command));
|
||||||
}
|
}
|
||||||
|
|
||||||
public class HttpResponseCallable implements Callable<HttpResponse> {
|
public class HttpResponseCallable implements Callable<HttpResponse> {
|
||||||
|
@ -148,7 +148,7 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
|
||||||
filter.filter(request);
|
filter.filter(request);
|
||||||
}
|
}
|
||||||
checkRequestHasContentLengthOrChunkedEncoding(request,
|
checkRequestHasContentLengthOrChunkedEncoding(request,
|
||||||
"After filtering, the request has niether chunked encoding nor content length: " + request);
|
"After filtering, the request has niether chunked encoding nor content length: " + request);
|
||||||
logger.debug("Sending request %s: %s", request.hashCode(), request.getRequestLine());
|
logger.debug("Sending request %s: %s", request.hashCode(), request.getRequestLine());
|
||||||
wirePayloadIfEnabled(wire, request);
|
wirePayloadIfEnabled(wire, request);
|
||||||
nativeRequest = convert(request);
|
nativeRequest = convert(request);
|
||||||
|
@ -174,7 +174,7 @@ public abstract class BaseHttpCommandExecutorService<Q> implements HttpCommandEx
|
||||||
continue;
|
continue;
|
||||||
} else {
|
} else {
|
||||||
command.setException(new HttpResponseException(e.getMessage() + " connecting to "
|
command.setException(new HttpResponseException(e.getMessage() + " connecting to "
|
||||||
+ command.getRequest().getRequestLine(), command, null, e));
|
+ command.getRequest().getRequestLine(), command, null, e));
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
} finally {
|
} finally {
|
||||||
|
|
|
@ -25,13 +25,20 @@ import java.lang.reflect.Type;
|
||||||
*/
|
*/
|
||||||
public interface Json {
|
public interface Json {
|
||||||
/**
|
/**
|
||||||
* Serialize the object into json.
|
* Serialize the object into json. If the object is a generic type, use
|
||||||
|
* {@link #toJson(Object, Type)}
|
||||||
*/
|
*/
|
||||||
String toJson(Object src);
|
String toJson(Object src);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Deserialize the generic object from json. If the object is not a generic
|
* Serialize the generic object into json. If the object is not a generic, use
|
||||||
* type, use {@link #fromJson(Object, Class)}
|
* {@link #toJson(Object, Type)}
|
||||||
|
*/
|
||||||
|
String toJson(Object src, Type type);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Deserialize the generic object from json. If the object is not a generic type, use
|
||||||
|
* {@link #fromJson(Object, Class)}
|
||||||
*/
|
*/
|
||||||
<T> T fromJson(String json, Type type);
|
<T> T fromJson(String json, Type type);
|
||||||
|
|
||||||
|
|
|
@ -56,4 +56,9 @@ public class GsonWrapper implements Json {
|
||||||
return gson.toJson(src);
|
return gson.toJson(src);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toJson(Object src, Type type) {
|
||||||
|
return gson.toJson(src, type);
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@ import java.net.URI;
|
||||||
|
|
||||||
import org.jclouds.rest.internal.RestContextImpl;
|
import org.jclouds.rest.internal.RestContextImpl;
|
||||||
|
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import java.util.concurrent.Future;
|
||||||
import com.google.inject.ImplementedBy;
|
import com.google.inject.ImplementedBy;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -41,7 +41,7 @@ public interface RestContext<S, A> {
|
||||||
/**
|
/**
|
||||||
* low-level api to the cloud. Threadsafe implementations will return a singleton.
|
* low-level api to the cloud. Threadsafe implementations will return a singleton.
|
||||||
*
|
*
|
||||||
* @return a connection to the cloud where all methods return {@link ListenableFuture}s
|
* @return a connection to the cloud where all methods return {@link Future}s
|
||||||
*/
|
*/
|
||||||
A getAsyncApi();
|
A getAsyncApi();
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@
|
||||||
package org.jclouds.rest;
|
package org.jclouds.rest;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.util.concurrent.MoreExecutors.sameThreadExecutor;
|
import static org.jclouds.concurrent.ConcurrentUtils.sameThreadExecutor;
|
||||||
import static org.jclouds.Constants.PROPERTY_API;
|
import static org.jclouds.Constants.PROPERTY_API;
|
||||||
import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
import static org.jclouds.Constants.PROPERTY_API_VERSION;
|
||||||
import static org.jclouds.Constants.PROPERTY_CREDENTIAL;
|
import static org.jclouds.Constants.PROPERTY_CREDENTIAL;
|
||||||
|
|
|
@ -20,16 +20,17 @@ package org.jclouds.rest;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Splitter.on;
|
|
||||||
import static com.google.common.base.Throwables.propagate;
|
import static com.google.common.base.Throwables.propagate;
|
||||||
import static com.google.common.collect.Iterables.concat;
|
import static com.google.common.collect.Iterables.concat;
|
||||||
import static com.google.common.collect.Iterables.size;
|
import static com.google.common.collect.Iterables.size;
|
||||||
import static com.google.common.collect.Iterables.transform;
|
import static com.google.common.collect.Iterables.transform;
|
||||||
import static java.util.Collections.EMPTY_LIST;
|
import static java.util.Collections.EMPTY_LIST;
|
||||||
import static org.jclouds.util.Utils.initContextBuilder;
|
import static org.jclouds.util.Utils.initContextBuilder;
|
||||||
|
import static org.jclouds.util.Utils.modulesForProviderInProperties;
|
||||||
import static org.jclouds.util.Utils.propagateAuthorizationOrOriginalException;
|
import static org.jclouds.util.Utils.propagateAuthorizationOrOriginalException;
|
||||||
import static org.jclouds.util.Utils.resolveContextBuilderClass;
|
import static org.jclouds.util.Utils.resolveContextBuilderClass;
|
||||||
import static org.jclouds.util.Utils.resolvePropertiesBuilderClass;
|
import static org.jclouds.util.Utils.resolvePropertiesBuilderClass;
|
||||||
|
import static org.jclouds.util.Utils.toStringAndClose;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
@ -43,14 +44,12 @@ import org.jclouds.PropertiesBuilder;
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Joiner;
|
import com.google.common.base.Joiner;
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Helper class to instantiate {@code RestContext} instances.
|
* Helper class to instantiate {@code RestContext} instances. "blobstore.properties"
|
||||||
* "blobstore.properties"
|
|
||||||
*
|
*
|
||||||
* At least one property is needed needed per context:
|
* At least one property is needed needed per context:
|
||||||
* <ul>
|
* <ul>
|
||||||
|
@ -74,23 +73,23 @@ import com.google.inject.Module;
|
||||||
public class RestContextFactory {
|
public class RestContextFactory {
|
||||||
|
|
||||||
public static <S, A> ContextSpec<S, A> contextSpec(String provider, String endpoint, String apiVersion,
|
public static <S, A> ContextSpec<S, A> contextSpec(String provider, String endpoint, String apiVersion,
|
||||||
String identity, String credential, Class<S> sync, Class<A> async,
|
String identity, String credential, Class<S> sync, Class<A> async,
|
||||||
Class<PropertiesBuilder> propertiesBuilderClass, Class<RestContextBuilder<S, A>> contextBuilderClass,
|
Class<PropertiesBuilder> propertiesBuilderClass, Class<RestContextBuilder<S, A>> contextBuilderClass,
|
||||||
Iterable<Module> modules) {
|
Iterable<Module> modules) {
|
||||||
return new ContextSpec<S, A>(provider, endpoint, apiVersion, identity, credential, sync, async,
|
return new ContextSpec<S, A>(provider, endpoint, apiVersion, identity, credential, sync, async,
|
||||||
propertiesBuilderClass, contextBuilderClass, modules);
|
propertiesBuilderClass, contextBuilderClass, modules);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <S, A> ContextSpec<S, A> contextSpec(String provider, String endpoint, String apiVersion,
|
public static <S, A> ContextSpec<S, A> contextSpec(String provider, String endpoint, String apiVersion,
|
||||||
String identity, String credential, Class<S> sync, Class<A> async) {
|
String identity, String credential, Class<S> sync, Class<A> async) {
|
||||||
return new ContextSpec<S, A>(provider, endpoint, apiVersion, identity, credential, sync, async);
|
return new ContextSpec<S, A>(provider, endpoint, apiVersion, identity, credential, sync, async);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <S, A> ContextSpec<S, A> contextSpec(String provider, String endpoint, String apiVersion,
|
public static <S, A> ContextSpec<S, A> contextSpec(String provider, String endpoint, String apiVersion,
|
||||||
String identity, String credential, Class<S> sync, Class<A> async, Iterable<Module> modules) {
|
String identity, String credential, Class<S> sync, Class<A> async, Iterable<Module> modules) {
|
||||||
return new ContextSpec<S, A>(provider, endpoint, apiVersion, identity, credential, sync, async,
|
return new ContextSpec<S, A>(provider, endpoint, apiVersion, identity, credential, sync, async,
|
||||||
PropertiesBuilder.class, (Class) RestContextBuilder.class, modules);
|
PropertiesBuilder.class, (Class) RestContextBuilder.class, modules);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static class ContextSpec<S, A> {
|
public static class ContextSpec<S, A> {
|
||||||
|
@ -106,8 +105,8 @@ public class RestContextFactory {
|
||||||
final Iterable<Module> modules;
|
final Iterable<Module> modules;
|
||||||
|
|
||||||
ContextSpec(String provider, String endpoint, String apiVersion, String identity, String credential,
|
ContextSpec(String provider, String endpoint, String apiVersion, String identity, String credential,
|
||||||
Class<S> sync, Class<A> async, Class<PropertiesBuilder> propertiesBuilderClass,
|
Class<S> sync, Class<A> async, Class<PropertiesBuilder> propertiesBuilderClass,
|
||||||
Class<RestContextBuilder<S, A>> contextBuilderClass, Iterable<Module> modules) {
|
Class<RestContextBuilder<S, A>> contextBuilderClass, Iterable<Module> modules) {
|
||||||
this.provider = checkNotNull(provider, "provider");
|
this.provider = checkNotNull(provider, "provider");
|
||||||
this.endpoint = endpoint;
|
this.endpoint = endpoint;
|
||||||
this.apiVersion = apiVersion;
|
this.apiVersion = apiVersion;
|
||||||
|
@ -116,10 +115,10 @@ public class RestContextFactory {
|
||||||
this.sync = sync;
|
this.sync = sync;
|
||||||
this.async = async;
|
this.async = async;
|
||||||
checkArgument(RestContextBuilder.class.isAssignableFrom(contextBuilderClass), contextBuilderClass.getName()
|
checkArgument(RestContextBuilder.class.isAssignableFrom(contextBuilderClass), contextBuilderClass.getName()
|
||||||
+ " is not a subclass of " + RestContextBuilder.class.getName());
|
+ " is not a subclass of " + RestContextBuilder.class.getName());
|
||||||
checkArgument(PropertiesBuilder.class.isAssignableFrom(propertiesBuilderClass), propertiesBuilderClass
|
checkArgument(PropertiesBuilder.class.isAssignableFrom(propertiesBuilderClass), propertiesBuilderClass
|
||||||
.getName()
|
.getName()
|
||||||
+ " is not a subclass of " + PropertiesBuilder.class.getName());
|
+ " is not a subclass of " + PropertiesBuilder.class.getName());
|
||||||
this.propertiesBuilderClass = propertiesBuilderClass;
|
this.propertiesBuilderClass = propertiesBuilderClass;
|
||||||
this.contextBuilderClass = contextBuilderClass;
|
this.contextBuilderClass = contextBuilderClass;
|
||||||
this.modules = modules;
|
this.modules = modules;
|
||||||
|
@ -127,9 +126,9 @@ public class RestContextFactory {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public ContextSpec(String provider, String endpoint, String apiVersion, String identity, String credential,
|
public ContextSpec(String provider, String endpoint, String apiVersion, String identity, String credential,
|
||||||
Class<S> sync, Class<A> async) {
|
Class<S> sync, Class<A> async) {
|
||||||
this(provider, endpoint, apiVersion, identity, credential, sync, async, PropertiesBuilder.class,
|
this(provider, endpoint, apiVersion, identity, credential, sync, async, PropertiesBuilder.class,
|
||||||
(Class) RestContextBuilder.class, EMPTY_LIST);
|
(Class) RestContextBuilder.class, EMPTY_LIST);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -151,7 +150,7 @@ public class RestContextFactory {
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
return "[provider=" + provider + ", endpoint=" + endpoint + ", apiVersion=" + apiVersion + ", identity="
|
return "[provider=" + provider + ", endpoint=" + endpoint + ", apiVersion=" + apiVersion + ", identity="
|
||||||
+ identity + "]";
|
+ identity + "]";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -216,8 +215,8 @@ public class RestContextFactory {
|
||||||
private final Properties properties;
|
private final Properties properties;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes with the default properties built-in to jclouds. This is
|
* Initializes with the default properties built-in to jclouds. This is typically stored in the
|
||||||
* typically stored in the classpath resource {@code rest.properties}
|
* classpath resource {@code rest.properties}
|
||||||
*
|
*
|
||||||
* @see RestContextFactory#getPropertiesFromResource
|
* @see RestContextFactory#getPropertiesFromResource
|
||||||
*/
|
*/
|
||||||
|
@ -226,8 +225,8 @@ public class RestContextFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes with the default properties built-in to jclouds. This is
|
* Initializes with the default properties built-in to jclouds. This is typically stored in the
|
||||||
* typically stored in the classpath resource {@code filename}
|
* classpath resource {@code filename}
|
||||||
*
|
*
|
||||||
* @param filename
|
* @param filename
|
||||||
* name of the properties file to initialize from
|
* name of the properties file to initialize from
|
||||||
|
@ -240,8 +239,8 @@ public class RestContextFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Loads the default properties that define the {@code RestContext} objects.
|
* Loads the default properties that define the {@code RestContext} objects. <h3>properties file
|
||||||
* <h3>properties file format</h3>
|
* format</h3>
|
||||||
*
|
*
|
||||||
* Two properties are needed per context:
|
* Two properties are needed per context:
|
||||||
* <ul>
|
* <ul>
|
||||||
|
@ -271,8 +270,7 @@ public class RestContextFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Initializes the {@code RestContext} definitions from the specified
|
* Initializes the {@code RestContext} definitions from the specified properties.
|
||||||
* properties.
|
|
||||||
*/
|
*/
|
||||||
@Inject
|
@Inject
|
||||||
public RestContextFactory(Properties properties) {
|
public RestContextFactory(Properties properties) {
|
||||||
|
@ -284,16 +282,16 @@ public class RestContextFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see RestContextFactory#createContextBuilder(String, Properties,
|
* @see RestContextFactory#createContextBuilder(String, Properties, Iterable<? extends Module>,
|
||||||
* Iterable<? extends Module>, Properties)
|
* Properties)
|
||||||
*/
|
*/
|
||||||
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, Properties overrides) {
|
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, Properties overrides) {
|
||||||
return createContextBuilder(provider, null, null, ImmutableSet.<Module> of(), overrides);
|
return createContextBuilder(provider, null, null, ImmutableSet.<Module> of(), overrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see RestContextFactory#createContextBuilder(String, Properties,
|
* @see RestContextFactory#createContextBuilder(String, Properties, Iterable<? extends Module>,
|
||||||
* Iterable<? extends Module>, Properties)
|
* Properties)
|
||||||
*/
|
*/
|
||||||
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, Iterable<Module> modules) {
|
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, Iterable<Module> modules) {
|
||||||
return createContextBuilder(provider, null, null, modules, NO_PROPERTIES);
|
return createContextBuilder(provider, null, null, modules, NO_PROPERTIES);
|
||||||
|
@ -301,37 +299,36 @@ public class RestContextFactory {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* Identity will be found by searching {@code jclouds.identity} failing that
|
* Identity will be found by searching {@code jclouds.identity} failing that {@code
|
||||||
* {@code provider.identity} where provider corresponds to the parameter.
|
* provider.identity} where provider corresponds to the parameter. Same pattern is used for
|
||||||
* Same pattern is used for credential ({@code jclouds.credential} failing
|
* credential ({@code jclouds.credential} failing that {@code provider.credential}).
|
||||||
* that {@code provider.credential}).
|
|
||||||
*
|
*
|
||||||
* @param <S>
|
* @param <S>
|
||||||
* Type of the provider specific client
|
* Type of the provider specific client
|
||||||
* @param <A>
|
* @param <A>
|
||||||
* Type of the provide specific async client (same as above, yet
|
* Type of the provide specific async client (same as above, yet all methods return
|
||||||
* all methods return {@code Future} results)
|
* {@code Future} results)
|
||||||
* @param provider
|
* @param provider
|
||||||
* name of the provider (ex. s3, bluelock, etc.)
|
* name of the provider (ex. s3, bluelock, etc.)
|
||||||
* @param wiring
|
* @param wiring
|
||||||
* defines how objects are bound to interfaces, pass in here to
|
* defines how objects are bound to interfaces, pass in here to override this, or
|
||||||
* override this, or specify service implementations.
|
* specify service implementations.
|
||||||
* @param overrides
|
* @param overrides
|
||||||
* properties to pass to the context.
|
* properties to pass to the context.
|
||||||
*/
|
*/
|
||||||
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, Iterable<? extends Module> wiring,
|
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, Iterable<? extends Module> wiring,
|
||||||
Properties overrides) {
|
Properties overrides) {
|
||||||
return createContextBuilder(provider, null, null, wiring, overrides);
|
return createContextBuilder(provider, null, null, wiring, overrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, @Nullable String identity,
|
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, @Nullable String identity,
|
||||||
@Nullable String credential, Properties properties) {
|
@Nullable String credential, Properties properties) {
|
||||||
return createContextBuilder(provider, identity, credential, EMPTY_LIST, properties);
|
return createContextBuilder(provider, identity, credential, EMPTY_LIST, properties);
|
||||||
}
|
}
|
||||||
|
|
||||||
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, @Nullable String identity,
|
public <S, A> RestContextBuilder<S, A> createContextBuilder(String provider, @Nullable String identity,
|
||||||
@Nullable String credential, Iterable<? extends Module> wiring) {
|
@Nullable String credential, Iterable<? extends Module> wiring) {
|
||||||
return createContextBuilder(provider, identity, credential, wiring, NO_PROPERTIES);
|
return createContextBuilder(provider, identity, credential, wiring, NO_PROPERTIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,14 +341,14 @@ public class RestContextFactory {
|
||||||
* @param credential
|
* @param credential
|
||||||
* nullable, if credentials are present in the overrides
|
* nullable, if credentials are present in the overrides
|
||||||
* @param wiring
|
* @param wiring
|
||||||
* Configuration you'd like to pass to the context. Ex.
|
* Configuration you'd like to pass to the context. Ex. ImmutableSet.<Module>of(new
|
||||||
* ImmutableSet.<Module>of(new ExecutorServiceModule(myexecutor))
|
* ExecutorServiceModule(myexecutor))
|
||||||
* @param overrides
|
* @param overrides
|
||||||
* properties to override defaults with.
|
* properties to override defaults with.
|
||||||
* @return initialized context ready for use
|
* @return initialized context ready for use
|
||||||
*/
|
*/
|
||||||
public <S, A> RestContextBuilder<S, A> createContextBuilder(String providerName, @Nullable String identity,
|
public <S, A> RestContextBuilder<S, A> createContextBuilder(String providerName, @Nullable String identity,
|
||||||
@Nullable String credential, Iterable<? extends Module> wiring, Properties _overrides) {
|
@Nullable String credential, Iterable<? extends Module> wiring, Properties _overrides) {
|
||||||
checkNotNull(wiring, "wiring");
|
checkNotNull(wiring, "wiring");
|
||||||
ContextSpec<S, A> contextSpec = createContextSpec(providerName, identity, credential, wiring, _overrides);
|
ContextSpec<S, A> contextSpec = createContextSpec(providerName, identity, credential, wiring, _overrides);
|
||||||
return createContextBuilder(contextSpec, _overrides);
|
return createContextBuilder(contextSpec, _overrides);
|
||||||
|
@ -370,37 +367,37 @@ public class RestContextFactory {
|
||||||
if (contextSpec.sync != null) {
|
if (contextSpec.sync != null) {
|
||||||
props.setProperty(contextSpec.provider + ".sync", contextSpec.sync.getName());
|
props.setProperty(contextSpec.provider + ".sync", contextSpec.sync.getName());
|
||||||
props.setProperty(contextSpec.provider + ".async", checkNotNull(contextSpec.async, "contextSpec.async")
|
props.setProperty(contextSpec.provider + ".async", checkNotNull(contextSpec.async, "contextSpec.async")
|
||||||
.getName());
|
.getName());
|
||||||
} else {
|
} else {
|
||||||
props.setProperty(contextSpec.provider + ".contextbuilder", checkNotNull(contextSpec.contextBuilderClass,
|
props.setProperty(contextSpec.provider + ".contextbuilder", checkNotNull(contextSpec.contextBuilderClass,
|
||||||
"contextSpec.contextBuilderClass").getName());
|
"contextSpec.contextBuilderClass").getName());
|
||||||
|
|
||||||
props.setProperty(contextSpec.provider + ".propertiesbuilder", checkNotNull(
|
props.setProperty(contextSpec.provider + ".propertiesbuilder", checkNotNull(
|
||||||
contextSpec.propertiesBuilderClass, "contextSpec.propertiesBuilderClass").getName());
|
contextSpec.propertiesBuilderClass, "contextSpec.propertiesBuilderClass").getName());
|
||||||
}
|
}
|
||||||
if (size(contextSpec.modules) > 0) {
|
if (size(contextSpec.modules) > 0) {
|
||||||
props.setProperty(contextSpec.provider + ".modules", Joiner.on(',').join(
|
props.setProperty(contextSpec.provider + ".modules", Joiner.on(',').join(
|
||||||
transform(contextSpec.modules, new Function<Module, String>() {
|
transform(contextSpec.modules, new Function<Module, String>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String apply(Module from) {
|
public String apply(Module from) {
|
||||||
return from.getClass().getName();
|
return from.getClass().getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
})));
|
})));
|
||||||
}
|
}
|
||||||
return props;
|
return props;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <S, A> ContextSpec<S, A> createContextSpec(String providerName, String identity, String credential,
|
public <S, A> ContextSpec<S, A> createContextSpec(String providerName, String identity, String credential,
|
||||||
Properties _overrides) {
|
Properties _overrides) {
|
||||||
return createContextSpec(providerName, identity, credential, EMPTY_LIST, _overrides);
|
return createContextSpec(providerName, identity, credential, EMPTY_LIST, _overrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <S, A> ContextSpec<S, A> createContextSpec(String providerName, String identity, String credential,
|
public <S, A> ContextSpec<S, A> createContextSpec(String providerName, String identity, String credential,
|
||||||
Iterable<? extends Module> wiring, Properties _overrides) {
|
Iterable<? extends Module> wiring, Properties _overrides) {
|
||||||
checkNotNull(providerName, "providerName");
|
checkNotNull(providerName, "providerName");
|
||||||
checkNotNull(_overrides, "overrides");
|
checkNotNull(_overrides, "overrides");
|
||||||
|
|
||||||
|
@ -412,11 +409,10 @@ public class RestContextFactory {
|
||||||
String apiVersion = props.getProperty(providerName + ".apiversion", null);
|
String apiVersion = props.getProperty(providerName + ".apiversion", null);
|
||||||
identity = props.getProperty(providerName + ".identity", props.getProperty("jclouds.identity", identity));
|
identity = props.getProperty(providerName + ".identity", props.getProperty("jclouds.identity", identity));
|
||||||
credential = loadCredentialOrDefault(props, providerName + ".credential", loadCredentialOrDefault(props,
|
credential = loadCredentialOrDefault(props, providerName + ".credential", loadCredentialOrDefault(props,
|
||||||
"jclouds.credential", credential));
|
"jclouds.credential", credential));
|
||||||
String syncClassName = props.getProperty(providerName + ".sync", null);
|
String syncClassName = props.getProperty(providerName + ".sync", null);
|
||||||
String asyncClassName = props.getProperty(providerName + ".async", null);
|
String asyncClassName = props.getProperty(providerName + ".async", null);
|
||||||
Iterable<Module> modules = concat(modulesFromProperty(props, "jclouds.modules"), modulesFromProperty(props,
|
Iterable<Module> modules = concat(modulesForProviderInProperties(providerName, props), wiring);
|
||||||
providerName + ".modules"), wiring);
|
|
||||||
|
|
||||||
Class<RestContextBuilder<S, A>> contextBuilderClass;
|
Class<RestContextBuilder<S, A>> contextBuilderClass;
|
||||||
Class<PropertiesBuilder> propertiesBuilderClass;
|
Class<PropertiesBuilder> propertiesBuilderClass;
|
||||||
|
@ -433,7 +429,7 @@ public class RestContextFactory {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
ContextSpec<S, A> contextSpec = new ContextSpec<S, A>(providerName, endpoint, apiVersion, identity, credential,
|
ContextSpec<S, A> contextSpec = new ContextSpec<S, A>(providerName, endpoint, apiVersion, identity, credential,
|
||||||
sync, async, propertiesBuilderClass, contextBuilderClass, modules);
|
sync, async, propertiesBuilderClass, contextBuilderClass, modules);
|
||||||
return contextSpec;
|
return contextSpec;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -442,8 +438,8 @@ public class RestContextFactory {
|
||||||
return properties.getProperty(property);
|
return properties.getProperty(property);
|
||||||
else if (properties.containsKey(property + ".resource"))
|
else if (properties.containsKey(property + ".resource"))
|
||||||
try {
|
try {
|
||||||
return org.jclouds.util.Utils.toStringAndClose(RestContextFactory.class.getResourceAsStream(properties
|
return toStringAndClose(RestContextFactory.class.getResourceAsStream(properties.getProperty(property
|
||||||
.getProperty(property + ".resource")));
|
+ ".resource")));
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
throw new RuntimeException("error reading resource: " + properties.getProperty(property + ".resource"));
|
throw new RuntimeException("error reading resource: " + properties.getProperty(property + ".resource"));
|
||||||
}
|
}
|
||||||
|
@ -457,51 +453,26 @@ public class RestContextFactory {
|
||||||
return credential;
|
return credential;
|
||||||
}
|
}
|
||||||
|
|
||||||
static Iterable<Module> modulesFromProperty(Properties props, String property) {
|
|
||||||
String moduleClasses = props.getProperty(property, null);
|
|
||||||
Iterable<Module> modules = ImmutableSet.of();
|
|
||||||
if (moduleClasses != null) {
|
|
||||||
Iterable<String> transformer = ImmutableList.copyOf(on(',').split(moduleClasses));
|
|
||||||
modules = transform(transformer, new Function<String, Module>() {
|
|
||||||
|
|
||||||
@Override
|
|
||||||
public Module apply(String from) {
|
|
||||||
try {
|
|
||||||
return (Module) Class.forName(from).newInstance();
|
|
||||||
} catch (InstantiationException e) {
|
|
||||||
throw new RuntimeException("error instantiating " + from, e);
|
|
||||||
} catch (IllegalAccessException e) {
|
|
||||||
throw new RuntimeException("error instantiating " + from, e);
|
|
||||||
} catch (ClassNotFoundException e) {
|
|
||||||
throw new RuntimeException("error instantiating " + from, e);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
});
|
|
||||||
}
|
|
||||||
return modules;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static <S, A> RestContextBuilder<S, A> createContextBuilder(ContextSpec<S, A> contextSpec) {
|
public static <S, A> RestContextBuilder<S, A> createContextBuilder(ContextSpec<S, A> contextSpec) {
|
||||||
return createContextBuilder(contextSpec, NO_PROPERTIES);
|
return createContextBuilder(contextSpec, NO_PROPERTIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <S, A> RestContextBuilder<S, A> createContextBuilder(ContextSpec<S, A> contextSpec,
|
public static <S, A> RestContextBuilder<S, A> createContextBuilder(ContextSpec<S, A> contextSpec,
|
||||||
Properties overrides) {
|
Properties overrides) {
|
||||||
return createContextBuilder(contextSpec, EMPTY_LIST, overrides);
|
return createContextBuilder(contextSpec, EMPTY_LIST, overrides);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <S, A> RestContextBuilder<S, A> createContextBuilder(ContextSpec<S, A> contextSpec,
|
public static <S, A> RestContextBuilder<S, A> createContextBuilder(ContextSpec<S, A> contextSpec,
|
||||||
Iterable<Module> modules) {
|
Iterable<Module> modules) {
|
||||||
return createContextBuilder(contextSpec, modules, NO_PROPERTIES);
|
return createContextBuilder(contextSpec, modules, NO_PROPERTIES);
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <S, A> RestContextBuilder<S, A> createContextBuilder(ContextSpec<S, A> contextSpec,
|
public static <S, A> RestContextBuilder<S, A> createContextBuilder(ContextSpec<S, A> contextSpec,
|
||||||
Iterable<Module> modules, Properties overrides) {
|
Iterable<Module> modules, Properties overrides) {
|
||||||
try {
|
try {
|
||||||
PropertiesBuilder builder = contextSpec.propertiesBuilderClass.getConstructor(Properties.class).newInstance(
|
PropertiesBuilder builder = contextSpec.propertiesBuilderClass.getConstructor(Properties.class).newInstance(
|
||||||
overrides);
|
overrides);
|
||||||
|
|
||||||
builder.provider(contextSpec.provider);
|
builder.provider(contextSpec.provider);
|
||||||
if (contextSpec.apiVersion != null)
|
if (contextSpec.apiVersion != null)
|
||||||
|
@ -512,7 +483,7 @@ public class RestContextFactory {
|
||||||
builder.endpoint(contextSpec.endpoint);
|
builder.endpoint(contextSpec.endpoint);
|
||||||
|
|
||||||
RestContextBuilder<S, A> contextBuilder = initContextBuilder(contextSpec.contextBuilderClass,
|
RestContextBuilder<S, A> contextBuilder = initContextBuilder(contextSpec.contextBuilderClass,
|
||||||
contextSpec.sync, contextSpec.async, builder.build());
|
contextSpec.sync, contextSpec.async, builder.build());
|
||||||
|
|
||||||
contextBuilder.withModules(concat(modules, contextSpec.modules));
|
contextBuilder.withModules(concat(modules, contextSpec.modules));
|
||||||
|
|
||||||
|
@ -550,37 +521,34 @@ public class RestContextFactory {
|
||||||
* @see RestContextFactory#createContextBuilder(String, Iterable)
|
* @see RestContextFactory#createContextBuilder(String, Iterable)
|
||||||
*/
|
*/
|
||||||
public <S, A> RestContext<S, A> createContext(String provider, Iterable<? extends Module> wiring,
|
public <S, A> RestContext<S, A> createContext(String provider, Iterable<? extends Module> wiring,
|
||||||
Properties overrides) {
|
Properties overrides) {
|
||||||
RestContextBuilder<S, A> builder = createContextBuilder(provider, wiring, overrides);
|
RestContextBuilder<S, A> builder = createContextBuilder(provider, wiring, overrides);
|
||||||
return buildContextUnwrappingExceptions(builder);
|
return buildContextUnwrappingExceptions(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see RestContextFactory#createContextBuilder(String, String,String,
|
* @see RestContextFactory#createContextBuilder(String, String,String, Properties)
|
||||||
* Properties)
|
|
||||||
*/
|
*/
|
||||||
public <S, A> RestContext<S, A> createContext(String provider, @Nullable String identity,
|
public <S, A> RestContext<S, A> createContext(String provider, @Nullable String identity,
|
||||||
@Nullable String credential, Properties properties) {
|
@Nullable String credential, Properties properties) {
|
||||||
RestContextBuilder<S, A> builder = createContextBuilder(provider, identity, credential, properties);
|
RestContextBuilder<S, A> builder = createContextBuilder(provider, identity, credential, properties);
|
||||||
return buildContextUnwrappingExceptions(builder);
|
return buildContextUnwrappingExceptions(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see RestContextFactory#createContextBuilder(String, String,String,
|
* @see RestContextFactory#createContextBuilder(String, String,String, Iterable)
|
||||||
* Iterable)
|
|
||||||
*/
|
*/
|
||||||
public <S, A> RestContext<S, A> createContext(String provider, @Nullable String identity,
|
public <S, A> RestContext<S, A> createContext(String provider, @Nullable String identity,
|
||||||
@Nullable String credential, Iterable<? extends Module> wiring) {
|
@Nullable String credential, Iterable<? extends Module> wiring) {
|
||||||
RestContextBuilder<S, A> builder = createContextBuilder(provider, identity, credential, wiring);
|
RestContextBuilder<S, A> builder = createContextBuilder(provider, identity, credential, wiring);
|
||||||
return buildContextUnwrappingExceptions(builder);
|
return buildContextUnwrappingExceptions(builder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see RestContextFactory#createContextBuilder(String, String,String,
|
* @see RestContextFactory#createContextBuilder(String, String,String, Iterable, Properties)
|
||||||
* Iterable, Properties)
|
|
||||||
*/
|
*/
|
||||||
public <S, A> RestContext<S, A> createContext(String provider, @Nullable String identity,
|
public <S, A> RestContext<S, A> createContext(String provider, @Nullable String identity,
|
||||||
@Nullable String credential, Iterable<? extends Module> wiring, Properties overrides) {
|
@Nullable String credential, Iterable<? extends Module> wiring, Properties overrides) {
|
||||||
RestContextBuilder<S, A> builder = createContextBuilder(provider, identity, credential, wiring, overrides);
|
RestContextBuilder<S, A> builder = createContextBuilder(provider, identity, credential, wiring, overrides);
|
||||||
return buildContextUnwrappingExceptions(builder);
|
return buildContextUnwrappingExceptions(builder);
|
||||||
}
|
}
|
||||||
|
@ -610,11 +578,10 @@ public class RestContextFactory {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @see RestContextFactory#createContextBuilder(ContextSpec, Iterable,
|
* @see RestContextFactory#createContextBuilder(ContextSpec, Iterable, Properties)
|
||||||
* Properties)
|
|
||||||
*/
|
*/
|
||||||
public static <S, A> RestContext<S, A> createContext(ContextSpec<S, A> contextSpec, Iterable<Module> modules,
|
public static <S, A> RestContext<S, A> createContext(ContextSpec<S, A> contextSpec, Iterable<Module> modules,
|
||||||
Properties overrides) {
|
Properties overrides) {
|
||||||
RestContextBuilder<S, A> builder = createContextBuilder(contextSpec, modules, overrides);
|
RestContextBuilder<S, A> builder = createContextBuilder(contextSpec, modules, overrides);
|
||||||
return buildContextUnwrappingExceptions(builder);
|
return buildContextUnwrappingExceptions(builder);
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,7 +33,7 @@ import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.concurrent.FutureExceptionParser;
|
import org.jclouds.concurrent.ExceptionParsingListenableFuture;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.HttpResponse;
|
import org.jclouds.http.HttpResponse;
|
||||||
import org.jclouds.http.TransformingHttpCommand;
|
import org.jclouds.http.TransformingHttpCommand;
|
||||||
|
@ -70,7 +70,7 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Inject
|
@Inject
|
||||||
public AsyncRestClientProxy(Injector injector, Factory factory, RestAnnotationProcessor<T> util,
|
public AsyncRestClientProxy(Injector injector, Factory factory, RestAnnotationProcessor<T> util,
|
||||||
TypeLiteral<T> typeLiteral, @Named("async") ConcurrentMap<ClassMethodArgs, Object> delegateMap) {
|
TypeLiteral<T> typeLiteral, @Named("async") ConcurrentMap<ClassMethodArgs, Object> delegateMap) {
|
||||||
this.injector = injector;
|
this.injector = injector;
|
||||||
this.annotationProcessor = util;
|
this.annotationProcessor = util;
|
||||||
this.declaring = (Class<T>) typeLiteral.getRawType();
|
this.declaring = (Class<T>) typeLiteral.getRawType();
|
||||||
|
@ -90,19 +90,19 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
|
||||||
} else if (method.isAnnotationPresent(Delegate.class)) {
|
} else if (method.isAnnotationPresent(Delegate.class)) {
|
||||||
return delegateMap.get(new ClassMethodArgs(method.getReturnType(), method, args));
|
return delegateMap.get(new ClassMethodArgs(method.getReturnType(), method, args));
|
||||||
} else if (annotationProcessor.getDelegateOrNull(method) != null
|
} else if (annotationProcessor.getDelegateOrNull(method) != null
|
||||||
&& ListenableFuture.class.isAssignableFrom(method.getReturnType())) {
|
&& ListenableFuture.class.isAssignableFrom(method.getReturnType())) {
|
||||||
return createFuture(method, args);
|
return createListenableFuture(method, args);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("method is intended solely to set constants: " + method);
|
throw new RuntimeException("method is intended solely to set constants: " + method);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private ListenableFuture<?> createFuture(Method method, Object[] args) throws ExecutionException {
|
private ListenableFuture<?> createListenableFuture(Method method, Object[] args) throws ExecutionException {
|
||||||
method = annotationProcessor.getDelegateOrNull(method);
|
method = annotationProcessor.getDelegateOrNull(method);
|
||||||
logger.trace("Converting %s.%s", declaring.getSimpleName(), method.getName());
|
logger.trace("Converting %s.%s", declaring.getSimpleName(), method.getName());
|
||||||
Function<Exception, ?> exceptionParser = annotationProcessor
|
Function<Exception, ?> exceptionParser = annotationProcessor
|
||||||
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method);
|
.createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(method);
|
||||||
// in case there is an exception creating the request, we should at least
|
// in case there is an exception creating the request, we should at least
|
||||||
// pass in args
|
// pass in args
|
||||||
if (exceptionParser instanceof InvocationContext) {
|
if (exceptionParser instanceof InvocationContext) {
|
||||||
|
@ -128,15 +128,15 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
|
||||||
|
|
||||||
Function<HttpResponse, ?> transformer = annotationProcessor.createResponseParser(method, request);
|
Function<HttpResponse, ?> transformer = annotationProcessor.createResponseParser(method, request);
|
||||||
logger.trace("Response from %s.%s is parsed by %s", declaring.getSimpleName(), method.getName(), transformer
|
logger.trace("Response from %s.%s is parsed by %s", declaring.getSimpleName(), method.getName(), transformer
|
||||||
.getClass().getSimpleName());
|
.getClass().getSimpleName());
|
||||||
|
|
||||||
logger.debug("Invoking %s.%s", declaring.getSimpleName(), method.getName());
|
logger.debug("Invoking %s.%s", declaring.getSimpleName(), method.getName());
|
||||||
ListenableFuture<?> result = commandFactory.create(request, transformer).execute();
|
ListenableFuture<?> result = commandFactory.create(request, transformer).execute();
|
||||||
|
|
||||||
if (exceptionParser != null) {
|
if (exceptionParser != null) {
|
||||||
logger.trace("Exceptions from %s.%s are parsed by %s", declaring.getSimpleName(), method.getName(),
|
logger.trace("Exceptions from %s.%s are parsed by %s", declaring.getSimpleName(), method.getName(),
|
||||||
exceptionParser.getClass().getSimpleName());
|
exceptionParser.getClass().getSimpleName());
|
||||||
result = new FutureExceptionParser(result, exceptionParser);
|
result = new ExceptionParsingListenableFuture(result, exceptionParser);
|
||||||
}
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
|
@ -159,7 +159,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
static final Map<MethodKey, Method> delegationMap = newHashMap();
|
static final Map<MethodKey, Method> delegationMap = newHashMap();
|
||||||
|
|
||||||
static Map<Method, Map<Integer, Set<Annotation>>> createMethodToIndexOfParamToAnnotation(
|
static Map<Method, Map<Integer, Set<Annotation>>> createMethodToIndexOfParamToAnnotation(
|
||||||
final Class<? extends Annotation> annotation) {
|
final Class<? extends Annotation> annotation) {
|
||||||
return new MapMaker().makeComputingMap(new Function<Method, Map<Integer, Set<Annotation>>>() {
|
return new MapMaker().makeComputingMap(new Function<Method, Map<Integer, Set<Annotation>>>() {
|
||||||
public Map<Integer, Set<Annotation>> apply(final Method method) {
|
public Map<Integer, Set<Annotation>> apply(final Method method) {
|
||||||
return new MapMaker().makeComputingMap(new GetAnnotationsForMethodParameterIndex(method, annotation));
|
return new MapMaker().makeComputingMap(new GetAnnotationsForMethodParameterIndex(method, annotation));
|
||||||
|
@ -193,7 +193,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private static final Class<? extends HttpRequestOptions[]> optionsVarArgsClass = new HttpRequestOptions[] {}
|
private static final Class<? extends HttpRequestOptions[]> optionsVarArgsClass = new HttpRequestOptions[] {}
|
||||||
.getClass();
|
.getClass();
|
||||||
|
|
||||||
private static final Function<? super Entry<String, String>, ? extends Part> ENTRY_TO_PART = new Function<Entry<String, String>, Part>() {
|
private static final Function<? super Entry<String, String>, ? extends Part> ENTRY_TO_PART = new Function<Entry<String, String>, Part>() {
|
||||||
|
|
||||||
|
@ -205,17 +205,17 @@ public class RestAnnotationProcessor<T> {
|
||||||
};
|
};
|
||||||
|
|
||||||
private final Map<Method, Set<Integer>> methodToIndexesOfOptions = new MapMaker()
|
private final Map<Method, Set<Integer>> methodToIndexesOfOptions = new MapMaker()
|
||||||
.makeComputingMap(new Function<Method, Set<Integer>>() {
|
.makeComputingMap(new Function<Method, Set<Integer>>() {
|
||||||
public Set<Integer> apply(final Method method) {
|
public Set<Integer> apply(final Method method) {
|
||||||
Set<Integer> toReturn = newHashSet();
|
Set<Integer> toReturn = newHashSet();
|
||||||
for (int index = 0; index < method.getParameterTypes().length; index++) {
|
for (int index = 0; index < method.getParameterTypes().length; index++) {
|
||||||
Class<?> type = method.getParameterTypes()[index];
|
Class<?> type = method.getParameterTypes()[index];
|
||||||
if (HttpRequestOptions.class.isAssignableFrom(type) || optionsVarArgsClass.isAssignableFrom(type))
|
if (HttpRequestOptions.class.isAssignableFrom(type) || optionsVarArgsClass.isAssignableFrom(type))
|
||||||
toReturn.add(index);
|
toReturn.add(index);
|
||||||
|
}
|
||||||
|
return toReturn;
|
||||||
}
|
}
|
||||||
return toReturn;
|
});
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
private final ParseSax.Factory parserFactory;
|
private final ParseSax.Factory parserFactory;
|
||||||
private final HttpUtils utils;
|
private final HttpUtils utils;
|
||||||
|
@ -233,7 +233,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static Function<HttpResponse, ?> createResponseParser(ParseSax.Factory parserFactory, Injector injector,
|
public static Function<HttpResponse, ?> createResponseParser(ParseSax.Factory parserFactory, Injector injector,
|
||||||
Method method, HttpRequest request) {
|
Method method, HttpRequest request) {
|
||||||
Function<HttpResponse, ?> transformer;
|
Function<HttpResponse, ?> transformer;
|
||||||
Class<? extends HandlerWithResult<?>> handler = getSaxResponseParserClassOrNull(method);
|
Class<? extends HandlerWithResult<?>> handler = getSaxResponseParserClassOrNull(method);
|
||||||
if (handler != null) {
|
if (handler != null) {
|
||||||
|
@ -254,7 +254,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static Function<Exception, ?> createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(
|
public static Function<Exception, ?> createExceptionParserOrThrowResourceNotFoundOn404IfNoAnnotation(
|
||||||
Injector injector, Method method) {
|
Injector injector, Method method) {
|
||||||
ExceptionParser annotation = method.getAnnotation(ExceptionParser.class);
|
ExceptionParser annotation = method.getAnnotation(ExceptionParser.class);
|
||||||
if (annotation != null) {
|
if (annotation != null) {
|
||||||
return injector.getInstance(annotation.value());
|
return injector.getInstance(annotation.value());
|
||||||
|
@ -265,7 +265,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Inject
|
@Inject
|
||||||
public RestAnnotationProcessor(Injector injector, ParseSax.Factory parserFactory, HttpUtils utils,
|
public RestAnnotationProcessor(Injector injector, ParseSax.Factory parserFactory, HttpUtils utils,
|
||||||
TypeLiteral<T> typeLiteral) {
|
TypeLiteral<T> typeLiteral) {
|
||||||
this.declaring = (Class<T>) typeLiteral.getRawType();
|
this.declaring = (Class<T>) typeLiteral.getRawType();
|
||||||
this.injector = injector;
|
this.injector = injector;
|
||||||
this.parserFactory = parserFactory;
|
this.parserFactory = parserFactory;
|
||||||
|
@ -380,7 +380,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
public GeneratedHttpRequest<T> createRequest(Method method, Object... args) {
|
public GeneratedHttpRequest<T> createRequest(Method method, Object... args) {
|
||||||
inputParamValidator.validateMethodParametersOrThrow(method, args);
|
inputParamValidator.validateMethodParametersOrThrow(method, args);
|
||||||
ClassMethodArgs cma = logger.isTraceEnabled() ? new ClassMethodArgs(method.getDeclaringClass(), method, args)
|
ClassMethodArgs cma = logger.isTraceEnabled() ? new ClassMethodArgs(method.getDeclaringClass(), method, args)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
URI endpoint = callerEndpoint;
|
URI endpoint = callerEndpoint;
|
||||||
try {
|
try {
|
||||||
|
@ -453,7 +453,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
GeneratedHttpRequest<T> request = new GeneratedHttpRequest<T>(httpMethod, endpoint, skips, declaring, method,
|
GeneratedHttpRequest<T> request = new GeneratedHttpRequest<T>(httpMethod, endpoint, skips, declaring, method,
|
||||||
args);
|
args);
|
||||||
addHostHeaderIfAnnotatedWithVirtualHost(headers, request.getEndpoint().getHost(), method);
|
addHostHeaderIfAnnotatedWithVirtualHost(headers, request.getEndpoint().getHost(), method);
|
||||||
addFiltersIfAnnotated(method, request);
|
addFiltersIfAnnotated(method, request);
|
||||||
|
|
||||||
|
@ -483,7 +483,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
builder.path(clazz);
|
builder.path(clazz);
|
||||||
builder.path(method);
|
builder.path(method);
|
||||||
return builder.buildFromEncodedMap(convertUnsafe(encodeValues(getPathParamKeyValues(method, args), skips)))
|
return builder.buildFromEncodedMap(convertUnsafe(encodeValues(getPathParamKeyValues(method, args), skips)))
|
||||||
.getPath();
|
.getPath();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Multimap<String, String> addPathAndGetTokens(Class<?> clazz, Method method, Object[] args, UriBuilder builder) {
|
private Multimap<String, String> addPathAndGetTokens(Class<?> clazz, Method method, Object[] args, UriBuilder builder) {
|
||||||
|
@ -498,14 +498,14 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static URI replaceQuery(Provider<UriBuilder> uriBuilderProvider, URI in, String newQuery,
|
public static URI replaceQuery(Provider<UriBuilder> uriBuilderProvider, URI in, String newQuery,
|
||||||
@Nullable Comparator<Entry<String, String>> sorter, char... skips) {
|
@Nullable Comparator<Entry<String, String>> sorter, char... skips) {
|
||||||
UriBuilder builder = uriBuilderProvider.get().uri(in);
|
UriBuilder builder = uriBuilderProvider.get().uri(in);
|
||||||
builder.replaceQuery(makeQueryLine(parseQueryToMap(newQuery), sorter, skips));
|
builder.replaceQuery(makeQueryLine(parseQueryToMap(newQuery), sorter, skips));
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addMatrixParams(UriBuilder builder, Collection<Entry<String, String>> tokenValues, Method method,
|
private void addMatrixParams(UriBuilder builder, Collection<Entry<String, String>> tokenValues, Method method,
|
||||||
Object... args) {
|
Object... args) {
|
||||||
if (declaring.isAnnotationPresent(MatrixParams.class)) {
|
if (declaring.isAnnotationPresent(MatrixParams.class)) {
|
||||||
MatrixParams matrix = declaring.getAnnotation(MatrixParams.class);
|
MatrixParams matrix = declaring.getAnnotation(MatrixParams.class);
|
||||||
addMatrix(builder, matrix, tokenValues);
|
addMatrix(builder, matrix, tokenValues);
|
||||||
|
@ -522,7 +522,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Multimap<String, String> addFormParams(Collection<Entry<String, String>> tokenValues, Method method,
|
private Multimap<String, String> addFormParams(Collection<Entry<String, String>> tokenValues, Method method,
|
||||||
Object... args) {
|
Object... args) {
|
||||||
Multimap<String, String> formMap = LinkedListMultimap.create();
|
Multimap<String, String> formMap = LinkedListMultimap.create();
|
||||||
if (declaring.isAnnotationPresent(FormParams.class)) {
|
if (declaring.isAnnotationPresent(FormParams.class)) {
|
||||||
FormParams form = declaring.getAnnotation(FormParams.class);
|
FormParams form = declaring.getAnnotation(FormParams.class);
|
||||||
|
@ -541,7 +541,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private Multimap<String, String> addQueryParams(Collection<Entry<String, String>> tokenValues, Method method,
|
private Multimap<String, String> addQueryParams(Collection<Entry<String, String>> tokenValues, Method method,
|
||||||
Object... args) {
|
Object... args) {
|
||||||
Multimap<String, String> queryMap = LinkedListMultimap.create();
|
Multimap<String, String> queryMap = LinkedListMultimap.create();
|
||||||
if (declaring.isAnnotationPresent(QueryParams.class)) {
|
if (declaring.isAnnotationPresent(QueryParams.class)) {
|
||||||
QueryParams query = declaring.getAnnotation(QueryParams.class);
|
QueryParams query = declaring.getAnnotation(QueryParams.class);
|
||||||
|
@ -560,7 +560,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addForm(Multimap<String, String> formParams, FormParams form,
|
private void addForm(Multimap<String, String> formParams, FormParams form,
|
||||||
Collection<Entry<String, String>> tokenValues) {
|
Collection<Entry<String, String>> tokenValues) {
|
||||||
for (int i = 0; i < form.keys().length; i++) {
|
for (int i = 0; i < form.keys().length; i++) {
|
||||||
if (form.values()[i].equals(FormParams.NULL)) {
|
if (form.values()[i].equals(FormParams.NULL)) {
|
||||||
formParams.removeAll(form.keys()[i]);
|
formParams.removeAll(form.keys()[i]);
|
||||||
|
@ -572,7 +572,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addQuery(Multimap<String, String> queryParams, QueryParams query,
|
private void addQuery(Multimap<String, String> queryParams, QueryParams query,
|
||||||
Collection<Entry<String, String>> tokenValues) {
|
Collection<Entry<String, String>> tokenValues) {
|
||||||
for (int i = 0; i < query.keys().length; i++) {
|
for (int i = 0; i < query.keys().length; i++) {
|
||||||
if (query.values()[i].equals(QueryParams.NULL)) {
|
if (query.values()[i].equals(QueryParams.NULL)) {
|
||||||
queryParams.removeAll(query.keys()[i]);
|
queryParams.removeAll(query.keys()[i]);
|
||||||
|
@ -615,7 +615,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static URI getEndpointInParametersOrNull(Method method, Object[] args, Injector injector) {
|
public static URI getEndpointInParametersOrNull(Method method, Object[] args, Injector injector) {
|
||||||
Map<Integer, Set<Annotation>> map = RestAnnotationProcessor.indexWithOnlyOneAnnotation(method, "@EndpointParam",
|
Map<Integer, Set<Annotation>> map = RestAnnotationProcessor.indexWithOnlyOneAnnotation(method, "@EndpointParam",
|
||||||
RestAnnotationProcessor.methodToIndexOfParamToEndpointParamAnnotations);
|
RestAnnotationProcessor.methodToIndexOfParamToEndpointParamAnnotations);
|
||||||
if (map.size() == 1 && args.length > 0) {
|
if (map.size() == 1 && args.length > 0) {
|
||||||
EndpointParam annotation = (EndpointParam) map.values().iterator().next().iterator().next();
|
EndpointParam annotation = (EndpointParam) map.values().iterator().next().iterator().next();
|
||||||
int index = map.keySet().iterator().next();
|
int index = map.keySet().iterator().next();
|
||||||
|
@ -623,7 +623,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
try {
|
try {
|
||||||
URI returnVal = parser.apply(args[index]);
|
URI returnVal = parser.apply(args[index]);
|
||||||
checkArgument(returnVal != null, String.format("endpoint for [%s] not configured for %s", args[index],
|
checkArgument(returnVal != null, String.format("endpoint for [%s] not configured for %s", args[index],
|
||||||
method));
|
method));
|
||||||
return returnVal;
|
return returnVal;
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
throw new IllegalArgumentException(String.format("argument at index %d on method %s", index, method), e);
|
throw new IllegalArgumentException(String.format("argument at index %d on method %s", index, method), e);
|
||||||
|
@ -666,13 +666,13 @@ public class RestAnnotationProcessor<T> {
|
||||||
ResponseParser annotation = method.getAnnotation(ResponseParser.class);
|
ResponseParser annotation = method.getAnnotation(ResponseParser.class);
|
||||||
if (annotation == null) {
|
if (annotation == null) {
|
||||||
if (method.getReturnType().equals(void.class)
|
if (method.getReturnType().equals(void.class)
|
||||||
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureVoidLiteral)) {
|
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureVoidLiteral)) {
|
||||||
return Key.get(ReleasePayloadAndReturn.class);
|
return Key.get(ReleasePayloadAndReturn.class);
|
||||||
} else if (method.getReturnType().equals(boolean.class) || method.getReturnType().equals(Boolean.class)
|
} else if (method.getReturnType().equals(boolean.class) || method.getReturnType().equals(Boolean.class)
|
||||||
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureBooleanLiteral)) {
|
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureBooleanLiteral)) {
|
||||||
return Key.get(ReturnTrueIf2xx.class);
|
return Key.get(ReturnTrueIf2xx.class);
|
||||||
} else if (method.getReturnType().equals(InputStream.class)
|
} else if (method.getReturnType().equals(InputStream.class)
|
||||||
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureInputStreamLiteral)) {
|
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureInputStreamLiteral)) {
|
||||||
return Key.get(ReturnInputStream.class);
|
return Key.get(ReturnInputStream.class);
|
||||||
} else if (getAcceptHeadersOrNull(method).contains(MediaType.APPLICATION_JSON)) {
|
} else if (getAcceptHeadersOrNull(method).contains(MediaType.APPLICATION_JSON)) {
|
||||||
Type returnVal;
|
Type returnVal;
|
||||||
|
@ -693,10 +693,10 @@ public class RestAnnotationProcessor<T> {
|
||||||
parserType = Types.newParameterizedType(ParseJson.class, returnVal);
|
parserType = Types.newParameterizedType(ParseJson.class, returnVal);
|
||||||
return (Key<? extends Function<HttpResponse, ?>>) Key.get(parserType);
|
return (Key<? extends Function<HttpResponse, ?>>) Key.get(parserType);
|
||||||
} else if (method.getReturnType().equals(String.class)
|
} else if (method.getReturnType().equals(String.class)
|
||||||
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureStringLiteral)) {
|
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureStringLiteral)) {
|
||||||
return Key.get(ReturnStringIf2xx.class);
|
return Key.get(ReturnStringIf2xx.class);
|
||||||
} else if (method.getReturnType().equals(URI.class)
|
} else if (method.getReturnType().equals(URI.class)
|
||||||
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureURILiteral)) {
|
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureURILiteral)) {
|
||||||
return Key.get(ParseURIFromListOrLocationHeaderIf20x.class);
|
return Key.get(ParseURIFromListOrLocationHeaderIf20x.class);
|
||||||
} else {
|
} else {
|
||||||
throw new IllegalStateException("You must specify a ResponseParser annotation on: " + method.toString());
|
throw new IllegalStateException("You must specify a ResponseParser annotation on: " + method.toString());
|
||||||
|
@ -728,7 +728,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
} else {
|
} else {
|
||||||
if (postBinders[0] instanceof org.jclouds.rest.MapBinder) {
|
if (postBinders[0] instanceof org.jclouds.rest.MapBinder) {
|
||||||
throw new IllegalArgumentException("we currently do not support multiple varargs postBinders in: "
|
throw new IllegalArgumentException("we currently do not support multiple varargs postBinders in: "
|
||||||
+ method.getName());
|
+ method.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if (arg instanceof org.jclouds.rest.MapBinder) {
|
} else if (arg instanceof org.jclouds.rest.MapBinder) {
|
||||||
|
@ -765,8 +765,8 @@ public class RestAnnotationProcessor<T> {
|
||||||
Set<String> requests = IsHttpMethod.getHttpMethods(method);
|
Set<String> requests = IsHttpMethod.getHttpMethods(method);
|
||||||
if (requests == null || requests.size() != 1) {
|
if (requests == null || requests.size() != 1) {
|
||||||
throw new IllegalStateException(
|
throw new IllegalStateException(
|
||||||
"You must use at least one, but no more than one http method or pathparam annotation on: "
|
"You must use at least one, but no more than one http method or pathparam annotation on: "
|
||||||
+ method.toString());
|
+ method.toString());
|
||||||
}
|
}
|
||||||
return requests.iterator().next();
|
return requests.iterator().next();
|
||||||
}
|
}
|
||||||
|
@ -789,12 +789,12 @@ public class RestAnnotationProcessor<T> {
|
||||||
mapBinder.bindToRequest(request, mapParams);
|
mapBinder.bindToRequest(request, mapParams);
|
||||||
} else {
|
} else {
|
||||||
OUTER: for (Entry<Integer, Set<Annotation>> entry : filterValues(
|
OUTER: for (Entry<Integer, Set<Annotation>> entry : filterValues(
|
||||||
methodToIndexOfParamToDecoratorParamAnnotation.get(request.getJavaMethod()),
|
methodToIndexOfParamToDecoratorParamAnnotation.get(request.getJavaMethod()),
|
||||||
new Predicate<Set<Annotation>>() {
|
new Predicate<Set<Annotation>>() {
|
||||||
public boolean apply(Set<Annotation> input) {
|
public boolean apply(Set<Annotation> input) {
|
||||||
return input.size() >= 1;
|
return input.size() >= 1;
|
||||||
}
|
}
|
||||||
}).entrySet()) {
|
}).entrySet()) {
|
||||||
boolean shouldBreak = false;
|
boolean shouldBreak = false;
|
||||||
BinderParam payloadAnnotation = (BinderParam) entry.getValue().iterator().next();
|
BinderParam payloadAnnotation = (BinderParam) entry.getValue().iterator().next();
|
||||||
Binder binder = injector.getInstance(payloadAnnotation.value());
|
Binder binder = injector.getInstance(payloadAnnotation.value());
|
||||||
|
@ -830,18 +830,18 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Map<Integer, Set<Annotation>> indexWithOnlyOneAnnotation(Method method, String description,
|
public static Map<Integer, Set<Annotation>> indexWithOnlyOneAnnotation(Method method, String description,
|
||||||
Map<Method, Map<Integer, Set<Annotation>>> toRefine) {
|
Map<Method, Map<Integer, Set<Annotation>>> toRefine) {
|
||||||
Map<Integer, Set<Annotation>> indexToPayloadAnnotation = filterValues(toRefine.get(method),
|
Map<Integer, Set<Annotation>> indexToPayloadAnnotation = filterValues(toRefine.get(method),
|
||||||
new Predicate<Set<Annotation>>() {
|
new Predicate<Set<Annotation>>() {
|
||||||
public boolean apply(Set<Annotation> input) {
|
public boolean apply(Set<Annotation> input) {
|
||||||
return input.size() == 1;
|
return input.size() == 1;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if (indexToPayloadAnnotation.size() > 1) {
|
if (indexToPayloadAnnotation.size() > 1) {
|
||||||
throw new IllegalStateException(String.format(
|
throw new IllegalStateException(String.format(
|
||||||
"You must not specify more than one %s annotation on: %s; found %s", description, method.toString(),
|
"You must not specify more than one %s annotation on: %s; found %s", description, method.toString(),
|
||||||
indexToPayloadAnnotation));
|
indexToPayloadAnnotation));
|
||||||
}
|
}
|
||||||
return indexToPayloadAnnotation;
|
return indexToPayloadAnnotation;
|
||||||
}
|
}
|
||||||
|
@ -861,7 +861,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
} else {
|
} else {
|
||||||
if (options[0] instanceof HttpRequestOptions) {
|
if (options[0] instanceof HttpRequestOptions) {
|
||||||
throw new IllegalArgumentException("we currently do not support multiple varargs options in: "
|
throw new IllegalArgumentException("we currently do not support multiple varargs options in: "
|
||||||
+ method.getName());
|
+ method.getName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -873,7 +873,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public Multimap<String, String> buildHeaders(Collection<Entry<String, String>> tokenValues, Method method,
|
public Multimap<String, String> buildHeaders(Collection<Entry<String, String>> tokenValues, Method method,
|
||||||
final Object... args) {
|
final Object... args) {
|
||||||
Multimap<String, String> headers = LinkedHashMultimap.create();
|
Multimap<String, String> headers = LinkedHashMultimap.create();
|
||||||
addHeaderIfAnnotationPresentOnMethod(headers, method, tokenValues);
|
addHeaderIfAnnotationPresentOnMethod(headers, method, tokenValues);
|
||||||
Map<Integer, Set<Annotation>> indexToHeaderParam = methodToIndexOfParamToHeaderParamAnnotations.get(method);
|
Map<Integer, Set<Annotation>> indexToHeaderParam = methodToIndexOfParamToHeaderParamAnnotations.get(method);
|
||||||
|
@ -920,7 +920,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
public void addHeaderIfAnnotationPresentOnMethod(Multimap<String, String> headers, Method method,
|
public void addHeaderIfAnnotationPresentOnMethod(Multimap<String, String> headers, Method method,
|
||||||
Collection<Entry<String, String>> tokenValues) {
|
Collection<Entry<String, String>> tokenValues) {
|
||||||
if (declaring.isAnnotationPresent(Headers.class)) {
|
if (declaring.isAnnotationPresent(Headers.class)) {
|
||||||
Headers header = declaring.getAnnotation(Headers.class);
|
Headers header = declaring.getAnnotation(Headers.class);
|
||||||
addHeader(headers, header, tokenValues);
|
addHeader(headers, header, tokenValues);
|
||||||
|
@ -932,7 +932,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addHeader(Multimap<String, String> headers, Headers header,
|
private void addHeader(Multimap<String, String> headers, Headers header,
|
||||||
Collection<Entry<String, String>> tokenValues) {
|
Collection<Entry<String, String>> tokenValues) {
|
||||||
for (int i = 0; i < header.keys().length; i++) {
|
for (int i = 0; i < header.keys().length; i++) {
|
||||||
String value = header.values()[i];
|
String value = header.values()[i];
|
||||||
value = replaceTokens(value, tokenValues);
|
value = replaceTokens(value, tokenValues);
|
||||||
|
|
|
@ -22,8 +22,10 @@ import static com.google.common.base.Preconditions.checkArgument;
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static com.google.common.base.Predicates.instanceOf;
|
import static com.google.common.base.Predicates.instanceOf;
|
||||||
import static com.google.common.base.Predicates.notNull;
|
import static com.google.common.base.Predicates.notNull;
|
||||||
|
import static com.google.common.base.Splitter.on;
|
||||||
import static com.google.common.base.Throwables.getCausalChain;
|
import static com.google.common.base.Throwables.getCausalChain;
|
||||||
import static com.google.common.base.Throwables.propagate;
|
import static com.google.common.base.Throwables.propagate;
|
||||||
|
import static com.google.common.collect.Iterables.concat;
|
||||||
import static com.google.common.collect.Iterables.filter;
|
import static com.google.common.collect.Iterables.filter;
|
||||||
import static com.google.common.collect.Iterables.find;
|
import static com.google.common.collect.Iterables.find;
|
||||||
import static com.google.common.collect.Iterables.get;
|
import static com.google.common.collect.Iterables.get;
|
||||||
|
@ -64,9 +66,11 @@ import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.common.io.OutputSupplier;
|
import com.google.common.io.OutputSupplier;
|
||||||
|
import com.google.inject.Module;
|
||||||
import com.google.inject.ProvisionException;
|
import com.google.inject.ProvisionException;
|
||||||
import com.google.inject.spi.Message;
|
import com.google.inject.spi.Message;
|
||||||
|
|
||||||
|
@ -206,7 +210,7 @@ public class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static boolean eventuallyTrue(Supplier<Boolean> assertion, long inconsistencyMillis)
|
public static boolean eventuallyTrue(Supplier<Boolean> assertion, long inconsistencyMillis)
|
||||||
throws InterruptedException {
|
throws InterruptedException {
|
||||||
|
|
||||||
for (int i = 0; i < 30; i++) {
|
for (int i = 0; i < 30; i++) {
|
||||||
if (!assertion.get()) {
|
if (!assertion.get()) {
|
||||||
|
@ -241,15 +245,14 @@ public class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode the given string with the given encoding, if possible. If the
|
* Encode the given string with the given encoding, if possible. If the encoding fails with
|
||||||
* encoding fails with {@link UnsupportedEncodingException}, log a warning
|
* {@link UnsupportedEncodingException}, log a warning and fall back to the system's default
|
||||||
* and fall back to the system's default encoding.
|
* encoding.
|
||||||
*
|
*
|
||||||
* @param str
|
* @param str
|
||||||
* what to encode
|
* what to encode
|
||||||
* @param charsetName
|
* @param charsetName
|
||||||
* the name of a supported {@link java.nio.charset.Charset
|
* the name of a supported {@link java.nio.charset.Charset </code>charset<code>}
|
||||||
* </code>charset<code>}
|
|
||||||
* @return properly encoded String.
|
* @return properly encoded String.
|
||||||
*/
|
*/
|
||||||
public static byte[] encodeString(String str, String charsetName) {
|
public static byte[] encodeString(String str, String charsetName) {
|
||||||
|
@ -257,16 +260,15 @@ public class Utils {
|
||||||
return str.getBytes(charsetName);
|
return str.getBytes(charsetName);
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
logger.warn(e, "Failed to encode string to bytes with encoding " + charsetName
|
logger.warn(e, "Failed to encode string to bytes with encoding " + charsetName
|
||||||
+ ". Falling back to system's default encoding");
|
+ ". Falling back to system's default encoding");
|
||||||
return str.getBytes();
|
return str.getBytes();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Encode the given string with the UTF-8 encoding, the sane default. In the
|
* Encode the given string with the UTF-8 encoding, the sane default. In the very unlikely event
|
||||||
* very unlikely event the encoding fails with
|
* the encoding fails with {@link UnsupportedEncodingException}, log a warning and fall back to
|
||||||
* {@link UnsupportedEncodingException}, log a warning and fall back to the
|
* the system's default encoding.
|
||||||
* system's default encoding.
|
|
||||||
*
|
*
|
||||||
* @param str
|
* @param str
|
||||||
* what to encode
|
* what to encode
|
||||||
|
@ -317,8 +319,7 @@ public class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Will throw an exception if the argument is null or empty. Accepts a custom
|
* Will throw an exception if the argument is null or empty. Accepts a custom error message.
|
||||||
* error message.
|
|
||||||
*
|
*
|
||||||
* @param nullableString
|
* @param nullableString
|
||||||
* string to verify. Can be null or empty.
|
* string to verify. Can be null or empty.
|
||||||
|
@ -330,8 +331,8 @@ public class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a set of supported providers. Idea stolen from pallets
|
* Gets a set of supported providers. Idea stolen from pallets (supported-clouds). Uses
|
||||||
* (supported-clouds). Uses rest.properties to populate the set.
|
* rest.properties to populate the set.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
public static Iterable<String> getSupportedProviders() {
|
public static Iterable<String> getSupportedProviders() {
|
||||||
|
@ -339,8 +340,8 @@ public class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets a set of supported providers. Idea stolen from pallets
|
* Gets a set of supported providers. Idea stolen from pallets (supported-clouds). Uses
|
||||||
* (supported-clouds). Uses rest.properties to populate the set.
|
* rest.properties to populate the set.
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -356,7 +357,7 @@ public class Utils {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Iterable<String> getSupportedProvidersOfTypeInProperties(
|
public static Iterable<String> getSupportedProvidersOfTypeInProperties(
|
||||||
final Class<? extends RestContextBuilder> type, final Properties properties) {
|
final Class<? extends RestContextBuilder> type, final Properties properties) {
|
||||||
return filter(transform(filter(properties.entrySet(), new Predicate<Map.Entry<Object, Object>>() {
|
return filter(transform(filter(properties.entrySet(), new Predicate<Map.Entry<Object, Object>>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -387,8 +388,8 @@ public class Utils {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static <S, A> Class<RestContextBuilder<S, A>> resolveContextBuilderClass(String provider,
|
public static <S, A> Class<RestContextBuilder<S, A>> resolveContextBuilderClass(String provider,
|
||||||
Properties properties) throws ClassNotFoundException, IllegalArgumentException, SecurityException,
|
Properties properties) throws ClassNotFoundException, IllegalArgumentException, SecurityException,
|
||||||
InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
||||||
String contextBuilderClassName = properties.getProperty(provider + ".contextbuilder");
|
String contextBuilderClassName = properties.getProperty(provider + ".contextbuilder");
|
||||||
String syncClassName = properties.getProperty(provider + ".sync");
|
String syncClassName = properties.getProperty(provider + ".sync");
|
||||||
String asyncClassName = properties.getProperty(provider + ".async");
|
String asyncClassName = properties.getProperty(provider + ".async");
|
||||||
|
@ -397,7 +398,7 @@ public class Utils {
|
||||||
Class.forName(syncClassName);
|
Class.forName(syncClassName);
|
||||||
Class.forName(asyncClassName);
|
Class.forName(asyncClassName);
|
||||||
return (Class<RestContextBuilder<S, A>>) (contextBuilderClassName != null ? Class
|
return (Class<RestContextBuilder<S, A>>) (contextBuilderClassName != null ? Class
|
||||||
.forName(contextBuilderClassName) : RestContextBuilder.class);
|
.forName(contextBuilderClassName) : RestContextBuilder.class);
|
||||||
} else {
|
} else {
|
||||||
checkArgument(contextBuilderClassName != null, "please configure contextbuilder class for " + provider);
|
checkArgument(contextBuilderClassName != null, "please configure contextbuilder class for " + provider);
|
||||||
return (Class<RestContextBuilder<S, A>>) Class.forName(contextBuilderClassName);
|
return (Class<RestContextBuilder<S, A>>) Class.forName(contextBuilderClassName);
|
||||||
|
@ -405,9 +406,9 @@ public class Utils {
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <S, A> RestContextBuilder<S, A> initContextBuilder(
|
public static <S, A> RestContextBuilder<S, A> initContextBuilder(
|
||||||
Class<RestContextBuilder<S, A>> contextBuilderClass, @Nullable Class<S> sync, @Nullable Class<A> async,
|
Class<RestContextBuilder<S, A>> contextBuilderClass, @Nullable Class<S> sync, @Nullable Class<A> async,
|
||||||
Properties properties) throws ClassNotFoundException, IllegalArgumentException, SecurityException,
|
Properties properties) throws ClassNotFoundException, IllegalArgumentException, SecurityException,
|
||||||
InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
InstantiationException, IllegalAccessException, InvocationTargetException, NoSuchMethodException {
|
||||||
checkArgument(properties != null, "please configure properties for " + contextBuilderClass);
|
checkArgument(properties != null, "please configure properties for " + contextBuilderClass);
|
||||||
try {
|
try {
|
||||||
return (RestContextBuilder<S, A>) contextBuilderClass.getConstructor(Properties.class).newInstance(properties);
|
return (RestContextBuilder<S, A>) contextBuilderClass.getConstructor(Properties.class).newInstance(properties);
|
||||||
|
@ -415,14 +416,14 @@ public class Utils {
|
||||||
checkArgument(sync != null, "please configure sync class for " + contextBuilderClass);
|
checkArgument(sync != null, "please configure sync class for " + contextBuilderClass);
|
||||||
checkArgument(async != null, "please configure async class for " + contextBuilderClass);
|
checkArgument(async != null, "please configure async class for " + contextBuilderClass);
|
||||||
return (RestContextBuilder<S, A>) contextBuilderClass.getConstructor(sync.getClass(), async.getClass(),
|
return (RestContextBuilder<S, A>) contextBuilderClass.getConstructor(sync.getClass(), async.getClass(),
|
||||||
Properties.class).newInstance(sync, async, properties);
|
Properties.class).newInstance(sync, async, properties);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public static Class<PropertiesBuilder> resolvePropertiesBuilderClass(String providerName, Properties props)
|
public static Class<PropertiesBuilder> resolvePropertiesBuilderClass(String providerName, Properties props)
|
||||||
throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException,
|
throws ClassNotFoundException, InstantiationException, IllegalAccessException, InvocationTargetException,
|
||||||
NoSuchMethodException {
|
NoSuchMethodException {
|
||||||
String propertiesBuilderClassName = props.getProperty(providerName + ".propertiesbuilder", null);
|
String propertiesBuilderClassName = props.getProperty(providerName + ".propertiesbuilder", null);
|
||||||
if (propertiesBuilderClassName != null) {
|
if (propertiesBuilderClassName != null) {
|
||||||
return (Class<PropertiesBuilder>) Class.forName(propertiesBuilderClassName);
|
return (Class<PropertiesBuilder>) Class.forName(propertiesBuilderClassName);
|
||||||
|
@ -430,4 +431,37 @@ public class Utils {
|
||||||
return PropertiesBuilder.class;
|
return PropertiesBuilder.class;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static Iterable<Module> modulesForProviderInProperties(String providerName, Properties props) {
|
||||||
|
return concat(modulesFromProperty(props, "jclouds.modules"),
|
||||||
|
modulesFromProperty(props, providerName + ".modules"));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Iterable<Module> modulesFromProperty(Properties props, String property) {
|
||||||
|
return modulesFromCommaDelimitedString(props.getProperty(property, null));
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Iterable<Module> modulesFromCommaDelimitedString(String moduleClasses) {
|
||||||
|
Iterable<Module> modules = ImmutableSet.of();
|
||||||
|
if (moduleClasses != null) {
|
||||||
|
Iterable<String> transformer = ImmutableList.copyOf(on(',').split(moduleClasses));
|
||||||
|
modules = transform(transformer, new Function<String, Module>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Module apply(String from) {
|
||||||
|
try {
|
||||||
|
return (Module) Class.forName(from).newInstance();
|
||||||
|
} catch (InstantiationException e) {
|
||||||
|
throw new RuntimeException("error instantiating " + from, e);
|
||||||
|
} catch (IllegalAccessException e) {
|
||||||
|
throw new RuntimeException("error instantiating " + from, e);
|
||||||
|
} catch (ClassNotFoundException e) {
|
||||||
|
throw new RuntimeException("error instantiating " + from, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
return modules;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue