mirror of https://github.com/apache/jclouds.git
Issue 690:Update to guava 10.0rc2 and change from MapMaker to CacheBuilder
This commit is contained in:
parent
d039fe7d96
commit
4cd94489c9
|
@ -25,9 +25,6 @@ import static org.jclouds.tools.ant.taskdefs.compute.ComputeTaskUtils.ipOrEmptyS
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.apache.tools.ant.BuildException;
|
import org.apache.tools.ant.BuildException;
|
||||||
import org.apache.tools.ant.Project;
|
import org.apache.tools.ant.Project;
|
||||||
|
@ -43,10 +40,12 @@ import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.compute.predicates.NodePredicates;
|
import org.jclouds.compute.predicates.NodePredicates;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.http.HttpUtils;
|
import org.jclouds.http.HttpUtils;
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.util.CredentialUtils;
|
import org.jclouds.util.CredentialUtils;
|
||||||
|
|
||||||
import com.google.common.base.CaseFormat;
|
import com.google.common.base.CaseFormat;
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
|
||||||
|
@ -56,7 +55,7 @@ import com.google.inject.Provider;
|
||||||
*/
|
*/
|
||||||
public class ComputeTask extends Task {
|
public class ComputeTask extends Task {
|
||||||
|
|
||||||
private final Map<URI, ComputeServiceContext> computeMap;
|
private final Cache<URI, ComputeServiceContext> computeMap;
|
||||||
private String provider;
|
private String provider;
|
||||||
private String actions;
|
private String actions;
|
||||||
private NodeElement nodeElement;
|
private NodeElement nodeElement;
|
||||||
|
@ -72,7 +71,7 @@ public class ComputeTask extends Task {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public ComputeTask(@Nullable Map<URI, ComputeServiceContext> computeMap) {
|
public ComputeTask(@Nullable Cache<URI, ComputeServiceContext> computeMap) {
|
||||||
this.computeMap = computeMap != null ? computeMap : buildComputeMap(projectProvider);
|
this.computeMap = computeMap != null ? computeMap : buildComputeMap(projectProvider);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -88,7 +87,7 @@ public class ComputeTask extends Task {
|
||||||
* makes a connection to the compute service and invokes
|
* makes a connection to the compute service and invokes
|
||||||
*/
|
*/
|
||||||
public void execute() throws BuildException {
|
public void execute() throws BuildException {
|
||||||
ComputeServiceContext context = computeMap.get(HttpUtils.createUri(provider));
|
ComputeServiceContext context = computeMap.getUnchecked(HttpUtils.createUri(provider));
|
||||||
|
|
||||||
try {
|
try {
|
||||||
for (String action : Splitter.on(',').split(actions)) {
|
for (String action : Splitter.on(',').split(actions)) {
|
||||||
|
|
|
@ -22,7 +22,6 @@ import static org.jclouds.rest.RestContextFactory.getPropertiesFromResource;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Map;
|
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
@ -43,11 +42,12 @@ import org.jclouds.ssh.jsch.config.JschSshClientModule;
|
||||||
import org.jclouds.tools.ant.logging.config.AntLoggingModule;
|
import org.jclouds.tools.ant.logging.config.AntLoggingModule;
|
||||||
|
|
||||||
import com.google.common.base.Charsets;
|
import com.google.common.base.Charsets;
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.base.Splitter;
|
import com.google.common.base.Splitter;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.ImmutableSet;
|
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.io.Files;
|
import com.google.common.io.Files;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
@ -67,12 +67,12 @@ public class ComputeTaskUtils {
|
||||||
* allows access to the ant project to retrieve default properties needed for compute
|
* allows access to the ant project to retrieve default properties needed for compute
|
||||||
* providers.
|
* providers.
|
||||||
*/
|
*/
|
||||||
static Map<URI, ComputeServiceContext> buildComputeMap(final Provider<Project> projectProvider) {
|
static Cache<URI, ComputeServiceContext> buildComputeMap(final Provider<Project> projectProvider) {
|
||||||
return new MapMaker().makeComputingMap(new Function<URI, ComputeServiceContext>() {
|
return CacheBuilder.newBuilder().build(new CacheLoader<URI, ComputeServiceContext>() {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public ComputeServiceContext apply(URI from) {
|
public ComputeServiceContext load(URI from) {
|
||||||
Properties props = getPropertiesFromResource("/rest.properties");
|
Properties props = getPropertiesFromResource("/rest.properties");
|
||||||
props.putAll(projectProvider.get().getProperties());
|
props.putAll(projectProvider.get().getProperties());
|
||||||
// adding the properties to the factory will allow us to pass
|
// adding the properties to the factory will allow us to pass
|
||||||
|
|
|
@ -68,6 +68,7 @@ import com.google.common.annotations.VisibleForTesting;
|
||||||
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.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
import com.google.common.collect.ImmutableMultimap.Builder;
|
import com.google.common.collect.ImmutableMultimap.Builder;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
@ -78,8 +79,8 @@ import com.google.common.collect.ImmutableSet;
|
||||||
@Singleton
|
@Singleton
|
||||||
public class EC2ComputeService extends BaseComputeService {
|
public class EC2ComputeService extends BaseComputeService {
|
||||||
private final EC2Client ec2Client;
|
private final EC2Client ec2Client;
|
||||||
private final Map<RegionAndName, KeyPair> credentialsMap;
|
private final Cache<RegionAndName, KeyPair> credentialsMap;
|
||||||
private final Map<RegionAndName, String> securityGroupMap;
|
private final Cache<RegionAndName, String> securityGroupMap;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected EC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
|
protected EC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
|
||||||
|
@ -96,7 +97,7 @@ public class EC2ComputeService extends BaseComputeService {
|
||||||
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
|
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
|
||||||
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
|
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
|
||||||
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap) {
|
Cache<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Cache<RegionAndName, String> securityGroupMap) {
|
||||||
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
|
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
|
||||||
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy,
|
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy,
|
||||||
templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, nodeSuspended,
|
templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, nodeSuspended,
|
||||||
|
@ -116,7 +117,7 @@ public class EC2ComputeService extends BaseComputeService {
|
||||||
try {
|
try {
|
||||||
ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, groupName);
|
ec2Client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, groupName);
|
||||||
// TODO: test this clear happens
|
// TODO: test this clear happens
|
||||||
securityGroupMap.remove(new RegionNameAndIngressRules(region, groupName, null, false));
|
securityGroupMap.invalidate(new RegionNameAndIngressRules(region, groupName, null, false));
|
||||||
logger.debug("<< deleted securityGroup(%s)", groupName);
|
logger.debug("<< deleted securityGroup(%s)", groupName);
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
logger.debug("<< inUse securityGroup(%s)", groupName);
|
logger.debug("<< inUse securityGroup(%s)", groupName);
|
||||||
|
@ -142,7 +143,7 @@ public class EC2ComputeService extends BaseComputeService {
|
||||||
logger.debug(">> deleting keyPair(%s)", keyPair.getKeyName());
|
logger.debug(">> deleting keyPair(%s)", keyPair.getKeyName());
|
||||||
ec2Client.getKeyPairServices().deleteKeyPairInRegion(region, keyPair.getKeyName());
|
ec2Client.getKeyPairServices().deleteKeyPairInRegion(region, keyPair.getKeyName());
|
||||||
// TODO: test this clear happens
|
// TODO: test this clear happens
|
||||||
credentialsMap.remove(new RegionAndName(region, keyPair.getKeyName()));
|
credentialsMap.invalidate(new RegionAndName(region, keyPair.getKeyName()));
|
||||||
logger.debug("<< deleted keyPair(%s)", keyPair.getKeyName());
|
logger.debug("<< deleted keyPair(%s)", keyPair.getKeyName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -22,8 +22,6 @@ import static com.google.common.collect.Iterables.toArray;
|
||||||
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
|
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
|
||||||
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
|
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
@ -37,6 +35,7 @@ import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExc
|
||||||
|
|
||||||
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.cache.Cache;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -59,12 +58,12 @@ public class EC2ComputeServiceContextModule extends BaseComputeServiceContextMod
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Supplier<Map<RegionAndName, ? extends Image>> provideRegionAndNameToImageSupplierCache(
|
protected Supplier<Cache<RegionAndName, ? extends Image>> provideRegionAndNameToImageSupplierCache(
|
||||||
@Named(PROPERTY_SESSION_INTERVAL) long seconds, final RegionAndNameToImageSupplier supplier) {
|
@Named(PROPERTY_SESSION_INTERVAL) long seconds, final RegionAndNameToImageSupplier supplier) {
|
||||||
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Map<RegionAndName, ? extends Image>>(
|
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Cache<RegionAndName, ? extends Image>>(
|
||||||
authException, seconds, new Supplier<Map<RegionAndName, ? extends Image>>() {
|
authException, seconds, new Supplier<Cache<RegionAndName, ? extends Image>>() {
|
||||||
@Override
|
@Override
|
||||||
public Map<RegionAndName, ? extends Image> get() {
|
public Cache<RegionAndName, ? extends Image> get() {
|
||||||
return supplier.get();
|
return supplier.get();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.ec2.compute.config;
|
package org.jclouds.ec2.compute.config;
|
||||||
|
|
||||||
import static com.google.common.collect.Maps.newLinkedHashMap;
|
|
||||||
|
|
||||||
import java.security.SecureRandom;
|
import java.security.SecureRandom;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
|
@ -39,7 +37,6 @@ import org.jclouds.ec2.EC2AsyncClient;
|
||||||
import org.jclouds.ec2.EC2Client;
|
import org.jclouds.ec2.EC2Client;
|
||||||
import org.jclouds.ec2.compute.EC2ComputeService;
|
import org.jclouds.ec2.compute.EC2ComputeService;
|
||||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
|
|
||||||
import org.jclouds.ec2.compute.functions.CreateSecurityGroupIfNeeded;
|
import org.jclouds.ec2.compute.functions.CreateSecurityGroupIfNeeded;
|
||||||
import org.jclouds.ec2.compute.functions.CreateUniqueKeyPair;
|
import org.jclouds.ec2.compute.functions.CreateUniqueKeyPair;
|
||||||
import org.jclouds.ec2.compute.functions.CredentialsForInstance;
|
import org.jclouds.ec2.compute.functions.CredentialsForInstance;
|
||||||
|
@ -55,8 +52,11 @@ import org.jclouds.rest.internal.RestContextImpl;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.MapMaker;
|
import com.google.common.collect.Maps;
|
||||||
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;
|
||||||
|
@ -69,11 +69,11 @@ import com.google.inject.TypeLiteral;
|
||||||
public class EC2ComputeServiceDependenciesModule extends AbstractModule {
|
public class EC2ComputeServiceDependenciesModule extends AbstractModule {
|
||||||
|
|
||||||
public static final Map<InstanceState, NodeState> instanceToNodeState = ImmutableMap
|
public static final Map<InstanceState, NodeState> instanceToNodeState = ImmutableMap
|
||||||
.<InstanceState, NodeState> builder().put(InstanceState.PENDING, NodeState.PENDING).put(
|
.<InstanceState, NodeState> builder().put(InstanceState.PENDING, NodeState.PENDING)
|
||||||
InstanceState.RUNNING, NodeState.RUNNING).put(InstanceState.SHUTTING_DOWN, NodeState.PENDING).put(
|
.put(InstanceState.RUNNING, NodeState.RUNNING).put(InstanceState.SHUTTING_DOWN, NodeState.PENDING)
|
||||||
InstanceState.TERMINATED, NodeState.TERMINATED).put(InstanceState.STOPPING, NodeState.PENDING)
|
.put(InstanceState.TERMINATED, NodeState.TERMINATED).put(InstanceState.STOPPING, NodeState.PENDING)
|
||||||
.put(InstanceState.STOPPED, NodeState.SUSPENDED).put(InstanceState.UNRECOGNIZED, NodeState.UNRECOGNIZED)
|
.put(InstanceState.STOPPED, NodeState.SUSPENDED).put(InstanceState.UNRECOGNIZED, NodeState.UNRECOGNIZED)
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
@Provides
|
@Provides
|
||||||
|
@ -88,13 +88,13 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
|
||||||
bind(ComputeService.class).to(EC2ComputeService.class);
|
bind(ComputeService.class).to(EC2ComputeService.class);
|
||||||
bind(new TypeLiteral<Function<RunningInstance, NodeMetadata>>() {
|
bind(new TypeLiteral<Function<RunningInstance, NodeMetadata>>() {
|
||||||
}).to(RunningInstanceToNodeMetadata.class);
|
}).to(RunningInstanceToNodeMetadata.class);
|
||||||
bind(new TypeLiteral<Function<RunningInstance, Credentials>>() {
|
bind(new TypeLiteral<CacheLoader<RunningInstance, Credentials>>() {
|
||||||
}).to(CredentialsForInstance.class);
|
}).to(CredentialsForInstance.class);
|
||||||
bind(new TypeLiteral<Function<RegionNameAndIngressRules, String>>() {
|
bind(new TypeLiteral<CacheLoader<RegionAndName, String>>() {
|
||||||
}).to(CreateSecurityGroupIfNeeded.class);
|
}).to(CreateSecurityGroupIfNeeded.class);
|
||||||
bind(new TypeLiteral<Function<RegionAndName, KeyPair>>() {
|
bind(new TypeLiteral<CacheLoader<RegionAndName, KeyPair>>() {
|
||||||
}).to(CreateUniqueKeyPair.class);
|
}).to(CreateUniqueKeyPair.class);
|
||||||
bind(new TypeLiteral<Function<RegionAndName, Image>>() {
|
bind(new TypeLiteral<CacheLoader<RegionAndName, Image>>() {
|
||||||
}).to(RegionAndIdToImage.class);
|
}).to(RegionAndIdToImage.class);
|
||||||
bind(new TypeLiteral<ComputeServiceContext>() {
|
bind(new TypeLiteral<ComputeServiceContext>() {
|
||||||
}).to(new TypeLiteral<ComputeServiceContextImpl<EC2Client, EC2AsyncClient>>() {
|
}).to(new TypeLiteral<ComputeServiceContextImpl<EC2Client, EC2AsyncClient>>() {
|
||||||
|
@ -120,25 +120,35 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected final Map<RegionAndName, KeyPair> credentialsMap(Function<RegionAndName, KeyPair> in) {
|
protected Cache<RunningInstance, Credentials> credentialsMap(CacheLoader<RunningInstance, Credentials> in) {
|
||||||
// doesn't seem to clear when someone issues remove(key)
|
return CacheBuilder.newBuilder().build(in);
|
||||||
// return new MapMaker().makeComputingMap(in);
|
|
||||||
return newLinkedHashMap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@Named("SECURITY")
|
protected Cache<RegionAndName, KeyPair> keypairMap(CacheLoader<RegionAndName, KeyPair> in) {
|
||||||
protected final Map<RegionAndName, String> securityGroupMap(Function<RegionNameAndIngressRules, String> in) {
|
return CacheBuilder.newBuilder().build(in);
|
||||||
// doesn't seem to clear when someone issues remove(key)
|
|
||||||
// return new MapMaker().makeComputingMap(in);
|
|
||||||
return newLinkedHashMap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Map<RegionAndName, Image> provideImageMap(Function<RegionAndName, Image> regionAndIdToImage) {
|
// keys that we know about.
|
||||||
return new MapMaker().makeComputingMap(regionAndIdToImage);
|
protected Map<RegionAndName, KeyPair> knownKeys(){
|
||||||
|
return Maps.newConcurrentMap();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
@Named("SECURITY")
|
||||||
|
protected Cache<RegionAndName, String> securityGroupMap(CacheLoader<RegionAndName, String> in) {
|
||||||
|
return CacheBuilder.newBuilder().build(in);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
// keys that we know about.
|
||||||
|
protected Map<RegionAndName, Image> knownImages(){
|
||||||
|
return Maps.newConcurrentMap();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,14 +25,15 @@ import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.ec2.EC2Client;
|
import org.jclouds.ec2.EC2Client;
|
||||||
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
|
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
|
||||||
import org.jclouds.ec2.domain.IpProtocol;
|
import org.jclouds.ec2.domain.IpProtocol;
|
||||||
import org.jclouds.ec2.domain.UserIdGroupPair;
|
import org.jclouds.ec2.domain.UserIdGroupPair;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,7 +41,7 @@ import com.google.common.collect.Iterables;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class CreateSecurityGroupIfNeeded implements Function<RegionNameAndIngressRules, String> {
|
public class CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndName, String> {
|
||||||
@Resource
|
@Resource
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
@ -52,8 +53,9 @@ public class CreateSecurityGroupIfNeeded implements Function<RegionNameAndIngres
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String apply(RegionNameAndIngressRules from) {
|
public String load(RegionAndName from) {
|
||||||
createSecurityGroupInRegion(from.getRegion(), from.getName(), from.getPorts());
|
RegionNameAndIngressRules realFrom = RegionNameAndIngressRules.class.cast(from);
|
||||||
|
createSecurityGroupInRegion(from.getRegion(), from.getName(), realFrom.getPorts());
|
||||||
return from.getName();
|
return from.getName();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,6 +20,8 @@ package org.jclouds.ec2.compute.functions;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
@ -32,30 +34,33 @@ import org.jclouds.ec2.domain.KeyPair;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class CreateUniqueKeyPair implements Function<RegionAndName, KeyPair> {
|
public class CreateUniqueKeyPair extends CacheLoader<RegionAndName, KeyPair> {
|
||||||
@Resource
|
@Resource
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
protected final EC2Client ec2Client;
|
protected final EC2Client ec2Client;
|
||||||
protected final Supplier<String> randomSuffix;
|
protected final Supplier<String> randomSuffix;
|
||||||
|
protected final Map<RegionAndName, KeyPair> knownKeys;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public CreateUniqueKeyPair(EC2Client ec2Client, Supplier<String> randomSuffix) {
|
public CreateUniqueKeyPair(Map<RegionAndName, KeyPair> knownKeys, EC2Client ec2Client, Supplier<String> randomSuffix) {
|
||||||
|
this.knownKeys = knownKeys;
|
||||||
this.ec2Client = ec2Client;
|
this.ec2Client = ec2Client;
|
||||||
this.randomSuffix = randomSuffix;
|
this.randomSuffix = randomSuffix;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public KeyPair apply(RegionAndName from) {
|
public KeyPair load(RegionAndName from) {
|
||||||
return createNewKeyPairInRegion(from.getRegion(), from.getName());
|
return knownKeys.containsKey(from) ? knownKeys.get(from) : createNewKeyPairInRegion(from.getRegion(),
|
||||||
|
from.getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
|
|
@ -20,43 +20,44 @@ package org.jclouds.ec2.compute.functions;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
|
||||||
import org.jclouds.ec2.domain.KeyPair;
|
|
||||||
import org.jclouds.ec2.domain.RunningInstance;
|
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
|
import org.jclouds.compute.strategy.PopulateDefaultLoginCredentialsForImageStrategy;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
|
import org.jclouds.ec2.domain.KeyPair;
|
||||||
|
import org.jclouds.ec2.domain.RunningInstance;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class CredentialsForInstance implements Function<RunningInstance, Credentials> {
|
public class CredentialsForInstance extends CacheLoader<RunningInstance, Credentials> {
|
||||||
private final Map<RegionAndName, KeyPair> credentialsMap;
|
private final Cache<RegionAndName, KeyPair> credentialsMap;
|
||||||
private final PopulateDefaultLoginCredentialsForImageStrategy credentialProvider;
|
private final PopulateDefaultLoginCredentialsForImageStrategy credentialProvider;
|
||||||
private final Map<RegionAndName, Image> imageForInstance;
|
private final Supplier<Cache<RegionAndName, ? extends Image>> imageMap;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
CredentialsForInstance(Map<RegionAndName, KeyPair> credentialsMap,
|
CredentialsForInstance(Cache<RegionAndName, KeyPair> credentialsMap,
|
||||||
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider, Map<RegionAndName, Image> imageForInstance) {
|
PopulateDefaultLoginCredentialsForImageStrategy credentialProvider, Supplier<Cache<RegionAndName, ? extends Image>> imageMap) {
|
||||||
this.credentialsMap = checkNotNull(credentialsMap, "credentialsMap");
|
this.credentialsMap = checkNotNull(credentialsMap, "credentialsMap");
|
||||||
this.credentialProvider = checkNotNull(credentialProvider, "credentialProvider");
|
this.credentialProvider = checkNotNull(credentialProvider, "credentialProvider");
|
||||||
this.imageForInstance = imageForInstance;
|
this.imageMap = imageMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Credentials apply(RunningInstance instance) {
|
public Credentials load(RunningInstance instance) throws ExecutionException {
|
||||||
Credentials credentials = null;// default if no keypair exists
|
Credentials credentials = null;// default if no keypair exists
|
||||||
|
|
||||||
if (instance.getKeyName() != null) {
|
if (instance.getKeyName() != null) {
|
||||||
credentials = new Credentials(getLoginAccountFor(instance), getPrivateKeyOrNull(instance));
|
credentials = new Credentials(getLoginAccountFor(instance), getPrivateKeyOrNull(instance));
|
||||||
}
|
}
|
||||||
|
@ -64,15 +65,15 @@ public class CredentialsForInstance implements Function<RunningInstance, Credent
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
String getPrivateKeyOrNull(RunningInstance instance) {
|
String getPrivateKeyOrNull(RunningInstance instance) throws ExecutionException {
|
||||||
KeyPair keyPair = credentialsMap.get(new RegionAndName(instance.getRegion(), instance.getKeyName()));
|
KeyPair keyPair = credentialsMap.get(new RegionAndName(instance.getRegion(), instance.getKeyName()));
|
||||||
return keyPair != null ? keyPair.getKeyMaterial() : null;
|
return keyPair != null ? keyPair.getKeyMaterial() : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
String getLoginAccountFor(RunningInstance from) {
|
String getLoginAccountFor(RunningInstance from) throws ExecutionException {
|
||||||
return checkNotNull(
|
return checkNotNull(
|
||||||
credentialProvider.execute(imageForInstance.get(new RegionAndName(from.getRegion(), from.getImageId()))),
|
credentialProvider.execute(imageMap.get().get(new RegionAndName(from.getRegion(), from.getImageId()))),
|
||||||
"login from image: " + from.getImageId()).identity;
|
"login from image: " + from.getImageId()).identity;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -20,19 +20,19 @@ package org.jclouds.ec2.compute.functions;
|
||||||
|
|
||||||
import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.imageIds;
|
import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.imageIds;
|
||||||
|
|
||||||
import java.util.NoSuchElementException;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.ec2.EC2Client;
|
import org.jclouds.ec2.EC2Client;
|
||||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
import org.jclouds.compute.domain.Image;
|
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.ResourceNotFoundException;
|
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -40,33 +40,31 @@ import com.google.common.collect.Iterables;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public final class RegionAndIdToImage implements Function<RegionAndName, Image> {
|
public class RegionAndIdToImage extends CacheLoader<RegionAndName, Image> {
|
||||||
@Resource
|
@Resource
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
private final Map<RegionAndName, Image> knownImages;
|
||||||
private final EC2ImageParser parser;
|
private final EC2ImageParser parser;
|
||||||
private final EC2Client sync;
|
private final EC2Client sync;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public RegionAndIdToImage(EC2ImageParser parser, EC2Client sync) {
|
public RegionAndIdToImage(Map<RegionAndName, Image> knownImages, EC2ImageParser parser, EC2Client sync) {
|
||||||
|
this.knownImages = knownImages;
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
this.sync = sync;
|
this.sync = sync;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Image apply(RegionAndName key) {
|
@Override
|
||||||
|
public Image load(RegionAndName key) throws ExecutionException{
|
||||||
|
if (knownImages.containsKey(key))
|
||||||
|
return knownImages.get(key);
|
||||||
try {
|
try {
|
||||||
org.jclouds.ec2.domain.Image image = Iterables.getOnlyElement(sync.getAMIServices()
|
org.jclouds.ec2.domain.Image image = Iterables.getOnlyElement(sync.getAMIServices()
|
||||||
.describeImagesInRegion(key.getRegion(), imageIds(key.getName())));
|
.describeImagesInRegion(key.getRegion(), imageIds(key.getName())));
|
||||||
return parser.apply(image);
|
return parser.apply(image);
|
||||||
} catch (NoSuchElementException e) {
|
|
||||||
logger.debug(message(key, e));
|
|
||||||
return null;
|
|
||||||
} catch (ResourceNotFoundException e) {
|
|
||||||
logger.debug(message(key, e));
|
|
||||||
return null;
|
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logger.warn(e, message(key, e));
|
throw new ExecutionException(message(key, e), e);
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -30,11 +30,6 @@ import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
|
||||||
import org.jclouds.ec2.domain.BlockDevice;
|
|
||||||
import org.jclouds.ec2.domain.InstanceState;
|
|
||||||
import org.jclouds.ec2.domain.RootDeviceType;
|
|
||||||
import org.jclouds.ec2.domain.RunningInstance;
|
|
||||||
import org.jclouds.collect.Memoized;
|
import org.jclouds.collect.Memoized;
|
||||||
import org.jclouds.compute.domain.Hardware;
|
import org.jclouds.compute.domain.Hardware;
|
||||||
import org.jclouds.compute.domain.HardwareBuilder;
|
import org.jclouds.compute.domain.HardwareBuilder;
|
||||||
|
@ -46,6 +41,11 @@ import org.jclouds.compute.domain.Volume;
|
||||||
import org.jclouds.compute.domain.internal.VolumeImpl;
|
import org.jclouds.compute.domain.internal.VolumeImpl;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
|
import org.jclouds.ec2.domain.BlockDevice;
|
||||||
|
import org.jclouds.ec2.domain.InstanceState;
|
||||||
|
import org.jclouds.ec2.domain.RootDeviceType;
|
||||||
|
import org.jclouds.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.util.NullSafeCollections;
|
import org.jclouds.util.NullSafeCollections;
|
||||||
|
|
||||||
|
@ -53,8 +53,10 @@ import com.google.common.annotations.VisibleForTesting;
|
||||||
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.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
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.util.concurrent.UncheckedExecutionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -67,17 +69,17 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
|
||||||
|
|
||||||
protected final Supplier<Set<? extends Location>> locations;
|
protected final Supplier<Set<? extends Location>> locations;
|
||||||
protected final Supplier<Set<? extends Hardware>> hardware;
|
protected final Supplier<Set<? extends Hardware>> hardware;
|
||||||
protected final Map<RegionAndName, Image> instanceToImage;
|
protected final Supplier<Cache<RegionAndName, ? extends Image>> imageMap;
|
||||||
protected final Map<String, Credentials> credentialStore;
|
protected final Map<String, Credentials> credentialStore;
|
||||||
protected final Map<InstanceState, NodeState> instanceToNodeState;
|
protected final Map<InstanceState, NodeState> instanceToNodeState;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected RunningInstanceToNodeMetadata(Map<InstanceState, NodeState> instanceToNodeState,
|
protected RunningInstanceToNodeMetadata(Map<InstanceState, NodeState> instanceToNodeState,
|
||||||
Map<String, Credentials> credentialStore, Map<RegionAndName, Image> instanceToImage,
|
Map<String, Credentials> credentialStore, Supplier<Cache<RegionAndName, ? extends Image>> imageMap,
|
||||||
@Memoized Supplier<Set<? extends Location>> locations, @Memoized Supplier<Set<? extends Hardware>> hardware) {
|
@Memoized Supplier<Set<? extends Location>> locations, @Memoized Supplier<Set<? extends Hardware>> hardware) {
|
||||||
this.locations = checkNotNull(locations, "locations");
|
this.locations = checkNotNull(locations, "locations");
|
||||||
this.hardware = checkNotNull(hardware, "hardware");
|
this.hardware = checkNotNull(hardware, "hardware");
|
||||||
this.instanceToImage = checkNotNull(instanceToImage, "instanceToImage");
|
this.imageMap = checkNotNull(imageMap, "imageMap");
|
||||||
this.instanceToNodeState = checkNotNull(instanceToNodeState, "instanceToNodeState");
|
this.instanceToNodeState = checkNotNull(instanceToNodeState, "instanceToNodeState");
|
||||||
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
|
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
|
||||||
}
|
}
|
||||||
|
@ -106,17 +108,13 @@ public class RunningInstanceToNodeMetadata implements Function<RunningInstance,
|
||||||
// extract the operating system from the image
|
// extract the operating system from the image
|
||||||
RegionAndName regionAndName = new RegionAndName(instance.getRegion(), instance.getImageId());
|
RegionAndName regionAndName = new RegionAndName(instance.getRegion(), instance.getImageId());
|
||||||
try {
|
try {
|
||||||
Image image = instanceToImage.get(regionAndName);
|
Image image = imageMap.get().getUnchecked(regionAndName);
|
||||||
if (image != null)
|
if (image != null)
|
||||||
builder.operatingSystem(image.getOperatingSystem());
|
builder.operatingSystem(image.getOperatingSystem());
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
// The instanceToImage Map may throw NullPointerException (actually subclass
|
logger.debug("image not found for %s: %s", regionAndName, e);
|
||||||
// NullOutputException) if the
|
} catch (UncheckedExecutionException e) {
|
||||||
// computing Function returns a null value.
|
logger.debug("error getting image for %s: %s", regionAndName, e);
|
||||||
//
|
|
||||||
// See the following for more information:
|
|
||||||
// MapMaker.makeComputingMap()
|
|
||||||
// RegionAndIdToImage.apply()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return builder.build();
|
return builder.build();
|
||||||
|
|
|
@ -20,9 +20,9 @@ package org.jclouds.ec2.compute.internal;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkArgument;
|
import static com.google.common.base.Preconditions.checkArgument;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
@ -38,7 +38,8 @@ import org.jclouds.domain.Location;
|
||||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.collect.ComputationException;
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -46,13 +47,13 @@ import com.google.common.collect.ComputationException;
|
||||||
*/
|
*/
|
||||||
public class EC2TemplateBuilderImpl extends TemplateBuilderImpl {
|
public class EC2TemplateBuilderImpl extends TemplateBuilderImpl {
|
||||||
|
|
||||||
private final Map<RegionAndName, Image> imageMap;
|
private final Supplier<Cache<RegionAndName, ? extends Image>> imageMap;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected EC2TemplateBuilderImpl(@Memoized Supplier<Set<? extends Location>> locations,
|
protected EC2TemplateBuilderImpl(@Memoized Supplier<Set<? extends Location>> locations,
|
||||||
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
|
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
|
||||||
Supplier<Location> defaultLocation, @Named("DEFAULT") Provider<TemplateOptions> optionsProvider,
|
Supplier<Location> defaultLocation, @Named("DEFAULT") Provider<TemplateOptions> optionsProvider,
|
||||||
@Named("DEFAULT") Provider<TemplateBuilder> defaultTemplateProvider, Map<RegionAndName, Image> imageMap) {
|
@Named("DEFAULT") Provider<TemplateBuilder> defaultTemplateProvider, Supplier<Cache<RegionAndName, ? extends Image>> imageMap) {
|
||||||
super(locations, images, sizes, defaultLocation, optionsProvider, defaultTemplateProvider);
|
super(locations, images, sizes, defaultLocation, optionsProvider, defaultTemplateProvider);
|
||||||
this.imageMap = imageMap;
|
this.imageMap = imageMap;
|
||||||
}
|
}
|
||||||
|
@ -67,11 +68,13 @@ public class EC2TemplateBuilderImpl extends TemplateBuilderImpl {
|
||||||
"amazon image ids must include the region ( ex. us-east-1/ami-7ea24a17 ) you specified: " + imageId);
|
"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().get(key);
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
throw new NoSuchElementException(String.format("could not get imageId(%s/%s)", key.getRegion(), key.getName()));
|
||||||
|
} catch (UncheckedExecutionException e) {
|
||||||
|
throw new NoSuchElementException(String.format("could not get imageId(%s/%s)", key.getRegion(), key.getName()));
|
||||||
} catch (NullPointerException nex) {
|
} catch (NullPointerException nex) {
|
||||||
throw new NoSuchElementException(String.format("imageId(%s/%s) not found", key.getRegion(), key.getName()));
|
throw new NoSuchElementException(String.format("imageId(%s/%s) not found", key.getRegion(), key.getName()));
|
||||||
} catch (ComputationException nex) {
|
|
||||||
throw new NoSuchElementException(String.format("imageId(%s/%s) not found", key.getRegion(), key.getName()));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
|
|
|
@ -23,7 +23,6 @@ import static com.google.common.base.Preconditions.checkState;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
|
@ -37,11 +36,13 @@ import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
||||||
import org.jclouds.ec2.domain.BlockDeviceMapping;
|
import org.jclouds.ec2.domain.BlockDeviceMapping;
|
||||||
import org.jclouds.ec2.domain.KeyPair;
|
import org.jclouds.ec2.domain.KeyPair;
|
||||||
import org.jclouds.ec2.options.RunInstancesOptions;
|
import org.jclouds.ec2.options.RunInstancesOptions;
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.ImmutableSet.Builder;
|
import com.google.common.collect.ImmutableSet.Builder;
|
||||||
|
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -49,26 +50,21 @@ import com.google.common.collect.ImmutableSet.Builder;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
|
public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public final Map<RegionAndName, KeyPair> credentialsMap;
|
public final Map<RegionAndName, KeyPair> knownKeys;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public final Map<RegionAndName, String> securityGroupMap;
|
public final Cache<RegionAndName, KeyPair> credentialsMap;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public final Function<RegionAndName, KeyPair> createUniqueKeyPair;
|
public final Cache<RegionAndName, String> securityGroupMap;
|
||||||
@VisibleForTesting
|
|
||||||
public final Function<RegionNameAndIngressRules, String> createSecurityGroupIfNeeded;
|
|
||||||
protected final Provider<RunInstancesOptions> optionsProvider;
|
protected final Provider<RunInstancesOptions> optionsProvider;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions(Map<RegionAndName, KeyPair> credentialsMap,
|
public CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions(Map<RegionAndName, KeyPair> knownKeys, Cache<RegionAndName, KeyPair> credentialsMap,
|
||||||
@Named("SECURITY") Map<RegionAndName, String> securityGroupMap, Function<RegionAndName, KeyPair> createUniqueKeyPair,
|
@Named("SECURITY") Cache<RegionAndName, String> securityGroupMap,
|
||||||
Function<RegionNameAndIngressRules, String> createSecurityGroupIfNeeded,
|
|
||||||
Provider<RunInstancesOptions> optionsProvider) {
|
Provider<RunInstancesOptions> optionsProvider) {
|
||||||
|
this.knownKeys=knownKeys;
|
||||||
this.credentialsMap = credentialsMap;
|
this.credentialsMap = credentialsMap;
|
||||||
this.securityGroupMap = securityGroupMap;
|
this.securityGroupMap = securityGroupMap;
|
||||||
this.createUniqueKeyPair = createUniqueKeyPair;
|
|
||||||
this.createSecurityGroupIfNeeded = createSecurityGroupIfNeeded;
|
|
||||||
this.optionsProvider = optionsProvider;
|
this.optionsProvider = optionsProvider;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -123,40 +119,32 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
|
||||||
if (options.getOverridingCredentials() != null && options.getOverridingCredentials().credential != null) {
|
if (options.getOverridingCredentials() != null && options.getOverridingCredentials().credential != null) {
|
||||||
KeyPair keyPair = KeyPair.builder().region(region).keyName(keyPairName).keyFingerprint("//TODO")
|
KeyPair keyPair = KeyPair.builder().region(region).keyName(keyPairName).keyFingerprint("//TODO")
|
||||||
.keyMaterial(options.getOverridingCredentials().credential).build();
|
.keyMaterial(options.getOverridingCredentials().credential).build();
|
||||||
putKeyPairIntoCredentialMap(keyPair);
|
|
||||||
|
RegionAndName key = new RegionAndName(region, group);
|
||||||
|
knownKeys.put(key, keyPair);
|
||||||
|
credentialsMap.invalidate(key);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (options.getRunScript() != null) {
|
if (options.getRunScript() != null) {
|
||||||
RegionAndName regionAndName = new RegionAndName(region, keyPairName);
|
RegionAndName regionAndName = new RegionAndName(region, keyPairName);
|
||||||
checkState(credentialsMap.containsKey(regionAndName),
|
String message = String.format("no private key configured for: %s; please use options.overrideLoginCredentialWith(rsa_private_text)",
|
||||||
"no private key configured for: %s; please use options.overrideLoginCredentialWith(rsa_private_text)",
|
regionAndName);
|
||||||
regionAndName);
|
// test to see if this is in cache.
|
||||||
|
try {
|
||||||
|
credentialsMap.getUnchecked(regionAndName);
|
||||||
|
} catch (NullPointerException nex) {
|
||||||
|
throw new IllegalArgumentException(message, nex);
|
||||||
|
} catch (UncheckedExecutionException nex) {
|
||||||
|
throw new IllegalArgumentException(message, nex);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return keyPairName;
|
return keyPairName;
|
||||||
}
|
}
|
||||||
|
|
||||||
// base EC2 driver currently does not support key import
|
// base EC2 driver currently does not support key import
|
||||||
protected String createOrImportKeyPair(String region, String group, TemplateOptions options) {
|
protected String createOrImportKeyPair(String region, String group, TemplateOptions options) {
|
||||||
return createUniqueKeyPairAndPutIntoMap(region, group);
|
return credentialsMap.getUnchecked(new RegionAndName(region, group)).getKeyName();
|
||||||
}
|
|
||||||
|
|
||||||
protected String createUniqueKeyPairAndPutIntoMap(String region, String group) {
|
|
||||||
RegionAndName regionAndName = new RegionAndName(region, group);
|
|
||||||
KeyPair keyPair = createUniqueKeyPair.apply(regionAndName);
|
|
||||||
putKeyPairIntoCredentialMap(keyPair);
|
|
||||||
return keyPair.getKeyName();
|
|
||||||
}
|
|
||||||
|
|
||||||
protected void putKeyPairIntoCredentialMap(KeyPair keyPair) {
|
|
||||||
// get or create incidental resources
|
|
||||||
// TODO race condition. we were using MapMaker, but it doesn't seem to
|
|
||||||
// refresh properly
|
|
||||||
// when
|
|
||||||
// another thread
|
|
||||||
// deletes a key
|
|
||||||
credentialsMap.put(new RegionAndName(keyPair.getRegion(), keyPair.getKeyName()), keyPair);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
|
@ -177,11 +165,8 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
|
||||||
regionNameAndIngessRulesForMarkerGroup = new RegionNameAndIngressRules(region, markerGroup,
|
regionNameAndIngessRulesForMarkerGroup = new RegionNameAndIngressRules(region, markerGroup,
|
||||||
options.getInboundPorts(), true);
|
options.getInboundPorts(), true);
|
||||||
}
|
}
|
||||||
|
// this will create if not yet exists.
|
||||||
if (!securityGroupMap.containsKey(regionNameAndIngessRulesForMarkerGroup)) {
|
securityGroupMap.getUnchecked(regionNameAndIngessRulesForMarkerGroup);
|
||||||
securityGroupMap.put(regionNameAndIngessRulesForMarkerGroup,
|
|
||||||
createSecurityGroupIfNeeded.apply(regionNameAndIngessRulesForMarkerGroup));
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return groups.build();
|
return groups.build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,6 +52,7 @@ import org.jclouds.logging.Logger;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
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.cache.Cache;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
@ -77,7 +78,7 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final ComputeUtils utils;
|
final ComputeUtils utils;
|
||||||
final InstancePresent instancePresent;
|
final InstancePresent instancePresent;
|
||||||
final Function<RunningInstance, Credentials> instanceToCredentials;
|
final Cache<RunningInstance, Credentials> instanceToCredentials;
|
||||||
final Map<String, Credentials> credentialStore;
|
final Map<String, Credentials> credentialStore;
|
||||||
final Provider<TemplateBuilder> templateBuilderProvider;
|
final Provider<TemplateBuilder> templateBuilderProvider;
|
||||||
|
|
||||||
|
@ -87,7 +88,7 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
|
||||||
Provider<TemplateBuilder> templateBuilderProvider,
|
Provider<TemplateBuilder> templateBuilderProvider,
|
||||||
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
||||||
InstancePresent instancePresent, Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
|
InstancePresent instancePresent, Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
|
||||||
Function<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore,
|
Cache<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore,
|
||||||
ComputeUtils utils) {
|
ComputeUtils utils) {
|
||||||
this.client = checkNotNull(client, "client");
|
this.client = checkNotNull(client, "client");
|
||||||
this.templateBuilderProvider = checkNotNull(templateBuilderProvider, "templateBuilderProvider");
|
this.templateBuilderProvider = checkNotNull(templateBuilderProvider, "templateBuilderProvider");
|
||||||
|
|
|
@ -18,16 +18,16 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.ec2.compute.suppliers;
|
package org.jclouds.ec2.compute.suppliers;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -36,16 +36,16 @@ import com.google.common.collect.Sets;
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class EC2ImageSupplier implements Supplier<Set<? extends Image>> {
|
public class EC2ImageSupplier implements Supplier<Set<? extends Image>> {
|
||||||
private final Supplier<Map<RegionAndName, ? extends Image>> map;
|
private final Supplier<Cache<RegionAndName, ? extends Image>> map;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
EC2ImageSupplier(Supplier<Map<RegionAndName, ? extends Image>> map) {
|
EC2ImageSupplier(Supplier<Cache<RegionAndName, ? extends Image>> map) {
|
||||||
this.map = map;
|
this.map = map;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<? extends Image> get() {
|
public Set<? extends Image> get() {
|
||||||
return Sets.newLinkedHashSet(map.get().values());
|
return Sets.newLinkedHashSet(map.get().asMap().values());
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -25,8 +25,8 @@ import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.ownedBy;
|
||||||
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
|
import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_AMI_OWNERS;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -45,16 +45,19 @@ import org.jclouds.logging.Logger;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.collect.ImmutableMap.Builder;
|
import com.google.common.collect.ImmutableMap.Builder;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class RegionAndNameToImageSupplier implements Supplier<Map<RegionAndName, ? extends Image>> {
|
public class RegionAndNameToImageSupplier implements Supplier<Cache<RegionAndName, ? extends Image>> {
|
||||||
@Resource
|
@Resource
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
@ -63,20 +66,23 @@ public class RegionAndNameToImageSupplier implements Supplier<Map<RegionAndName,
|
||||||
private final DescribeImagesParallel describer;
|
private final DescribeImagesParallel describer;
|
||||||
private final String[] amiOwners;
|
private final String[] amiOwners;
|
||||||
private final EC2ImageParser parser;
|
private final EC2ImageParser parser;
|
||||||
private final Map<RegionAndName, Image> images;
|
private final Map<RegionAndName, Image> knownImages;
|
||||||
|
private final CacheLoader<RegionAndName, Image> regionAndIdToImage;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected RegionAndNameToImageSupplier(@Region Set<String> regions, DescribeImagesParallel describer,
|
protected RegionAndNameToImageSupplier(@Region Set<String> regions, DescribeImagesParallel describer,
|
||||||
@Named(PROPERTY_EC2_AMI_OWNERS) String[] amiOwners, EC2ImageParser parser, Map<RegionAndName, Image> images) {
|
@Named(PROPERTY_EC2_AMI_OWNERS) String[] amiOwners, EC2ImageParser parser,
|
||||||
|
Map<RegionAndName, Image> knownImages, CacheLoader<RegionAndName, Image> regionAndIdToImage) {
|
||||||
this.regions = regions;
|
this.regions = regions;
|
||||||
this.describer = describer;
|
this.describer = describer;
|
||||||
this.amiOwners = amiOwners;
|
this.amiOwners = amiOwners;
|
||||||
this.parser = parser;
|
this.parser = parser;
|
||||||
this.images = images;
|
this.knownImages = knownImages;
|
||||||
|
this.regionAndIdToImage = regionAndIdToImage;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<RegionAndName, ? extends Image> get() {
|
public Cache<RegionAndName, ? extends Image> get() {
|
||||||
if (amiOwners.length == 0) {
|
if (amiOwners.length == 0) {
|
||||||
logger.debug(">> no owners specified, skipping image parsing");
|
logger.debug(">> no owners specified, skipping image parsing");
|
||||||
} else {
|
} else {
|
||||||
|
@ -87,8 +93,8 @@ public class RegionAndNameToImageSupplier implements Supplier<Map<RegionAndName,
|
||||||
|
|
||||||
Iterable<? extends Image> parsedImages = ImmutableSet.copyOf(filter(transform(describer.apply(queries), parser), Predicates
|
Iterable<? extends Image> parsedImages = ImmutableSet.copyOf(filter(transform(describer.apply(queries), parser), Predicates
|
||||||
.notNull()));
|
.notNull()));
|
||||||
|
knownImages.clear();
|
||||||
images.putAll(uniqueIndex(parsedImages, new Function<Image, RegionAndName>() {
|
knownImages.putAll(uniqueIndex(parsedImages, new Function<Image, RegionAndName>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RegionAndName apply(Image from) {
|
public RegionAndName apply(Image from) {
|
||||||
|
@ -96,14 +102,18 @@ public class RegionAndNameToImageSupplier implements Supplier<Map<RegionAndName,
|
||||||
}
|
}
|
||||||
|
|
||||||
}));
|
}));
|
||||||
|
logger.debug("<< images(%d)", knownImages.size());
|
||||||
logger.debug("<< images(%d)", images.size());
|
|
||||||
}
|
}
|
||||||
return images;
|
Cache<RegionAndName, Image> cache = CacheBuilder.newBuilder().build(regionAndIdToImage);
|
||||||
|
// seed the cache
|
||||||
|
for (RegionAndName image : knownImages.keySet()) {
|
||||||
|
cache.getUnchecked(image);
|
||||||
|
}
|
||||||
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Iterable<Entry<String, DescribeImagesOptions>> getDescribeQueriesForOwnersInRegions(Set<String> regions,
|
public Iterable<Entry<String, DescribeImagesOptions>> getDescribeQueriesForOwnersInRegions(Set<String> regions,
|
||||||
String[] amiOwners) {
|
String[] amiOwners) {
|
||||||
DescribeImagesOptions options = getOptionsForOwners(amiOwners);
|
DescribeImagesOptions options = getOptionsForOwners(amiOwners);
|
||||||
Builder<String, DescribeImagesOptions> builder = ImmutableMap.<String, DescribeImagesOptions> builder();
|
Builder<String, DescribeImagesOptions> builder = ImmutableMap.<String, DescribeImagesOptions> builder();
|
||||||
for (String region : regions)
|
for (String region : regions)
|
||||||
|
|
|
@ -25,8 +25,10 @@ import static org.easymock.classextension.EasyMock.verify;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
import org.jclouds.ec2.EC2Client;
|
import org.jclouds.ec2.EC2Client;
|
||||||
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
import org.jclouds.ec2.domain.KeyPair;
|
import org.jclouds.ec2.domain.KeyPair;
|
||||||
import org.jclouds.ec2.services.KeyPairClient;
|
import org.jclouds.ec2.services.KeyPairClient;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
@ -38,58 +40,127 @@ import com.google.common.base.Supplier;
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit")
|
@Test(groups = "unit")
|
||||||
public class CreateUniqueKeyPairTest {
|
public class CreateUniqueKeyPairTest {
|
||||||
@SuppressWarnings( { "unchecked" })
|
@SuppressWarnings({ "unchecked" })
|
||||||
@Test
|
@Test
|
||||||
public void testApply() throws UnknownHostException {
|
public void testApply() throws UnknownHostException {
|
||||||
EC2Client client = createMock(EC2Client.class);
|
EC2Client client = createMock(EC2Client.class);
|
||||||
KeyPairClient keyClient = createMock(KeyPairClient.class);
|
KeyPairClient keyClient = createMock(KeyPairClient.class);
|
||||||
Supplier<String> uniqueIdSupplier = createMock(Supplier.class);
|
Supplier<String> uniqueIdSupplier = createMock(Supplier.class);
|
||||||
|
Map<RegionAndName, KeyPair> knownKeys = createMock(Map.class);
|
||||||
|
|
||||||
KeyPair pair = createMock(KeyPair.class);
|
KeyPair pair = createMock(KeyPair.class);
|
||||||
|
|
||||||
expect(client.getKeyPairServices()).andReturn(keyClient).atLeastOnce();
|
expect(client.getKeyPairServices()).andReturn(keyClient).atLeastOnce();
|
||||||
|
|
||||||
expect(uniqueIdSupplier.get()).andReturn("1");
|
expect(uniqueIdSupplier.get()).andReturn("1");
|
||||||
expect(keyClient.createKeyPairInRegion("region", "jclouds#tag#region#1")).andReturn(pair);
|
expect(keyClient.createKeyPairInRegion("region", "jclouds#group#region#1")).andReturn(pair);
|
||||||
|
|
||||||
replay(client);
|
replay(client);
|
||||||
|
replay(knownKeys);
|
||||||
replay(keyClient);
|
replay(keyClient);
|
||||||
replay(uniqueIdSupplier);
|
replay(uniqueIdSupplier);
|
||||||
|
|
||||||
CreateUniqueKeyPair parser = new CreateUniqueKeyPair(client, uniqueIdSupplier);
|
CreateUniqueKeyPair parser = new CreateUniqueKeyPair(knownKeys, client, uniqueIdSupplier);
|
||||||
|
|
||||||
assertEquals(parser.createNewKeyPairInRegion("region", "tag"), pair);
|
assertEquals(parser.createNewKeyPairInRegion("region", "group"), pair);
|
||||||
|
|
||||||
verify(client);
|
verify(client);
|
||||||
|
verify(knownKeys);
|
||||||
verify(keyClient);
|
verify(keyClient);
|
||||||
verify(uniqueIdSupplier);
|
verify(uniqueIdSupplier);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings( { "unchecked" })
|
@SuppressWarnings({ "unchecked" })
|
||||||
@Test
|
@Test
|
||||||
public void testApplyWithIllegalStateException() throws UnknownHostException {
|
public void testApplyWithIllegalStateException() throws UnknownHostException {
|
||||||
EC2Client client = createMock(EC2Client.class);
|
EC2Client client = createMock(EC2Client.class);
|
||||||
KeyPairClient keyClient = createMock(KeyPairClient.class);
|
KeyPairClient keyClient = createMock(KeyPairClient.class);
|
||||||
Supplier<String> uniqueIdSupplier = createMock(Supplier.class);
|
Supplier<String> uniqueIdSupplier = createMock(Supplier.class);
|
||||||
|
Map<RegionAndName, KeyPair> knownKeys = createMock(Map.class);
|
||||||
|
|
||||||
KeyPair pair = createMock(KeyPair.class);
|
KeyPair pair = createMock(KeyPair.class);
|
||||||
|
|
||||||
expect(client.getKeyPairServices()).andReturn(keyClient).atLeastOnce();
|
expect(client.getKeyPairServices()).andReturn(keyClient).atLeastOnce();
|
||||||
|
|
||||||
expect(uniqueIdSupplier.get()).andReturn("1");
|
expect(uniqueIdSupplier.get()).andReturn("1");
|
||||||
expect(keyClient.createKeyPairInRegion("region", "jclouds#tag#region#1")).andThrow(new IllegalStateException());
|
expect(keyClient.createKeyPairInRegion("region", "jclouds#group#region#1")).andThrow(new IllegalStateException());
|
||||||
expect(uniqueIdSupplier.get()).andReturn("2");
|
expect(uniqueIdSupplier.get()).andReturn("2");
|
||||||
expect(keyClient.createKeyPairInRegion("region", "jclouds#tag#region#2")).andReturn(pair);
|
expect(keyClient.createKeyPairInRegion("region", "jclouds#group#region#2")).andReturn(pair);
|
||||||
|
|
||||||
replay(client);
|
replay(client);
|
||||||
|
replay(knownKeys);
|
||||||
replay(keyClient);
|
replay(keyClient);
|
||||||
replay(uniqueIdSupplier);
|
replay(uniqueIdSupplier);
|
||||||
|
|
||||||
CreateUniqueKeyPair parser = new CreateUniqueKeyPair(client, uniqueIdSupplier);
|
CreateUniqueKeyPair parser = new CreateUniqueKeyPair(knownKeys, client, uniqueIdSupplier);
|
||||||
|
|
||||||
assertEquals(parser.createNewKeyPairInRegion("region", "tag"), pair);
|
assertEquals(parser.createNewKeyPairInRegion("region", "group"), pair);
|
||||||
|
|
||||||
verify(client);
|
verify(client);
|
||||||
|
verify(knownKeys);
|
||||||
|
verify(keyClient);
|
||||||
|
verify(uniqueIdSupplier);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "unchecked" })
|
||||||
|
@Test
|
||||||
|
public void testApplyWhenKnownKeyExists() throws UnknownHostException {
|
||||||
|
EC2Client client = createMock(EC2Client.class);
|
||||||
|
KeyPairClient keyClient = createMock(KeyPairClient.class);
|
||||||
|
Supplier<String> uniqueIdSupplier = createMock(Supplier.class);
|
||||||
|
Map<RegionAndName, KeyPair> knownKeys = createMock(Map.class);
|
||||||
|
|
||||||
|
KeyPair pair = createMock(KeyPair.class);
|
||||||
|
|
||||||
|
expect(knownKeys.containsKey(new RegionAndName("region", "group"))).andReturn(true);
|
||||||
|
expect(knownKeys.get(new RegionAndName("region", "group"))).andReturn(pair);
|
||||||
|
|
||||||
|
replay(client);
|
||||||
|
replay(knownKeys);
|
||||||
|
replay(keyClient);
|
||||||
|
replay(uniqueIdSupplier);
|
||||||
|
|
||||||
|
CreateUniqueKeyPair parser = new CreateUniqueKeyPair(knownKeys, client, uniqueIdSupplier);
|
||||||
|
|
||||||
|
assertEquals(parser.load(new RegionAndName("region", "group")), pair);
|
||||||
|
|
||||||
|
verify(client);
|
||||||
|
verify(knownKeys);
|
||||||
|
verify(keyClient);
|
||||||
|
verify(uniqueIdSupplier);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings({ "unchecked" })
|
||||||
|
@Test
|
||||||
|
public void testApplyWhenKnownKeyDoesntExist() throws UnknownHostException {
|
||||||
|
EC2Client client = createMock(EC2Client.class);
|
||||||
|
KeyPairClient keyClient = createMock(KeyPairClient.class);
|
||||||
|
Supplier<String> uniqueIdSupplier = createMock(Supplier.class);
|
||||||
|
Map<RegionAndName, KeyPair> knownKeys = createMock(Map.class);
|
||||||
|
|
||||||
|
KeyPair pair = createMock(KeyPair.class);
|
||||||
|
|
||||||
|
expect(client.getKeyPairServices()).andReturn(keyClient).atLeastOnce();
|
||||||
|
|
||||||
|
expect(knownKeys.containsKey(new RegionAndName("region", "group"))).andReturn(false);
|
||||||
|
expect(uniqueIdSupplier.get()).andReturn("1");
|
||||||
|
expect(keyClient.createKeyPairInRegion("region", "jclouds#group#region#1")).andThrow(new IllegalStateException());
|
||||||
|
expect(uniqueIdSupplier.get()).andReturn("2");
|
||||||
|
expect(keyClient.createKeyPairInRegion("region", "jclouds#group#region#2")).andReturn(pair);
|
||||||
|
|
||||||
|
replay(client);
|
||||||
|
replay(knownKeys);
|
||||||
|
replay(keyClient);
|
||||||
|
replay(uniqueIdSupplier);
|
||||||
|
|
||||||
|
CreateUniqueKeyPair parser = new CreateUniqueKeyPair(knownKeys, client, uniqueIdSupplier);
|
||||||
|
|
||||||
|
assertEquals(parser.load(new RegionAndName("region", "group")), pair);
|
||||||
|
|
||||||
|
verify(client);
|
||||||
|
verify(knownKeys);
|
||||||
verify(keyClient);
|
verify(keyClient);
|
||||||
verify(uniqueIdSupplier);
|
verify(uniqueIdSupplier);
|
||||||
|
|
||||||
|
|
|
@ -26,13 +26,15 @@ import static org.easymock.classextension.EasyMock.verify;
|
||||||
import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.imageIds;
|
import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.imageIds;
|
||||||
import static org.testng.Assert.assertEquals;
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.ec2.EC2Client;
|
import org.jclouds.ec2.EC2Client;
|
||||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
import org.jclouds.ec2.services.AMIClient;
|
import org.jclouds.ec2.services.AMIClient;
|
||||||
import org.jclouds.compute.domain.Image;
|
|
||||||
import org.jclouds.rest.ResourceNotFoundException;
|
import org.jclouds.rest.ResourceNotFoundException;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
@ -46,46 +48,85 @@ public class RegionAndIdToImageTest {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test
|
||||||
public void testApply() {
|
public void testApply() throws ExecutionException {
|
||||||
|
|
||||||
EC2ImageParser parser = createMock(EC2ImageParser.class);
|
EC2ImageParser parser = createMock(EC2ImageParser.class);
|
||||||
EC2Client caller = createMock(EC2Client.class);
|
EC2Client caller = createMock(EC2Client.class);
|
||||||
AMIClient client = createMock(AMIClient.class);
|
AMIClient client = createMock(AMIClient.class);
|
||||||
|
Map<RegionAndName, Image> knownImages = createMock(Map.class);
|
||||||
|
|
||||||
org.jclouds.ec2.domain.Image ec2Image = createMock(org.jclouds.ec2.domain.Image.class);
|
org.jclouds.ec2.domain.Image ec2Image = createMock(org.jclouds.ec2.domain.Image.class);
|
||||||
Image image = createNiceMock(Image.class);
|
Image image = createNiceMock(Image.class);
|
||||||
Set<? extends org.jclouds.ec2.domain.Image> images = ImmutableSet.<org.jclouds.ec2.domain.Image> of(ec2Image);
|
Set<? extends org.jclouds.ec2.domain.Image> images = ImmutableSet.<org.jclouds.ec2.domain.Image> of(ec2Image);
|
||||||
|
|
||||||
|
expect(knownImages.containsKey(new RegionAndName("region", "ami"))).andReturn(false);
|
||||||
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
|
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
|
||||||
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn(Set.class.cast(images));
|
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn(Set.class.cast(images));
|
||||||
expect(parser.apply(ec2Image)).andReturn(image);
|
expect(parser.apply(ec2Image)).andReturn(image);
|
||||||
|
|
||||||
|
replay(knownImages);
|
||||||
replay(caller);
|
replay(caller);
|
||||||
replay(image);
|
replay(image);
|
||||||
replay(parser);
|
replay(parser);
|
||||||
replay(client);
|
replay(client);
|
||||||
|
|
||||||
RegionAndIdToImage function = new RegionAndIdToImage(parser, caller);
|
RegionAndIdToImage function = new RegionAndIdToImage(knownImages, parser, caller);
|
||||||
|
|
||||||
assertEquals(function.apply(new RegionAndName("region", "ami")), image);
|
assertEquals(function.load(new RegionAndName("region", "ami")), image);
|
||||||
|
|
||||||
verify(caller);
|
verify(caller);
|
||||||
verify(image);
|
verify(image);
|
||||||
verify(parser);
|
verify(image);
|
||||||
|
verify(knownImages);
|
||||||
verify(client);
|
verify(client);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test
|
||||||
public void testApplyNotFound() {
|
public void testApplyWhenFoundDoesntCallClient() throws ExecutionException {
|
||||||
|
|
||||||
EC2ImageParser parser = createMock(EC2ImageParser.class);
|
EC2ImageParser parser = createMock(EC2ImageParser.class);
|
||||||
EC2Client caller = createMock(EC2Client.class);
|
EC2Client caller = createMock(EC2Client.class);
|
||||||
AMIClient client = createMock(AMIClient.class);
|
AMIClient client = createMock(AMIClient.class);
|
||||||
|
Map<RegionAndName, Image> knownImages = createMock(Map.class);
|
||||||
|
|
||||||
|
Image image = createNiceMock(Image.class);
|
||||||
|
|
||||||
|
expect(knownImages.containsKey(new RegionAndName("region", "ami"))).andReturn(true);
|
||||||
|
expect(knownImages.get(new RegionAndName("region", "ami"))).andReturn(image);
|
||||||
|
|
||||||
|
replay(knownImages);
|
||||||
|
replay(caller);
|
||||||
|
replay(image);
|
||||||
|
replay(parser);
|
||||||
|
replay(client);
|
||||||
|
|
||||||
|
RegionAndIdToImage function = new RegionAndIdToImage(knownImages, parser, caller);
|
||||||
|
|
||||||
|
assertEquals(function.load(new RegionAndName("region", "ami")), image);
|
||||||
|
|
||||||
|
verify(caller);
|
||||||
|
verify(image);
|
||||||
|
verify(image);
|
||||||
|
verify(knownImages);
|
||||||
|
verify(client);
|
||||||
|
|
||||||
|
}
|
||||||
|
@SuppressWarnings("unchecked")
|
||||||
|
@Test(expectedExceptions = ExecutionException.class)
|
||||||
|
public void testApplyNotFoundMakesExecutionException() throws ExecutionException {
|
||||||
|
|
||||||
|
EC2ImageParser parser = createMock(EC2ImageParser.class);
|
||||||
|
EC2Client caller = createMock(EC2Client.class);
|
||||||
|
AMIClient client = createMock(AMIClient.class);
|
||||||
|
Map<RegionAndName, Image> knownImages = createMock(Map.class);
|
||||||
|
|
||||||
org.jclouds.ec2.domain.Image ec2Image = createMock(org.jclouds.ec2.domain.Image.class);
|
org.jclouds.ec2.domain.Image ec2Image = createMock(org.jclouds.ec2.domain.Image.class);
|
||||||
Image image = createNiceMock(Image.class);
|
Image image = createNiceMock(Image.class);
|
||||||
Set<? extends org.jclouds.ec2.domain.Image> images = ImmutableSet.<org.jclouds.ec2.domain.Image> of(ec2Image);
|
Set<? extends org.jclouds.ec2.domain.Image> images = ImmutableSet.<org.jclouds.ec2.domain.Image> of(ec2Image);
|
||||||
|
|
||||||
|
expect(knownImages.containsKey(new RegionAndName("region", "ami"))).andReturn(false);
|
||||||
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
|
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
|
||||||
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn(Set.class.cast(images));
|
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn(Set.class.cast(images));
|
||||||
expect(parser.apply(ec2Image)).andThrow(new ResourceNotFoundException());
|
expect(parser.apply(ec2Image)).andThrow(new ResourceNotFoundException());
|
||||||
|
@ -93,45 +134,52 @@ public class RegionAndIdToImageTest {
|
||||||
replay(caller);
|
replay(caller);
|
||||||
replay(image);
|
replay(image);
|
||||||
replay(parser);
|
replay(parser);
|
||||||
|
replay(knownImages);
|
||||||
replay(client);
|
replay(client);
|
||||||
|
|
||||||
RegionAndIdToImage function = new RegionAndIdToImage(parser, caller);
|
RegionAndIdToImage function = new RegionAndIdToImage(knownImages, parser, caller);
|
||||||
|
|
||||||
assertEquals(function.apply(new RegionAndName("region", "ami")), null);
|
assertEquals(function.load(new RegionAndName("region", "ami")), null);
|
||||||
|
|
||||||
verify(caller);
|
verify(caller);
|
||||||
verify(image);
|
verify(image);
|
||||||
verify(parser);
|
verify(parser);
|
||||||
|
verify(knownImages);
|
||||||
verify(client);
|
verify(client);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Test
|
@Test(expectedExceptions = ExecutionException.class)
|
||||||
public void testApplyNoSuchElementException() {
|
public void testApplyNoSuchElementExceptionMakesExecutionException() throws ExecutionException {
|
||||||
|
|
||||||
EC2ImageParser parser = createMock(EC2ImageParser.class);
|
EC2ImageParser parser = createMock(EC2ImageParser.class);
|
||||||
EC2Client caller = createMock(EC2Client.class);
|
EC2Client caller = createMock(EC2Client.class);
|
||||||
AMIClient client = createMock(AMIClient.class);
|
AMIClient client = createMock(AMIClient.class);
|
||||||
|
Map<RegionAndName, Image> knownImages = createMock(Map.class);
|
||||||
|
|
||||||
org.jclouds.ec2.domain.Image ec2Image = createMock(org.jclouds.ec2.domain.Image.class);
|
org.jclouds.ec2.domain.Image ec2Image = createMock(org.jclouds.ec2.domain.Image.class);
|
||||||
Image image = createNiceMock(Image.class);
|
Image image = createNiceMock(Image.class);
|
||||||
Set<? extends org.jclouds.ec2.domain.Image> images = ImmutableSet.<org.jclouds.ec2.domain.Image> of(ec2Image);
|
Set<? extends org.jclouds.ec2.domain.Image> images = ImmutableSet.<org.jclouds.ec2.domain.Image> of(ec2Image);
|
||||||
|
|
||||||
|
expect(knownImages.containsKey(new RegionAndName("region", "ami"))).andReturn(false);
|
||||||
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
|
expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
|
||||||
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn(Set.class.cast(images));
|
expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn(Set.class.cast(images));
|
||||||
expect(parser.apply(ec2Image)).andThrow(new NoSuchElementException());
|
expect(parser.apply(ec2Image)).andThrow(new NoSuchElementException());
|
||||||
|
|
||||||
replay(caller);
|
replay(caller);
|
||||||
replay(image);
|
replay(image);
|
||||||
|
replay(knownImages);
|
||||||
replay(parser);
|
replay(parser);
|
||||||
replay(client);
|
replay(client);
|
||||||
|
|
||||||
RegionAndIdToImage function = new RegionAndIdToImage(parser, caller);
|
RegionAndIdToImage function = new RegionAndIdToImage(knownImages, parser, caller);
|
||||||
|
|
||||||
assertEquals(function.apply(new RegionAndName("region", "ami")), null);
|
assertEquals(function.load(new RegionAndName("region", "ami")), null);
|
||||||
|
|
||||||
verify(caller);
|
verify(caller);
|
||||||
verify(image);
|
verify(image);
|
||||||
|
verify(knownImages);
|
||||||
verify(parser);
|
verify(parser);
|
||||||
verify(client);
|
verify(client);
|
||||||
|
|
||||||
|
|
|
@ -25,8 +25,6 @@ import java.net.UnknownHostException;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
|
||||||
|
|
||||||
import org.jclouds.compute.domain.Hardware;
|
import org.jclouds.compute.domain.Hardware;
|
||||||
import org.jclouds.compute.domain.Image;
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.compute.domain.NodeMetadata;
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
@ -43,14 +41,18 @@ import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
import org.jclouds.ec2.domain.InstanceState;
|
import org.jclouds.ec2.domain.InstanceState;
|
||||||
import org.jclouds.ec2.domain.RunningInstance;
|
import org.jclouds.ec2.domain.RunningInstance;
|
||||||
import org.jclouds.ec2.xml.DescribeInstancesResponseHandlerTest;
|
import org.jclouds.ec2.xml.DescribeInstancesResponseHandlerTest;
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.base.Suppliers;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
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.Maps;
|
import com.google.common.collect.Maps;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -167,14 +169,14 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
// Handle the case when the installed AMI no longer can be found in AWS.
|
// Handle the case when the installed AMI no longer can be found in AWS.
|
||||||
|
|
||||||
// Create a null-returning function to simulate that the AMI can't be found.
|
// Create a null-returning function to simulate that the AMI can't be found.
|
||||||
Function<RegionAndName, Image> nullReturningFunction = new Function<RegionAndName, Image>() {
|
CacheLoader<RegionAndName, Image> nullReturningFunction = new CacheLoader<RegionAndName, Image>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Image apply(@Nullable RegionAndName from) {
|
public Image load(@Nullable RegionAndName from) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
Map<RegionAndName, Image> instanceToImage = new MapMaker().makeComputingMap(nullReturningFunction);
|
Cache<RegionAndName, Image> instanceToImage = CacheBuilder.newBuilder().build(nullReturningFunction);
|
||||||
|
|
||||||
RunningInstanceToNodeMetadata parser = createNodeParser(ImmutableSet.of(m1_small32().build()), ImmutableSet
|
RunningInstanceToNodeMetadata parser = createNodeParser(ImmutableSet.of(m1_small32().build()), ImmutableSet
|
||||||
.of(provider), ImmutableMap.<String, Credentials> of(),
|
.of(provider), ImmutableMap.<String, Credentials> of(),
|
||||||
|
@ -197,25 +199,31 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
protected RunningInstanceToNodeMetadata createNodeParser(final ImmutableSet<Hardware> hardware,
|
protected RunningInstanceToNodeMetadata createNodeParser(final ImmutableSet<Hardware> hardware,
|
||||||
final ImmutableSet<Location> locations, Set<org.jclouds.compute.domain.Image> images,
|
final ImmutableSet<Location> locations, final Set<org.jclouds.compute.domain.Image> images,
|
||||||
Map<String, Credentials> credentialStore) {
|
Map<String, Credentials> credentialStore) {
|
||||||
Map<InstanceState, NodeState> instanceToNodeState = EC2ComputeServiceDependenciesModule.instanceToNodeState;
|
Map<InstanceState, NodeState> instanceToNodeState = EC2ComputeServiceDependenciesModule.instanceToNodeState;
|
||||||
|
|
||||||
Map<RegionAndName, Image> instanceToImage = Maps.uniqueIndex(images, new Function<Image, RegionAndName>() {
|
CacheLoader<RegionAndName, Image> getRealImage = new CacheLoader<RegionAndName, Image>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RegionAndName apply(Image from) {
|
public Image load(@Nullable RegionAndName from) {
|
||||||
return new RegionAndName(from.getLocation().getId(), from.getProviderId());
|
return Maps.uniqueIndex(images, new Function<Image, RegionAndName>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public RegionAndName apply(Image from) {
|
||||||
|
return new RegionAndName(from.getLocation().getId(), from.getProviderId());
|
||||||
|
}
|
||||||
|
|
||||||
|
}).get(from);
|
||||||
}
|
}
|
||||||
|
};
|
||||||
});
|
Cache<RegionAndName, Image> instanceToImage = CacheBuilder.newBuilder().build(getRealImage);
|
||||||
|
|
||||||
return createNodeParser(hardware, locations, credentialStore, instanceToNodeState, instanceToImage);
|
return createNodeParser(hardware, locations, credentialStore, instanceToNodeState, instanceToImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private RunningInstanceToNodeMetadata createNodeParser(final ImmutableSet<Hardware> hardware,
|
private RunningInstanceToNodeMetadata createNodeParser(final ImmutableSet<Hardware> hardware,
|
||||||
final ImmutableSet<Location> locations, Map<String, Credentials> credentialStore,
|
final ImmutableSet<Location> locations, Map<String, Credentials> credentialStore,
|
||||||
Map<InstanceState, NodeState> instanceToNodeState, Map<RegionAndName, Image> instanceToImage) {
|
Map<InstanceState, NodeState> instanceToNodeState, Cache<RegionAndName, Image> instanceToImage) {
|
||||||
Supplier<Set<? extends Location>> locationSupplier = new Supplier<Set<? extends Location>>() {
|
Supplier<Set<? extends Location>> locationSupplier = new Supplier<Set<? extends Location>>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -233,7 +241,8 @@ public class RunningInstanceToNodeMetadataTest {
|
||||||
|
|
||||||
};
|
};
|
||||||
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(instanceToNodeState, credentialStore,
|
RunningInstanceToNodeMetadata parser = new RunningInstanceToNodeMetadata(instanceToNodeState, credentialStore,
|
||||||
instanceToImage, locationSupplier, hardwareSupplier);
|
Suppliers.<Cache<RegionAndName, ? extends Image>> ofInstance(instanceToImage), locationSupplier,
|
||||||
|
hardwareSupplier);
|
||||||
return parser;
|
return parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,6 @@ import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
|
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
|
|
||||||
|
@ -46,11 +45,12 @@ import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.base.Suppliers;
|
import com.google.common.base.Suppliers;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.MapMaker;
|
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -67,22 +67,21 @@ public class EC2TemplateBuilderImplTest extends TemplateBuilderImplTest {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected EC2TemplateBuilderImpl createTemplateBuilder(final Image knownImage,
|
protected EC2TemplateBuilderImpl createTemplateBuilder(final Image knownImage,
|
||||||
@Memoized Supplier<Set<? extends Location>> locations, @Memoized Supplier<Set<? extends Image>> images,
|
@Memoized Supplier<Set<? extends Location>> locations, @Memoized Supplier<Set<? extends Image>> images,
|
||||||
@Memoized Supplier<Set<? extends Hardware>> sizes, Location defaultLocation,
|
@Memoized Supplier<Set<? extends Hardware>> sizes, Location defaultLocation,
|
||||||
Provider<TemplateOptions> optionsProvider, Provider<TemplateBuilder> templateBuilderProvider) {
|
Provider<TemplateOptions> optionsProvider, Provider<TemplateBuilder> templateBuilderProvider) {
|
||||||
final RegionAndName knownRegionAndName = new RegionAndName("region", "ami");
|
final RegionAndName knownRegionAndName = new RegionAndName("region", "ami");
|
||||||
|
|
||||||
ConcurrentMap<RegionAndName, Image> imageMap = new MapMaker()
|
Cache<RegionAndName, ? extends Image> imageMap = CacheBuilder.newBuilder().build(new CacheLoader<RegionAndName, Image>() {
|
||||||
.makeComputingMap(new Function<RegionAndName, Image>() {
|
@Override
|
||||||
@Override
|
public Image load(RegionAndName from) {
|
||||||
public Image apply(RegionAndName from) {
|
return from.equals(knownRegionAndName) ? knownImage : null;
|
||||||
return from.equals(knownRegionAndName) ? knownImage : null;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
return new EC2TemplateBuilderImpl(locations, images, sizes, Suppliers.ofInstance(defaultLocation),
|
return new EC2TemplateBuilderImpl(locations, images, sizes, Suppliers.ofInstance(defaultLocation),
|
||||||
optionsProvider, templateBuilderProvider, imageMap);
|
optionsProvider, templateBuilderProvider, Suppliers.<Cache<RegionAndName, ? extends Image>>ofInstance(imageMap));
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -91,11 +90,11 @@ public class EC2TemplateBuilderImplTest extends TemplateBuilderImplTest {
|
||||||
Location location = new LocationBuilder().scope(LocationScope.REGION).id("region").description("region").build();
|
Location location = new LocationBuilder().scope(LocationScope.REGION).id("region").description("region").build();
|
||||||
|
|
||||||
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
|
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
|
||||||
.<Location> of(location));
|
.<Location> of(location));
|
||||||
Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(Sets
|
Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(Sets
|
||||||
.<Image> newLinkedHashSet());
|
.<Image> newLinkedHashSet());
|
||||||
Supplier<Set<? extends Hardware>> sizes = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
|
Supplier<Set<? extends Hardware>> sizes = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
|
||||||
.<Hardware> of(c1_medium().build()));
|
.<Hardware> of(c1_medium().build()));
|
||||||
|
|
||||||
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
|
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
|
||||||
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
||||||
|
@ -127,7 +126,7 @@ public class EC2TemplateBuilderImplTest extends TemplateBuilderImplTest {
|
||||||
replay(templateBuilderProvider);
|
replay(templateBuilderProvider);
|
||||||
|
|
||||||
TemplateBuilderImpl template = createTemplateBuilder(knownImage, locations, images, sizes, location,
|
TemplateBuilderImpl template = createTemplateBuilder(knownImage, locations, images, sizes, location,
|
||||||
optionsProvider, templateBuilderProvider);
|
optionsProvider, templateBuilderProvider);
|
||||||
|
|
||||||
assertEquals(template.imageId("region/ami").build().getImage(), knownImage);
|
assertEquals(template.imageId("region/ami").build().getImage(), knownImage);
|
||||||
|
|
||||||
|
@ -144,10 +143,10 @@ public class EC2TemplateBuilderImplTest extends TemplateBuilderImplTest {
|
||||||
Location location = new LocationBuilder().scope(LocationScope.REGION).id("region").description("region").build();
|
Location location = new LocationBuilder().scope(LocationScope.REGION).id("region").description("region").build();
|
||||||
|
|
||||||
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
|
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
|
||||||
.<Location> of(location));
|
.<Location> of(location));
|
||||||
Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.<Image> of());
|
Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.<Image> of());
|
||||||
Supplier<Set<? extends Hardware>> sizes = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
|
Supplier<Set<? extends Hardware>> sizes = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
|
||||||
.<Hardware> of(c1_medium().build()));
|
.<Hardware> of(c1_medium().build()));
|
||||||
|
|
||||||
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
|
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
|
||||||
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
Provider<TemplateBuilder> templateBuilderProvider = createMock(Provider.class);
|
||||||
|
@ -162,7 +161,7 @@ public class EC2TemplateBuilderImplTest extends TemplateBuilderImplTest {
|
||||||
replay(templateBuilderProvider);
|
replay(templateBuilderProvider);
|
||||||
|
|
||||||
TemplateBuilderImpl template = createTemplateBuilder(knownImage, locations, images, sizes, location,
|
TemplateBuilderImpl template = createTemplateBuilder(knownImage, locations, images, sizes, location,
|
||||||
optionsProvider, templateBuilderProvider);
|
optionsProvider, templateBuilderProvider);
|
||||||
try {
|
try {
|
||||||
template.imageId("ami").build();
|
template.imageId("ami").build();
|
||||||
assert false;
|
assert false;
|
||||||
|
@ -181,10 +180,10 @@ public class EC2TemplateBuilderImplTest extends TemplateBuilderImplTest {
|
||||||
Location location = new LocationBuilder().scope(LocationScope.REGION).id("region").description("region").build();
|
Location location = new LocationBuilder().scope(LocationScope.REGION).id("region").description("region").build();
|
||||||
|
|
||||||
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
|
Supplier<Set<? extends Location>> locations = Suppliers.<Set<? extends Location>> ofInstance(ImmutableSet
|
||||||
.<Location> of(location));
|
.<Location> of(location));
|
||||||
Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.<Image> of());
|
Supplier<Set<? extends Image>> images = Suppliers.<Set<? extends Image>> ofInstance(ImmutableSet.<Image> of());
|
||||||
Supplier<Set<? extends Hardware>> sizes = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
|
Supplier<Set<? extends Hardware>> sizes = Suppliers.<Set<? extends Hardware>> ofInstance(ImmutableSet
|
||||||
.<Hardware> of(c1_medium().build()));
|
.<Hardware> of(c1_medium().build()));
|
||||||
|
|
||||||
Location defaultLocation = createMock(Location.class);
|
Location defaultLocation = createMock(Location.class);
|
||||||
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
|
Provider<TemplateOptions> optionsProvider = createMock(Provider.class);
|
||||||
|
@ -202,7 +201,7 @@ public class EC2TemplateBuilderImplTest extends TemplateBuilderImplTest {
|
||||||
replay(templateBuilderProvider);
|
replay(templateBuilderProvider);
|
||||||
|
|
||||||
TemplateBuilderImpl template = createTemplateBuilder(knownImage, locations, images, sizes, defaultLocation,
|
TemplateBuilderImpl template = createTemplateBuilder(knownImage, locations, images, sizes, defaultLocation,
|
||||||
optionsProvider, templateBuilderProvider);
|
optionsProvider, templateBuilderProvider);
|
||||||
|
|
||||||
assertEquals(template.imageId("region/bad").build().getImage(), knownImage);
|
assertEquals(template.imageId("region/bad").build().getImage(), knownImage);
|
||||||
|
|
||||||
|
|
|
@ -27,6 +27,7 @@ import static org.testng.Assert.assertEquals;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
|
|
||||||
|
@ -38,8 +39,6 @@ import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.ec2.compute.domain.EC2HardwareBuilder;
|
import org.jclouds.ec2.compute.domain.EC2HardwareBuilder;
|
||||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
|
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
|
||||||
import org.jclouds.ec2.compute.functions.CreateSecurityGroupIfNeeded;
|
|
||||||
import org.jclouds.ec2.compute.functions.CreateUniqueKeyPair;
|
|
||||||
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
||||||
import org.jclouds.ec2.domain.BlockDeviceMapping;
|
import org.jclouds.ec2.domain.BlockDeviceMapping;
|
||||||
import org.jclouds.ec2.domain.KeyPair;
|
import org.jclouds.ec2.domain.KeyPair;
|
||||||
|
@ -48,14 +47,14 @@ import org.jclouds.encryption.internal.Base64;
|
||||||
import org.jclouds.scriptbuilder.domain.Statements;
|
import org.jclouds.scriptbuilder.domain.Statements;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit")
|
@Test(groups = "unit", singleThreaded = true, testName = "CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest")
|
||||||
public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
|
|
||||||
private static final Provider<RunInstancesOptions> OPTIONS_PROVIDER = new javax.inject.Provider<RunInstancesOptions>() {
|
private static final Provider<RunInstancesOptions> OPTIONS_PROVIDER = new javax.inject.Provider<RunInstancesOptions>() {
|
||||||
|
@ -209,7 +208,7 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
verifyStrategy(strategy);
|
verifyStrategy(strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test(expectedExceptions = IllegalStateException.class)
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_reusesKeyWhenToldToWithRunScriptButNoCredentials() {
|
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_reusesKeyWhenToldToWithRunScriptButNoCredentials() {
|
||||||
// setup constants
|
// setup constants
|
||||||
String region = Region.AP_SOUTHEAST_1;
|
String region = Region.AP_SOUTHEAST_1;
|
||||||
|
@ -225,7 +224,8 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
||||||
expect(options.getOverridingCredentials()).andReturn(null);
|
expect(options.getOverridingCredentials()).andReturn(null);
|
||||||
expect(options.getRunScript()).andReturn(Statements.exec("echo foo"));
|
expect(options.getRunScript()).andReturn(Statements.exec("echo foo"));
|
||||||
expect(strategy.credentialsMap.containsKey(new RegionAndName(region, userSuppliedKeyPair))).andReturn(false);
|
|
||||||
|
expect(strategy.credentialsMap.getUnchecked(new RegionAndName(region, userSuppliedKeyPair))).andThrow(new NullPointerException());
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -256,7 +256,8 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
||||||
expect(options.getOverridingCredentials()).andReturn(null);
|
expect(options.getOverridingCredentials()).andReturn(null);
|
||||||
expect(options.getRunScript()).andReturn(Statements.exec("echo foo"));
|
expect(options.getRunScript()).andReturn(Statements.exec("echo foo"));
|
||||||
expect(strategy.credentialsMap.containsKey(new RegionAndName(region, userSuppliedKeyPair))).andReturn(true);
|
|
||||||
|
expect(strategy.credentialsMap.getUnchecked(new RegionAndName(region, userSuppliedKeyPair))).andReturn(keyPair);
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -287,11 +288,13 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
||||||
expect(options.getOverridingCredentials()).andReturn(new Credentials(null, "MyRsa")).atLeastOnce();
|
expect(options.getOverridingCredentials()).andReturn(new Credentials(null, "MyRsa")).atLeastOnce();
|
||||||
expect(
|
expect(
|
||||||
strategy.credentialsMap.put(new RegionAndName(region, userSuppliedKeyPair), KeyPair.builder()
|
strategy.knownKeys.put(
|
||||||
.region(region).keyName(userSuppliedKeyPair).keyFingerprint("//TODO").keyMaterial("MyRsa").build()))
|
new RegionAndName(region, tag),
|
||||||
.andReturn(null);
|
KeyPair.builder().region(region).keyName(userSuppliedKeyPair).keyFingerprint("//TODO")
|
||||||
|
.keyMaterial("MyRsa").build())).andReturn(null);
|
||||||
|
strategy.credentialsMap.invalidate(new RegionAndName(region, tag));
|
||||||
expect(options.getRunScript()).andReturn(Statements.exec("echo foo"));
|
expect(options.getRunScript()).andReturn(Statements.exec("echo foo"));
|
||||||
expect(strategy.credentialsMap.containsKey(new RegionAndName(region, userSuppliedKeyPair))).andReturn(true);
|
expect(strategy.credentialsMap.getUnchecked(new RegionAndName(region, userSuppliedKeyPair))).andReturn(keyPair);
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -307,7 +310,8 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
verifyStrategy(strategy);
|
verifyStrategy(strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_createsNewKeyPairAndReturnsItsNameByDefault() {
|
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_createsNewKeyPairAndReturnsItsNameByDefault()
|
||||||
|
throws ExecutionException {
|
||||||
// setup constants
|
// setup constants
|
||||||
String region = Region.AP_SOUTHEAST_1;
|
String region = Region.AP_SOUTHEAST_1;
|
||||||
String tag = "tag";
|
String tag = "tag";
|
||||||
|
@ -323,11 +327,8 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
// setup expectations
|
// setup expectations
|
||||||
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
||||||
expect(options.shouldAutomaticallyCreateKeyPair()).andReturn(shouldAutomaticallyCreateKeyPair);
|
expect(options.shouldAutomaticallyCreateKeyPair()).andReturn(shouldAutomaticallyCreateKeyPair);
|
||||||
expect(strategy.createUniqueKeyPair.apply(new RegionAndName(region, tag))).andReturn(keyPair);
|
|
||||||
expect(keyPair.getRegion()).andReturn(region).atLeastOnce();
|
|
||||||
expect(keyPair.getKeyName()).andReturn(systemGeneratedKeyPairName).atLeastOnce();
|
expect(keyPair.getKeyName()).andReturn(systemGeneratedKeyPairName).atLeastOnce();
|
||||||
expect(strategy.credentialsMap.put(new RegionAndName(region, systemGeneratedKeyPairName), keyPair)).andReturn(
|
expect(strategy.credentialsMap.getUnchecked(new RegionAndName(region, tag))).andReturn(keyPair);
|
||||||
null);
|
|
||||||
expect(options.getRunScript()).andReturn(null);
|
expect(options.getRunScript()).andReturn(null);
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
|
@ -377,7 +378,8 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
verifyStrategy(strategy);
|
verifyStrategy(strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetSecurityGroupsForTagAndOptions_createsNewGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesntExist() {
|
public void testGetSecurityGroupsForTagAndOptions_createsNewGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesntExist()
|
||||||
|
throws ExecutionException {
|
||||||
// setup constants
|
// setup constants
|
||||||
String region = Region.AP_SOUTHEAST_1;
|
String region = Region.AP_SOUTHEAST_1;
|
||||||
String tag = "tag";
|
String tag = "tag";
|
||||||
|
@ -385,7 +387,6 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
Set<String> groupIds = ImmutableSet.<String> of();
|
Set<String> groupIds = ImmutableSet.<String> of();
|
||||||
int[] ports = new int[] {};
|
int[] ports = new int[] {};
|
||||||
boolean shouldAuthorizeSelf = true;
|
boolean shouldAuthorizeSelf = true;
|
||||||
boolean groupExisted = false;
|
|
||||||
Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup);
|
Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup);
|
||||||
|
|
||||||
// create mocks
|
// create mocks
|
||||||
|
@ -397,9 +398,7 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
|
expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
|
||||||
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
||||||
ports, shouldAuthorizeSelf);
|
ports, shouldAuthorizeSelf);
|
||||||
expect(strategy.securityGroupMap.containsKey(regionNameAndIngressRules)).andReturn(groupExisted);
|
expect(strategy.securityGroupMap.getUnchecked(regionNameAndIngressRules)).andReturn(tag);
|
||||||
expect(strategy.createSecurityGroupIfNeeded.apply(regionNameAndIngressRules)).andReturn(generatedMarkerGroup);
|
|
||||||
expect(strategy.securityGroupMap.put(regionNameAndIngressRules, generatedMarkerGroup)).andReturn(null);
|
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -413,7 +412,8 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
verifyStrategy(strategy);
|
verifyStrategy(strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetSecurityGroupsForTagAndOptions_createsNewGroupByDefaultWhenPortsAreSpecifiedWhenDoesntExist() {
|
public void testGetSecurityGroupsForTagAndOptions_createsNewGroupByDefaultWhenPortsAreSpecifiedWhenDoesntExist()
|
||||||
|
throws ExecutionException {
|
||||||
// setup constants
|
// setup constants
|
||||||
String region = Region.AP_SOUTHEAST_1;
|
String region = Region.AP_SOUTHEAST_1;
|
||||||
String tag = "tag";
|
String tag = "tag";
|
||||||
|
@ -421,7 +421,6 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
Set<String> groupIds = ImmutableSet.<String> of();
|
Set<String> groupIds = ImmutableSet.<String> of();
|
||||||
int[] ports = new int[] { 22, 80 };
|
int[] ports = new int[] { 22, 80 };
|
||||||
boolean shouldAuthorizeSelf = true;
|
boolean shouldAuthorizeSelf = true;
|
||||||
boolean groupExisted = false;
|
|
||||||
Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup);
|
Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup);
|
||||||
|
|
||||||
// create mocks
|
// create mocks
|
||||||
|
@ -433,9 +432,7 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
|
expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
|
||||||
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
||||||
ports, shouldAuthorizeSelf);
|
ports, shouldAuthorizeSelf);
|
||||||
expect(strategy.securityGroupMap.containsKey(regionNameAndIngressRules)).andReturn(groupExisted);
|
expect(strategy.securityGroupMap.getUnchecked(regionNameAndIngressRules)).andReturn(generatedMarkerGroup);
|
||||||
expect(strategy.createSecurityGroupIfNeeded.apply(regionNameAndIngressRules)).andReturn(generatedMarkerGroup);
|
|
||||||
expect(strategy.securityGroupMap.put(regionNameAndIngressRules, generatedMarkerGroup)).andReturn(null);
|
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -449,7 +446,8 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
verifyStrategy(strategy);
|
verifyStrategy(strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void testGetSecurityGroupsForTagAndOptions_reusesGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesExist() {
|
public void testGetSecurityGroupsForTagAndOptions_reusesGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesExist()
|
||||||
|
throws ExecutionException {
|
||||||
// setup constants
|
// setup constants
|
||||||
String region = Region.AP_SOUTHEAST_1;
|
String region = Region.AP_SOUTHEAST_1;
|
||||||
String tag = "tag";
|
String tag = "tag";
|
||||||
|
@ -457,7 +455,6 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
Set<String> groupIds = ImmutableSet.<String> of();
|
Set<String> groupIds = ImmutableSet.<String> of();
|
||||||
int[] ports = new int[] {};
|
int[] ports = new int[] {};
|
||||||
boolean shouldAuthorizeSelf = true;
|
boolean shouldAuthorizeSelf = true;
|
||||||
boolean groupExisted = true;
|
|
||||||
Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup);
|
Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup);
|
||||||
|
|
||||||
// create mocks
|
// create mocks
|
||||||
|
@ -469,7 +466,7 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
|
expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
|
||||||
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
||||||
ports, shouldAuthorizeSelf);
|
ports, shouldAuthorizeSelf);
|
||||||
expect(strategy.securityGroupMap.containsKey(regionNameAndIngressRules)).andReturn(groupExisted);
|
expect(strategy.securityGroupMap.getUnchecked(regionNameAndIngressRules)).andReturn(generatedMarkerGroup);
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -501,13 +498,9 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
// setup expectations
|
// setup expectations
|
||||||
expect(options.getGroups()).andReturn(groupIds).atLeastOnce();
|
expect(options.getGroups()).andReturn(groupIds).atLeastOnce();
|
||||||
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
||||||
ports, shouldAuthorizeSelf); // note
|
ports, shouldAuthorizeSelf);
|
||||||
// this
|
|
||||||
// works
|
expect(strategy.securityGroupMap.getUnchecked(regionNameAndIngressRules)).andReturn(groupExisted ? "tag" : null);
|
||||||
// since
|
|
||||||
// there's
|
|
||||||
// no equals on portsq
|
|
||||||
expect(strategy.securityGroupMap.containsKey(regionNameAndIngressRules)).andReturn(groupExisted);
|
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -522,28 +515,24 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyStrategy(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy) {
|
private void verifyStrategy(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy) {
|
||||||
|
verify(strategy.knownKeys);
|
||||||
verify(strategy.credentialsMap);
|
verify(strategy.credentialsMap);
|
||||||
verify(strategy.securityGroupMap);
|
verify(strategy.securityGroupMap);
|
||||||
verify(strategy.createUniqueKeyPair);
|
|
||||||
verify(strategy.createSecurityGroupIfNeeded);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions setupStrategy() {
|
private CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions setupStrategy() {
|
||||||
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
|
Map<RegionAndName, KeyPair> knownKeys = createMock(Map.class);
|
||||||
Map<RegionAndName, String> securityGroupMap = createMock(Map.class);
|
Cache<RegionAndName, KeyPair> credentialsMap = createMock(Cache.class);
|
||||||
CreateUniqueKeyPair createUniqueKeyPair = createMock(CreateUniqueKeyPair.class);
|
Cache<RegionAndName, String> securityGroupMap = createMock(Cache.class);
|
||||||
Function<RegionNameAndIngressRules, String> createSecurityGroupIfNeeded = createMock(CreateSecurityGroupIfNeeded.class);
|
return new CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions(knownKeys, credentialsMap, securityGroupMap,
|
||||||
|
OPTIONS_PROVIDER);
|
||||||
return new CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions(credentialsMap, securityGroupMap,
|
|
||||||
createUniqueKeyPair, createSecurityGroupIfNeeded, OPTIONS_PROVIDER);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void replayStrategy(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy) {
|
private void replayStrategy(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy) {
|
||||||
|
replay(strategy.knownKeys);
|
||||||
replay(strategy.credentialsMap);
|
replay(strategy.credentialsMap);
|
||||||
replay(strategy.securityGroupMap);
|
replay(strategy.securityGroupMap);
|
||||||
replay(strategy.createUniqueKeyPair);
|
|
||||||
replay(strategy.createSecurityGroupIfNeeded);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -51,7 +51,7 @@ import org.jclouds.ec2.options.RunInstancesOptions;
|
||||||
import org.jclouds.ec2.services.InstanceClient;
|
import org.jclouds.ec2.services.InstanceClient;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
|
@ -222,7 +222,7 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
|
||||||
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = createMock(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class);
|
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = createMock(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class);
|
||||||
InstancePresent instancePresent = createMock(InstancePresent.class);
|
InstancePresent instancePresent = createMock(InstancePresent.class);
|
||||||
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata = createMock(RunningInstanceToNodeMetadata.class);
|
RunningInstanceToNodeMetadata runningInstanceToNodeMetadata = createMock(RunningInstanceToNodeMetadata.class);
|
||||||
Function<RunningInstance, Credentials> instanceToCredentials = createMock(Function.class);
|
Cache<RunningInstance, Credentials> instanceToCredentials = createMock(Cache.class);
|
||||||
Map<String, Credentials> credentialStore = createMock(Map.class);
|
Map<String, Credentials> credentialStore = createMock(Map.class);
|
||||||
ComputeUtils utils = createMock(ComputeUtils.class);
|
ComputeUtils utils = createMock(ComputeUtils.class);
|
||||||
return new EC2CreateNodesInGroupThenAddToSet(client, Providers.<TemplateBuilder> of(template),
|
return new EC2CreateNodesInGroupThenAddToSet(client, Providers.<TemplateBuilder> of(template),
|
||||||
|
|
|
@ -25,13 +25,17 @@ import java.net.URI;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.aws.domain.Region;
|
import org.jclouds.aws.domain.Region;
|
||||||
import org.jclouds.aws.filters.FormSigner;
|
import org.jclouds.aws.filters.FormSigner;
|
||||||
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.date.DateService;
|
import org.jclouds.date.DateService;
|
||||||
import org.jclouds.ec2.EC2AsyncClient;
|
import org.jclouds.ec2.EC2AsyncClient;
|
||||||
import org.jclouds.ec2.EC2Client;
|
import org.jclouds.ec2.EC2Client;
|
||||||
import org.jclouds.ec2.EC2ContextBuilder;
|
import org.jclouds.ec2.EC2ContextBuilder;
|
||||||
import org.jclouds.ec2.EC2PropertiesBuilder;
|
import org.jclouds.ec2.EC2PropertiesBuilder;
|
||||||
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
import org.jclouds.ec2.config.EC2RestClientModule;
|
import org.jclouds.ec2.config.EC2RestClientModule;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.RequiresHttp;
|
import org.jclouds.http.RequiresHttp;
|
||||||
|
@ -42,8 +46,12 @@ import org.jclouds.rest.RestContextSpec;
|
||||||
import org.testng.annotations.BeforeTest;
|
import org.testng.annotations.BeforeTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -58,6 +66,19 @@ public abstract class BaseEC2AsyncClientTest<T> extends RestClientTest<T> {
|
||||||
super(EC2Client.class, EC2AsyncClient.class, DELEGATE_MAP);
|
super(EC2Client.class, EC2AsyncClient.class, DELEGATE_MAP);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
Cache<RegionAndName, Image> provide(){
|
||||||
|
return CacheBuilder.newBuilder().build(new CacheLoader<RegionAndName, Image>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Image load(RegionAndName key) throws Exception {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
protected String provideTimeStamp(DateService dateService, int expiration) {
|
protected String provideTimeStamp(DateService dateService, int expiration) {
|
||||||
return "2009-11-08T15:54:08.897Z";
|
return "2009-11-08T15:54:08.897Z";
|
||||||
|
|
|
@ -46,7 +46,6 @@ import org.jclouds.compute.domain.internal.VolumeImpl;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
import org.jclouds.elasticstack.ElasticStackAsyncClient;
|
|
||||||
import org.jclouds.elasticstack.ElasticStackClient;
|
import org.jclouds.elasticstack.ElasticStackClient;
|
||||||
import org.jclouds.elasticstack.domain.Device;
|
import org.jclouds.elasticstack.domain.Device;
|
||||||
import org.jclouds.elasticstack.domain.Drive;
|
import org.jclouds.elasticstack.domain.Drive;
|
||||||
|
@ -62,23 +61,25 @@ import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
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.cache.Cache;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.ImmutableSet.Builder;
|
import com.google.common.collect.ImmutableSet.Builder;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* defines the connection between the {@link ElasticStackClient} implementation and the jclouds
|
* defines the connection between the {@link ElasticStackClient} implementation
|
||||||
* {@link ComputeService}
|
* and the jclouds {@link ComputeService}
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class ElasticStackComputeServiceAdapter implements
|
public class ElasticStackComputeServiceAdapter implements
|
||||||
ComputeServiceAdapter<ServerInfo, Hardware, DriveInfo, Location> {
|
ComputeServiceAdapter<ServerInfo, Hardware, DriveInfo, Location> {
|
||||||
private final ElasticStackClient client;
|
private final ElasticStackClient client;
|
||||||
private final ElasticStackAsyncClient aclient;
|
|
||||||
private final Predicate<DriveInfo> driveNotClaimed;
|
private final Predicate<DriveInfo> driveNotClaimed;
|
||||||
private final Map<String, WellKnownImage> preinstalledImages;
|
private final Map<String, WellKnownImage> preinstalledImages;
|
||||||
private final Map<String, DriveInfo> cache;
|
private final Cache<String, DriveInfo> cache;
|
||||||
private final JustProvider locationSupplier;
|
private final JustProvider locationSupplier;
|
||||||
private final String defaultVncPassword;
|
private final String defaultVncPassword;
|
||||||
private final ExecutorService executor;
|
private final ExecutorService executor;
|
||||||
|
@ -88,13 +89,11 @@ public class ElasticStackComputeServiceAdapter implements
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public ElasticStackComputeServiceAdapter(ElasticStackClient client, ElasticStackAsyncClient aclient,
|
public ElasticStackComputeServiceAdapter(ElasticStackClient client, Predicate<DriveInfo> driveNotClaimed,
|
||||||
Predicate<DriveInfo> driveNotClaimed, JustProvider locationSupplier,
|
JustProvider locationSupplier, Map<String, WellKnownImage> preinstalledImages, Cache<String, DriveInfo> cache,
|
||||||
Map<String, WellKnownImage> preinstalledImages, Map<String, DriveInfo> cache,
|
@Named(ElasticStackConstants.PROPERTY_VNC_PASSWORD) String defaultVncPassword,
|
||||||
@Named(ElasticStackConstants.PROPERTY_VNC_PASSWORD) String defaultVncPassword,
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
|
||||||
this.client = checkNotNull(client, "client");
|
this.client = checkNotNull(client, "client");
|
||||||
this.aclient = checkNotNull(aclient, "aclient");
|
|
||||||
this.driveNotClaimed = checkNotNull(driveNotClaimed, "driveNotClaimed");
|
this.driveNotClaimed = checkNotNull(driveNotClaimed, "driveNotClaimed");
|
||||||
this.locationSupplier = checkNotNull(locationSupplier, "locationSupplier");
|
this.locationSupplier = checkNotNull(locationSupplier, "locationSupplier");
|
||||||
this.preinstalledImages = checkNotNull(preinstalledImages, "preinstalledImages");
|
this.preinstalledImages = checkNotNull(preinstalledImages, "preinstalledImages");
|
||||||
|
@ -105,12 +104,12 @@ public class ElasticStackComputeServiceAdapter implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServerInfo createNodeWithGroupEncodedIntoNameThenStoreCredentials(String tag, String name, Template template,
|
public ServerInfo createNodeWithGroupEncodedIntoNameThenStoreCredentials(String tag, String name, Template template,
|
||||||
Map<String, Credentials> credentialStore) {
|
Map<String, Credentials> credentialStore) {
|
||||||
long bootSize = (long) (template.getHardware().getVolumes().get(0).getSize() * 1024 * 1024 * 1024l);
|
long bootSize = (long) (template.getHardware().getVolumes().get(0).getSize() * 1024 * 1024 * 1024l);
|
||||||
|
|
||||||
logger.debug(">> creating boot drive bytes(%d)", bootSize);
|
logger.debug(">> creating boot drive bytes(%d)", bootSize);
|
||||||
DriveInfo drive = client.createDrive(new Drive.Builder().name(template.getImage().getId()).size(bootSize)
|
DriveInfo drive = client
|
||||||
.build());
|
.createDrive(new Drive.Builder().name(template.getImage().getId()).size(bootSize).build());
|
||||||
logger.debug("<< drive(%s)", drive.getUuid());
|
logger.debug("<< drive(%s)", drive.getUuid());
|
||||||
|
|
||||||
logger.debug(">> imaging boot drive source(%s)", template.getImage().getId());
|
logger.debug(">> imaging boot drive source(%s)", template.getImage().getId());
|
||||||
|
@ -121,17 +120,16 @@ public class ElasticStackComputeServiceAdapter implements
|
||||||
client.destroyDrive(drive.getUuid());
|
client.destroyDrive(drive.getUuid());
|
||||||
throw new IllegalStateException("could not image drive in time!");
|
throw new IllegalStateException("could not image drive in time!");
|
||||||
}
|
}
|
||||||
cache.put(drive.getUuid(), drive);
|
|
||||||
|
|
||||||
Server toCreate = small(name, drive.getUuid(), defaultVncPassword).mem(template.getHardware().getRam()).cpu(
|
Server toCreate = small(name, drive.getUuid(), defaultVncPassword).mem(template.getHardware().getRam())
|
||||||
(int) (template.getHardware().getProcessors().get(0).getSpeed())).build();
|
.cpu((int) (template.getHardware().getProcessors().get(0).getSpeed())).build();
|
||||||
|
|
||||||
ServerInfo from = client.createServer(toCreate);
|
ServerInfo from = client.createServer(toCreate);
|
||||||
client.startServer(from.getUuid());
|
client.startServer(from.getUuid());
|
||||||
from = client.getServerInfo(from.getUuid());
|
from = client.getServerInfo(from.getUuid());
|
||||||
// store the credentials so that later functions can use them
|
// store the credentials so that later functions can use them
|
||||||
credentialStore.put("node#"+ from.getUuid(), new Credentials(template.getImage().getDefaultCredentials().identity,
|
credentialStore.put("node#" + from.getUuid(), new Credentials(
|
||||||
from.getVnc().getPassword()));
|
template.getImage().getDefaultCredentials().identity, from.getVnc().getPassword()));
|
||||||
return from;
|
return from;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,30 +153,40 @@ public class ElasticStackComputeServiceAdapter implements
|
||||||
return "sizeLessThanOrEqual(" + size + ")";
|
return "sizeLessThanOrEqual(" + size + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
}).ids(id).ram(ram).processors(ImmutableList.of(new Processor(1, cpu))).volumes(
|
}).ids(id).ram(ram).processors(ImmutableList.of(new Processor(1, cpu)))
|
||||||
ImmutableList.<Volume> of(new VolumeImpl(size, true, true))).build());
|
.volumes(ImmutableList.<Volume> of(new VolumeImpl(size, true, true))).build());
|
||||||
}
|
}
|
||||||
return hardware.build();
|
return hardware.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* look up the current standard images and do not error out, if they are not found.
|
* look up the current standard images and do not error out, if they are not
|
||||||
|
* found.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Iterable<DriveInfo> listImages() {
|
public Iterable<DriveInfo> listImages() {
|
||||||
Iterable<DriveInfo> drives = transformParallel(preinstalledImages.keySet(),
|
Iterable<DriveInfo> drives = transformParallel(preinstalledImages.keySet(),
|
||||||
new Function<String, Future<DriveInfo>>() {
|
new Function<String, Future<DriveInfo>>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Future<DriveInfo> apply(String input) {
|
public Future<DriveInfo> apply(String input) {
|
||||||
return aclient.getDriveInfo(input);
|
try {
|
||||||
|
return Futures.immediateFuture(cache.getUnchecked(input));
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
logger.debug("drive %s not found", input);
|
||||||
|
} catch (UncheckedExecutionException e) {
|
||||||
|
logger.warn(e, "error finding drive %s: %s", input, e.getMessage());
|
||||||
}
|
}
|
||||||
|
return Futures.immediateFuture(null);
|
||||||
|
}
|
||||||
|
|
||||||
}, executor, null, logger, "drives");
|
@Override
|
||||||
Iterable<DriveInfo> returnVal = filter(drives, notNull());
|
public String toString() {
|
||||||
for (DriveInfo drive : returnVal)
|
return "seedDriveCache()";
|
||||||
cache.put(drive.getUuid(), drive);
|
}
|
||||||
return returnVal;
|
|
||||||
|
}, executor, null, logger, "drives");
|
||||||
|
return filter(drives, notNull());
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
@ -186,7 +194,7 @@ public class ElasticStackComputeServiceAdapter implements
|
||||||
public Iterable<ServerInfo> listNodes() {
|
public Iterable<ServerInfo> listNodes() {
|
||||||
return (Iterable<ServerInfo>) client.listServerInfo();
|
return (Iterable<ServerInfo>) client.listServerInfo();
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Override
|
@Override
|
||||||
public Iterable<Location> listLocations() {
|
public Iterable<Location> listLocations() {
|
||||||
|
|
|
@ -38,10 +38,10 @@ import org.jclouds.elasticstack.ElasticStackAsyncClient;
|
||||||
import org.jclouds.elasticstack.ElasticStackClient;
|
import org.jclouds.elasticstack.ElasticStackClient;
|
||||||
import org.jclouds.elasticstack.compute.ElasticStackComputeServiceAdapter;
|
import org.jclouds.elasticstack.compute.ElasticStackComputeServiceAdapter;
|
||||||
import org.jclouds.elasticstack.compute.functions.ServerInfoToNodeMetadata;
|
import org.jclouds.elasticstack.compute.functions.ServerInfoToNodeMetadata;
|
||||||
import org.jclouds.elasticstack.compute.functions.WellKnownImageToImage;
|
|
||||||
import org.jclouds.elasticstack.compute.functions.ServerInfoToNodeMetadata.DeviceToVolume;
|
import org.jclouds.elasticstack.compute.functions.ServerInfoToNodeMetadata.DeviceToVolume;
|
||||||
import org.jclouds.elasticstack.compute.functions.ServerInfoToNodeMetadata.FindImageForId;
|
import org.jclouds.elasticstack.compute.functions.ServerInfoToNodeMetadata.FindImageForId;
|
||||||
import org.jclouds.elasticstack.compute.functions.ServerInfoToNodeMetadata.GetImageIdFromServer;
|
import org.jclouds.elasticstack.compute.functions.ServerInfoToNodeMetadata.GetImageIdFromServer;
|
||||||
|
import org.jclouds.elasticstack.compute.functions.WellKnownImageToImage;
|
||||||
import org.jclouds.elasticstack.domain.Device;
|
import org.jclouds.elasticstack.domain.Device;
|
||||||
import org.jclouds.elasticstack.domain.DriveInfo;
|
import org.jclouds.elasticstack.domain.DriveInfo;
|
||||||
import org.jclouds.elasticstack.domain.Server;
|
import org.jclouds.elasticstack.domain.Server;
|
||||||
|
@ -59,7 +59,9 @@ 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.Predicates;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
import com.google.common.collect.MapMaker;
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.Maps;
|
import com.google.common.collect.Maps;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import com.google.inject.TypeLiteral;
|
import com.google.inject.TypeLiteral;
|
||||||
|
@ -104,12 +106,12 @@ public class ElasticStackComputeServiceContextModule
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Map<String, DriveInfo> cache(GetDrive getDrive) {
|
protected Cache<String, DriveInfo> cache(GetDrive getDrive) {
|
||||||
return new MapMaker().makeComputingMap(getDrive);
|
return CacheBuilder.newBuilder().build(getDrive);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public static class GetDrive implements Function<String, DriveInfo> {
|
public static class GetDrive extends CacheLoader<String, DriveInfo> {
|
||||||
private final ElasticStackClient client;
|
private final ElasticStackClient client;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
|
@ -118,7 +120,7 @@ public class ElasticStackComputeServiceContextModule
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public DriveInfo apply(String input) {
|
public DriveInfo load(String input) {
|
||||||
return client.getDriveInfo(input);
|
return client.getDriveInfo(input);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -18,27 +18,44 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.elasticstack.compute.functions;
|
package org.jclouds.elasticstack.compute.functions;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import com.google.common.base.Supplier;
|
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
|
||||||
import com.google.common.collect.ImmutableList;
|
|
||||||
import com.google.common.collect.ImmutableMap;
|
|
||||||
import com.google.common.collect.ImmutableSet;
|
|
||||||
import com.google.common.collect.Iterables;
|
|
||||||
import org.jclouds.collect.FindResourceInSet;
|
|
||||||
import org.jclouds.collect.Memoized;
|
|
||||||
import org.jclouds.compute.domain.*;
|
|
||||||
import org.jclouds.domain.Credentials;
|
|
||||||
import org.jclouds.domain.Location;
|
|
||||||
import org.jclouds.elasticstack.domain.*;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
|
||||||
import javax.inject.Singleton;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import static com.google.common.base.Preconditions.checkNotNull;
|
import javax.annotation.Resource;
|
||||||
import static org.jclouds.compute.util.ComputeServiceUtils.parseGroupFromName;
|
import javax.inject.Inject;
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
import org.jclouds.collect.FindResourceInSet;
|
||||||
|
import org.jclouds.collect.Memoized;
|
||||||
|
import org.jclouds.compute.domain.HardwareBuilder;
|
||||||
|
import org.jclouds.compute.domain.Image;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadata;
|
||||||
|
import org.jclouds.compute.domain.NodeMetadataBuilder;
|
||||||
|
import org.jclouds.compute.domain.NodeState;
|
||||||
|
import org.jclouds.compute.domain.Processor;
|
||||||
|
import org.jclouds.compute.domain.Volume;
|
||||||
|
import org.jclouds.compute.domain.VolumeBuilder;
|
||||||
|
import org.jclouds.domain.Credentials;
|
||||||
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.elasticstack.domain.Device;
|
||||||
|
import org.jclouds.elasticstack.domain.DriveInfo;
|
||||||
|
import org.jclouds.elasticstack.domain.Server;
|
||||||
|
import org.jclouds.elasticstack.domain.ServerInfo;
|
||||||
|
import org.jclouds.elasticstack.domain.ServerStatus;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.collect.ImmutableList;
|
||||||
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -93,16 +110,19 @@ public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetada
|
||||||
builder.state(serverStatusToNodeState.get(from.getStatus()));
|
builder.state(serverStatusToNodeState.get(from.getStatus()));
|
||||||
builder.publicAddresses(ImmutableSet.<String> of(from.getNics().get(0).getDhcp()));
|
builder.publicAddresses(ImmutableSet.<String> of(from.getNics().get(0).getDhcp()));
|
||||||
builder.privateAddresses(ImmutableSet.<String> of());
|
builder.privateAddresses(ImmutableSet.<String> of());
|
||||||
builder.credentials(credentialStore.get("node#"+ from.getUuid()));
|
builder.credentials(credentialStore.get("node#" + from.getUuid()));
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public static final class DeviceToVolume implements Function<Device, Volume> {
|
public static final class DeviceToVolume implements Function<Device, Volume> {
|
||||||
private final Map<String, DriveInfo> cache;
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
private final Cache<String, DriveInfo> cache;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public DeviceToVolume(Map<String, DriveInfo> cache) {
|
public DeviceToVolume(Cache<String, DriveInfo> cache) {
|
||||||
this.cache = checkNotNull(cache, "cache");
|
this.cache = checkNotNull(cache, "cache");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -110,27 +130,34 @@ public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetada
|
||||||
public Volume apply(Device input) {
|
public Volume apply(Device input) {
|
||||||
VolumeBuilder builder = new VolumeBuilder();
|
VolumeBuilder builder = new VolumeBuilder();
|
||||||
builder.id(input.getId());
|
builder.id(input.getId());
|
||||||
DriveInfo drive = cache.get(input.getDriveUuid());
|
try {
|
||||||
if (drive != null) {
|
DriveInfo drive = cache.getUnchecked(input.getDriveUuid());
|
||||||
builder.size(drive.getSize() / 1024 / 1024f);
|
builder.size(drive.getSize() / 1024 / 1024f);
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
logger.debug("drive %s not found", input.getDriveUuid());
|
||||||
|
} catch (UncheckedExecutionException e) {
|
||||||
|
logger.warn(e, "error finding drive %s: %s", input.getDriveUuid(), e.getMessage());
|
||||||
}
|
}
|
||||||
return new VolumeBuilder().durable(true).type(Volume.Type.NAS).build();
|
return new VolumeBuilder().durable(true).type(Volume.Type.NAS).build();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* When we create the boot drive of the server, by convention we set the name to the image it
|
* When we create the boot drive of the server, by convention we set the name
|
||||||
* came from.
|
* to the image it came from.
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public static class GetImageIdFromServer implements Function<Server, String> {
|
public static class GetImageIdFromServer implements Function<Server, String> {
|
||||||
private final Map<String, DriveInfo> cache;
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
private final Cache<String, DriveInfo> cache;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public GetImageIdFromServer(Map<String, DriveInfo> cache) {
|
public GetImageIdFromServer(Cache<String, DriveInfo> cache) {
|
||||||
this.cache = cache;
|
this.cache = cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,9 +168,12 @@ public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetada
|
||||||
Device bootDevice = from.getDevices().get(bootDeviceId);
|
Device bootDevice = from.getDevices().get(bootDeviceId);
|
||||||
if (bootDevice != null) {
|
if (bootDevice != null) {
|
||||||
try {
|
try {
|
||||||
imageId = cache.get(bootDevice.getDriveUuid()).getName();
|
DriveInfo drive = cache.getUnchecked(bootDevice.getDriveUuid());
|
||||||
|
imageId = drive.getName();
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
|
logger.debug("drive %s not found", bootDevice.getDriveUuid());
|
||||||
|
} catch (UncheckedExecutionException e) {
|
||||||
|
logger.warn(e, "error finding drive %s: %s", bootDevice.getDriveUuid(), e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return imageId;
|
return imageId;
|
||||||
|
|
|
@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static org.jclouds.trmk.vcloud_0_8.reference.TerremarkConstants.PROPERTY_TERREMARK_EXTENSION_NS;
|
import static org.jclouds.trmk.vcloud_0_8.reference.TerremarkConstants.PROPERTY_TERREMARK_EXTENSION_NS;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
@ -33,6 +34,7 @@ import org.jclouds.rest.binders.BindToStringPayload;
|
||||||
import org.jclouds.util.Patterns;
|
import org.jclouds.util.Patterns;
|
||||||
import org.jclouds.util.Strings2;
|
import org.jclouds.util.Strings2;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -61,9 +63,13 @@ public class BindAddInternetServiceToXmlPayload implements MapBinder {
|
||||||
String description = postParams.get("description");
|
String description = postParams.get("description");
|
||||||
String payload = Strings2.replaceTokens(xmlTemplate,
|
String payload = Strings2.replaceTokens(xmlTemplate,
|
||||||
ImmutableMap.of("name", name, "protocol", protocol, "port", port, "enabled", enabled, "ns", ns));
|
ImmutableMap.of("name", name, "protocol", protocol, "port", port, "enabled", enabled, "ns", ns));
|
||||||
payload = Strings2.replaceAll(payload, Patterns.TOKEN_TO_PATTERN.get("description"), description == null ? ""
|
try {
|
||||||
: String.format("\n\t<Description>%s</Description>", description));
|
payload = Strings2.replaceAll(payload, Patterns.TOKEN_TO_PATTERN.get("description"), description == null ? ""
|
||||||
payload = Strings2.replaceAll(payload, Patterns.TOKEN_TO_PATTERN.get("monitor"), getMonitorString(postParams));
|
: String.format("\n\t<Description>%s</Description>", description));
|
||||||
|
payload = Strings2.replaceAll(payload, Patterns.TOKEN_TO_PATTERN.get("monitor"), getMonitorString(postParams));
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
}
|
||||||
return stringBinder.bindToRequest(request, payload);
|
return stringBinder.bindToRequest(request, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkNotNull;
|
||||||
import static org.jclouds.trmk.vcloud_0_8.reference.TerremarkConstants.PROPERTY_TERREMARK_EXTENSION_NS;
|
import static org.jclouds.trmk.vcloud_0_8.reference.TerremarkConstants.PROPERTY_TERREMARK_EXTENSION_NS;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
@ -33,6 +34,7 @@ import org.jclouds.rest.binders.BindToStringPayload;
|
||||||
import org.jclouds.util.Patterns;
|
import org.jclouds.util.Patterns;
|
||||||
import org.jclouds.util.Strings2;
|
import org.jclouds.util.Strings2;
|
||||||
|
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -62,8 +64,12 @@ public class BindAddNodeServiceToXmlPayload implements MapBinder {
|
||||||
|
|
||||||
String payload = Strings2.replaceTokens(xmlTemplate,
|
String payload = Strings2.replaceTokens(xmlTemplate,
|
||||||
ImmutableMap.of("name", name, "ipAddress", ipAddress, "port", port, "enabled", enabled, "ns", ns));
|
ImmutableMap.of("name", name, "ipAddress", ipAddress, "port", port, "enabled", enabled, "ns", ns));
|
||||||
payload = Strings2.replaceAll(payload, Patterns.TOKEN_TO_PATTERN.get("description"), description == null ? ""
|
try {
|
||||||
: String.format("\n <Description>%s</Description>", description));
|
payload = Strings2.replaceAll(payload, Patterns.TOKEN_TO_PATTERN.get("description"), description == null ? ""
|
||||||
|
: String.format("\n <Description>%s</Description>", description));
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
}
|
||||||
return stringBinder.bindToRequest(request, payload);
|
return stringBinder.bindToRequest(request, payload);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -57,7 +57,7 @@ public interface ComputeServiceConstants {
|
||||||
public static class ReferenceData {
|
public static class ReferenceData {
|
||||||
@Inject(optional = true)
|
@Inject(optional = true)
|
||||||
@Named(PROPERTY_OS_VERSION_MAP_JSON)
|
@Named(PROPERTY_OS_VERSION_MAP_JSON)
|
||||||
public String osVersionMapJson = "{\"suse\":{\"\":\"\",\"11\":\"11\",\"11 SP1\":\"11 SP1\"},\"debian\":{\"\":\"\",\"lenny\":\"5.0\",\"squeeze\":\"6.0\"},\"centos\":{\"\":\"\",\"5\":\"5.0\",\"5.2\":\"5.2\",\"5.3\":\"5.3\",\"5.4\":\"5.4\",\"5.5\":\"5.5\"},\"rhel\":{\"\":\"\",\"5\":\"5.0\",\"5.2\":\"5.2\",\"5.3\":\"5.3\",\"5.4\":\"5.4\",\"5.5\":\"5.5\"},\"solaris\":{\"\":\"\",\"10\":\"10\"},\"ubuntu\":{\"\":\"\",\"hardy\":\"8.04\",\"karmic\":\"9.10\",\"lucid\":\"10.04\",\"10.04.1\":\"10.04\",\"maverick\":\"10.10\",\"natty\":\"11.04\",\"oneiric\":\"11.10\"},\"windows\":{\"\":\"\",\"2003\":\"2003\",\"2003 Standard\":\"2003\",\"2003 R2\":\"2003 R2\",\"2008\":\"2008\",\"2008 Web\":\"2008\",\"2008 Server\":\"2008\",\"Server 2008\":\"2008\",\"2008 R1\":\"2008 R1\",\"2008 R2\":\"2008 R2\",\"Server 2008 R2\":\"2008 R2\",\"2008 Server R2\":\"2008 R2\",\"2008 SP2\":\"2008 SP2\",\"Server 2008 SP2\":\"2008 SP2\"}}";
|
public String osVersionMapJson = "{\"suse\":{\"\":\"\",\"11\":\"11\",\"11 SP1\":\"11 SP1\"},\"debian\":{\"\":\"\",\"lenny\":\"5.0\",\"squeeze\":\"6.0\"},\"centos\":{\"\":\"\",\"5\":\"5.0\",\"5.2\":\"5.2\",\"5.3\":\"5.3\",\"5.4\":\"5.4\",\"5.5\":\"5.5\",\"5.6\":\"5.6\",\"5.7\":\"5.7\",\"6.0\":\"6.0\"},\"rhel\":{\"\":\"\",\"5\":\"5.0\",\"5.2\":\"5.2\",\"5.3\":\"5.3\",\"5.4\":\"5.4\",\"5.5\":\"5.5\",\"5.6\":\"5.6\",\"5.7\":\"5.7\",\"6.0\":\"6.0\"},\"solaris\":{\"\":\"\",\"10\":\"10\"},\"ubuntu\":{\"\":\"\",\"hardy\":\"8.04\",\"karmic\":\"9.10\",\"lucid\":\"10.04\",\"10.04.1\":\"10.04\",\"maverick\":\"10.10\",\"natty\":\"11.04\",\"oneiric\":\"11.10\"},\"windows\":{\"\":\"\",\"2003\":\"2003\",\"2003 Standard\":\"2003\",\"2003 R2\":\"2003 R2\",\"2008\":\"2008\",\"2008 Web\":\"2008\",\"2008 Server\":\"2008\",\"Server 2008\":\"2008\",\"2008 R1\":\"2008 R1\",\"2008 R2\":\"2008 R2\",\"Server 2008 R2\":\"2008 R2\",\"2008 Server R2\":\"2008 R2\",\"2008 SP2\":\"2008 SP2\",\"Server 2008 SP2\":\"2008 SP2\"}}";
|
||||||
}
|
}
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
|
|
|
@ -109,7 +109,7 @@
|
||||||
<dependency>
|
<dependency>
|
||||||
<groupId>com.google.guava</groupId>
|
<groupId>com.google.guava</groupId>
|
||||||
<artifactId>guava</artifactId>
|
<artifactId>guava</artifactId>
|
||||||
<version>r09</version>
|
<version>10.0-rc2</version>
|
||||||
</dependency>
|
</dependency>
|
||||||
</dependencies>
|
</dependencies>
|
||||||
|
|
||||||
|
|
|
@ -69,7 +69,7 @@ public class Futures {
|
||||||
// ExecutionException / CancellationException / RuntimeException
|
// ExecutionException / CancellationException / RuntimeException
|
||||||
// The task is done, run the listeners.
|
// The task is done, run the listeners.
|
||||||
}
|
}
|
||||||
executionList.run();
|
executionList.execute();
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -116,7 +116,7 @@ public class Futures {
|
||||||
if (delegate.isDone()) {
|
if (delegate.isDone()) {
|
||||||
// If the delegate is already done, run the execution list
|
// If the delegate is already done, run the execution list
|
||||||
// immediately on the current thread.
|
// immediately on the current thread.
|
||||||
executionList.run();
|
executionList.execute();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
adapterExecutor.execute(new CallGetAndRunExecutionList<T>(delegate, executionList));
|
adapterExecutor.execute(new CallGetAndRunExecutionList<T>(delegate, executionList));
|
||||||
|
|
|
@ -26,7 +26,6 @@ import java.lang.reflect.Proxy;
|
||||||
import java.util.Arrays;
|
import java.util.Arrays;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -38,6 +37,7 @@ import org.jclouds.internal.ClassMethodArgs;
|
||||||
import org.jclouds.rest.annotations.Delegate;
|
import org.jclouds.rest.annotations.Delegate;
|
||||||
import org.jclouds.util.Throwables2;
|
import org.jclouds.util.Throwables2;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
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.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
@ -62,13 +62,13 @@ public class SyncProxy implements InvocationHandler {
|
||||||
private final Map<Method, Method> methodMap;
|
private final Map<Method, Method> methodMap;
|
||||||
private final Map<Method, Method> syncMethodMap;
|
private final Map<Method, Method> syncMethodMap;
|
||||||
private final Map<Method, Long> timeoutMap;
|
private final Map<Method, Long> timeoutMap;
|
||||||
private final ConcurrentMap<ClassMethodArgs, Object> delegateMap;
|
private final Cache<ClassMethodArgs, Object> delegateMap;
|
||||||
private final Map<Class<?>, Class<?>> sync2Async;
|
private final Map<Class<?>, Class<?>> sync2Async;
|
||||||
private static final Set<Method> objectMethods = ImmutableSet.of(Object.class.getMethods());
|
private static final Set<Method> objectMethods = ImmutableSet.of(Object.class.getMethods());
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public SyncProxy(Class<?> declaring, Object async,
|
public SyncProxy(Class<?> declaring, Object async,
|
||||||
@Named("sync") ConcurrentMap<ClassMethodArgs, Object> delegateMap, Map<Class<?>, Class<?>> sync2Async)
|
@Named("sync") Cache<ClassMethodArgs, Object> delegateMap, Map<Class<?>, Class<?>> sync2Async)
|
||||||
throws SecurityException, NoSuchMethodException {
|
throws SecurityException, NoSuchMethodException {
|
||||||
this.delegateMap = delegateMap;
|
this.delegateMap = delegateMap;
|
||||||
this.delegate = async;
|
this.delegate = async;
|
||||||
|
|
|
@ -20,10 +20,11 @@ package org.jclouds.json.internal;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.lang.reflect.Type;
|
import java.lang.reflect.Type;
|
||||||
import java.util.Map;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.collect.MapMaker;
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.gson.JsonDeserializationContext;
|
import com.google.gson.JsonDeserializationContext;
|
||||||
import com.google.gson.JsonDeserializer;
|
import com.google.gson.JsonDeserializer;
|
||||||
import com.google.gson.JsonElement;
|
import com.google.gson.JsonElement;
|
||||||
|
@ -46,29 +47,26 @@ public class EnumTypeAdapterThatReturnsFromValue<T extends Enum<T>> implements J
|
||||||
try {
|
try {
|
||||||
return (T) Enum.valueOf((Class<T>) classOfT, json.getAsString());
|
return (T) Enum.valueOf((Class<T>) classOfT, json.getAsString());
|
||||||
} catch (IllegalArgumentException e) {
|
} catch (IllegalArgumentException e) {
|
||||||
Method converter = classToConvert.get(classOfT);
|
try {
|
||||||
if (converter != null)
|
Method converter = classToConvert.get((Class<?>) classOfT);
|
||||||
try {
|
return (T) converter.invoke(null, json.getAsString());
|
||||||
return (T) converter.invoke(null, json.getAsString());
|
} catch (Exception e1) {
|
||||||
} catch (Exception e1) {
|
|
||||||
throw e;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
throw e;
|
throw e;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final static Map<Class<?>, Method> classToConvert = new MapMaker()
|
private final static Cache<Class<?>, Method> classToConvert = CacheBuilder.newBuilder()
|
||||||
.makeComputingMap(new Function<Class<?>, Method>() {
|
.build(new CacheLoader<Class<?>, Method>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Method apply(Class<?> from) {
|
public Method load(Class<?> from) throws ExecutionException {
|
||||||
try {
|
try {
|
||||||
Method method = from.getMethod("fromValue", String.class);
|
Method method = from.getMethod("fromValue", String.class);
|
||||||
method.setAccessible(true);
|
method.setAccessible(true);
|
||||||
return method;
|
return method;
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
return null;
|
throw new ExecutionException(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -20,8 +20,8 @@ package org.jclouds.rest.binders;
|
||||||
|
|
||||||
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.net.InternetDomainName.fromLenient;
|
import static com.google.common.net.InternetDomainName.from;
|
||||||
import static com.google.common.net.InternetDomainName.isValidLenient;
|
import static com.google.common.net.InternetDomainName.isValid;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
|
@ -51,9 +51,9 @@ public class BindAsHostPrefix implements Binder {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
public <R extends HttpRequest> R bindToRequest(R request, Object payload) {
|
public <R extends HttpRequest> R bindToRequest(R request, Object payload) {
|
||||||
checkNotNull(payload, "hostprefix");
|
checkNotNull(payload, "hostprefix");
|
||||||
checkArgument(isValidLenient(request.getEndpoint().getHost()), "this is only valid for hostnames: " + request);
|
checkArgument(isValid(request.getEndpoint().getHost()), "this is only valid for hostnames: " + request);
|
||||||
UriBuilder builder = uriBuilderProvider.get().uri(request.getEndpoint());
|
UriBuilder builder = uriBuilderProvider.get().uri(request.getEndpoint());
|
||||||
InternetDomainName name = fromLenient(request.getEndpoint().getHost()).child(payload.toString());
|
InternetDomainName name = from(request.getEndpoint().getHost()).child(payload.toString());
|
||||||
builder.host(name.name());
|
builder.host(name.name());
|
||||||
return (R) request.toBuilder().endpoint(builder.build()).build();
|
return (R) request.toBuilder().endpoint(builder.build()).build();
|
||||||
}
|
}
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
package org.jclouds.rest.config;
|
package org.jclouds.rest.config;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
@ -28,6 +27,7 @@ import org.jclouds.concurrent.internal.SyncProxy;
|
||||||
import org.jclouds.internal.ClassMethodArgs;
|
import org.jclouds.internal.ClassMethodArgs;
|
||||||
|
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Key;
|
import com.google.inject.Key;
|
||||||
import com.google.inject.Provider;
|
import com.google.inject.Provider;
|
||||||
|
@ -58,8 +58,8 @@ public class ClientProvider<S, A> implements Provider<S> {
|
||||||
@Singleton
|
@Singleton
|
||||||
public S get() {
|
public S get() {
|
||||||
A client = (A) injector.getInstance(Key.get(asyncClientType));
|
A client = (A) injector.getInstance(Key.get(asyncClientType));
|
||||||
ConcurrentMap<ClassMethodArgs, Object> delegateMap = injector.getInstance(Key.get(
|
Cache<ClassMethodArgs, Object> delegateMap = injector.getInstance(Key.get(
|
||||||
new TypeLiteral<ConcurrentMap<ClassMethodArgs, Object>>() {
|
new TypeLiteral<Cache<ClassMethodArgs, Object>>() {
|
||||||
}, Names.named("sync")));
|
}, Names.named("sync")));
|
||||||
try {
|
try {
|
||||||
return (S) SyncProxy.proxy(syncClientType, new SyncProxy(syncClientType, client,
|
return (S) SyncProxy.proxy(syncClientType, new SyncProxy(syncClientType, client,
|
||||||
|
|
|
@ -21,35 +21,37 @@ package org.jclouds.rest.config;
|
||||||
import static com.google.common.base.Preconditions.checkState;
|
import static com.google.common.base.Preconditions.checkState;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
import javax.inject.Provider;
|
||||||
|
|
||||||
import org.jclouds.concurrent.internal.SyncProxy;
|
import org.jclouds.concurrent.internal.SyncProxy;
|
||||||
import org.jclouds.internal.ClassMethodArgs;
|
import org.jclouds.internal.ClassMethodArgs;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
|
||||||
import com.google.common.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
import com.google.inject.Provider;
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
public class CreateClientForCaller implements Function<ClassMethodArgs, Object> {
|
public class CreateClientForCaller extends CacheLoader<ClassMethodArgs, Object> {
|
||||||
private final ConcurrentMap<ClassMethodArgs, Object> asyncMap;
|
private final Cache<ClassMethodArgs, Object> asyncMap;
|
||||||
private final Provider<ConcurrentMap<ClassMethodArgs, Object>> delegateMap;
|
private final Provider<Cache<ClassMethodArgs, Object>> delegateMap;
|
||||||
Map<Class<?>, Class<?>> sync2Async;
|
Map<Class<?>, Class<?>> sync2Async;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
CreateClientForCaller(@Named("async") ConcurrentMap<ClassMethodArgs, Object> asyncMap,
|
CreateClientForCaller(@Named("async") Cache<ClassMethodArgs, Object> asyncMap,
|
||||||
@Named("sync") Provider<ConcurrentMap<ClassMethodArgs, Object>> delegateMap) {
|
@Named("sync") Provider<Cache<ClassMethodArgs, Object>> delegateMap) {
|
||||||
this.asyncMap = asyncMap;
|
this.asyncMap = asyncMap;
|
||||||
this.delegateMap = delegateMap;
|
this.delegateMap = delegateMap;
|
||||||
}
|
}
|
||||||
|
|
||||||
public Object apply(ClassMethodArgs from) {
|
@Override
|
||||||
|
public Object load(ClassMethodArgs from) throws ExecutionException {
|
||||||
Class<?> syncClass = from.getMethod().getReturnType();
|
Class<?> syncClass = from.getMethod().getReturnType();
|
||||||
Class<?> asyncClass = sync2Async.get(syncClass);
|
Class<?> asyncClass = sync2Async.get(syncClass);
|
||||||
checkState(asyncClass != null, "configuration error, sync class " + syncClass
|
checkState(asyncClass != null, "configuration error, sync class " + syncClass
|
||||||
|
|
|
@ -19,7 +19,6 @@
|
||||||
package org.jclouds.rest.config;
|
package org.jclouds.rest.config;
|
||||||
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
@ -30,8 +29,9 @@ import org.jclouds.rest.ConfiguresRestClient;
|
||||||
import org.jclouds.rest.RestContext;
|
import org.jclouds.rest.RestContext;
|
||||||
import org.jclouds.rest.internal.RestContextImpl;
|
import org.jclouds.rest.internal.RestContextImpl;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.MapMaker;
|
|
||||||
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;
|
||||||
|
@ -125,10 +125,10 @@ public class RestClientModule<S, A> extends AbstractModule {
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@Named("sync")
|
@Named("sync")
|
||||||
ConcurrentMap<ClassMethodArgs, Object> provideSyncDelegateMap(
|
Cache<ClassMethodArgs, Object> provideSyncDelegateMap(
|
||||||
CreateClientForCaller createClientForCaller) {
|
CreateClientForCaller createClientForCaller) {
|
||||||
createClientForCaller.sync2Async = delegates;
|
createClientForCaller.sync2Async = delegates;
|
||||||
return new MapMaker().makeComputingMap(createClientForCaller);
|
return CacheBuilder.newBuilder().build(createClientForCaller);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -18,8 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.rest.config;
|
package org.jclouds.rest.config;
|
||||||
|
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
import javax.ws.rs.core.UriBuilder;
|
import javax.ws.rs.core.UriBuilder;
|
||||||
|
@ -42,8 +40,10 @@ import org.jclouds.rest.internal.RestAnnotationProcessor;
|
||||||
import org.jclouds.rest.internal.SeedAnnotationCache;
|
import org.jclouds.rest.internal.SeedAnnotationCache;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.MapMaker;
|
|
||||||
import com.google.inject.AbstractModule;
|
import com.google.inject.AbstractModule;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
|
@ -77,18 +77,18 @@ public class RestModule extends AbstractModule {
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected ConcurrentMap<Class<?>, Boolean> seedAnnotationCache(SeedAnnotationCache seedAnnotationCache) {
|
protected Cache<Class<?>, Boolean> seedAnnotationCache(SeedAnnotationCache seedAnnotationCache) {
|
||||||
return new MapMaker().makeComputingMap(seedAnnotationCache);
|
return CacheBuilder.newBuilder().build(seedAnnotationCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@Named("async")
|
@Named("async")
|
||||||
ConcurrentMap<ClassMethodArgs, Object> provideAsyncDelegateMap(CreateAsyncClientForCaller createAsyncClientForCaller) {
|
Cache<ClassMethodArgs, Object> provideAsyncDelegateMap(CreateAsyncClientForCaller createAsyncClientForCaller) {
|
||||||
return new MapMaker().makeComputingMap(createAsyncClientForCaller);
|
return CacheBuilder.newBuilder().build(createAsyncClientForCaller);
|
||||||
}
|
}
|
||||||
|
|
||||||
static class CreateAsyncClientForCaller implements Function<ClassMethodArgs, Object> {
|
static class CreateAsyncClientForCaller extends CacheLoader<ClassMethodArgs, Object> {
|
||||||
private final Injector injector;
|
private final Injector injector;
|
||||||
private final AsyncRestClientProxy.Factory factory;
|
private final AsyncRestClientProxy.Factory factory;
|
||||||
|
|
||||||
|
@ -100,7 +100,7 @@ public class RestModule extends AbstractModule {
|
||||||
|
|
||||||
@SuppressWarnings( { "unchecked", "rawtypes" })
|
@SuppressWarnings( { "unchecked", "rawtypes" })
|
||||||
@Override
|
@Override
|
||||||
public Object apply(final ClassMethodArgs from) {
|
public Object load(final ClassMethodArgs from) {
|
||||||
Class clazz = from.getAsyncClass();
|
Class clazz = from.getAsyncClass();
|
||||||
TypeLiteral typeLiteral = TypeLiteral.get(clazz);
|
TypeLiteral typeLiteral = TypeLiteral.get(clazz);
|
||||||
RestAnnotationProcessor util = (RestAnnotationProcessor) injector.getInstance(Key.get(TypeLiteral.get(Types
|
RestAnnotationProcessor util = (RestAnnotationProcessor) injector.getInstance(Key.get(TypeLiteral.get(Types
|
||||||
|
@ -108,8 +108,8 @@ public class RestModule extends AbstractModule {
|
||||||
// cannot use child injectors due to the super coarse guice lock on
|
// cannot use child injectors due to the super coarse guice lock on
|
||||||
// Singleton
|
// Singleton
|
||||||
util.setCaller(from);
|
util.setCaller(from);
|
||||||
ConcurrentMap<ClassMethodArgs, Object> delegateMap = injector.getInstance(Key.get(
|
Cache<ClassMethodArgs, Object> delegateMap = injector.getInstance(Key.get(
|
||||||
new TypeLiteral<ConcurrentMap<ClassMethodArgs, Object>>() {
|
new TypeLiteral<Cache<ClassMethodArgs, Object>>() {
|
||||||
}, Names.named("async")));
|
}, Names.named("async")));
|
||||||
AsyncRestClientProxy proxy = new AsyncRestClientProxy(injector, factory, util, typeLiteral, delegateMap);
|
AsyncRestClientProxy proxy = new AsyncRestClientProxy(injector, factory, util, typeLiteral, delegateMap);
|
||||||
injector.injectMembers(proxy);
|
injector.injectMembers(proxy);
|
||||||
|
|
|
@ -27,7 +27,6 @@ import java.lang.annotation.Annotation;
|
||||||
import java.lang.reflect.InvocationHandler;
|
import java.lang.reflect.InvocationHandler;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.NoSuchElementException;
|
import java.util.NoSuchElementException;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
|
||||||
import java.util.concurrent.ExecutionException;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
|
@ -49,6 +48,7 @@ import org.jclouds.util.Throwables2;
|
||||||
|
|
||||||
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.cache.Cache;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
import com.google.common.util.concurrent.Futures;
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
@ -76,12 +76,12 @@ public class AsyncRestClientProxy<T> implements InvocationHandler {
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
private final ConcurrentMap<ClassMethodArgs, Object> delegateMap;
|
private final Cache<ClassMethodArgs, Object> delegateMap;
|
||||||
|
|
||||||
@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") Cache<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();
|
||||||
|
|
|
@ -49,9 +49,8 @@ import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.SortedSet;
|
import java.util.SortedSet;
|
||||||
import java.util.concurrent.ConcurrentMap;
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import org.jclouds.javax.annotation.Nullable;
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Provider;
|
import javax.inject.Provider;
|
||||||
|
@ -98,6 +97,7 @@ import org.jclouds.io.Payloads;
|
||||||
import org.jclouds.io.payloads.MultipartForm;
|
import org.jclouds.io.payloads.MultipartForm;
|
||||||
import org.jclouds.io.payloads.Part;
|
import org.jclouds.io.payloads.Part;
|
||||||
import org.jclouds.io.payloads.Part.PartOptions;
|
import org.jclouds.io.payloads.Part.PartOptions;
|
||||||
|
import org.jclouds.javax.annotation.Nullable;
|
||||||
import org.jclouds.json.internal.GsonWrapper;
|
import org.jclouds.json.internal.GsonWrapper;
|
||||||
import org.jclouds.logging.Logger;
|
import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.Binder;
|
import org.jclouds.rest.Binder;
|
||||||
|
@ -137,6 +137,10 @@ import com.google.common.base.Function;
|
||||||
import com.google.common.base.Functions;
|
import com.google.common.base.Functions;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Predicates;
|
import com.google.common.base.Predicates;
|
||||||
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
@ -145,7 +149,6 @@ import com.google.common.collect.Iterables;
|
||||||
import com.google.common.collect.LinkedHashMultimap;
|
import com.google.common.collect.LinkedHashMultimap;
|
||||||
import com.google.common.collect.LinkedListMultimap;
|
import com.google.common.collect.LinkedListMultimap;
|
||||||
import com.google.common.collect.Lists;
|
import com.google.common.collect.Lists;
|
||||||
import com.google.common.collect.MapMaker;
|
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
@ -167,25 +170,25 @@ public class RestAnnotationProcessor<T> {
|
||||||
private final Class<T> declaring;
|
private final Class<T> declaring;
|
||||||
|
|
||||||
// TODO replace with Table object
|
// TODO replace with Table object
|
||||||
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToBinderParamAnnotation = createMethodToIndexOfParamToAnnotation(BinderParam.class);
|
static final Cache<Method, Cache<Integer, Set<Annotation>>> methodToIndexOfParamToBinderParamAnnotation = createMethodToIndexOfParamToAnnotation(BinderParam.class);
|
||||||
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToWrapWithAnnotation = createMethodToIndexOfParamToAnnotation(WrapWith.class);
|
static final Cache<Method, Cache<Integer, Set<Annotation>>> methodToIndexOfParamToWrapWithAnnotation = createMethodToIndexOfParamToAnnotation(WrapWith.class);
|
||||||
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToHeaderParamAnnotations = createMethodToIndexOfParamToAnnotation(HeaderParam.class);
|
static final Cache<Method, Cache<Integer, Set<Annotation>>> methodToIndexOfParamToHeaderParamAnnotations = createMethodToIndexOfParamToAnnotation(HeaderParam.class);
|
||||||
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToEndpointAnnotations = createMethodToIndexOfParamToAnnotation(Endpoint.class);
|
static final Cache<Method, Cache<Integer, Set<Annotation>>> methodToIndexOfParamToEndpointAnnotations = createMethodToIndexOfParamToAnnotation(Endpoint.class);
|
||||||
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToEndpointParamAnnotations = createMethodToIndexOfParamToAnnotation(EndpointParam.class);
|
static final Cache<Method, Cache<Integer, Set<Annotation>>> methodToIndexOfParamToEndpointParamAnnotations = createMethodToIndexOfParamToAnnotation(EndpointParam.class);
|
||||||
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToMatrixParamAnnotations = createMethodToIndexOfParamToAnnotation(MatrixParam.class);
|
static final Cache<Method, Cache<Integer, Set<Annotation>>> methodToIndexOfParamToMatrixParamAnnotations = createMethodToIndexOfParamToAnnotation(MatrixParam.class);
|
||||||
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToFormParamAnnotations = createMethodToIndexOfParamToAnnotation(FormParam.class);
|
static final Cache<Method, Cache<Integer, Set<Annotation>>> methodToIndexOfParamToFormParamAnnotations = createMethodToIndexOfParamToAnnotation(FormParam.class);
|
||||||
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToQueryParamAnnotations = createMethodToIndexOfParamToAnnotation(QueryParam.class);
|
static final Cache<Method, Cache<Integer, Set<Annotation>>> methodToIndexOfParamToQueryParamAnnotations = createMethodToIndexOfParamToAnnotation(QueryParam.class);
|
||||||
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToPathParamAnnotations = createMethodToIndexOfParamToAnnotation(PathParam.class);
|
static final Cache<Method, Cache<Integer, Set<Annotation>>> methodToIndexOfParamToPathParamAnnotations = createMethodToIndexOfParamToAnnotation(PathParam.class);
|
||||||
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToPostParamAnnotations = createMethodToIndexOfParamToAnnotation(PayloadParam.class);
|
static final Cache<Method, Cache<Integer, Set<Annotation>>> methodToIndexOfParamToPostParamAnnotations = createMethodToIndexOfParamToAnnotation(PayloadParam.class);
|
||||||
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToPartParamAnnotations = createMethodToIndexOfParamToAnnotation(PartParam.class);
|
static final Cache<Method, Cache<Integer, Set<Annotation>>> methodToIndexOfParamToPartParamAnnotations = createMethodToIndexOfParamToAnnotation(PartParam.class);
|
||||||
static final Map<Method, Map<Integer, Set<Annotation>>> methodToIndexOfParamToParamParserAnnotations = createMethodToIndexOfParamToAnnotation(ParamParser.class);
|
static final Cache<Method, Cache<Integer, Set<Annotation>>> methodToIndexOfParamToParamParserAnnotations = createMethodToIndexOfParamToAnnotation(ParamParser.class);
|
||||||
static final Map<MethodKey, Method> delegationMap = newHashMap();
|
static final Map<MethodKey, Method> delegationMap = newHashMap();
|
||||||
|
|
||||||
static Map<Method, Map<Integer, Set<Annotation>>> createMethodToIndexOfParamToAnnotation(
|
static Cache<Method, Cache<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 CacheBuilder.newBuilder().build(new CacheLoader<Method, Cache<Integer, Set<Annotation>>>() {
|
||||||
public Map<Integer, Set<Annotation>> apply(Method method) {
|
public Cache<Integer, Set<Annotation>> load(Method method) {
|
||||||
return new MapMaker().makeComputingMap(new GetAnnotationsForMethodParameterIndex(method, annotation));
|
return CacheBuilder.newBuilder().build(CacheLoader.from(new GetAnnotationsForMethodParameterIndex(method, annotation)));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
@ -201,17 +204,17 @@ public class RestAnnotationProcessor<T> {
|
||||||
|
|
||||||
public Set<Annotation> apply(final Integer index) {
|
public Set<Annotation> apply(final Integer index) {
|
||||||
return ImmutableSet.<Annotation> copyOf(filter(ImmutableList.copyOf(method.getParameterAnnotations()[index]),
|
return ImmutableSet.<Annotation> copyOf(filter(ImmutableList.copyOf(method.getParameterAnnotations()[index]),
|
||||||
new Predicate<Annotation>() {
|
new Predicate<Annotation>() {
|
||||||
public boolean apply(Annotation input) {
|
public boolean apply(Annotation input) {
|
||||||
return input.annotationType().equals(clazz);
|
return input.annotationType().equals(clazz);
|
||||||
}
|
}
|
||||||
}));
|
}));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
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>() {
|
||||||
|
|
||||||
|
@ -222,23 +225,24 @@ public class RestAnnotationProcessor<T> {
|
||||||
|
|
||||||
};
|
};
|
||||||
|
|
||||||
static final Map<Method, Set<Integer>> methodToIndexesOfOptions = new MapMaker()
|
static final Cache<Method, Set<Integer>> methodToIndexesOfOptions = CacheBuilder.newBuilder().build(
|
||||||
.makeComputingMap(new Function<Method, Set<Integer>>() {
|
new CacheLoader<Method, Set<Integer>>() {
|
||||||
public Set<Integer> apply(Method method) {
|
@Override
|
||||||
Builder<Integer> toReturn = ImmutableSet.<Integer> builder();
|
public Set<Integer> load(Method method) {
|
||||||
for (int index = 0; index < method.getParameterTypes().length; index++) {
|
Builder<Integer> toReturn = ImmutableSet.<Integer> builder();
|
||||||
Class<?> type = method.getParameterTypes()[index];
|
for (int index = 0; index < method.getParameterTypes().length; index++) {
|
||||||
if (HttpRequestOptions.class.isAssignableFrom(type) || optionsVarArgsClass.isAssignableFrom(type))
|
Class<?> type = method.getParameterTypes()[index];
|
||||||
toReturn.add(index);
|
if (HttpRequestOptions.class.isAssignableFrom(type) || optionsVarArgsClass.isAssignableFrom(type))
|
||||||
}
|
toReturn.add(index);
|
||||||
return toReturn.build();
|
|
||||||
}
|
}
|
||||||
});
|
return toReturn.build();
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
private final ParseSax.Factory parserFactory;
|
private final ParseSax.Factory parserFactory;
|
||||||
private final HttpUtils utils;
|
private final HttpUtils utils;
|
||||||
private final Provider<UriBuilder> uriBuilderProvider;
|
private final Provider<UriBuilder> uriBuilderProvider;
|
||||||
private final ConcurrentMap<Class<?>, Boolean> seedAnnotationCache;
|
private final Cache<Class<?>, Boolean> seedAnnotationCache;
|
||||||
private final String apiVersion;
|
private final String apiVersion;
|
||||||
private char[] skips;
|
private char[] skips;
|
||||||
|
|
||||||
|
@ -252,7 +256,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) {
|
||||||
|
@ -272,9 +276,9 @@ public class RestAnnotationProcessor<T> {
|
||||||
if (method.isAnnotationPresent(SelectJson.class)) {
|
if (method.isAnnotationPresent(SelectJson.class)) {
|
||||||
Type returnVal = getReturnTypeForMethod(method);
|
Type returnVal = getReturnTypeForMethod(method);
|
||||||
if (method.isAnnotationPresent(OnlyElement.class))
|
if (method.isAnnotationPresent(OnlyElement.class))
|
||||||
returnVal = Types.newParameterizedType(Set.class,returnVal);
|
returnVal = Types.newParameterizedType(Set.class, returnVal);
|
||||||
transformer = new ParseFirstJsonValueNamed(injector.getInstance(GsonWrapper.class), TypeLiteral.get(returnVal),
|
transformer = new ParseFirstJsonValueNamed(injector.getInstance(GsonWrapper.class),
|
||||||
method.getAnnotation(SelectJson.class).value());
|
TypeLiteral.get(returnVal), method.getAnnotation(SelectJson.class).value());
|
||||||
if (method.isAnnotationPresent(OnlyElement.class))
|
if (method.isAnnotationPresent(OnlyElement.class))
|
||||||
transformer = Functions.compose(new OnlyElementOrNull(), transformer);
|
transformer = Functions.compose(new OnlyElementOrNull(), transformer);
|
||||||
} else {
|
} else {
|
||||||
|
@ -290,7 +294,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());
|
||||||
|
@ -300,9 +304,9 @@ public class RestAnnotationProcessor<T> {
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Inject
|
@Inject
|
||||||
public RestAnnotationProcessor(Injector injector, ConcurrentMap<Class<?>, Boolean> seedAnnotationCache,
|
public RestAnnotationProcessor(Injector injector, Cache<Class<?>, Boolean> seedAnnotationCache,
|
||||||
@Named(Constants.PROPERTY_API_VERSION) String apiVersion, ParseSax.Factory parserFactory, HttpUtils utils,
|
@Named(Constants.PROPERTY_API_VERSION) String apiVersion, ParseSax.Factory parserFactory, HttpUtils utils,
|
||||||
TypeLiteral<T> typeLiteral) {
|
TypeLiteral<T> typeLiteral) throws ExecutionException {
|
||||||
this.declaring = (Class<T>) typeLiteral.getRawType();
|
this.declaring = (Class<T>) typeLiteral.getRawType();
|
||||||
this.injector = injector;
|
this.injector = injector;
|
||||||
this.parserFactory = parserFactory;
|
this.parserFactory = parserFactory;
|
||||||
|
@ -366,8 +370,8 @@ public class RestAnnotationProcessor<T> {
|
||||||
this.name = method.getName();
|
this.name = method.getName();
|
||||||
this.declaringPackage = method.getDeclaringClass().getPackage();
|
this.declaringPackage = method.getDeclaringClass().getPackage();
|
||||||
int parametersTypeHashCode = 0;
|
int parametersTypeHashCode = 0;
|
||||||
for (Class<?> param: method.getParameterTypes())
|
for (Class<?> param : method.getParameterTypes())
|
||||||
parametersTypeHashCode +=param.hashCode();
|
parametersTypeHashCode += param.hashCode();
|
||||||
this.parametersTypeHashCode = parametersTypeHashCode;
|
this.parametersTypeHashCode = parametersTypeHashCode;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,154 +383,166 @@ public class RestAnnotationProcessor<T> {
|
||||||
private URI callerEndpoint;
|
private URI callerEndpoint;
|
||||||
|
|
||||||
public void setCaller(ClassMethodArgs caller) {
|
public void setCaller(ClassMethodArgs caller) {
|
||||||
seedAnnotationCache.get(caller.getMethod().getDeclaringClass());
|
try {
|
||||||
|
seedAnnotationCache.get(caller.getMethod().getDeclaringClass());
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
}
|
||||||
this.caller = caller;
|
this.caller = caller;
|
||||||
try {
|
try {
|
||||||
callerEndpoint = getEndpointFor(caller.getMethod(), caller.getArgs(), injector);
|
callerEndpoint = getEndpointFor(caller.getMethod(), caller.getArgs(), injector);
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public GeneratedHttpRequest<T> createRequest(Method method, Object... args) {
|
public GeneratedHttpRequest<T> createRequest(Method method, Object... args) {
|
||||||
inputParamValidator.validateMethodParametersOrThrow(method, args);
|
try {
|
||||||
ClassMethodArgs cma = logger.isTraceEnabled() ? new ClassMethodArgs(method.getDeclaringClass(), method, args)
|
inputParamValidator.validateMethodParametersOrThrow(method, args);
|
||||||
|
ClassMethodArgs cma = logger.isTraceEnabled() ? new ClassMethodArgs(method.getDeclaringClass(), method, args)
|
||||||
: null;
|
: null;
|
||||||
|
|
||||||
URI endpoint = callerEndpoint;
|
URI endpoint = callerEndpoint;
|
||||||
try {
|
try {
|
||||||
if (endpoint == null) {
|
if (endpoint == null) {
|
||||||
endpoint = getEndpointFor(method, args, injector);
|
endpoint = getEndpointFor(method, args, injector);
|
||||||
logger.trace("using endpoint %s for %s", endpoint, cma);
|
logger.trace("using endpoint %s for %s", endpoint, cma);
|
||||||
|
} else {
|
||||||
|
logger.trace("using endpoint %s from caller %s for %s", caller, endpoint, cma);
|
||||||
|
}
|
||||||
|
} catch (IllegalStateException e) {
|
||||||
|
logger.trace("looking up default endpoint for %s", cma);
|
||||||
|
endpoint = injector.getInstance(Key.get(URI.class, org.jclouds.location.Provider.class));
|
||||||
|
logger.trace("using default endpoint %s for %s", endpoint, cma);
|
||||||
|
}
|
||||||
|
GeneratedHttpRequest.Builder<T> requestBuilder;
|
||||||
|
HttpRequest r = RestAnnotationProcessor.findHttpRequestInArgs(args);
|
||||||
|
if (r != null) {
|
||||||
|
requestBuilder = GeneratedHttpRequest.Builder.<T> from(r);
|
||||||
|
endpoint = r.getEndpoint();
|
||||||
} else {
|
} else {
|
||||||
logger.trace("using endpoint %s from caller %s for %s", caller, endpoint, cma);
|
requestBuilder = GeneratedHttpRequest.<T> builder();
|
||||||
}
|
requestBuilder.method(getHttpMethodOrConstantOrThrowException(method));
|
||||||
} catch (IllegalStateException e) {
|
|
||||||
logger.trace("looking up default endpoint for %s", cma);
|
|
||||||
endpoint = injector.getInstance(Key.get(URI.class, org.jclouds.location.Provider.class));
|
|
||||||
logger.trace("using default endpoint %s for %s", endpoint, cma);
|
|
||||||
}
|
|
||||||
GeneratedHttpRequest.Builder<T> requestBuilder;
|
|
||||||
HttpRequest r = RestAnnotationProcessor.findHttpRequestInArgs(args);
|
|
||||||
if (r != null) {
|
|
||||||
requestBuilder = GeneratedHttpRequest.Builder.<T> from(r);
|
|
||||||
endpoint = r.getEndpoint();
|
|
||||||
} else {
|
|
||||||
requestBuilder = GeneratedHttpRequest.<T> builder();
|
|
||||||
requestBuilder.method(getHttpMethodOrConstantOrThrowException(method));
|
|
||||||
}
|
|
||||||
|
|
||||||
requestBuilder.declaring(declaring).javaMethod(method).args(args).skips(skips);
|
|
||||||
requestBuilder.filters(getFiltersIfAnnotated(method));
|
|
||||||
|
|
||||||
UriBuilder builder = uriBuilderProvider.get().uri(endpoint);
|
|
||||||
|
|
||||||
Multimap<String, String> tokenValues = LinkedHashMultimap.create();
|
|
||||||
|
|
||||||
tokenValues.put(Constants.PROPERTY_API_VERSION, apiVersion);
|
|
||||||
|
|
||||||
tokenValues.putAll(addPathAndGetTokens(declaring, method, args, builder));
|
|
||||||
|
|
||||||
Multimap<String, String> formParams = addFormParams(tokenValues.entries(), method, args);
|
|
||||||
Multimap<String, String> queryParams = addQueryParams(tokenValues.entries(), method, args);
|
|
||||||
Multimap<String, String> matrixParams = addMatrixParams(tokenValues.entries(), method, args);
|
|
||||||
Multimap<String, String> headers = buildHeaders(tokenValues.entries(), method, args);
|
|
||||||
if (r != null)
|
|
||||||
headers.putAll(r.getHeaders());
|
|
||||||
|
|
||||||
if (shouldAddHostHeader(method)) {
|
|
||||||
StringBuilder hostHeader = new StringBuilder(endpoint.getHost());
|
|
||||||
if (endpoint.getPort() != -1)
|
|
||||||
hostHeader.append(":").append(endpoint.getPort());
|
|
||||||
headers.put(HOST, hostHeader.toString());
|
|
||||||
}
|
|
||||||
|
|
||||||
Payload payload = null;
|
|
||||||
HttpRequestOptions options = findOptionsIn(method, args);
|
|
||||||
if (options != null) {
|
|
||||||
injector.injectMembers(options);// TODO test case
|
|
||||||
for (Entry<String, String> header : options.buildRequestHeaders().entries()) {
|
|
||||||
headers.put(header.getKey(), Strings2.replaceTokens(header.getValue(), tokenValues.entries()));
|
|
||||||
}
|
|
||||||
for (Entry<String, String> matrix : options.buildMatrixParameters().entries()) {
|
|
||||||
matrixParams.put(matrix.getKey(), Strings2.replaceTokens(matrix.getValue(), tokenValues.entries()));
|
|
||||||
}
|
|
||||||
for (Entry<String, String> query : options.buildQueryParameters().entries()) {
|
|
||||||
queryParams.put(query.getKey(), Strings2.replaceTokens(query.getValue(), tokenValues.entries()));
|
|
||||||
}
|
|
||||||
for (Entry<String, String> form : options.buildFormParameters().entries()) {
|
|
||||||
formParams.put(form.getKey(), Strings2.replaceTokens(form.getValue(), tokenValues.entries()));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String pathSuffix = options.buildPathSuffix();
|
requestBuilder.declaring(declaring).javaMethod(method).args(args).skips(skips);
|
||||||
if (pathSuffix != null) {
|
requestBuilder.filters(getFiltersIfAnnotated(method));
|
||||||
builder.path(pathSuffix);
|
|
||||||
|
UriBuilder builder = uriBuilderProvider.get().uri(endpoint);
|
||||||
|
|
||||||
|
Multimap<String, String> tokenValues = LinkedHashMultimap.create();
|
||||||
|
|
||||||
|
tokenValues.put(Constants.PROPERTY_API_VERSION, apiVersion);
|
||||||
|
|
||||||
|
tokenValues.putAll(addPathAndGetTokens(declaring, method, args, builder));
|
||||||
|
|
||||||
|
Multimap<String, String> formParams = addFormParams(tokenValues.entries(), method, args);
|
||||||
|
Multimap<String, String> queryParams = addQueryParams(tokenValues.entries(), method, args);
|
||||||
|
Multimap<String, String> matrixParams = addMatrixParams(tokenValues.entries(), method, args);
|
||||||
|
Multimap<String, String> headers = buildHeaders(tokenValues.entries(), method, args);
|
||||||
|
if (r != null)
|
||||||
|
headers.putAll(r.getHeaders());
|
||||||
|
|
||||||
|
if (shouldAddHostHeader(method)) {
|
||||||
|
StringBuilder hostHeader = new StringBuilder(endpoint.getHost());
|
||||||
|
if (endpoint.getPort() != -1)
|
||||||
|
hostHeader.append(":").append(endpoint.getPort());
|
||||||
|
headers.put(HOST, hostHeader.toString());
|
||||||
}
|
}
|
||||||
String stringPayload = options.buildStringPayload();
|
|
||||||
if (stringPayload != null)
|
|
||||||
payload = Payloads.newStringPayload(stringPayload);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (matrixParams.size() > 0) {
|
Payload payload = null;
|
||||||
for (String key : matrixParams.keySet())
|
HttpRequestOptions options = findOptionsIn(method, args);
|
||||||
builder.matrixParam(key, Lists.newArrayList(matrixParams.get(key)).toArray());
|
if (options != null) {
|
||||||
}
|
injector.injectMembers(options);// TODO test case
|
||||||
|
for (Entry<String, String> header : options.buildRequestHeaders().entries()) {
|
||||||
|
headers.put(header.getKey(), Strings2.replaceTokens(header.getValue(), tokenValues.entries()));
|
||||||
|
}
|
||||||
|
for (Entry<String, String> matrix : options.buildMatrixParameters().entries()) {
|
||||||
|
matrixParams.put(matrix.getKey(), Strings2.replaceTokens(matrix.getValue(), tokenValues.entries()));
|
||||||
|
}
|
||||||
|
for (Entry<String, String> query : options.buildQueryParameters().entries()) {
|
||||||
|
queryParams.put(query.getKey(), Strings2.replaceTokens(query.getValue(), tokenValues.entries()));
|
||||||
|
}
|
||||||
|
for (Entry<String, String> form : options.buildFormParameters().entries()) {
|
||||||
|
formParams.put(form.getKey(), Strings2.replaceTokens(form.getValue(), tokenValues.entries()));
|
||||||
|
}
|
||||||
|
|
||||||
if (queryParams.size() > 0) {
|
String pathSuffix = options.buildPathSuffix();
|
||||||
builder.replaceQuery(ModifyRequest.makeQueryLine(queryParams, null, skips));
|
if (pathSuffix != null) {
|
||||||
}
|
builder.path(pathSuffix);
|
||||||
|
}
|
||||||
requestBuilder.headers(filterOutContentHeaders(headers));
|
String stringPayload = options.buildStringPayload();
|
||||||
|
if (stringPayload != null)
|
||||||
try {
|
payload = Payloads.newStringPayload(stringPayload);
|
||||||
requestBuilder.endpoint(builder.buildFromEncodedMap(Maps2.convertUnsafe(tokenValues)));
|
|
||||||
} catch (IllegalArgumentException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
} catch (UriBuilderException e) {
|
|
||||||
throw new IllegalStateException(e);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (payload == null)
|
|
||||||
payload = findPayloadInArgs(args);
|
|
||||||
List<? extends Part> parts = getParts(method, args, concat(tokenValues.entries(), formParams.entries()));
|
|
||||||
if (parts.size() > 0) {
|
|
||||||
if (formParams.size() > 0) {
|
|
||||||
parts = newLinkedList(concat(transform(formParams.entries(), ENTRY_TO_PART), parts));
|
|
||||||
}
|
}
|
||||||
payload = new MultipartForm(BOUNDARY, parts);
|
|
||||||
} else if (formParams.size() > 0) {
|
if (matrixParams.size() > 0) {
|
||||||
payload = Payloads.newUrlEncodedFormPayload(formParams, skips);
|
for (String key : matrixParams.keySet())
|
||||||
} else if (headers.containsKey(CONTENT_TYPE)) {
|
builder.matrixParam(key, Lists.newArrayList(matrixParams.get(key)).toArray());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (queryParams.size() > 0) {
|
||||||
|
builder.replaceQuery(ModifyRequest.makeQueryLine(queryParams, null, skips));
|
||||||
|
}
|
||||||
|
|
||||||
|
requestBuilder.headers(filterOutContentHeaders(headers));
|
||||||
|
|
||||||
|
try {
|
||||||
|
requestBuilder.endpoint(builder.buildFromEncodedMap(Maps2.convertUnsafe(tokenValues)));
|
||||||
|
} catch (IllegalArgumentException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
} catch (UriBuilderException e) {
|
||||||
|
throw new IllegalStateException(e);
|
||||||
|
}
|
||||||
|
|
||||||
if (payload == null)
|
if (payload == null)
|
||||||
payload = Payloads.newByteArrayPayload(new byte[] {});
|
payload = findPayloadInArgs(args);
|
||||||
payload.getContentMetadata().setContentType(Iterables.get(headers.get(CONTENT_TYPE), 0));
|
List<? extends Part> parts = getParts(method, args, concat(tokenValues.entries(), formParams.entries()));
|
||||||
}
|
if (parts.size() > 0) {
|
||||||
if (payload != null) {
|
if (formParams.size() > 0) {
|
||||||
requestBuilder.payload(payload);
|
parts = newLinkedList(concat(transform(formParams.entries(), ENTRY_TO_PART), parts));
|
||||||
}
|
}
|
||||||
GeneratedHttpRequest<T> request = requestBuilder.build();
|
payload = new MultipartForm(BOUNDARY, parts);
|
||||||
|
} else if (formParams.size() > 0) {
|
||||||
org.jclouds.rest.MapBinder mapBinder = getMapPayloadBinderOrNull(method, args);
|
payload = Payloads.newUrlEncodedFormPayload(formParams, skips);
|
||||||
if (mapBinder != null) {
|
} else if (headers.containsKey(CONTENT_TYPE)) {
|
||||||
Map<String, String> mapParams = buildPostParams(method, args);
|
if (payload == null)
|
||||||
if (method.isAnnotationPresent(PayloadParams.class)) {
|
payload = Payloads.newByteArrayPayload(new byte[] {});
|
||||||
PayloadParams params = method.getAnnotation(PayloadParams.class);
|
payload.getContentMetadata().setContentType(Iterables.get(headers.get(CONTENT_TYPE), 0));
|
||||||
addMapPayload(mapParams, params, headers.entries());
|
|
||||||
}
|
}
|
||||||
request = mapBinder.bindToRequest(request, mapParams);
|
if (payload != null) {
|
||||||
} else {
|
requestBuilder.payload(payload);
|
||||||
request = decorateRequest(request);
|
}
|
||||||
}
|
GeneratedHttpRequest<T> request = requestBuilder.build();
|
||||||
|
|
||||||
if (request.getPayload() != null)
|
org.jclouds.rest.MapBinder mapBinder = getMapPayloadBinderOrNull(method, args);
|
||||||
request.getPayload().getContentMetadata().setPropertiesFromHttpHeaders(headers);
|
if (mapBinder != null) {
|
||||||
utils.checkRequestHasRequiredProperties(request);
|
Map<String, String> mapParams = buildPostParams(method, args);
|
||||||
return request;
|
if (method.isAnnotationPresent(PayloadParams.class)) {
|
||||||
|
PayloadParams params = method.getAnnotation(PayloadParams.class);
|
||||||
|
addMapPayload(mapParams, params, headers.entries());
|
||||||
|
}
|
||||||
|
request = mapBinder.bindToRequest(request, mapParams);
|
||||||
|
} else {
|
||||||
|
request = decorateRequest(request);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.getPayload() != null)
|
||||||
|
request.getPayload().getContentMetadata().setPropertiesFromHttpHeaders(headers);
|
||||||
|
utils.checkRequestHasRequiredProperties(request);
|
||||||
|
return request;
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
Throwables.propagate(e);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static Multimap<String, String> filterOutContentHeaders(Multimap<String, String> headers) {
|
public static Multimap<String, String> filterOutContentHeaders(Multimap<String, String> headers) {
|
||||||
// TODO make a filter like {@link Maps.filterKeys} instead of this
|
// TODO make a filter like {@link Maps.filterKeys} instead of this
|
||||||
ImmutableMultimap.Builder<String, String> headersBuilder = ImmutableMultimap.builder();
|
ImmutableMultimap.Builder<String, String> headersBuilder = ImmutableMultimap.builder();
|
||||||
// http message usually comes in as a null key header, let's filter it out.
|
// http message usually comes in as a null key header, let's filter it
|
||||||
|
// out.
|
||||||
for (String header : Iterables.filter(headers.keySet(), Predicates.notNull())) {
|
for (String header : Iterables.filter(headers.keySet(), Predicates.notNull())) {
|
||||||
if (!ContentMetadata.HTTP_HEADERS.contains(header)) {
|
if (!ContentMetadata.HTTP_HEADERS.contains(header)) {
|
||||||
headersBuilder.putAll(header, headers.get(header));
|
headersBuilder.putAll(header, headers.get(header));
|
||||||
|
@ -537,7 +553,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
|
|
||||||
public static final String BOUNDARY = "--JCLOUDS--";
|
public static final String BOUNDARY = "--JCLOUDS--";
|
||||||
|
|
||||||
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) throws ExecutionException {
|
||||||
if (clazz.isAnnotationPresent(Path.class))
|
if (clazz.isAnnotationPresent(Path.class))
|
||||||
builder.path(clazz);
|
builder.path(clazz);
|
||||||
if (method.isAnnotationPresent(Path.class))
|
if (method.isAnnotationPresent(Path.class))
|
||||||
|
@ -550,14 +566,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(ModifyRequest.makeQueryLine(ModifyRequest.parseQueryToMap(newQuery), sorter, skips));
|
builder.replaceQuery(ModifyRequest.makeQueryLine(ModifyRequest.parseQueryToMap(newQuery), sorter, skips));
|
||||||
return builder.build();
|
return builder.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Multimap<String, String> addMatrixParams(Collection<Entry<String, String>> tokenValues, Method method,
|
private Multimap<String, String> addMatrixParams(Collection<Entry<String, String>> tokenValues, Method method,
|
||||||
Object... args) {
|
Object... args) throws ExecutionException {
|
||||||
Multimap<String, String> matrixMap = LinkedListMultimap.create();
|
Multimap<String, String> matrixMap = LinkedListMultimap.create();
|
||||||
if (declaring.isAnnotationPresent(MatrixParams.class)) {
|
if (declaring.isAnnotationPresent(MatrixParams.class)) {
|
||||||
MatrixParams matrix = declaring.getAnnotation(MatrixParams.class);
|
MatrixParams matrix = declaring.getAnnotation(MatrixParams.class);
|
||||||
|
@ -576,7 +592,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) throws ExecutionException {
|
||||||
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);
|
||||||
|
@ -595,7 +611,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) throws ExecutionException {
|
||||||
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);
|
||||||
|
@ -614,7 +630,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]);
|
||||||
|
@ -626,7 +642,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]);
|
||||||
|
@ -638,7 +654,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addMatrix(Multimap<String, String> matrixParams, MatrixParams matrix,
|
private void addMatrix(Multimap<String, String> matrixParams, MatrixParams matrix,
|
||||||
Collection<Entry<String, String>> tokenValues) {
|
Collection<Entry<String, String>> tokenValues) {
|
||||||
for (int i = 0; i < matrix.keys().length; i++) {
|
for (int i = 0; i < matrix.keys().length; i++) {
|
||||||
if (matrix.values()[i].equals(MatrixParams.NULL)) {
|
if (matrix.values()[i].equals(MatrixParams.NULL)) {
|
||||||
matrixParams.removeAll(matrix.keys()[i]);
|
matrixParams.removeAll(matrix.keys()[i]);
|
||||||
|
@ -650,7 +666,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void addMapPayload(Map<String, String> postParams, PayloadParams mapDefaults,
|
private void addMapPayload(Map<String, String> postParams, PayloadParams mapDefaults,
|
||||||
Collection<Entry<String, String>> tokenValues) {
|
Collection<Entry<String, String>> tokenValues) {
|
||||||
for (int i = 0; i < mapDefaults.keys().length; i++) {
|
for (int i = 0; i < mapDefaults.keys().length; i++) {
|
||||||
if (mapDefaults.values()[i].equals(PayloadParams.NULL)) {
|
if (mapDefaults.values()[i].equals(PayloadParams.NULL)) {
|
||||||
postParams.put(mapDefaults.keys()[i], null);
|
postParams.put(mapDefaults.keys()[i], null);
|
||||||
|
@ -683,9 +699,10 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
|
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
public static URI getEndpointInParametersOrNull(Method method, final Object[] args, Injector injector) {
|
public static URI getEndpointInParametersOrNull(Method method, final Object[] args, Injector injector)
|
||||||
|
throws ExecutionException {
|
||||||
Map<Integer, Set<Annotation>> map = indexWithAtLeastOneAnnotation(method,
|
Map<Integer, Set<Annotation>> map = indexWithAtLeastOneAnnotation(method,
|
||||||
methodToIndexOfParamToEndpointParamAnnotations);
|
methodToIndexOfParamToEndpointParamAnnotations);
|
||||||
if (map.size() >= 1 && args.length > 0) {
|
if (map.size() >= 1 && args.length > 0) {
|
||||||
EndpointParam firstAnnotation = (EndpointParam) get(get(map.values(), 0), 0);
|
EndpointParam firstAnnotation = (EndpointParam) get(get(map.values(), 0), 0);
|
||||||
Function<Object, URI> parser = injector.getInstance(firstAnnotation.parser());
|
Function<Object, URI> parser = injector.getInstance(firstAnnotation.parser());
|
||||||
|
@ -694,8 +711,8 @@ public class RestAnnotationProcessor<T> {
|
||||||
int index = map.keySet().iterator().next();
|
int index = map.keySet().iterator().next();
|
||||||
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,
|
||||||
method));
|
String.format("endpoint for [%s] not configured for %s", args[index], 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);
|
||||||
|
@ -712,19 +729,19 @@ public class RestAnnotationProcessor<T> {
|
||||||
});
|
});
|
||||||
try {
|
try {
|
||||||
URI returnVal = parser.apply(argsToParse);
|
URI returnVal = parser.apply(argsToParse);
|
||||||
checkArgument(returnVal != null, String.format("endpoint for [%s] not configured for %s", argsToParse,
|
checkArgument(returnVal != null,
|
||||||
method));
|
String.format("endpoint for [%s] not configured for %s", argsToParse, method));
|
||||||
return returnVal;
|
return returnVal;
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
throw new IllegalArgumentException(String.format("illegal argument in [%s] for method %s", argsToParse,
|
throw new IllegalArgumentException(String.format("illegal argument in [%s] for method %s", argsToParse,
|
||||||
method), e);
|
method), e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static URI getEndpointFor(Method method, Object[] args, Injector injector) {
|
public static URI getEndpointFor(Method method, Object[] args, Injector injector) throws ExecutionException {
|
||||||
URI endpoint = getEndpointInParametersOrNull(method, args, injector);
|
URI endpoint = getEndpointInParametersOrNull(method, args, injector);
|
||||||
if (endpoint == null) {
|
if (endpoint == null) {
|
||||||
Endpoint annotation;
|
Endpoint annotation;
|
||||||
|
@ -753,29 +770,29 @@ public class RestAnnotationProcessor<T> {
|
||||||
public static final TypeLiteral<ListenableFuture<HttpResponse>> futureHttpResponseLiteral = new TypeLiteral<ListenableFuture<HttpResponse>>() {
|
public static final TypeLiteral<ListenableFuture<HttpResponse>> futureHttpResponseLiteral = new TypeLiteral<ListenableFuture<HttpResponse>>() {
|
||||||
};
|
};
|
||||||
|
|
||||||
@SuppressWarnings( { "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
public static Key<? extends Function<HttpResponse, ?>> getParserOrThrowException(Method method) {
|
public static Key<? extends Function<HttpResponse, ?>> getParserOrThrowException(Method method) {
|
||||||
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 (method.getReturnType().equals(HttpResponse.class)
|
} else if (method.getReturnType().equals(HttpResponse.class)
|
||||||
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureHttpResponseLiteral)) {
|
|| TypeLiteral.get(method.getGenericReturnType()).equals(futureHttpResponseLiteral)) {
|
||||||
return Key.get((Class) IdentityFunction.class);
|
return Key.get((Class) IdentityFunction.class);
|
||||||
} else if (getAcceptHeadersOrNull(method).contains(MediaType.APPLICATION_JSON)) {
|
} else if (getAcceptHeadersOrNull(method).contains(MediaType.APPLICATION_JSON)) {
|
||||||
return getJsonParserKeyForMethod(method);
|
return getJsonParserKeyForMethod(method);
|
||||||
} 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());
|
||||||
|
@ -804,7 +821,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
return returnVal;
|
return returnVal;
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings( { "unchecked", "rawtypes" })
|
@SuppressWarnings({ "unchecked", "rawtypes" })
|
||||||
public static Key<? extends Function<HttpResponse, ?>> getJsonParserKeyForMethodAnType(Method method, Type returnVal) {
|
public static Key<? extends Function<HttpResponse, ?>> getJsonParserKeyForMethodAnType(Method method, Type returnVal) {
|
||||||
ParameterizedType parserType;
|
ParameterizedType parserType;
|
||||||
if (method.isAnnotationPresent(Unwrap.class)) {
|
if (method.isAnnotationPresent(Unwrap.class)) {
|
||||||
|
@ -820,7 +837,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
parserType = Types.newParameterizedType(UnwrapOnlyNestedJsonValueInSet.class, returnVal);
|
parserType = Types.newParameterizedType(UnwrapOnlyNestedJsonValueInSet.class, returnVal);
|
||||||
else
|
else
|
||||||
throw new IllegalStateException(String.format("depth(%d) edgeCollection(%s) not yet supported for @Unwrap",
|
throw new IllegalStateException(String.format("depth(%d) edgeCollection(%s) not yet supported for @Unwrap",
|
||||||
depth, edgeCollection));
|
depth, edgeCollection));
|
||||||
} else {
|
} else {
|
||||||
parserType = Types.newParameterizedType(ParseJson.class, returnVal);
|
parserType = Types.newParameterizedType(ParseJson.class, returnVal);
|
||||||
}
|
}
|
||||||
|
@ -850,7 +867,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) {
|
||||||
|
@ -883,8 +900,8 @@ public class RestAnnotationProcessor<T> {
|
||||||
Set<String> requests = getHttpMethods(method);
|
Set<String> requests = 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();
|
||||||
}
|
}
|
||||||
|
@ -902,11 +919,13 @@ public class RestAnnotationProcessor<T> {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
public GeneratedHttpRequest<T> decorateRequest(GeneratedHttpRequest<T> request) {
|
public GeneratedHttpRequest<T> decorateRequest(GeneratedHttpRequest<T> request) throws NegativeArraySizeException,
|
||||||
|
ExecutionException {
|
||||||
OUTER: for (Entry<Integer, Set<Annotation>> entry : concat(//
|
OUTER: for (Entry<Integer, Set<Annotation>> entry : concat(//
|
||||||
filterValues(methodToIndexOfParamToBinderParamAnnotation.get(request.getJavaMethod()), notEmpty)
|
filterValues(methodToIndexOfParamToBinderParamAnnotation.get(request.getJavaMethod()).asMap(), notEmpty)
|
||||||
.entrySet(), //
|
.entrySet(), //
|
||||||
filterValues(methodToIndexOfParamToWrapWithAnnotation.get(request.getJavaMethod()), notEmpty).entrySet())) {
|
filterValues(methodToIndexOfParamToWrapWithAnnotation.get(request.getJavaMethod()).asMap(), notEmpty)
|
||||||
|
.entrySet())) {
|
||||||
boolean shouldBreak = false;
|
boolean shouldBreak = false;
|
||||||
Annotation annotation = Iterables.get(entry.getValue(), 0);
|
Annotation annotation = Iterables.get(entry.getValue(), 0);
|
||||||
Binder binder;
|
Binder binder;
|
||||||
|
@ -914,7 +933,7 @@ public class RestAnnotationProcessor<T> {
|
||||||
binder = injector.getInstance(BinderParam.class.cast(annotation).value());
|
binder = injector.getInstance(BinderParam.class.cast(annotation).value());
|
||||||
else
|
else
|
||||||
binder = injector.getInstance(BindToJsonPayloadWrappedWith.Factory.class).create(
|
binder = injector.getInstance(BindToJsonPayloadWrappedWith.Factory.class).create(
|
||||||
WrapWith.class.cast(annotation).value());
|
WrapWith.class.cast(annotation).value());
|
||||||
if (request.getArgs().size() >= entry.getKey() + 1 && request.getArgs().get(entry.getKey()) != null) {
|
if (request.getArgs().size() >= entry.getKey() + 1 && request.getArgs().get(entry.getKey()) != null) {
|
||||||
Object input;
|
Object input;
|
||||||
Class<?> parameterType = request.getJavaMethod().getParameterTypes()[entry.getKey()];
|
Class<?> parameterType = request.getJavaMethod().getParameterTypes()[entry.getKey()];
|
||||||
|
@ -947,28 +966,28 @@ 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) {
|
Cache<Method, Cache<Integer, Set<Annotation>>> toRefine) throws ExecutionException {
|
||||||
Map<Integer, Set<Annotation>> indexToPayloadAnnotation = indexWithAtLeastOneAnnotation(method, toRefine);
|
Map<Integer, Set<Annotation>> indexToPayloadAnnotation = indexWithAtLeastOneAnnotation(method, toRefine);
|
||||||
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Map<Integer, Set<Annotation>> indexWithAtLeastOneAnnotation(Method method,
|
private static Map<Integer, Set<Annotation>> indexWithAtLeastOneAnnotation(Method method,
|
||||||
Map<Method, Map<Integer, Set<Annotation>>> toRefine) {
|
Cache<Method, Cache<Integer, Set<Annotation>>> toRefine) throws ExecutionException {
|
||||||
Map<Integer, Set<Annotation>> indexToPayloadAnnotation = filterValues(toRefine.get(method),
|
Map<Integer, Set<Annotation>> indexToPayloadAnnotation = filterValues(toRefine.get(method).asMap(),
|
||||||
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;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
return indexToPayloadAnnotation;
|
return indexToPayloadAnnotation;
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpRequestOptions findOptionsIn(Method method, Object... args) {
|
private HttpRequestOptions findOptionsIn(Method method, Object... args) throws ExecutionException {
|
||||||
for (int index : methodToIndexesOfOptions.get(method)) {
|
for (int index : methodToIndexesOfOptions.get(method)) {
|
||||||
if (args.length >= index + 1) {// accomodate varargs
|
if (args.length >= index + 1) {// accomodate varargs
|
||||||
if (args[index] instanceof Object[]) {
|
if (args[index] instanceof Object[]) {
|
||||||
|
@ -983,7 +1002,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 {
|
||||||
|
@ -995,11 +1014,11 @@ 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) throws ExecutionException {
|
||||||
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);
|
Cache<Integer, Set<Annotation>> indexToHeaderParam = methodToIndexOfParamToHeaderParamAnnotations.get(method);
|
||||||
for (Entry<Integer, Set<Annotation>> entry : indexToHeaderParam.entrySet()) {
|
for (Entry<Integer, Set<Annotation>> entry : indexToHeaderParam.asMap().entrySet()) {
|
||||||
for (Annotation key : entry.getValue()) {
|
for (Annotation key : entry.getValue()) {
|
||||||
String value = args[entry.getKey()].toString();
|
String value = args[entry.getKey()].toString();
|
||||||
value = Strings2.replaceTokens(value, tokenValues);
|
value = Strings2.replaceTokens(value, tokenValues);
|
||||||
|
@ -1042,7 +1061,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);
|
||||||
|
@ -1054,7 +1073,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 = Strings2.replaceTokens(value, tokenValues);
|
value = Strings2.replaceTokens(value, tokenValues);
|
||||||
|
@ -1063,10 +1082,10 @@ public class RestAnnotationProcessor<T> {
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
List<? extends Part> getParts(Method method, Object[] args, Iterable<Entry<String, String>> iterable) {
|
List<? extends Part> getParts(Method method, Object[] args, Iterable<Entry<String, String>> iterable) throws ExecutionException {
|
||||||
List<Part> parts = newLinkedList();
|
List<Part> parts = newLinkedList();
|
||||||
Map<Integer, Set<Annotation>> indexToPartParam = methodToIndexOfParamToPartParamAnnotations.get(method);
|
Cache<Integer, Set<Annotation>> indexToPartParam = methodToIndexOfParamToPartParamAnnotations.get(method);
|
||||||
for (Entry<Integer, Set<Annotation>> entry : indexToPartParam.entrySet()) {
|
for (Entry<Integer, Set<Annotation>> entry : indexToPartParam.asMap().entrySet()) {
|
||||||
for (Annotation key : entry.getValue()) {
|
for (Annotation key : entry.getValue()) {
|
||||||
PartParam param = (PartParam) key;
|
PartParam param = (PartParam) key;
|
||||||
PartOptions options = new PartOptions();
|
PartOptions options = new PartOptions();
|
||||||
|
@ -1101,12 +1120,12 @@ public class RestAnnotationProcessor<T> {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Multimap<String, String> getPathParamKeyValues(Method method, Object... args) {
|
private Multimap<String, String> getPathParamKeyValues(Method method, Object... args) throws ExecutionException {
|
||||||
Multimap<String, String> pathParamValues = LinkedHashMultimap.create();
|
Multimap<String, String> pathParamValues = LinkedHashMultimap.create();
|
||||||
Map<Integer, Set<Annotation>> indexToPathParam = methodToIndexOfParamToPathParamAnnotations.get(method);
|
Cache<Integer, Set<Annotation>> indexToPathParam = methodToIndexOfParamToPathParamAnnotations.get(method);
|
||||||
|
|
||||||
Map<Integer, Set<Annotation>> indexToParamExtractor = methodToIndexOfParamToParamParserAnnotations.get(method);
|
Cache<Integer, Set<Annotation>> indexToParamExtractor = methodToIndexOfParamToParamParserAnnotations.get(method);
|
||||||
for (Entry<Integer, Set<Annotation>> entry : indexToPathParam.entrySet()) {
|
for (Entry<Integer, Set<Annotation>> entry : indexToPathParam.asMap().entrySet()) {
|
||||||
for (Annotation key : entry.getValue()) {
|
for (Annotation key : entry.getValue()) {
|
||||||
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
||||||
String paramKey = ((PathParam) key).value();
|
String paramKey = ((PathParam) key).value();
|
||||||
|
@ -1138,12 +1157,12 @@ public class RestAnnotationProcessor<T> {
|
||||||
return encoded;
|
return encoded;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Multimap<String, String> getMatrixParamKeyValues(Method method, Object... args) {
|
private Multimap<String, String> getMatrixParamKeyValues(Method method, Object... args) throws ExecutionException {
|
||||||
Multimap<String, String> matrixParamValues = LinkedHashMultimap.create();
|
Multimap<String, String> matrixParamValues = LinkedHashMultimap.create();
|
||||||
Map<Integer, Set<Annotation>> indexToMatrixParam = methodToIndexOfParamToMatrixParamAnnotations.get(method);
|
Cache<Integer, Set<Annotation>> indexToMatrixParam = methodToIndexOfParamToMatrixParamAnnotations.get(method);
|
||||||
|
|
||||||
Map<Integer, Set<Annotation>> indexToParamExtractor = methodToIndexOfParamToParamParserAnnotations.get(method);
|
Cache<Integer, Set<Annotation>> indexToParamExtractor = methodToIndexOfParamToParamParserAnnotations.get(method);
|
||||||
for (Entry<Integer, Set<Annotation>> entry : indexToMatrixParam.entrySet()) {
|
for (Entry<Integer, Set<Annotation>> entry : indexToMatrixParam.asMap().entrySet()) {
|
||||||
for (Annotation key : entry.getValue()) {
|
for (Annotation key : entry.getValue()) {
|
||||||
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
||||||
String paramKey = ((MatrixParam) key).value();
|
String paramKey = ((MatrixParam) key).value();
|
||||||
|
@ -1167,12 +1186,12 @@ public class RestAnnotationProcessor<T> {
|
||||||
return matrixParamValues;
|
return matrixParamValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Multimap<String, String> getFormParamKeyValues(Method method, Object... args) {
|
private Multimap<String, String> getFormParamKeyValues(Method method, Object... args) throws ExecutionException {
|
||||||
Multimap<String, String> formParamValues = LinkedHashMultimap.create();
|
Multimap<String, String> formParamValues = LinkedHashMultimap.create();
|
||||||
Map<Integer, Set<Annotation>> indexToFormParam = methodToIndexOfParamToFormParamAnnotations.get(method);
|
Cache<Integer, Set<Annotation>> indexToFormParam = methodToIndexOfParamToFormParamAnnotations.get(method);
|
||||||
|
|
||||||
Map<Integer, Set<Annotation>> indexToParamExtractor = methodToIndexOfParamToParamParserAnnotations.get(method);
|
Cache<Integer, Set<Annotation>> indexToParamExtractor = methodToIndexOfParamToParamParserAnnotations.get(method);
|
||||||
for (Entry<Integer, Set<Annotation>> entry : indexToFormParam.entrySet()) {
|
for (Entry<Integer, Set<Annotation>> entry : indexToFormParam.asMap().entrySet()) {
|
||||||
for (Annotation key : entry.getValue()) {
|
for (Annotation key : entry.getValue()) {
|
||||||
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
||||||
String paramKey = ((FormParam) key).value();
|
String paramKey = ((FormParam) key).value();
|
||||||
|
@ -1196,12 +1215,12 @@ public class RestAnnotationProcessor<T> {
|
||||||
return formParamValues;
|
return formParamValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Multimap<String, String> getQueryParamKeyValues(Method method, Object... args) {
|
private Multimap<String, String> getQueryParamKeyValues(Method method, Object... args) throws ExecutionException {
|
||||||
Multimap<String, String> queryParamValues = LinkedHashMultimap.create();
|
Multimap<String, String> queryParamValues = LinkedHashMultimap.create();
|
||||||
Map<Integer, Set<Annotation>> indexToQueryParam = methodToIndexOfParamToQueryParamAnnotations.get(method);
|
Cache<Integer, Set<Annotation>> indexToQueryParam = methodToIndexOfParamToQueryParamAnnotations.get(method);
|
||||||
|
|
||||||
Map<Integer, Set<Annotation>> indexToParamExtractor = methodToIndexOfParamToParamParserAnnotations.get(method);
|
Cache<Integer, Set<Annotation>> indexToParamExtractor = methodToIndexOfParamToParamParserAnnotations.get(method);
|
||||||
for (Entry<Integer, Set<Annotation>> entry : indexToQueryParam.entrySet()) {
|
for (Entry<Integer, Set<Annotation>> entry : indexToQueryParam.asMap().entrySet()) {
|
||||||
for (Annotation key : entry.getValue()) {
|
for (Annotation key : entry.getValue()) {
|
||||||
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
||||||
String paramKey = ((QueryParam) key).value();
|
String paramKey = ((QueryParam) key).value();
|
||||||
|
@ -1225,11 +1244,11 @@ public class RestAnnotationProcessor<T> {
|
||||||
return queryParamValues;
|
return queryParamValues;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, String> buildPostParams(Method method, Object... args) {
|
private Map<String, String> buildPostParams(Method method, Object... args) throws ExecutionException {
|
||||||
Map<String, String> postParams = newHashMap();
|
Map<String, String> postParams = newHashMap();
|
||||||
Map<Integer, Set<Annotation>> indexToPathParam = methodToIndexOfParamToPostParamAnnotations.get(method);
|
Cache<Integer, Set<Annotation>> indexToPathParam = methodToIndexOfParamToPostParamAnnotations.get(method);
|
||||||
Map<Integer, Set<Annotation>> indexToParamExtractor = methodToIndexOfParamToParamParserAnnotations.get(method);
|
Cache<Integer, Set<Annotation>> indexToParamExtractor = methodToIndexOfParamToParamParserAnnotations.get(method);
|
||||||
for (Entry<Integer, Set<Annotation>> entry : indexToPathParam.entrySet()) {
|
for (Entry<Integer, Set<Annotation>> entry : indexToPathParam.asMap().entrySet()) {
|
||||||
for (Annotation key : entry.getValue()) {
|
for (Annotation key : entry.getValue()) {
|
||||||
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
Set<Annotation> extractors = indexToParamExtractor.get(entry.getKey());
|
||||||
String paramKey = ((PayloadParam) key).value();
|
String paramKey = ((PayloadParam) key).value();
|
||||||
|
|
|
@ -36,6 +36,7 @@ import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexOfP
|
||||||
import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexesOfOptions;
|
import static org.jclouds.rest.internal.RestAnnotationProcessor.methodToIndexesOfOptions;
|
||||||
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
import javax.annotation.Resource;
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
|
@ -48,7 +49,7 @@ import org.jclouds.logging.Logger;
|
||||||
import org.jclouds.rest.annotations.Delegate;
|
import org.jclouds.rest.annotations.Delegate;
|
||||||
import org.jclouds.rest.internal.RestAnnotationProcessor.MethodKey;
|
import org.jclouds.rest.internal.RestAnnotationProcessor.MethodKey;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Multimap;
|
import com.google.common.collect.Multimap;
|
||||||
import com.google.inject.Inject;
|
import com.google.inject.Inject;
|
||||||
|
@ -63,7 +64,7 @@ import com.google.inject.Provides;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public class SeedAnnotationCache implements Function<Class<?>, Boolean> {
|
public class SeedAnnotationCache extends CacheLoader<Class<?>, Boolean> {
|
||||||
@Resource
|
@Resource
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
@ -82,7 +83,8 @@ public class SeedAnnotationCache implements Function<Class<?>, Boolean> {
|
||||||
constants.put(key, value);
|
constants.put(key, value);
|
||||||
}
|
}
|
||||||
|
|
||||||
public Boolean apply(Class<?> declaring) {
|
@Override
|
||||||
|
public Boolean load(Class<?> declaring) throws ExecutionException {
|
||||||
for (Method method : difference(ImmutableSet.copyOf(declaring.getMethods()), ImmutableSet.copyOf(Object.class
|
for (Method method : difference(ImmutableSet.copyOf(declaring.getMethods()), ImmutableSet.copyOf(Object.class
|
||||||
.getMethods()))) {
|
.getMethods()))) {
|
||||||
if (isHttpMethod(method) || method.isAnnotationPresent(Delegate.class)) {
|
if (isHttpMethod(method) || method.isAnnotationPresent(Delegate.class)) {
|
||||||
|
|
|
@ -20,11 +20,12 @@ package org.jclouds.util;
|
||||||
|
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.Map;
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.collect.MapMaker;
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -43,36 +44,38 @@ public class Patterns {
|
||||||
public static final Pattern _7E_PATTERN = Pattern.compile("%7E");
|
public static final Pattern _7E_PATTERN = Pattern.compile("%7E");
|
||||||
public static final Pattern NEWLINE_PATTERN = Pattern.compile("\r?\n");
|
public static final Pattern NEWLINE_PATTERN = Pattern.compile("\r?\n");
|
||||||
public static final Pattern SLASH_PATTERN = Pattern.compile("[/]");
|
public static final Pattern SLASH_PATTERN = Pattern.compile("[/]");
|
||||||
public static final Pattern IP_PATTERN = Pattern
|
public static final Pattern IP_PATTERN = Pattern.compile("b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)"
|
||||||
.compile("b(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?).)"
|
+ "{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)b");
|
||||||
+ "{3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)b");
|
|
||||||
public static final Pattern LEADING_SLASHES = Pattern.compile("^[/]+");
|
public static final Pattern LEADING_SLASHES = Pattern.compile("^[/]+");
|
||||||
public static final Pattern TRAILING_SLASHES = Pattern.compile("[/]*$");
|
public static final Pattern TRAILING_SLASHES = Pattern.compile("[/]*$");
|
||||||
public static final Pattern REST_CONTEXT_BUILDER = Pattern.compile("(.*ContextBuilder)<([^,]+), ?([^>]+)>");
|
public static final Pattern REST_CONTEXT_BUILDER = Pattern.compile("(.*ContextBuilder)<([^,]+), ?([^>]+)>");
|
||||||
|
|
||||||
public final static Map<Character, Pattern> CHAR_TO_ENCODED_PATTERN = new MapMaker()
|
public final static Cache<Character, Pattern> CHAR_TO_ENCODED_PATTERN = CacheBuilder.newBuilder()
|
||||||
.makeComputingMap(new Function<Character, Pattern>() {
|
.<Character, Pattern> build(new CacheLoader<Character, Pattern>() {
|
||||||
public Pattern apply(Character plain) {
|
@Override
|
||||||
try {
|
public Pattern load(Character plain) throws ExecutionException {
|
||||||
String encoded = URLEncoder.encode(plain + "", "UTF-8");
|
try {
|
||||||
return Pattern.compile(encoded);
|
String encoded = URLEncoder.encode(plain + "", "UTF-8");
|
||||||
} catch (UnsupportedEncodingException e) {
|
return Pattern.compile(encoded);
|
||||||
throw new IllegalStateException("Bad encoding on input: " + plain, e);
|
} catch (UnsupportedEncodingException e) {
|
||||||
}
|
throw new ExecutionException("Bad encoding on input: " + plain, e);
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
public final static Map<Character, Pattern> CHAR_TO_PATTERN = new MapMaker()
|
public final static Cache<Character, Pattern> CHAR_TO_PATTERN = CacheBuilder.newBuilder()
|
||||||
.makeComputingMap(new Function<Character, Pattern>() {
|
.<Character, Pattern> build(new CacheLoader<Character, Pattern>() {
|
||||||
public Pattern apply(Character plain) {
|
@Override
|
||||||
return Pattern.compile(plain + "");
|
public Pattern load(Character plain) {
|
||||||
}
|
return Pattern.compile(plain + "");
|
||||||
});
|
}
|
||||||
|
});
|
||||||
|
|
||||||
public final static Map<String, Pattern> TOKEN_TO_PATTERN = new MapMaker()
|
public final static Cache<String, Pattern> TOKEN_TO_PATTERN = CacheBuilder.newBuilder()
|
||||||
.makeComputingMap(new Function<String, Pattern>() {
|
.<String, Pattern> build(new CacheLoader<String, Pattern>() {
|
||||||
public Pattern apply(String tokenValue) {
|
@Override
|
||||||
return Pattern.compile("\\{" + tokenValue + "\\}");
|
public Pattern load(String tokenValue) {
|
||||||
}
|
return Pattern.compile("\\{" + tokenValue + "\\}");
|
||||||
});
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
|
@ -37,6 +37,7 @@ import java.net.URLDecoder;
|
||||||
import java.net.URLEncoder;
|
import java.net.URLEncoder;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
|
||||||
|
@ -70,6 +71,8 @@ public class Strings2 {
|
||||||
return returnVal;
|
return returnVal;
|
||||||
} catch (UnsupportedEncodingException e) {
|
} catch (UnsupportedEncodingException e) {
|
||||||
throw new IllegalStateException("Bad encoding on input: " + in, e);
|
throw new IllegalStateException("Bad encoding on input: " + in, e);
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
throw new IllegalStateException("error creating pattern: " + in, e);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -87,7 +90,11 @@ public class Strings2 {
|
||||||
|
|
||||||
public static String replaceTokens(String value, Iterable<Entry<String, String>> tokenValues) {
|
public static String replaceTokens(String value, Iterable<Entry<String, String>> tokenValues) {
|
||||||
for (Entry<String, String> tokenValue : tokenValues) {
|
for (Entry<String, String> tokenValue : tokenValues) {
|
||||||
value = Strings2.replaceAll(value, TOKEN_TO_PATTERN.get(tokenValue.getKey()), tokenValue.getValue());
|
try {
|
||||||
|
value = Strings2.replaceAll(value, TOKEN_TO_PATTERN.get(tokenValue.getKey()), tokenValue.getValue());
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
throw new IllegalStateException("error creating pattern: " + tokenValue.getKey(), e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return value;
|
return value;
|
||||||
}
|
}
|
||||||
|
@ -107,7 +114,11 @@ public class Strings2 {
|
||||||
|
|
||||||
public static String replaceAll(String input, char match, String replacement) {
|
public static String replaceAll(String input, char match, String replacement) {
|
||||||
if (input.indexOf(match) != -1) {
|
if (input.indexOf(match) != -1) {
|
||||||
input = CHAR_TO_PATTERN.get(match).matcher(input).replaceAll(replacement);
|
try {
|
||||||
|
input = CHAR_TO_PATTERN.get(match).matcher(input).replaceAll(replacement);
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
throw new IllegalStateException("error creating pattern: " + match, e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return input;
|
return input;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,8 +88,8 @@ public class Throwables2 {
|
||||||
throw (Exception) throwable;
|
throw (Exception) throwable;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Throwables.throwCause(exception, true);
|
Throwables.propagateIfPossible(exception.getCause(), Exception.class);
|
||||||
return exception;
|
throw exception;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static <T> T propagateAuthorizationOrOriginalException(Exception e) {
|
public static <T> T propagateAuthorizationOrOriginalException(Exception e) {
|
||||||
|
|
|
@ -67,7 +67,7 @@ import com.google.common.collect.Sets;
|
||||||
*
|
*
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "performance", enabled = false, sequential = true, testName = "FuturesTransformPerformanceTest")
|
@Test(groups = "performance", enabled = false, singleThreaded = true, testName = "FuturesTransformPerformanceTest")
|
||||||
public class FuturesTransformPerformanceTest {
|
public class FuturesTransformPerformanceTest {
|
||||||
private static final int FUDGE = 5;
|
private static final int FUDGE = 5;
|
||||||
private static final int COUNT = 100;
|
private static final int COUNT = 100;
|
||||||
|
@ -175,7 +175,7 @@ public class FuturesTransformPerformanceTest {
|
||||||
long start = System.currentTimeMillis();
|
long start = System.currentTimeMillis();
|
||||||
Map<String, Future<Long>> responses = newHashMap();
|
Map<String, Future<Long>> responses = newHashMap();
|
||||||
for (int i = 0; i < COUNT; i++)
|
for (int i = 0; i < COUNT; i++)
|
||||||
responses.put(i + "", Futures.transform(Futures.makeListenable(simultateIO(), chainExecutor),
|
responses.put(i + "", Futures.transform(JdkFutureAdapters.listenInPoolThread(simultateIO(), chainExecutor),
|
||||||
new Function<Long, Long>() {
|
new Function<Long, Long>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -25,7 +25,6 @@ import java.io.IOException;
|
||||||
import java.io.UnsupportedEncodingException;
|
import java.io.UnsupportedEncodingException;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.Callable;
|
import java.util.concurrent.Callable;
|
||||||
import java.util.concurrent.ConcurrentHashMap;
|
|
||||||
import java.util.concurrent.ExecutorService;
|
import java.util.concurrent.ExecutorService;
|
||||||
import java.util.concurrent.Executors;
|
import java.util.concurrent.Executors;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
@ -36,6 +35,10 @@ import org.jclouds.internal.ClassMethodArgs;
|
||||||
import org.testng.annotations.BeforeTest;
|
import org.testng.annotations.BeforeTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.base.Functions;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.util.concurrent.ListenableFuture;
|
import com.google.common.util.concurrent.ListenableFuture;
|
||||||
|
@ -162,8 +165,8 @@ public class SyncProxyTest {
|
||||||
|
|
||||||
@BeforeTest
|
@BeforeTest
|
||||||
public void setUp() throws IllegalArgumentException, SecurityException, NoSuchMethodException {
|
public void setUp() throws IllegalArgumentException, SecurityException, NoSuchMethodException {
|
||||||
sync = SyncProxy.proxy(Sync.class, new SyncProxy(Sync.class, new Async(),
|
Cache<ClassMethodArgs, Object> cache = CacheBuilder.newBuilder().build(CacheLoader.from(Functions.<Object>constant(null)));
|
||||||
new ConcurrentHashMap<ClassMethodArgs, Object>(), ImmutableMap.<Class<?>, Class<?>> of()));
|
sync = SyncProxy.proxy(Sync.class, new SyncProxy(Sync.class, new Async(),cache, ImmutableMap.<Class<?>, Class<?>> of()));
|
||||||
// just to warm up
|
// just to warm up
|
||||||
sync.string();
|
sync.string();
|
||||||
}
|
}
|
||||||
|
@ -225,8 +228,9 @@ public class SyncProxyTest {
|
||||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
public void testWrongTypedException() throws IllegalArgumentException, SecurityException, NoSuchMethodException,
|
public void testWrongTypedException() throws IllegalArgumentException, SecurityException, NoSuchMethodException,
|
||||||
IOException {
|
IOException {
|
||||||
|
Cache<ClassMethodArgs, Object> cache = CacheBuilder.newBuilder().build(CacheLoader.from(Functions.<Object>constant(null)));
|
||||||
SyncProxy.proxy(SyncWrongException.class, new SyncProxy(SyncWrongException.class, new Async(),
|
SyncProxy.proxy(SyncWrongException.class, new SyncProxy(SyncWrongException.class, new Async(),
|
||||||
new ConcurrentHashMap<ClassMethodArgs, Object>(), ImmutableMap.<Class<?>, Class<?>> of()));
|
cache, ImmutableMap.<Class<?>, Class<?>> of()));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static interface SyncNoTimeOut {
|
private static interface SyncNoTimeOut {
|
||||||
|
@ -243,8 +247,9 @@ public class SyncProxyTest {
|
||||||
@Test(expectedExceptions = IllegalArgumentException.class)
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
public void testNoTimeOutException() throws IllegalArgumentException, SecurityException, NoSuchMethodException,
|
public void testNoTimeOutException() throws IllegalArgumentException, SecurityException, NoSuchMethodException,
|
||||||
IOException {
|
IOException {
|
||||||
|
Cache<ClassMethodArgs, Object> cache = CacheBuilder.newBuilder().build(CacheLoader.from(Functions.<Object>constant(null)));
|
||||||
SyncProxy.proxy(SyncNoTimeOut.class, new SyncProxy(SyncNoTimeOut.class, new Async(),
|
SyncProxy.proxy(SyncNoTimeOut.class, new SyncProxy(SyncNoTimeOut.class, new Async(),
|
||||||
new ConcurrentHashMap<ClassMethodArgs, Object>(), ImmutableMap.<Class<?>, Class<?>> of()));
|
cache, ImmutableMap.<Class<?>, Class<?>> of()));
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,81 @@
|
||||||
|
/**
|
||||||
|
* Licensed to jclouds, Inc. (jclouds) under one or more
|
||||||
|
* contributor license agreements. See the NOTICE file
|
||||||
|
* distributed with this work for additional information
|
||||||
|
* regarding copyright ownership. jclouds licenses this file
|
||||||
|
* to you under the Apache License, Version 2.0 (the
|
||||||
|
* "License"); you may not use this file except in compliance
|
||||||
|
* with the License. You may obtain a copy of the License at
|
||||||
|
*
|
||||||
|
* http://www.apache.org/licenses/LICENSE-2.0
|
||||||
|
*
|
||||||
|
* Unless required by applicable law or agreed to in writing,
|
||||||
|
* software distributed under the License is distributed on an
|
||||||
|
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
|
||||||
|
* KIND, either express or implied. See the License for the
|
||||||
|
* specific language governing permissions and limitations
|
||||||
|
* under the License.
|
||||||
|
*/
|
||||||
|
package org.jclouds.functions;
|
||||||
|
|
||||||
|
import static org.testng.Assert.assertEquals;
|
||||||
|
|
||||||
|
import java.util.concurrent.ExecutionException;
|
||||||
|
|
||||||
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
|
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||||
|
|
||||||
|
/**
|
||||||
|
*
|
||||||
|
* @author Adrian Cole
|
||||||
|
*/
|
||||||
|
@Test(groups = "unit", singleThreaded = true, testName = "CacheLearningTest")
|
||||||
|
public class CacheLearningTest {
|
||||||
|
@Test
|
||||||
|
public void howTo() throws ExecutionException {
|
||||||
|
Cache<String, String> cache = CacheBuilder.newBuilder().build(new CacheLoader<String, String>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String load(String key) throws Exception {
|
||||||
|
if (key.equals("runtimeexception"))
|
||||||
|
throw new RuntimeException("runtimeexception");
|
||||||
|
if (key.equals("exception"))
|
||||||
|
throw new Exception("exception");
|
||||||
|
return key.equals("foo") ? null : key;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "testLoader";
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
try {
|
||||||
|
cache.get("foo");
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
assertEquals(e.getMessage(), "testLoader returned null for key foo.");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
cache.get("exception");
|
||||||
|
} catch (ExecutionException e) {
|
||||||
|
assertEquals(e.getMessage(), "java.lang.Exception: exception");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
cache.get("runtimeexception");
|
||||||
|
} catch (UncheckedExecutionException e) {
|
||||||
|
assertEquals(e.getMessage(), "java.lang.RuntimeException: runtimeexception");
|
||||||
|
}
|
||||||
|
try {
|
||||||
|
cache.getUnchecked("exception");
|
||||||
|
} catch (UncheckedExecutionException e) {
|
||||||
|
assertEquals(e.getMessage(), "java.lang.Exception: exception");
|
||||||
|
}
|
||||||
|
assertEquals(cache.get("bar"), "bar");
|
||||||
|
assertEquals(cache.get("baz"), "baz");
|
||||||
|
assertEquals(cache.asMap().size(), 2);
|
||||||
|
}
|
||||||
|
}
|
|
@ -2157,7 +2157,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOneHeader() throws SecurityException, NoSuchMethodException {
|
public void testOneHeader() throws SecurityException, NoSuchMethodException, ExecutionException {
|
||||||
Method method = TestHeaders.class.getMethod("oneHeader", String.class);
|
Method method = TestHeaders.class.getMethod("oneHeader", String.class);
|
||||||
Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(
|
Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(
|
||||||
ImmutableMultimap.<String, String> of().entries(), method, "robot");
|
ImmutableMultimap.<String, String> of().entries(), method, "robot");
|
||||||
|
@ -2166,7 +2166,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testOneIntHeader() throws SecurityException, NoSuchMethodException {
|
public void testOneIntHeader() throws SecurityException, NoSuchMethodException, ExecutionException {
|
||||||
Method method = TestHeaders.class.getMethod("oneIntHeader", int.class);
|
Method method = TestHeaders.class.getMethod("oneIntHeader", int.class);
|
||||||
Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(
|
Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(
|
||||||
ImmutableMultimap.<String, String> of().entries(), method, 1);
|
ImmutableMultimap.<String, String> of().entries(), method, 1);
|
||||||
|
@ -2175,7 +2175,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTwoDifferentHeaders() throws SecurityException, NoSuchMethodException {
|
public void testTwoDifferentHeaders() throws SecurityException, NoSuchMethodException, ExecutionException {
|
||||||
Method method = TestHeaders.class.getMethod("twoDifferentHeaders", String.class, String.class);
|
Method method = TestHeaders.class.getMethod("twoDifferentHeaders", String.class, String.class);
|
||||||
Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(
|
Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(
|
||||||
ImmutableMultimap.<String, String> of().entries(), method, "robot", "egg");
|
ImmutableMultimap.<String, String> of().entries(), method, "robot", "egg");
|
||||||
|
@ -2185,7 +2185,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testTwoSameHeaders() throws SecurityException, NoSuchMethodException {
|
public void testTwoSameHeaders() throws SecurityException, NoSuchMethodException, ExecutionException {
|
||||||
Method method = TestHeaders.class.getMethod("twoSameHeaders", String.class, String.class);
|
Method method = TestHeaders.class.getMethod("twoSameHeaders", String.class, String.class);
|
||||||
Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(
|
Multimap<String, String> headers = factory(TestHeaders.class).buildHeaders(
|
||||||
ImmutableMultimap.<String, String> of().entries(), method, "robot", "egg");
|
ImmutableMultimap.<String, String> of().entries(), method, "robot", "egg");
|
||||||
|
@ -2228,7 +2228,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
||||||
|
|
||||||
@SuppressWarnings("static-access")
|
@SuppressWarnings("static-access")
|
||||||
@Test
|
@Test
|
||||||
public void testOneEndpointParam() throws SecurityException, NoSuchMethodException {
|
public void testOneEndpointParam() throws SecurityException, NoSuchMethodException, ExecutionException {
|
||||||
Method method = TestEndpointParams.class.getMethod("oneEndpointParam", String.class);
|
Method method = TestEndpointParams.class.getMethod("oneEndpointParam", String.class);
|
||||||
URI uri = factory(TestEndpointParams.class).getEndpointInParametersOrNull(method, new Object[] { "robot" },
|
URI uri = factory(TestEndpointParams.class).getEndpointInParametersOrNull(method, new Object[] { "robot" },
|
||||||
injector);
|
injector);
|
||||||
|
@ -2238,7 +2238,7 @@ public class RestAnnotationProcessorTest extends BaseRestClientTest {
|
||||||
|
|
||||||
@SuppressWarnings("static-access")
|
@SuppressWarnings("static-access")
|
||||||
@Test
|
@Test
|
||||||
public void testTwoDifferentEndpointParams() throws SecurityException, NoSuchMethodException {
|
public void testTwoDifferentEndpointParams() throws SecurityException, NoSuchMethodException, ExecutionException {
|
||||||
Method method = TestEndpointParams.class.getMethod("twoEndpointParams", String.class, String.class);
|
Method method = TestEndpointParams.class.getMethod("twoEndpointParams", String.class, String.class);
|
||||||
URI uri = factory(TestEndpointParams.class).getEndpointInParametersOrNull(method,
|
URI uri = factory(TestEndpointParams.class).getEndpointInParametersOrNull(method,
|
||||||
new Object[] { "robot", "egg" }, injector);
|
new Object[] { "robot", "egg" }, injector);
|
||||||
|
|
|
@ -64,6 +64,7 @@ import org.jclouds.util.Preconditions2;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Predicate;
|
import com.google.common.base.Predicate;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -71,7 +72,7 @@ import com.google.common.base.Supplier;
|
||||||
@Singleton
|
@Singleton
|
||||||
public class AWSEC2ComputeService extends EC2ComputeService {
|
public class AWSEC2ComputeService extends EC2ComputeService {
|
||||||
|
|
||||||
private final Map<RegionAndName, String> placementGroupMap;
|
private final Cache<RegionAndName, String> placementGroupMap;
|
||||||
private final Predicate<PlacementGroup> placementGroupDeleted;
|
private final Predicate<PlacementGroup> placementGroupDeleted;
|
||||||
private final AWSEC2Client ec2Client;
|
private final AWSEC2Client ec2Client;
|
||||||
|
|
||||||
|
@ -90,8 +91,8 @@ public class AWSEC2ComputeService extends EC2ComputeService {
|
||||||
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
|
RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
|
||||||
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
|
PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, AWSEC2Client ec2Client,
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, AWSEC2Client ec2Client,
|
||||||
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap,
|
Cache<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Cache<RegionAndName, String> securityGroupMap,
|
||||||
@Named("PLACEMENT") Map<RegionAndName, String> placementGroupMap,
|
@Named("PLACEMENT") Cache<RegionAndName, String> placementGroupMap,
|
||||||
@Named("DELETED") Predicate<PlacementGroup> placementGroupDeleted) {
|
@Named("DELETED") Predicate<PlacementGroup> placementGroupDeleted) {
|
||||||
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
|
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
|
||||||
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy,
|
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy,
|
||||||
|
@ -117,7 +118,7 @@ public class AWSEC2ComputeService extends EC2ComputeService {
|
||||||
checkState(
|
checkState(
|
||||||
placementGroupDeleted.apply(new PlacementGroup(region, placementGroup, "cluster", State.PENDING)),
|
placementGroupDeleted.apply(new PlacementGroup(region, placementGroup, "cluster", State.PENDING)),
|
||||||
String.format("placementGroup region(%s) name(%s) failed to delete", region, placementGroup));
|
String.format("placementGroup region(%s) name(%s) failed to delete", region, placementGroup));
|
||||||
placementGroupMap.remove(new RegionAndName(region, placementGroup));
|
placementGroupMap.invalidate(new RegionAndName(region, placementGroup));
|
||||||
logger.debug("<< deleted placementGroup(%s)", placementGroup);
|
logger.debug("<< deleted placementGroup(%s)", placementGroup);
|
||||||
} catch (IllegalStateException e) {
|
} catch (IllegalStateException e) {
|
||||||
logger.debug("<< inUse placementGroup(%s)", placementGroup);
|
logger.debug("<< inUse placementGroup(%s)", placementGroup);
|
||||||
|
|
|
@ -18,7 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.aws.ec2.compute;
|
package org.jclouds.aws.ec2.compute;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
|
@ -35,6 +34,7 @@ import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
|
import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -46,7 +46,7 @@ public class AWSEC2TemplateBuilderImpl extends EC2TemplateBuilderImpl {
|
||||||
protected AWSEC2TemplateBuilderImpl(@Memoized Supplier<Set<? extends Location>> locations,
|
protected AWSEC2TemplateBuilderImpl(@Memoized Supplier<Set<? extends Location>> locations,
|
||||||
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
|
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
|
||||||
Supplier<Location> defaultLocation, @Named("DEFAULT") Provider<TemplateOptions> optionsProvider,
|
Supplier<Location> defaultLocation, @Named("DEFAULT") Provider<TemplateOptions> optionsProvider,
|
||||||
@Named("DEFAULT") Provider<TemplateBuilder> defaultTemplateProvider, Map<RegionAndName, Image> imageMap) {
|
@Named("DEFAULT") Provider<TemplateBuilder> defaultTemplateProvider, Supplier<Cache<RegionAndName, ? extends Image>> imageMap) {
|
||||||
super(locations, images, sizes, defaultLocation, optionsProvider, defaultTemplateProvider, imageMap);
|
super(locations, images, sizes, defaultLocation, optionsProvider, defaultTemplateProvider, imageMap);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -21,8 +21,6 @@ package org.jclouds.aws.ec2.compute.config;
|
||||||
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
|
import static org.jclouds.Constants.PROPERTY_SESSION_INTERVAL;
|
||||||
import static org.jclouds.compute.domain.OsFamily.AMZN_LINUX;
|
import static org.jclouds.compute.domain.OsFamily.AMZN_LINUX;
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
|
|
||||||
import javax.inject.Named;
|
import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
@ -56,6 +54,7 @@ import org.jclouds.ec2.compute.suppliers.EC2HardwareSupplier;
|
||||||
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
|
import org.jclouds.rest.suppliers.MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
import com.google.inject.Injector;
|
import com.google.inject.Injector;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
|
@ -89,12 +88,12 @@ public class AWSEC2ComputeServiceContextModule extends BaseComputeServiceContext
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
protected Supplier<Map<RegionAndName, ? extends Image>> provideRegionAndNameToImageSupplierCache(
|
protected Supplier<Cache<RegionAndName, ? extends Image>> provideRegionAndNameToImageSupplierCache(
|
||||||
@Named(PROPERTY_SESSION_INTERVAL) long seconds, final AWSRegionAndNameToImageSupplier supplier) {
|
@Named(PROPERTY_SESSION_INTERVAL) long seconds, final AWSRegionAndNameToImageSupplier supplier) {
|
||||||
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Map<RegionAndName, ? extends Image>>(
|
return new MemoizedRetryOnTimeOutButNotOnAuthorizationExceptionSupplier<Cache<RegionAndName, ? extends Image>>(
|
||||||
authException, seconds, new Supplier<Map<RegionAndName, ? extends Image>>() {
|
authException, seconds, new Supplier<Cache<RegionAndName, ? extends Image>>() {
|
||||||
@Override
|
@Override
|
||||||
public Map<RegionAndName, ? extends Image> get() {
|
public Cache<RegionAndName, ? extends Image> get() {
|
||||||
return supplier.get();
|
return supplier.get();
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
|
@ -18,9 +18,6 @@
|
||||||
*/
|
*/
|
||||||
package org.jclouds.aws.ec2.compute.config;
|
package org.jclouds.aws.ec2.compute.config;
|
||||||
|
|
||||||
import static com.google.common.collect.Maps.newLinkedHashMap;
|
|
||||||
|
|
||||||
import java.util.Map;
|
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
|
|
||||||
|
@ -47,7 +44,6 @@ import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.ec2.compute.config.EC2ComputeServiceDependenciesModule;
|
import org.jclouds.ec2.compute.config.EC2ComputeServiceDependenciesModule;
|
||||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
|
|
||||||
import org.jclouds.ec2.compute.functions.CreateSecurityGroupIfNeeded;
|
import org.jclouds.ec2.compute.functions.CreateSecurityGroupIfNeeded;
|
||||||
import org.jclouds.ec2.compute.functions.CreateUniqueKeyPair;
|
import org.jclouds.ec2.compute.functions.CreateUniqueKeyPair;
|
||||||
import org.jclouds.ec2.compute.functions.CredentialsForInstance;
|
import org.jclouds.ec2.compute.functions.CredentialsForInstance;
|
||||||
|
@ -62,6 +58,9 @@ 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.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.Sets;
|
import com.google.common.collect.Sets;
|
||||||
import com.google.inject.Provides;
|
import com.google.inject.Provides;
|
||||||
import com.google.inject.Scopes;
|
import com.google.inject.Scopes;
|
||||||
|
@ -80,15 +79,15 @@ public class AWSEC2ComputeServiceDependenciesModule extends EC2ComputeServiceDep
|
||||||
bind(ComputeService.class).to(AWSEC2ComputeService.class);
|
bind(ComputeService.class).to(AWSEC2ComputeService.class);
|
||||||
bind(new TypeLiteral<Function<RunningInstance, NodeMetadata>>() {
|
bind(new TypeLiteral<Function<RunningInstance, NodeMetadata>>() {
|
||||||
}).to(RunningInstanceToNodeMetadata.class);
|
}).to(RunningInstanceToNodeMetadata.class);
|
||||||
bind(new TypeLiteral<Function<RunningInstance, Credentials>>() {
|
bind(new TypeLiteral<CacheLoader<RunningInstance, Credentials>>() {
|
||||||
}).to(CredentialsForInstance.class);
|
}).to(CredentialsForInstance.class);
|
||||||
bind(new TypeLiteral<Function<RegionNameAndIngressRules, String>>() {
|
bind(new TypeLiteral<CacheLoader<RegionAndName, String>>() {
|
||||||
}).to(CreateSecurityGroupIfNeeded.class);
|
}).to(CreateSecurityGroupIfNeeded.class);
|
||||||
bind(new TypeLiteral<Function<RegionAndName, KeyPair>>() {
|
bind(new TypeLiteral<CacheLoader<RegionAndName, KeyPair>>() {
|
||||||
}).to(CreateUniqueKeyPair.class);
|
}).to(CreateUniqueKeyPair.class);
|
||||||
bind(new TypeLiteral<Function<RegionNameAndPublicKeyMaterial, KeyPair>>() {
|
bind(new TypeLiteral<Function<RegionNameAndPublicKeyMaterial, KeyPair>>() {
|
||||||
}).to(ImportOrReturnExistingKeypair.class);
|
}).to(ImportOrReturnExistingKeypair.class);
|
||||||
bind(new TypeLiteral<Function<RegionAndName, Image>>() {
|
bind(new TypeLiteral<CacheLoader<RegionAndName, Image>>() {
|
||||||
}).to(RegionAndIdToImage.class);
|
}).to(RegionAndIdToImage.class);
|
||||||
bind(new TypeLiteral<ComputeServiceContext>() {
|
bind(new TypeLiteral<ComputeServiceContext>() {
|
||||||
}).to(new TypeLiteral<ComputeServiceContextImpl<AWSEC2Client, AWSEC2AsyncClient>>() {
|
}).to(new TypeLiteral<ComputeServiceContextImpl<AWSEC2Client, AWSEC2AsyncClient>>() {
|
||||||
|
@ -116,10 +115,8 @@ public class AWSEC2ComputeServiceDependenciesModule extends EC2ComputeServiceDep
|
||||||
@Provides
|
@Provides
|
||||||
@Singleton
|
@Singleton
|
||||||
@Named("PLACEMENT")
|
@Named("PLACEMENT")
|
||||||
protected Map<RegionAndName, String> placementGroupMap(CreateSecurityGroupIfNeeded in) {
|
protected Cache<RegionAndName, String> placementGroupMap(CreateSecurityGroupIfNeeded in) {
|
||||||
// doesn't seem to clear when someone issues remove(key)
|
return CacheBuilder.newBuilder().build(in);
|
||||||
// return new MapMaker().makeComputingMap(in);
|
|
||||||
return newLinkedHashMap();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Provides
|
@Provides
|
||||||
|
|
|
@ -38,6 +38,7 @@ import org.jclouds.ec2.domain.InstanceState;
|
||||||
import org.jclouds.ec2.domain.RunningInstance;
|
import org.jclouds.ec2.domain.RunningInstance;
|
||||||
|
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -47,9 +48,9 @@ public class AWSRunningInstanceToNodeMetadata extends RunningInstanceToNodeMetad
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected AWSRunningInstanceToNodeMetadata(Map<InstanceState, NodeState> instanceToNodeState,
|
protected AWSRunningInstanceToNodeMetadata(Map<InstanceState, NodeState> instanceToNodeState,
|
||||||
Map<String, Credentials> credentialStore, Map<RegionAndName, Image> instanceToImage,
|
Map<String, Credentials> credentialStore, Supplier<Cache<RegionAndName, ? extends Image>> imageMap,
|
||||||
@Memoized Supplier<Set<? extends Location>> locations, @Memoized Supplier<Set<? extends Hardware>> hardware) {
|
@Memoized Supplier<Set<? extends Location>> locations, @Memoized Supplier<Set<? extends Hardware>> hardware) {
|
||||||
super(instanceToNodeState, credentialStore, instanceToImage, locations, hardware);
|
super(instanceToNodeState, credentialStore, imageMap, locations, hardware);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
|
|
@ -49,6 +49,7 @@ import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -73,7 +74,7 @@ public class AWSEC2CreateNodesInGroupThenAddToSet extends EC2CreateNodesInGroupT
|
||||||
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
|
||||||
AWSEC2InstancePresent instancePresent,
|
AWSEC2InstancePresent instancePresent,
|
||||||
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
|
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
|
||||||
Function<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore,
|
Cache<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore,
|
||||||
ComputeUtils utils, SpotInstanceRequestToAWSRunningInstance spotConverter) {
|
ComputeUtils utils, SpotInstanceRequestToAWSRunningInstance spotConverter) {
|
||||||
super(client, templateBuilderProvider, createKeyPairAndSecurityGroupsAsNeededAndReturncustomize, instancePresent,
|
super(client, templateBuilderProvider, createKeyPairAndSecurityGroupsAsNeededAndReturncustomize, instancePresent,
|
||||||
runningInstanceToNodeMetadata, instanceToCredentials, credentialStore, utils);
|
runningInstanceToNodeMetadata, instanceToCredentials, credentialStore, utils);
|
||||||
|
|
|
@ -37,7 +37,6 @@ import org.jclouds.compute.domain.Template;
|
||||||
import org.jclouds.compute.options.TemplateOptions;
|
import org.jclouds.compute.options.TemplateOptions;
|
||||||
import org.jclouds.compute.reference.ComputeServiceConstants;
|
import org.jclouds.compute.reference.ComputeServiceConstants;
|
||||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
|
|
||||||
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
||||||
import org.jclouds.ec2.compute.strategy.CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
|
import org.jclouds.ec2.compute.strategy.CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
|
||||||
import org.jclouds.ec2.domain.KeyPair;
|
import org.jclouds.ec2.domain.KeyPair;
|
||||||
|
@ -47,6 +46,7 @@ import org.jclouds.logging.Logger;
|
||||||
import com.google.common.annotations.VisibleForTesting;
|
import com.google.common.annotations.VisibleForTesting;
|
||||||
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.cache.Cache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
*
|
*
|
||||||
|
@ -59,21 +59,21 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final Map<RegionAndName, String> placementGroupMap;
|
final Cache<RegionAndName, String> placementGroupMap;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded;
|
final CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded;
|
||||||
@VisibleForTesting
|
@VisibleForTesting
|
||||||
final Function<RegionNameAndPublicKeyMaterial, KeyPair> importExistingKeyPair;
|
final Function<RegionNameAndPublicKeyMaterial, KeyPair> importExistingKeyPair;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions(
|
public CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions(Map<RegionAndName, KeyPair> knownKeys,
|
||||||
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap,
|
Cache<RegionAndName, KeyPair> credentialsMap,
|
||||||
@Named("PLACEMENT") Map<RegionAndName, String> placementGroupMap,
|
@Named("SECURITY") Cache<RegionAndName, String> securityGroupMap,
|
||||||
Function<RegionAndName, KeyPair> createUniqueKeyPair,
|
Provider<RunInstancesOptions> optionsProvider,
|
||||||
Function<RegionNameAndIngressRules, String> createSecurityGroupIfNeeded,
|
@Named("PLACEMENT") Cache<RegionAndName, String> placementGroupMap,
|
||||||
Provider<RunInstancesOptions> optionsProvider, CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded,
|
CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded,
|
||||||
Function<RegionNameAndPublicKeyMaterial, KeyPair> importExistingKeyPair) {
|
Function<RegionNameAndPublicKeyMaterial, KeyPair> importExistingKeyPair) {
|
||||||
super(credentialsMap, securityGroupMap, createUniqueKeyPair, createSecurityGroupIfNeeded, optionsProvider);
|
super(knownKeys, credentialsMap, securityGroupMap, optionsProvider);
|
||||||
this.placementGroupMap = placementGroupMap;
|
this.placementGroupMap = placementGroupMap;
|
||||||
this.createPlacementGroupIfNeeded = createPlacementGroupIfNeeded;
|
this.createPlacementGroupIfNeeded = createPlacementGroupIfNeeded;
|
||||||
this.importExistingKeyPair = importExistingKeyPair;
|
this.importExistingKeyPair = importExistingKeyPair;
|
||||||
|
@ -110,9 +110,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions
|
||||||
// http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?using_cluster_computing.html
|
// http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?using_cluster_computing.html
|
||||||
placementGroupName = String.format("jclouds#%s#%s", group, region);
|
placementGroupName = String.format("jclouds#%s#%s", group, region);
|
||||||
RegionAndName regionAndName = new RegionAndName(region, placementGroupName);
|
RegionAndName regionAndName = new RegionAndName(region, placementGroupName);
|
||||||
if (!placementGroupMap.containsKey(regionAndName)) {
|
// make this entry as needed
|
||||||
placementGroupMap.put(regionAndName, createPlacementGroupIfNeeded.apply(regionAndName));
|
placementGroupMap.getUnchecked(regionAndName);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return placementGroupName;
|
return placementGroupName;
|
||||||
}
|
}
|
||||||
|
@ -120,7 +119,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions
|
||||||
@Override
|
@Override
|
||||||
protected String createOrImportKeyPair(String region, String group, TemplateOptions options) {
|
protected String createOrImportKeyPair(String region, String group, TemplateOptions options) {
|
||||||
RegionAndName key = new RegionAndName(region, "jclouds#" + group);
|
RegionAndName key = new RegionAndName(region, "jclouds#" + group);
|
||||||
KeyPair pair = credentialsMap.get(key);
|
KeyPair pair = knownKeys.get(key);
|
||||||
if (pair != null)
|
if (pair != null)
|
||||||
return pair.getKeyName();
|
return pair.getKeyName();
|
||||||
if (and(hasPublicKeyMaterial, or(doesntNeedSshAfterImportingPublicKey, hasLoginCredential)).apply(options)) {
|
if (and(hasPublicKeyMaterial, or(doesntNeedSshAfterImportingPublicKey, hasLoginCredential)).apply(options)) {
|
||||||
|
@ -128,12 +127,12 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions
|
||||||
options.dontAuthorizePublicKey();
|
options.dontAuthorizePublicKey();
|
||||||
if (hasLoginCredential.apply(options))
|
if (hasLoginCredential.apply(options))
|
||||||
pair = pair.toBuilder().keyMaterial(options.getOverridingCredentials().credential).build();
|
pair = pair.toBuilder().keyMaterial(options.getOverridingCredentials().credential).build();
|
||||||
credentialsMap.put(key, pair);
|
knownKeys.put(key, pair);
|
||||||
} else {
|
} else {
|
||||||
if (hasPublicKeyMaterial.apply(options)) {
|
if (hasPublicKeyMaterial.apply(options)) {
|
||||||
logger.warn("to avoid creating temporary keys in aws-ec2, use templateOption overrideLoginCredentialWith(id_rsa)");
|
logger.warn("to avoid creating temporary keys in aws-ec2, use templateOption overrideLoginCredentialWith(id_rsa)");
|
||||||
}
|
}
|
||||||
return createUniqueKeyPairAndPutIntoMap(region, group);
|
return super.createOrImportKeyPair(region, group, options);
|
||||||
}
|
}
|
||||||
return pair.getKeyName();
|
return pair.getKeyName();
|
||||||
}
|
}
|
||||||
|
|
|
@ -47,6 +47,9 @@ import com.google.common.base.Function;
|
||||||
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.base.Throwables;
|
import com.google.common.base.Throwables;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
@ -58,12 +61,13 @@ import com.google.common.util.concurrent.Futures;
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class AWSRegionAndNameToImageSupplier implements Supplier<Map<RegionAndName, ? extends Image>> {
|
public class AWSRegionAndNameToImageSupplier implements Supplier<Cache<RegionAndName, ? extends Image>> {
|
||||||
@Resource
|
@Resource
|
||||||
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
private final Map<RegionAndName, Image> images;
|
private final Map<RegionAndName, Image> knownImages;
|
||||||
|
private final CacheLoader<RegionAndName, Image> regionAndIdToImage;
|
||||||
private final Set<String> clusterComputeIds;
|
private final Set<String> clusterComputeIds;
|
||||||
private final CallForImages.Factory factory;
|
private final CallForImages.Factory factory;
|
||||||
private final ExecutorService executor;
|
private final ExecutorService executor;
|
||||||
|
@ -73,10 +77,11 @@ public class AWSRegionAndNameToImageSupplier implements Supplier<Map<RegionAndNa
|
||||||
private final Iterable<String> clusterRegions;
|
private final Iterable<String> clusterRegions;
|
||||||
private final String ccAmiQuery;
|
private final String ccAmiQuery;
|
||||||
|
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
protected AWSRegionAndNameToImageSupplier(@Region Set<String> regions,
|
protected AWSRegionAndNameToImageSupplier(@Region Set<String> regions,
|
||||||
@Named(PROPERTY_EC2_AMI_QUERY) String amiQuery, @Named(PROPERTY_EC2_CC_REGIONS) String clusterRegions,
|
@Named(PROPERTY_EC2_AMI_QUERY) String amiQuery, @Named(PROPERTY_EC2_CC_REGIONS) String clusterRegions,
|
||||||
@Named(PROPERTY_EC2_CC_AMI_QUERY) String ccAmiQuery, Map<RegionAndName, Image> images,
|
@Named(PROPERTY_EC2_CC_AMI_QUERY) String ccAmiQuery, Map<RegionAndName, Image> knownImages, CacheLoader<RegionAndName, Image> regionAndIdToImage,
|
||||||
CallForImages.Factory factory, @ClusterCompute Set<String> clusterComputeIds,
|
CallForImages.Factory factory, @ClusterCompute Set<String> clusterComputeIds,
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
this.factory = factory;
|
this.factory = factory;
|
||||||
|
@ -84,13 +89,14 @@ public class AWSRegionAndNameToImageSupplier implements Supplier<Map<RegionAndNa
|
||||||
this.amiQuery = amiQuery;
|
this.amiQuery = amiQuery;
|
||||||
this.clusterRegions = Splitter.on(',').split(clusterRegions);
|
this.clusterRegions = Splitter.on(',').split(clusterRegions);
|
||||||
this.ccAmiQuery = ccAmiQuery;
|
this.ccAmiQuery = ccAmiQuery;
|
||||||
this.images = images;
|
this.knownImages = knownImages;
|
||||||
|
this.regionAndIdToImage=regionAndIdToImage;
|
||||||
this.clusterComputeIds = clusterComputeIds;
|
this.clusterComputeIds = clusterComputeIds;
|
||||||
this.executor = executor;
|
this.executor = executor;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Map<RegionAndName, ? extends Image> get() {
|
public Cache<RegionAndName, ? extends Image> get() {
|
||||||
Future<Iterable<Image>> normalImages = images(regions, amiQuery, PROPERTY_EC2_AMI_QUERY);
|
Future<Iterable<Image>> normalImages = images(regions, amiQuery, PROPERTY_EC2_AMI_QUERY);
|
||||||
ImmutableSet<Image> clusterImages;
|
ImmutableSet<Image> clusterImages;
|
||||||
try {
|
try {
|
||||||
|
@ -115,8 +121,8 @@ public class AWSRegionAndNameToImageSupplier implements Supplier<Map<RegionAndNa
|
||||||
Throwables.propagate(e);
|
Throwables.propagate(e);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
knownImages.clear();
|
||||||
images.putAll(uniqueIndex(parsedImages, new Function<Image, RegionAndName>() {
|
knownImages.putAll(uniqueIndex(parsedImages, new Function<Image, RegionAndName>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RegionAndName apply(Image from) {
|
public RegionAndName apply(Image from) {
|
||||||
|
@ -124,7 +130,13 @@ public class AWSRegionAndNameToImageSupplier implements Supplier<Map<RegionAndNa
|
||||||
}
|
}
|
||||||
|
|
||||||
}));
|
}));
|
||||||
return images;
|
logger.debug("<< images(%d)", knownImages.size());
|
||||||
|
Cache<RegionAndName, Image> cache = CacheBuilder.newBuilder().build(regionAndIdToImage);
|
||||||
|
// seed the cache
|
||||||
|
for (RegionAndName image : knownImages.keySet()){
|
||||||
|
cache.getUnchecked(image);
|
||||||
|
}
|
||||||
|
return cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
private Future<Iterable<Image>> images(Iterable<String> regions, String query, String tag) {
|
private Future<Iterable<Image>> images(Iterable<String> regions, String query, String tag) {
|
||||||
|
|
|
@ -88,7 +88,7 @@ public class AWSEC2TemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
assert (template.getImage().getProviderId().startsWith("ami-")) : template;
|
assert (template.getImage().getProviderId().startsWith("ami-")) : template;
|
||||||
assertEquals(template.getImage().getOperatingSystem().getVersion(), "11.10");
|
assertEquals(template.getImage().getOperatingSystem().getVersion(), "11.04");
|
||||||
assertEquals(template.getImage().getOperatingSystem().is64Bit(), false);
|
assertEquals(template.getImage().getOperatingSystem().is64Bit(), false);
|
||||||
assertEquals(template.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
|
assertEquals(template.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
|
||||||
assertEquals(template.getImage().getUserMetadata().get("rootDeviceType"), "instance-store");
|
assertEquals(template.getImage().getUserMetadata().get("rootDeviceType"), "instance-store");
|
||||||
|
@ -107,7 +107,7 @@ public class AWSEC2TemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
|
||||||
.build();
|
.build();
|
||||||
|
|
||||||
assert (template.getImage().getProviderId().startsWith("ami-")) : template;
|
assert (template.getImage().getProviderId().startsWith("ami-")) : template;
|
||||||
assertEquals(template.getImage().getOperatingSystem().getVersion(), "11.10");
|
assertEquals(template.getImage().getOperatingSystem().getVersion(), "11.04");
|
||||||
assertEquals(template.getImage().getOperatingSystem().is64Bit(), false);
|
assertEquals(template.getImage().getOperatingSystem().is64Bit(), false);
|
||||||
assertEquals(template.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
|
assertEquals(template.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
|
||||||
assertEquals(template.getImage().getUserMetadata().get("rootDeviceType"), "instance-store");
|
assertEquals(template.getImage().getUserMetadata().get("rootDeviceType"), "instance-store");
|
||||||
|
@ -183,7 +183,7 @@ public class AWSEC2TemplateBuilderLiveTest extends BaseTemplateBuilderLiveTest {
|
||||||
fastestTemplate = context.getComputeService().templateBuilder().fastest().build();
|
fastestTemplate = context.getComputeService().templateBuilder().fastest().build();
|
||||||
assert (fastestTemplate.getImage().getProviderId().startsWith("ami-")) : fastestTemplate;
|
assert (fastestTemplate.getImage().getProviderId().startsWith("ami-")) : fastestTemplate;
|
||||||
assertEquals(fastestTemplate.getHardware().getProviderId(), InstanceType.CC1_4XLARGE);
|
assertEquals(fastestTemplate.getHardware().getProviderId(), InstanceType.CC1_4XLARGE);
|
||||||
assertEquals(fastestTemplate.getImage().getOperatingSystem().getVersion(), "11.10");
|
assertEquals(fastestTemplate.getImage().getOperatingSystem().getVersion(), "11.04");
|
||||||
assertEquals(fastestTemplate.getImage().getOperatingSystem().is64Bit(), true);
|
assertEquals(fastestTemplate.getImage().getOperatingSystem().is64Bit(), true);
|
||||||
assertEquals(fastestTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
|
assertEquals(fastestTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.UBUNTU);
|
||||||
assertEquals(fastestTemplate.getImage().getUserMetadata().get("rootDeviceType"), "ebs");
|
assertEquals(fastestTemplate.getImage().getUserMetadata().get("rootDeviceType"), "ebs");
|
||||||
|
|
|
@ -45,6 +45,10 @@ import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.base.Suppliers;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
@ -118,7 +122,7 @@ public class AWSRunningInstanceToNodeMetadataTest {
|
||||||
Map<String, Credentials> credentialStore) {
|
Map<String, Credentials> credentialStore) {
|
||||||
Map<InstanceState, NodeState> instanceToNodeState = EC2ComputeServiceDependenciesModule.instanceToNodeState;
|
Map<InstanceState, NodeState> instanceToNodeState = EC2ComputeServiceDependenciesModule.instanceToNodeState;
|
||||||
|
|
||||||
Map<RegionAndName, Image> instanceToImage = Maps.uniqueIndex(images, new Function<Image, RegionAndName>() {
|
final ImmutableMap<RegionAndName, Image> backing = Maps.uniqueIndex(images, new Function<Image, RegionAndName>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public RegionAndName apply(Image from) {
|
public RegionAndName apply(Image from) {
|
||||||
|
@ -126,13 +130,23 @@ public class AWSRunningInstanceToNodeMetadataTest {
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Cache<RegionAndName, Image> instanceToImage = CacheBuilder.newBuilder().build(new CacheLoader<RegionAndName, Image> (){
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Image load(RegionAndName key) throws Exception {
|
||||||
|
return backing.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
|
||||||
|
|
||||||
return createNodeParser(hardware, locations, credentialStore, instanceToNodeState, instanceToImage);
|
return createNodeParser(hardware, locations, credentialStore, instanceToNodeState, instanceToImage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private AWSRunningInstanceToNodeMetadata createNodeParser(final ImmutableSet<Hardware> hardware,
|
private AWSRunningInstanceToNodeMetadata createNodeParser(final ImmutableSet<Hardware> hardware,
|
||||||
final ImmutableSet<Location> locations, Map<String, Credentials> credentialStore,
|
final ImmutableSet<Location> locations, Map<String, Credentials> credentialStore,
|
||||||
Map<InstanceState, NodeState> instanceToNodeState, Map<RegionAndName, Image> instanceToImage) {
|
Map<InstanceState, NodeState> instanceToNodeState, Cache<RegionAndName, ? extends Image> instanceToImage) {
|
||||||
Supplier<Set<? extends Location>> locationSupplier = new Supplier<Set<? extends Location>>() {
|
Supplier<Set<? extends Location>> locationSupplier = new Supplier<Set<? extends Location>>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -150,7 +164,8 @@ public class AWSRunningInstanceToNodeMetadataTest {
|
||||||
|
|
||||||
};
|
};
|
||||||
AWSRunningInstanceToNodeMetadata parser = new AWSRunningInstanceToNodeMetadata(instanceToNodeState,
|
AWSRunningInstanceToNodeMetadata parser = new AWSRunningInstanceToNodeMetadata(instanceToNodeState,
|
||||||
credentialStore, instanceToImage, locationSupplier, hardwareSupplier);
|
credentialStore, Suppliers.<Cache<RegionAndName, ? extends Image>> ofInstance(instanceToImage),
|
||||||
|
locationSupplier, hardwareSupplier);
|
||||||
return parser;
|
return parser;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -54,13 +54,14 @@ import org.jclouds.scriptbuilder.domain.Statements;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.collect.ImmutableMultimap;
|
import com.google.common.collect.ImmutableMultimap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
*/
|
*/
|
||||||
@Test(groups = "unit")
|
@Test(groups = "unit", singleThreaded = true, testName = "CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsTest")
|
||||||
public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
||||||
private static final Provider<RunInstancesOptions> OPTIONS_PROVIDER = new javax.inject.Provider<RunInstancesOptions>() {
|
private static final Provider<RunInstancesOptions> OPTIONS_PROVIDER = new javax.inject.Provider<RunInstancesOptions>() {
|
||||||
|
|
||||||
|
@ -385,7 +386,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@Test(expectedExceptions = IllegalStateException.class)
|
@Test(expectedExceptions = IllegalArgumentException.class)
|
||||||
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_reusesKeyWhenToldToWithRunScriptButNoCredentials() {
|
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_reusesKeyWhenToldToWithRunScriptButNoCredentials() {
|
||||||
// setup constants
|
// setup constants
|
||||||
String region = Region.AP_SOUTHEAST_1;
|
String region = Region.AP_SOUTHEAST_1;
|
||||||
|
@ -401,7 +402,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
||||||
expect(options.getOverridingCredentials()).andReturn(null);
|
expect(options.getOverridingCredentials()).andReturn(null);
|
||||||
expect(options.getRunScript()).andReturn(Statements.exec("echo foo"));
|
expect(options.getRunScript()).andReturn(Statements.exec("echo foo"));
|
||||||
expect(strategy.credentialsMap.containsKey(new RegionAndName(region, userSuppliedKeyPair))).andReturn(false);
|
expect(strategy.credentialsMap.getUnchecked(new RegionAndName(region, userSuppliedKeyPair))).andThrow(new NullPointerException());
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -432,7 +433,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
||||||
expect(options.getOverridingCredentials()).andReturn(null);
|
expect(options.getOverridingCredentials()).andReturn(null);
|
||||||
expect(options.getRunScript()).andReturn(Statements.exec("echo foo"));
|
expect(options.getRunScript()).andReturn(Statements.exec("echo foo"));
|
||||||
expect(strategy.credentialsMap.containsKey(new RegionAndName(region, userSuppliedKeyPair))).andReturn(true);
|
expect(strategy.credentialsMap.getUnchecked(new RegionAndName(region, userSuppliedKeyPair))).andReturn(keyPair);
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -463,11 +464,13 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
||||||
expect(options.getOverridingCredentials()).andReturn(new Credentials(null, "MyRsa")).atLeastOnce();
|
expect(options.getOverridingCredentials()).andReturn(new Credentials(null, "MyRsa")).atLeastOnce();
|
||||||
expect(
|
expect(
|
||||||
strategy.credentialsMap.put(new RegionAndName(region, userSuppliedKeyPair), KeyPair.builder()
|
strategy.knownKeys.put(
|
||||||
.region(region).keyName(userSuppliedKeyPair).keyFingerprint("//TODO").keyMaterial("MyRsa").build()))
|
new RegionAndName(region, tag),
|
||||||
.andReturn(null);
|
KeyPair.builder().region(region).keyName(userSuppliedKeyPair).keyFingerprint("//TODO")
|
||||||
|
.keyMaterial("MyRsa").build())).andReturn(null);
|
||||||
|
strategy.credentialsMap.invalidate(new RegionAndName(region, tag));
|
||||||
expect(options.getRunScript()).andReturn(Statements.exec("echo foo"));
|
expect(options.getRunScript()).andReturn(Statements.exec("echo foo"));
|
||||||
expect(strategy.credentialsMap.containsKey(new RegionAndName(region, userSuppliedKeyPair))).andReturn(true);
|
expect(strategy.credentialsMap.getUnchecked(new RegionAndName(region, userSuppliedKeyPair))).andReturn(keyPair);
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -483,6 +486,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
verifyStrategy(strategy);
|
verifyStrategy(strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(enabled = false)
|
||||||
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_importsKeyPairAndUnsetsTemplateInstructionWhenPublicKeySuppliedAndAddsCredentialToMapWhenOverridingCredsAreSet() {
|
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_importsKeyPairAndUnsetsTemplateInstructionWhenPublicKeySuppliedAndAddsCredentialToMapWhenOverridingCredsAreSet() {
|
||||||
// setup constants
|
// setup constants
|
||||||
String region = Region.AP_SOUTHEAST_1;
|
String region = Region.AP_SOUTHEAST_1;
|
||||||
|
@ -496,18 +500,19 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
KeyPair keyPair = new KeyPair(region, "jclouds#" + group, "fingerprint", null);
|
KeyPair keyPair = new KeyPair(region, "jclouds#" + group, "fingerprint", null);
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
expect(strategy.knownKeys.get(new RegionAndName(region, "jclouds#" + group))).andReturn(null);
|
||||||
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
||||||
expect(options.shouldAutomaticallyCreateKeyPair()).andReturn(shouldAutomaticallyCreateKeyPair);
|
expect(options.shouldAutomaticallyCreateKeyPair()).andReturn(shouldAutomaticallyCreateKeyPair);
|
||||||
expect(strategy.credentialsMap.get(new RegionAndName(region, "jclouds#" + group))).andReturn(null);
|
expect(strategy.credentialsMap.getUnchecked(new RegionAndName(region, "jclouds#" + group))).andThrow(new NullPointerException());
|
||||||
expect(options.getPublicKey()).andReturn("ssh-rsa").times(2);
|
expect(options.getPublicKey()).andReturn("ssh-rsa").times(2);
|
||||||
expect(strategy.importExistingKeyPair.apply(new RegionNameAndPublicKeyMaterial(region, group, "ssh-rsa")))
|
expect(strategy.importExistingKeyPair.apply(new RegionNameAndPublicKeyMaterial(region, group, "ssh-rsa")))
|
||||||
.andReturn(keyPair);
|
.andReturn(keyPair);
|
||||||
expect(options.dontAuthorizePublicKey()).andReturn(options);
|
|
||||||
expect(options.getOverridingCredentials()).andReturn(new Credentials("foo", "bar")).times(3);
|
expect(options.getOverridingCredentials()).andReturn(new Credentials("foo", "bar")).times(3);
|
||||||
expect(options.getRunScript()).andReturn(null).times(2);
|
expect(options.getRunScript()).andReturn(null).times(2);
|
||||||
expect(options.getPrivateKey()).andReturn(null);
|
expect(options.getPrivateKey()).andReturn(null);
|
||||||
|
expect(options.dontAuthorizePublicKey()).andReturn(options);
|
||||||
expect(
|
expect(
|
||||||
strategy.credentialsMap.put(new RegionAndName(region, "jclouds#" + group),
|
strategy.knownKeys.put(new RegionAndName(region, "jclouds#" + group),
|
||||||
keyPair.toBuilder().keyMaterial("bar").build())).andReturn(null);
|
keyPair.toBuilder().keyMaterial("bar").build())).andReturn(null);
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
|
@ -521,7 +526,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
verify(options);
|
verify(options);
|
||||||
verifyStrategy(strategy);
|
verifyStrategy(strategy);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(enabled = false)
|
||||||
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_importsKeyPairAndUnsetsTemplateInstructionWhenPublicKeySupplied() {
|
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_importsKeyPairAndUnsetsTemplateInstructionWhenPublicKeySupplied() {
|
||||||
// setup constants
|
// setup constants
|
||||||
String region = Region.AP_SOUTHEAST_1;
|
String region = Region.AP_SOUTHEAST_1;
|
||||||
|
@ -535,9 +541,10 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
KeyPair keyPair = new KeyPair(region, "jclouds#" + group, "fingerprint", null);
|
KeyPair keyPair = new KeyPair(region, "jclouds#" + group, "fingerprint", null);
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
expect(strategy.knownKeys.get(new RegionAndName(region, "jclouds#" + group))).andReturn(null);
|
||||||
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
||||||
expect(options.shouldAutomaticallyCreateKeyPair()).andReturn(shouldAutomaticallyCreateKeyPair);
|
expect(options.shouldAutomaticallyCreateKeyPair()).andReturn(shouldAutomaticallyCreateKeyPair);
|
||||||
expect(strategy.credentialsMap.get(new RegionAndName(region, "jclouds#" + group))).andReturn(null);
|
expect(strategy.credentialsMap.getUnchecked(new RegionAndName(region, "jclouds#" + group))).andThrow(new NullPointerException());
|
||||||
expect(options.getPublicKey()).andReturn("ssh-rsa").times(2);
|
expect(options.getPublicKey()).andReturn("ssh-rsa").times(2);
|
||||||
expect(strategy.importExistingKeyPair.apply(new RegionNameAndPublicKeyMaterial(region, group, "ssh-rsa")))
|
expect(strategy.importExistingKeyPair.apply(new RegionNameAndPublicKeyMaterial(region, group, "ssh-rsa")))
|
||||||
.andReturn(keyPair);
|
.andReturn(keyPair);
|
||||||
|
@ -545,7 +552,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
expect(options.getOverridingCredentials()).andReturn(null);
|
expect(options.getOverridingCredentials()).andReturn(null);
|
||||||
expect(options.getRunScript()).andReturn(null).times(2);
|
expect(options.getRunScript()).andReturn(null).times(2);
|
||||||
expect(options.getPrivateKey()).andReturn(null);
|
expect(options.getPrivateKey()).andReturn(null);
|
||||||
expect(strategy.credentialsMap.put(new RegionAndName(region, "jclouds#" + group), keyPair)).andReturn(null);
|
expect(strategy.knownKeys.put(new RegionAndName(region, "jclouds#" + group), keyPair)).andReturn(null);
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -571,18 +578,15 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = setupStrategy();
|
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = setupStrategy();
|
||||||
AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class);
|
AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class);
|
||||||
KeyPair keyPair = createMock(KeyPair.class);
|
KeyPair keyPair = createMock(KeyPair.class);
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
expect(strategy.knownKeys.get(new RegionAndName(region, "jclouds#" + group))).andReturn(null);
|
||||||
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
||||||
expect(options.shouldAutomaticallyCreateKeyPair()).andReturn(shouldAutomaticallyCreateKeyPair);
|
expect(options.shouldAutomaticallyCreateKeyPair()).andReturn(shouldAutomaticallyCreateKeyPair);
|
||||||
expect(strategy.credentialsMap.get(new RegionAndName(region, "jclouds#" + group))).andReturn(null);
|
expect(strategy.credentialsMap.getUnchecked(new RegionAndName(region, group))).andReturn(keyPair);
|
||||||
expect(options.getPublicKey()).andReturn(null).times(2);
|
expect(options.getPublicKey()).andReturn(null).times(2);
|
||||||
expect(strategy.createUniqueKeyPair.apply(new RegionAndName(region, group))).andReturn(keyPair);
|
|
||||||
expect(keyPair.getRegion()).andReturn(region).atLeastOnce();
|
|
||||||
expect(keyPair.getKeyName()).andReturn(systemGeneratedKeyPairName).atLeastOnce();
|
expect(keyPair.getKeyName()).andReturn(systemGeneratedKeyPairName).atLeastOnce();
|
||||||
expect(options.getRunScript()).andReturn(null);
|
expect(options.getRunScript()).andReturn(null);
|
||||||
expect(strategy.credentialsMap.put(new RegionAndName(region, systemGeneratedKeyPairName), keyPair)).andReturn(
|
|
||||||
null);
|
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -613,10 +617,10 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
KeyPair keyPair = createMock(KeyPair.class);
|
KeyPair keyPair = createMock(KeyPair.class);
|
||||||
|
|
||||||
// setup expectations
|
// setup expectations
|
||||||
|
expect(strategy.knownKeys.get(new RegionAndName(region, "jclouds#" + group))).andReturn(keyPair);
|
||||||
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
|
||||||
expect(options.getRunScript()).andReturn(null);
|
expect(options.getRunScript()).andReturn(null);
|
||||||
expect(options.shouldAutomaticallyCreateKeyPair()).andReturn(shouldAutomaticallyCreateKeyPair);
|
expect(options.shouldAutomaticallyCreateKeyPair()).andReturn(shouldAutomaticallyCreateKeyPair);
|
||||||
expect(strategy.credentialsMap.get(new RegionAndName(region, "jclouds#" + group))).andReturn(keyPair);
|
|
||||||
expect(keyPair.getKeyName()).andReturn(systemGeneratedKeyPairName).atLeastOnce();
|
expect(keyPair.getKeyName()).andReturn(systemGeneratedKeyPairName).atLeastOnce();
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -673,7 +677,6 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
Set<String> groupNames = ImmutableSet.<String> of();
|
Set<String> groupNames = ImmutableSet.<String> of();
|
||||||
int[] ports = new int[] {};
|
int[] ports = new int[] {};
|
||||||
boolean shouldAuthorizeSelf = true;
|
boolean shouldAuthorizeSelf = true;
|
||||||
boolean groupExisted = false;
|
|
||||||
Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup);
|
Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup);
|
||||||
|
|
||||||
// create mocks
|
// create mocks
|
||||||
|
@ -686,9 +689,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
|
expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
|
||||||
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
||||||
ports, shouldAuthorizeSelf);
|
ports, shouldAuthorizeSelf);
|
||||||
expect(strategy.securityGroupMap.containsKey(regionNameAndIngressRules)).andReturn(groupExisted);
|
expect(strategy.securityGroupMap.getUnchecked(regionNameAndIngressRules)).andReturn(group);
|
||||||
expect(strategy.createSecurityGroupIfNeeded.apply(regionNameAndIngressRules)).andReturn(generatedMarkerGroup);
|
|
||||||
expect(strategy.securityGroupMap.put(regionNameAndIngressRules, generatedMarkerGroup)).andReturn(null);
|
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -710,7 +711,6 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
Set<String> groupNames = ImmutableSet.<String> of();
|
Set<String> groupNames = ImmutableSet.<String> of();
|
||||||
int[] ports = new int[] { 22, 80 };
|
int[] ports = new int[] { 22, 80 };
|
||||||
boolean shouldAuthorizeSelf = true;
|
boolean shouldAuthorizeSelf = true;
|
||||||
boolean groupExisted = false;
|
|
||||||
Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup);
|
Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup);
|
||||||
|
|
||||||
// create mocks
|
// create mocks
|
||||||
|
@ -723,9 +723,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
|
expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
|
||||||
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
||||||
ports, shouldAuthorizeSelf);
|
ports, shouldAuthorizeSelf);
|
||||||
expect(strategy.securityGroupMap.containsKey(regionNameAndIngressRules)).andReturn(groupExisted);
|
expect(strategy.securityGroupMap.getUnchecked(regionNameAndIngressRules)).andReturn(generatedMarkerGroup);
|
||||||
expect(strategy.createSecurityGroupIfNeeded.apply(regionNameAndIngressRules)).andReturn(generatedMarkerGroup);
|
|
||||||
expect(strategy.securityGroupMap.put(regionNameAndIngressRules, generatedMarkerGroup)).andReturn(null);
|
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -747,7 +745,6 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
Set<String> groupNames = ImmutableSet.<String> of();
|
Set<String> groupNames = ImmutableSet.<String> of();
|
||||||
int[] ports = new int[] {};
|
int[] ports = new int[] {};
|
||||||
boolean shouldAuthorizeSelf = true;
|
boolean shouldAuthorizeSelf = true;
|
||||||
boolean groupExisted = true;
|
|
||||||
Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup);
|
Set<String> returnVal = ImmutableSet.<String> of(generatedMarkerGroup);
|
||||||
|
|
||||||
// create mocks
|
// create mocks
|
||||||
|
@ -760,7 +757,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
|
expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
|
||||||
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
||||||
ports, shouldAuthorizeSelf);
|
ports, shouldAuthorizeSelf);
|
||||||
expect(strategy.securityGroupMap.containsKey(regionNameAndIngressRules)).andReturn(groupExisted);
|
expect(strategy.securityGroupMap.getUnchecked(regionNameAndIngressRules)).andReturn(generatedMarkerGroup);
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -793,13 +790,9 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
expect(options.getGroupIds()).andReturn(ImmutableSet.<String>of());
|
expect(options.getGroupIds()).andReturn(ImmutableSet.<String>of());
|
||||||
expect(options.getGroups()).andReturn(groupNames).atLeastOnce();
|
expect(options.getGroups()).andReturn(groupNames).atLeastOnce();
|
||||||
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
||||||
ports, shouldAuthorizeSelf); // note
|
ports, shouldAuthorizeSelf);
|
||||||
// this
|
|
||||||
// works
|
expect(strategy.securityGroupMap.getUnchecked(regionNameAndIngressRules)).andReturn(groupExisted ? "tag" : null);
|
||||||
// since
|
|
||||||
// there's
|
|
||||||
// no equals on portsq
|
|
||||||
expect(strategy.securityGroupMap.containsKey(regionNameAndIngressRules)).andReturn(groupExisted);
|
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -832,13 +825,9 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
expect(options.getGroupIds()).andReturn(ImmutableSet.<String>of("group1", "group2"));
|
expect(options.getGroupIds()).andReturn(ImmutableSet.<String>of("group1", "group2"));
|
||||||
expect(options.getGroups()).andReturn(groupNames).atLeastOnce();
|
expect(options.getGroups()).andReturn(groupNames).atLeastOnce();
|
||||||
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
|
||||||
ports, shouldAuthorizeSelf); // note
|
ports, shouldAuthorizeSelf);
|
||||||
// this
|
|
||||||
// works
|
expect(strategy.securityGroupMap.getUnchecked(regionNameAndIngressRules)).andReturn(groupExisted ? "tag" : null);
|
||||||
// since
|
|
||||||
// there's
|
|
||||||
// no equals on portsq
|
|
||||||
expect(strategy.securityGroupMap.containsKey(regionNameAndIngressRules)).andReturn(groupExisted);
|
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -895,11 +884,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
// setup expectations
|
// setup expectations
|
||||||
expect(options.getPlacementGroup()).andReturn(userSuppliedPlacementGroup);
|
expect(options.getPlacementGroup()).andReturn(userSuppliedPlacementGroup);
|
||||||
expect(options.shouldAutomaticallyCreatePlacementGroup()).andReturn(shouldAutomaticallyCreatePlacementGroup);
|
expect(options.shouldAutomaticallyCreatePlacementGroup()).andReturn(shouldAutomaticallyCreatePlacementGroup);
|
||||||
expect(strategy.placementGroupMap.containsKey(new RegionAndName(region, generatedMarkerGroup))).andReturn(false);
|
expect(strategy.placementGroupMap.getUnchecked(new RegionAndName(region, generatedMarkerGroup))).andReturn(generatedMarkerGroup);
|
||||||
expect(strategy.createPlacementGroupIfNeeded.apply(new RegionAndName(region, generatedMarkerGroup))).andReturn(
|
|
||||||
generatedMarkerGroup);
|
|
||||||
expect(strategy.placementGroupMap.put(new RegionAndName(region, generatedMarkerGroup), generatedMarkerGroup))
|
|
||||||
.andReturn(null);
|
|
||||||
|
|
||||||
// replay mocks
|
// replay mocks
|
||||||
replay(options);
|
replay(options);
|
||||||
|
@ -946,37 +931,33 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyStrategy(CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy) {
|
private void verifyStrategy(CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy) {
|
||||||
|
verify(strategy.knownKeys);
|
||||||
verify(strategy.credentialsMap);
|
verify(strategy.credentialsMap);
|
||||||
verify(strategy.securityGroupMap);
|
verify(strategy.securityGroupMap);
|
||||||
verify(strategy.placementGroupMap);
|
verify(strategy.placementGroupMap);
|
||||||
verify(strategy.createUniqueKeyPair);
|
|
||||||
verify(strategy.importExistingKeyPair);
|
verify(strategy.importExistingKeyPair);
|
||||||
verify(strategy.createSecurityGroupIfNeeded);
|
|
||||||
verify(strategy.createPlacementGroupIfNeeded);
|
verify(strategy.createPlacementGroupIfNeeded);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
private CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions setupStrategy() {
|
private CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions setupStrategy() {
|
||||||
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
|
Map<RegionAndName, KeyPair> knownKeys = createMock(Map.class);
|
||||||
Map<RegionAndName, String> securityGroupMap = createMock(Map.class);
|
Cache<RegionAndName, KeyPair> credentialsMap = createMock(Cache.class);
|
||||||
Map<RegionAndName, String> placementGroupMap = createMock(Map.class);
|
Cache<RegionAndName, String> securityGroupMap = createMock(Cache.class);
|
||||||
Function<RegionAndName, KeyPair> createOrGetKeyPair = createMock(Function.class);
|
Cache<RegionAndName, String> placementGroupMap = createMock(Cache.class);
|
||||||
Function<RegionNameAndIngressRules, String> createSecurityGroupIfNeeded = createMock(Function.class);
|
|
||||||
Function<RegionNameAndPublicKeyMaterial, KeyPair> importExistingKeyPair = createMock(Function.class);
|
Function<RegionNameAndPublicKeyMaterial, KeyPair> importExistingKeyPair = createMock(Function.class);
|
||||||
CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded = createMock(CreatePlacementGroupIfNeeded.class);
|
CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded = createMock(CreatePlacementGroupIfNeeded.class);
|
||||||
|
|
||||||
return new CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions(credentialsMap, securityGroupMap,
|
return new CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions(knownKeys, credentialsMap, securityGroupMap,
|
||||||
placementGroupMap, createOrGetKeyPair, createSecurityGroupIfNeeded, OPTIONS_PROVIDER,
|
OPTIONS_PROVIDER, placementGroupMap, createPlacementGroupIfNeeded, importExistingKeyPair);
|
||||||
createPlacementGroupIfNeeded, importExistingKeyPair);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private void replayStrategy(CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy) {
|
private void replayStrategy(CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy) {
|
||||||
|
replay(strategy.knownKeys);
|
||||||
replay(strategy.credentialsMap);
|
replay(strategy.credentialsMap);
|
||||||
replay(strategy.securityGroupMap);
|
replay(strategy.securityGroupMap);
|
||||||
replay(strategy.placementGroupMap);
|
replay(strategy.placementGroupMap);
|
||||||
replay(strategy.createUniqueKeyPair);
|
|
||||||
replay(strategy.importExistingKeyPair);
|
replay(strategy.importExistingKeyPair);
|
||||||
replay(strategy.createSecurityGroupIfNeeded);
|
|
||||||
replay(strategy.createPlacementGroupIfNeeded);
|
replay(strategy.createPlacementGroupIfNeeded);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,14 @@ import java.net.URI;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.aws.domain.Region;
|
import org.jclouds.aws.domain.Region;
|
||||||
import org.jclouds.aws.ec2.config.AWSEC2RestClientModule;
|
import org.jclouds.aws.ec2.config.AWSEC2RestClientModule;
|
||||||
import org.jclouds.aws.filters.FormSigner;
|
import org.jclouds.aws.filters.FormSigner;
|
||||||
|
import org.jclouds.compute.domain.Image;
|
||||||
import org.jclouds.date.DateService;
|
import org.jclouds.date.DateService;
|
||||||
|
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||||
import org.jclouds.http.HttpRequest;
|
import org.jclouds.http.HttpRequest;
|
||||||
import org.jclouds.http.RequiresHttp;
|
import org.jclouds.http.RequiresHttp;
|
||||||
import org.jclouds.rest.ConfiguresRestClient;
|
import org.jclouds.rest.ConfiguresRestClient;
|
||||||
|
@ -38,8 +42,12 @@ import org.jclouds.rest.RestContextSpec;
|
||||||
import org.testng.annotations.BeforeTest;
|
import org.testng.annotations.BeforeTest;
|
||||||
import org.testng.annotations.Test;
|
import org.testng.annotations.Test;
|
||||||
|
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
|
import com.google.common.cache.CacheBuilder;
|
||||||
|
import com.google.common.cache.CacheLoader;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.inject.Module;
|
import com.google.inject.Module;
|
||||||
|
import com.google.inject.Provides;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -60,6 +68,18 @@ public abstract class BaseAWSEC2AsyncClientTest<T> extends RestClientTest<T> {
|
||||||
bindRegionsToProvider(Regions.class);
|
bindRegionsToProvider(Regions.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Provides
|
||||||
|
@Singleton
|
||||||
|
Cache<RegionAndName, Image> provide(){
|
||||||
|
return CacheBuilder.newBuilder().build(new CacheLoader<RegionAndName, Image>() {
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Image load(RegionAndName key) throws Exception {
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
});
|
||||||
|
}
|
||||||
static class Regions implements javax.inject.Provider<Map<String, URI>> {
|
static class Regions implements javax.inject.Provider<Map<String, URI>> {
|
||||||
@Override
|
@Override
|
||||||
public Map<String, URI> get() {
|
public Map<String, URI> get() {
|
||||||
|
|
|
@ -32,7 +32,6 @@ import javax.inject.Named;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
import org.jclouds.Constants;
|
import org.jclouds.Constants;
|
||||||
import org.jclouds.cloudsigma.CloudSigmaAsyncClient;
|
|
||||||
import org.jclouds.cloudsigma.CloudSigmaClient;
|
import org.jclouds.cloudsigma.CloudSigmaClient;
|
||||||
import org.jclouds.cloudsigma.domain.Device;
|
import org.jclouds.cloudsigma.domain.Device;
|
||||||
import org.jclouds.cloudsigma.domain.DriveInfo;
|
import org.jclouds.cloudsigma.domain.DriveInfo;
|
||||||
|
@ -60,33 +59,35 @@ import org.jclouds.logging.Logger;
|
||||||
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.Predicates;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.ImmutableSet.Builder;
|
import com.google.common.collect.ImmutableSet.Builder;
|
||||||
|
import com.google.common.util.concurrent.Futures;
|
||||||
|
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* defines the connection between the {@link CloudSigmaClient} implementation and the jclouds
|
* defines the connection between the {@link CloudSigmaClient} implementation
|
||||||
* {@link ComputeService}
|
* and the jclouds {@link ComputeService}
|
||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public class CloudSigmaComputeServiceAdapter implements
|
public class CloudSigmaComputeServiceAdapter implements
|
||||||
ComputeServiceAdapter<ServerInfo, Hardware, DriveInfo, Location> {
|
ComputeServiceAdapter<ServerInfo, Hardware, DriveInfo, Location> {
|
||||||
private static final Predicate<DriveInfo> PREINSTALLED_DISK = Predicates.and(Predicates.notNull(),
|
private static final Predicate<DriveInfo> PREINSTALLED_DISK = Predicates.and(Predicates.notNull(),
|
||||||
new Predicate<DriveInfo>() {
|
new Predicate<DriveInfo>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public boolean apply(DriveInfo drive) {
|
public boolean apply(DriveInfo drive) {
|
||||||
return drive.getType().equals(DriveType.DISK) && drive.getDriveType().contains("preinstalled");
|
return drive.getType().equals(DriveType.DISK) && drive.getDriveType().contains("preinstalled");
|
||||||
}
|
}
|
||||||
|
|
||||||
});
|
});
|
||||||
private final CloudSigmaClient client;
|
private final CloudSigmaClient client;
|
||||||
private final CloudSigmaAsyncClient aclient;
|
|
||||||
private final Predicate<DriveInfo> driveNotClaimed;
|
private final Predicate<DriveInfo> driveNotClaimed;
|
||||||
private final JustProvider locationSupplier;
|
private final JustProvider locationSupplier;
|
||||||
private final String defaultVncPassword;
|
private final String defaultVncPassword;
|
||||||
private final Map<String, DriveInfo> cache;
|
private final Cache<String, DriveInfo> cache;
|
||||||
private final ExecutorService executor;
|
private final ExecutorService executor;
|
||||||
|
|
||||||
@Resource
|
@Resource
|
||||||
|
@ -94,12 +95,10 @@ public class CloudSigmaComputeServiceAdapter implements
|
||||||
protected Logger logger = Logger.NULL;
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public CloudSigmaComputeServiceAdapter(CloudSigmaClient client, CloudSigmaAsyncClient aclient,
|
public CloudSigmaComputeServiceAdapter(CloudSigmaClient client, Predicate<DriveInfo> driveNotClaimed,
|
||||||
Predicate<DriveInfo> driveNotClaimed, JustProvider locationSupplier,
|
JustProvider locationSupplier, @Named(CloudSigmaConstants.PROPERTY_VNC_PASSWORD) String defaultVncPassword,
|
||||||
@Named(CloudSigmaConstants.PROPERTY_VNC_PASSWORD) String defaultVncPassword, Map<String, DriveInfo> cache,
|
Cache<String, DriveInfo> cache, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
||||||
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
|
|
||||||
this.client = checkNotNull(client, "client");
|
this.client = checkNotNull(client, "client");
|
||||||
this.aclient = checkNotNull(aclient, "aclient");
|
|
||||||
this.driveNotClaimed = checkNotNull(driveNotClaimed, "driveNotClaimed");
|
this.driveNotClaimed = checkNotNull(driveNotClaimed, "driveNotClaimed");
|
||||||
this.locationSupplier = checkNotNull(locationSupplier, "locationSupplier");
|
this.locationSupplier = checkNotNull(locationSupplier, "locationSupplier");
|
||||||
this.defaultVncPassword = checkNotNull(defaultVncPassword, "defaultVncPassword");
|
this.defaultVncPassword = checkNotNull(defaultVncPassword, "defaultVncPassword");
|
||||||
|
@ -109,21 +108,20 @@ public class CloudSigmaComputeServiceAdapter implements
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public ServerInfo createNodeWithGroupEncodedIntoNameThenStoreCredentials(String tag, String name, Template template,
|
public ServerInfo createNodeWithGroupEncodedIntoNameThenStoreCredentials(String tag, String name, Template template,
|
||||||
Map<String, Credentials> credentialStore) {
|
Map<String, Credentials> credentialStore) {
|
||||||
long bootSize = (long) (template.getHardware().getVolumes().get(0).getSize() * 1024 * 1024 * 1024l);
|
long bootSize = (long) (template.getHardware().getVolumes().get(0).getSize() * 1024 * 1024 * 1024l);
|
||||||
logger.debug(">> imaging boot drive source(%s) bytes(%d)", template.getImage().getId(), bootSize);
|
logger.debug(">> imaging boot drive source(%s) bytes(%d)", template.getImage().getId(), bootSize);
|
||||||
DriveInfo drive = client.cloneDrive(template.getImage().getId(), template.getImage().getId(),
|
DriveInfo drive = client.cloneDrive(template.getImage().getId(), template.getImage().getId(),
|
||||||
new CloneDriveOptions().size(bootSize));
|
new CloneDriveOptions().size(bootSize));
|
||||||
boolean success = driveNotClaimed.apply(drive);
|
boolean success = driveNotClaimed.apply(drive);
|
||||||
logger.debug("<< image(%s) complete(%s)", drive.getUuid(), success);
|
logger.debug("<< image(%s) complete(%s)", drive.getUuid(), success);
|
||||||
if (!success) {
|
if (!success) {
|
||||||
client.destroyDrive(drive.getUuid());
|
client.destroyDrive(drive.getUuid());
|
||||||
throw new IllegalStateException("could not image drive in time!");
|
throw new IllegalStateException("could not image drive in time!");
|
||||||
}
|
}
|
||||||
cache.put(drive.getUuid(), drive);
|
|
||||||
|
|
||||||
Server toCreate = Servers.small(name, drive.getUuid(), defaultVncPassword).mem(template.getHardware().getRam())
|
Server toCreate = Servers.small(name, drive.getUuid(), defaultVncPassword).mem(template.getHardware().getRam())
|
||||||
.cpu((int) (template.getHardware().getProcessors().get(0).getSpeed())).build();
|
.cpu((int) (template.getHardware().getProcessors().get(0).getSpeed())).build();
|
||||||
|
|
||||||
logger.debug(">> creating server");
|
logger.debug(">> creating server");
|
||||||
ServerInfo from = client.createServer(toCreate);
|
ServerInfo from = client.createServer(toCreate);
|
||||||
|
@ -131,7 +129,7 @@ public class CloudSigmaComputeServiceAdapter implements
|
||||||
logger.debug(">> starting server(%s)", from.getUuid());
|
logger.debug(">> starting server(%s)", from.getUuid());
|
||||||
client.startServer(from.getUuid());
|
client.startServer(from.getUuid());
|
||||||
// store the credentials so that later functions can use them
|
// store the credentials so that later functions can use them
|
||||||
credentialStore.put("node#"+ from.getUuid(), new Credentials("cloudsigma", "cloudsigma"));
|
credentialStore.put("node#" + from.getUuid(), new Credentials("root", defaultVncPassword));
|
||||||
return from;
|
return from;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,30 +153,39 @@ public class CloudSigmaComputeServiceAdapter implements
|
||||||
return "sizeLessThanOrEqual(" + size + ")";
|
return "sizeLessThanOrEqual(" + size + ")";
|
||||||
}
|
}
|
||||||
|
|
||||||
}).ids(id).ram(ram).processors(ImmutableList.of(new Processor(1, cpu))).volumes(
|
}).ids(id).ram(ram).processors(ImmutableList.of(new Processor(1, cpu)))
|
||||||
ImmutableList.<Volume> of(new VolumeImpl(size, true, true))).build());
|
.volumes(ImmutableList.<Volume> of(new VolumeImpl(size, true, true))).build());
|
||||||
}
|
}
|
||||||
return hardware.build();
|
return hardware.build();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* look up the current standard images and do not error out, if they are not found.
|
* look up the current standard images and do not error out, if they are not
|
||||||
|
* found.
|
||||||
*/
|
*/
|
||||||
@Override
|
@Override
|
||||||
public Iterable<DriveInfo> listImages() {
|
public Iterable<DriveInfo> listImages() {
|
||||||
Iterable<DriveInfo> drives = transformParallel(client.listStandardDrives(),
|
Iterable<DriveInfo> drives = transformParallel(client.listStandardDrives(),
|
||||||
new Function<String, Future<DriveInfo>>() {
|
new Function<String, Future<DriveInfo>>() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Future<DriveInfo> apply(String input) {
|
public Future<DriveInfo> apply(String input) {
|
||||||
return aclient.getDriveInfo(input);
|
try {
|
||||||
|
return Futures.immediateFuture(cache.getUnchecked(input));
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
logger.debug("drive %s not found", input);
|
||||||
|
} catch (UncheckedExecutionException e) {
|
||||||
|
logger.warn(e, "error finding drive %s: %s", input, e.getMessage());
|
||||||
}
|
}
|
||||||
|
return Futures.immediateFuture(null);
|
||||||
|
}
|
||||||
|
|
||||||
}, executor, null, logger, "drives");
|
@Override
|
||||||
Iterable<DriveInfo> returnVal = filter(drives, PREINSTALLED_DISK);
|
public String toString() {
|
||||||
for (DriveInfo drive : returnVal)
|
return "seedDriveCache()";
|
||||||
cache.put(drive.getUuid(), drive);
|
}
|
||||||
return returnVal;
|
}, executor, null, logger, "drives");
|
||||||
|
return filter(drives, PREINSTALLED_DISK);
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
|
|
|
@ -25,6 +25,7 @@ import java.util.List;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
|
import javax.annotation.Resource;
|
||||||
import javax.inject.Inject;
|
import javax.inject.Inject;
|
||||||
import javax.inject.Singleton;
|
import javax.inject.Singleton;
|
||||||
|
|
||||||
|
@ -45,13 +46,16 @@ import org.jclouds.compute.domain.Volume;
|
||||||
import org.jclouds.compute.domain.VolumeBuilder;
|
import org.jclouds.compute.domain.VolumeBuilder;
|
||||||
import org.jclouds.domain.Credentials;
|
import org.jclouds.domain.Credentials;
|
||||||
import org.jclouds.domain.Location;
|
import org.jclouds.domain.Location;
|
||||||
|
import org.jclouds.logging.Logger;
|
||||||
|
|
||||||
import com.google.common.base.Function;
|
import com.google.common.base.Function;
|
||||||
import com.google.common.base.Supplier;
|
import com.google.common.base.Supplier;
|
||||||
|
import com.google.common.cache.Cache;
|
||||||
import com.google.common.collect.ImmutableList;
|
import com.google.common.collect.ImmutableList;
|
||||||
import com.google.common.collect.ImmutableMap;
|
import com.google.common.collect.ImmutableMap;
|
||||||
import com.google.common.collect.ImmutableSet;
|
import com.google.common.collect.ImmutableSet;
|
||||||
import com.google.common.collect.Iterables;
|
import com.google.common.collect.Iterables;
|
||||||
|
import com.google.common.util.concurrent.UncheckedExecutionException;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @author Adrian Cole
|
* @author Adrian Cole
|
||||||
|
@ -113,10 +117,13 @@ public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetada
|
||||||
|
|
||||||
@Singleton
|
@Singleton
|
||||||
public static final class DeviceToVolume implements Function<Device, Volume> {
|
public static final class DeviceToVolume implements Function<Device, Volume> {
|
||||||
private final Map<String, DriveInfo> cache;
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
private final Cache<String, DriveInfo> cache;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public DeviceToVolume(Map<String, DriveInfo> cache) {
|
public DeviceToVolume(Cache<String, DriveInfo> cache) {
|
||||||
this.cache = checkNotNull(cache, "cache");
|
this.cache = checkNotNull(cache, "cache");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -124,9 +131,13 @@ public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetada
|
||||||
public Volume apply(Device input) {
|
public Volume apply(Device input) {
|
||||||
VolumeBuilder builder = new VolumeBuilder();
|
VolumeBuilder builder = new VolumeBuilder();
|
||||||
builder.id(input.getId());
|
builder.id(input.getId());
|
||||||
DriveInfo drive = cache.get(input.getDriveUuid());
|
try {
|
||||||
if (drive != null) {
|
DriveInfo drive = cache.getUnchecked(input.getDriveUuid());
|
||||||
builder.size(drive.getSize() / 1024 / 1024f);
|
builder.size(drive.getSize() / 1024 / 1024f);
|
||||||
|
} catch (NullPointerException e) {
|
||||||
|
logger.debug("drive %s not found", input.getDriveUuid());
|
||||||
|
} catch (UncheckedExecutionException e) {
|
||||||
|
logger.warn(e, "error finding drive %s: %s", input.getDriveUuid(), e.getMessage());
|
||||||
}
|
}
|
||||||
return new VolumeBuilder().durable(true).type(Volume.Type.NAS).build();
|
return new VolumeBuilder().durable(true).type(Volume.Type.NAS).build();
|
||||||
}
|
}
|
||||||
|
@ -141,10 +152,13 @@ public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetada
|
||||||
*/
|
*/
|
||||||
@Singleton
|
@Singleton
|
||||||
public static class GetImageIdFromServer implements Function<Server, String> {
|
public static class GetImageIdFromServer implements Function<Server, String> {
|
||||||
private final Map<String, DriveInfo> cache;
|
@Resource
|
||||||
|
protected Logger logger = Logger.NULL;
|
||||||
|
|
||||||
|
private final Cache<String, DriveInfo> cache;
|
||||||
|
|
||||||
@Inject
|
@Inject
|
||||||
public GetImageIdFromServer(Map<String, DriveInfo> cache) {
|
public GetImageIdFromServer(Cache<String, DriveInfo> cache) {
|
||||||
this.cache = cache;
|
this.cache = cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -155,9 +169,12 @@ public class ServerInfoToNodeMetadata implements Function<ServerInfo, NodeMetada
|
||||||
Device bootDevice = from.getDevices().get(bootDeviceId);
|
Device bootDevice = from.getDevices().get(bootDeviceId);
|
||||||
if (bootDevice != null) {
|
if (bootDevice != null) {
|
||||||
try {
|
try {
|
||||||
imageId = cache.get(bootDevice.getDriveUuid()).getName();
|
DriveInfo drive = cache.getUnchecked(bootDevice.getDriveUuid());
|
||||||
|
imageId = drive.getName();
|
||||||
} catch (NullPointerException e) {
|
} catch (NullPointerException e) {
|
||||||
|
logger.debug("drive %s not found", bootDevice.getDriveUuid());
|
||||||
|
} catch (UncheckedExecutionException e) {
|
||||||
|
logger.warn(e, "error finding drive %s: %s", bootDevice.getDriveUuid(), e.getMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return imageId;
|
return imageId;
|
||||||
|
|
Loading…
Reference in New Issue