Issue 499:add and use import key support to aws-ec2

This commit is contained in:
Adrian Cole 2011-03-06 15:35:06 -05:00
parent d7814821a3
commit ebd4d1e432
26 changed files with 1123 additions and 468 deletions

View File

@ -19,9 +19,14 @@
package org.jclouds.ec2.compute; package org.jclouds.ec2.compute;
import static com.google.common.collect.Iterables.concat;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.transform;
import static org.jclouds.util.Preconditions2.checkNotEmpty;
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 java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import javax.inject.Inject; import javax.inject.Inject;
@ -40,13 +45,13 @@ import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.internal.BaseComputeService; import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts; import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.DestroyNodeStrategy; import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy; import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap; import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy; import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy; import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy; import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.SuspendNodeStrategy; import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
@ -55,12 +60,15 @@ 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.options.EC2TemplateOptions; import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.KeyPair; import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.util.Preconditions2; 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.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Supplier; import com.google.common.base.Supplier;
import com.google.common.collect.Maps; import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMap.Builder;
import com.google.common.collect.ImmutableSet;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -73,31 +81,30 @@ public class EC2ComputeService extends BaseComputeService {
@Inject @Inject
protected EC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore, protected EC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes, @Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy, @Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy, RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy, ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider, Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated, @Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended, @Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, Timeouts timeouts, InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, 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) { Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy, super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy,
stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, nodeSuspended,
nodeSuspended, initScriptRunnerFactory, timeouts, executor); initScriptRunnerFactory, timeouts, executor);
this.ec2Client = ec2Client; this.ec2Client = ec2Client;
this.credentialsMap = credentialsMap; this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap; this.securityGroupMap = securityGroupMap;
} }
@VisibleForTesting @VisibleForTesting
void deleteSecurityGroup(String region, String group) { void deleteSecurityGroup(String region, String group) {
Preconditions2.checkNotEmpty(group, "group"); checkNotEmpty(group, "group");
String groupName = String.format("jclouds#%s#%s", group, region); String groupName = String.format("jclouds#%s#%s", group, region);
if (ec2Client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, groupName).size() > 0) { if (ec2Client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, groupName).size() > 0) {
logger.debug(">> deleting securityGroup(%s)", groupName); logger.debug(">> deleting securityGroup(%s)", groupName);
@ -115,16 +122,54 @@ public class EC2ComputeService extends BaseComputeService {
@VisibleForTesting @VisibleForTesting
void deleteKeyPair(String region, String group) { void deleteKeyPair(String region, String group) {
for (KeyPair keyPair : ec2Client.getKeyPairServices().describeKeyPairsInRegion(region)) { for (KeyPair keyPair : ec2Client.getKeyPairServices().describeKeyPairsInRegion(region)) {
if (keyPair.getKeyName().matches(String.format("jclouds#%s#%s#%s", group, region, "[0-9a-f]+"))) { if (
logger.debug(">> deleting keyPair(%s)", keyPair.getKeyName()); // when the keypair is unique per group
ec2Client.getKeyPairServices().deleteKeyPairInRegion(region, keyPair.getKeyName()); keyPair.getKeyName().equals("jclouds#" + group)
// TODO: test this clear happens || keyPair.getKeyName().matches(String.format("jclouds#%s#%s", group, "[0-9a-f]+"))
credentialsMap.remove(new RegionAndName(region, keyPair.getKeyName())); // old keypair pattern too verbose as it has an unnecessary region qualifier
logger.debug("<< deleted keyPair(%s)", keyPair.getKeyName()); || keyPair.getKeyName().matches(String.format("jclouds#%s#%s#%s", group, region, "[0-9a-f]+"))) {
Set<String> instancesUsingKeyPair = extractIdsFromInstances(filter(concat(ec2Client.getInstanceServices()
.describeInstancesInRegion(region)), usingKeyPairAndNotDead(keyPair)));
if (instancesUsingKeyPair.size() > 0) {
logger.debug("<< inUse keyPair(%s), by (%s)", keyPair.getKeyName(), instancesUsingKeyPair);
} else {
logger.debug(">> deleting keyPair(%s)", keyPair.getKeyName());
ec2Client.getKeyPairServices().deleteKeyPairInRegion(region, keyPair.getKeyName());
// TODO: test this clear happens
credentialsMap.remove(new RegionAndName(region, keyPair.getKeyName()));
logger.debug("<< deleted keyPair(%s)", keyPair.getKeyName());
}
} }
} }
} }
protected ImmutableSet<String> extractIdsFromInstances(Iterable<? extends RunningInstance> deadOnes) {
return ImmutableSet.copyOf(transform(deadOnes, new Function<RunningInstance, String>() {
@Override
public String apply(RunningInstance input) {
return input.getId();
}
}));
}
protected Predicate<RunningInstance> usingKeyPairAndNotDead(final KeyPair keyPair) {
return new Predicate<RunningInstance>() {
@Override
public boolean apply(RunningInstance input) {
switch (input.getInstanceState()) {
case TERMINATED:
case SHUTTING_DOWN:
return false;
}
return keyPair.getKeyName().equals(input.getKeyName());
}
};
}
/** /**
* like {@link BaseComputeService#destroyNodesMatching} except that this will clean implicit * like {@link BaseComputeService#destroyNodesMatching} except that this will clean implicit
* keypairs and security groups. * keypairs and security groups.
@ -132,20 +177,20 @@ public class EC2ComputeService extends BaseComputeService {
@Override @Override
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) { public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
Set<? extends NodeMetadata> deadOnes = super.destroyNodesMatching(filter); Set<? extends NodeMetadata> deadOnes = super.destroyNodesMatching(filter);
Map<String, String> regionTags = Maps.newHashMap(); Builder<String, String> regionGroups = ImmutableMap.<String, String> builder();
for (NodeMetadata nodeMetadata : deadOnes) { for (NodeMetadata nodeMetadata : deadOnes) {
if (nodeMetadata.getGroup() != null) if (nodeMetadata.getGroup() != null)
regionTags.put(AWSUtils.parseHandle(nodeMetadata.getId())[0], nodeMetadata.getGroup()); regionGroups.put(AWSUtils.parseHandle(nodeMetadata.getId())[0], nodeMetadata.getGroup());
} }
for (Entry<String, String> regionTag : regionTags.entrySet()) { for (Entry<String, String> regionGroup : regionGroups.build().entrySet()) {
cleanUpIncidentalResources(regionTag); cleanUpIncidentalResources(regionGroup);
} }
return deadOnes; return deadOnes;
} }
protected void cleanUpIncidentalResources(Entry<String, String> regionTag) { protected void cleanUpIncidentalResources(Entry<String, String> regionGroup) {
deleteKeyPair(regionTag.getKey(), regionTag.getValue()); deleteKeyPair(regionGroup.getKey(), regionGroup.getValue());
deleteSecurityGroup(regionTag.getKey(), regionTag.getValue()); deleteSecurityGroup(regionGroup.getKey(), regionGroup.getValue());
} }
/** /**

View File

@ -43,6 +43,7 @@ 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;
@ -76,11 +77,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
@ -104,6 +105,12 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
}).to(RunningInstanceToNodeMetadata.class); }).to(RunningInstanceToNodeMetadata.class);
bind(new TypeLiteral<Function<RunningInstance, Credentials>>() { bind(new TypeLiteral<Function<RunningInstance, Credentials>>() {
}).to(CredentialsForInstance.class); }).to(CredentialsForInstance.class);
bind(new TypeLiteral<Function<RegionNameAndIngressRules, String>>() {
}).to(CreateSecurityGroupIfNeeded.class);
bind(new TypeLiteral<Function<RegionAndName, KeyPair>>() {
}).to(CreateUniqueKeyPair.class);
bind(new TypeLiteral<Function<RegionAndName, Image>>() {
}).to(RegionAndIdToImage.class);
bind(new TypeLiteral<ComputeServiceContext>() { bind(new TypeLiteral<ComputeServiceContext>() {
}).to(new TypeLiteral<ComputeServiceContextImpl<EC2Client, EC2AsyncClient>>() { }).to(new TypeLiteral<ComputeServiceContextImpl<EC2Client, EC2AsyncClient>>() {
}).in(Scopes.SINGLETON); }).in(Scopes.SINGLETON);
@ -128,7 +135,7 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
protected final Map<RegionAndName, KeyPair> credentialsMap(CreateUniqueKeyPair in) { protected final Map<RegionAndName, KeyPair> credentialsMap(Function<RegionAndName, KeyPair> in) {
// doesn't seem to clear when someone issues remove(key) // doesn't seem to clear when someone issues remove(key)
// return new MapMaker().makeComputingMap(in); // return new MapMaker().makeComputingMap(in);
return newLinkedHashMap(); return newLinkedHashMap();
@ -137,13 +144,12 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
@Provides @Provides
@Singleton @Singleton
@Named("SECURITY") @Named("SECURITY")
protected final Map<RegionAndName, String> securityGroupMap(CreateSecurityGroupIfNeeded in) { protected final Map<RegionAndName, String> securityGroupMap(Function<RegionNameAndIngressRules, String> in) {
// doesn't seem to clear when someone issues remove(key) // doesn't seem to clear when someone issues remove(key)
// return new MapMaker().makeComputingMap(in); // return new MapMaker().makeComputingMap(in);
return newLinkedHashMap(); return newLinkedHashMap();
} }
@Provides @Provides
@Singleton @Singleton
@Named(PROPERTY_EC2_AMI_OWNERS) @Named(PROPERTY_EC2_AMI_OWNERS)
@ -153,10 +159,9 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
return toArray(Splitter.on(',').split(amiOwners), String.class); return toArray(Splitter.on(',').split(amiOwners), String.class);
} }
@Provides @Provides
@Singleton @Singleton
protected Map<RegionAndName, Image> provideImageMap(RegionAndIdToImage regionAndIdToImage) { protected Map<RegionAndName, Image> provideImageMap(Function<RegionAndName, Image> regionAndIdToImage) {
return new MapMaker().makeComputingMap(regionAndIdToImage); return new MapMaker().makeComputingMap(regionAndIdToImage);
} }

View File

@ -73,7 +73,7 @@ public class RegionAndName {
@Override @Override
public String toString() { public String toString() {
return "RegionTag [region=" + region + ", name=" + name + "]"; return "[region=" + region + ", name=" + name + "]";
} }
} }

View File

@ -26,10 +26,10 @@ 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.RegionAndName;
import org.jclouds.ec2.domain.KeyPair; import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
@ -46,7 +46,7 @@ public class CreateUniqueKeyPair implements Function<RegionAndName, KeyPair> {
@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 Supplier<String> randomSuffix; protected final Supplier<String> randomSuffix;
@Inject @Inject
public CreateUniqueKeyPair(EC2Client ec2Client, Supplier<String> randomSuffix) { public CreateUniqueKeyPair(EC2Client ec2Client, Supplier<String> randomSuffix) {
@ -60,14 +60,14 @@ public class CreateUniqueKeyPair implements Function<RegionAndName, KeyPair> {
} }
@VisibleForTesting @VisibleForTesting
KeyPair createNewKeyPairInRegion(String region, String tag) { KeyPair createNewKeyPairInRegion(String region, String group) {
checkNotNull(region, "region"); checkNotNull(region, "region");
checkNotNull(tag, "tag"); checkNotNull(group, "group");
logger.debug(">> creating keyPair region(%s) tag(%s)", region, tag); logger.debug(">> creating keyPair region(%s) group(%s)", region, group);
KeyPair keyPair = null; KeyPair keyPair = null;
while (keyPair == null) { while (keyPair == null) {
try { try {
keyPair = ec2Client.getKeyPairServices().createKeyPairInRegion(region, getNextName(region, tag)); keyPair = ec2Client.getKeyPairServices().createKeyPairInRegion(region, getNextName(region, group));
logger.debug("<< created keyPair(%s)", keyPair.getKeyName()); logger.debug("<< created keyPair(%s)", keyPair.getKeyName());
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
@ -76,7 +76,7 @@ public class CreateUniqueKeyPair implements Function<RegionAndName, KeyPair> {
return keyPair; return keyPair;
} }
private String getNextName(String region, String tag) { private String getNextName(String region, String group) {
return String.format("jclouds#%s#%s#%s", tag, region, randomSuffix.get()); return String.format("jclouds#%s#%s#%s", group, region, randomSuffix.get());
} }
} }

View File

@ -82,7 +82,6 @@ public class EC2ImageParser implements Function<org.jclouds.ec2.domain.Image, Im
@Override @Override
public Image apply(final org.jclouds.ec2.domain.Image from) { public Image apply(final org.jclouds.ec2.domain.Image from) {
if (from.getImageType() != ImageType.MACHINE) { if (from.getImageType() != ImageType.MACHINE) {
logger.trace("skipping as not a machine image(%s)", from.getId());
return null; return null;
} }
ImageBuilder builder = new ImageBuilder(); ImageBuilder builder = new ImageBuilder();

View File

@ -27,21 +27,22 @@ import java.util.Set;
import javax.annotation.Nullable; import 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.Singleton; import javax.inject.Singleton;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
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;
import org.jclouds.ec2.options.RunInstancesOptions; import org.jclouds.ec2.options.RunInstancesOptions;
import com.google.common.annotations.VisibleForTesting; import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Sets; import com.google.common.base.Function;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.ImmutableSet.Builder;
/** /**
* *
@ -55,16 +56,16 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
@VisibleForTesting @VisibleForTesting
public final Map<RegionAndName, String> securityGroupMap; public final Map<RegionAndName, String> securityGroupMap;
@VisibleForTesting @VisibleForTesting
public final CreateUniqueKeyPair createUniqueKeyPair; public final Function<RegionAndName, KeyPair> createUniqueKeyPair;
@VisibleForTesting @VisibleForTesting
public final CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded; public final Function<RegionNameAndIngressRules, String> createSecurityGroupIfNeeded;
private final javax.inject.Provider<RunInstancesOptions> optionsProvider; protected final Provider<RunInstancesOptions> optionsProvider;
@Inject @Inject
public CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions(Map<RegionAndName, KeyPair> credentialsMap, public CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions(Map<RegionAndName, KeyPair> credentialsMap,
@Named("SECURITY") Map<RegionAndName, String> securityGroupMap, CreateUniqueKeyPair createUniqueKeyPair, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap, Function<RegionAndName, KeyPair> createUniqueKeyPair,
CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded, Function<RegionNameAndIngressRules, String> createSecurityGroupIfNeeded,
javax.inject.Provider<RunInstancesOptions> optionsProvider) { Provider<RunInstancesOptions> optionsProvider) {
this.credentialsMap = credentialsMap; this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap; this.securityGroupMap = securityGroupMap;
this.createUniqueKeyPair = createUniqueKeyPair; this.createUniqueKeyPair = createUniqueKeyPair;
@ -72,13 +73,13 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
this.optionsProvider = optionsProvider; this.optionsProvider = optionsProvider;
} }
public RunInstancesOptions execute(String region, String tag, Template template) { public RunInstancesOptions execute(String region, String group, Template template) {
RunInstancesOptions instanceOptions = getOptionsProvider().get().asType(template.getHardware().getId()); RunInstancesOptions instanceOptions = getOptionsProvider().get().asType(template.getHardware().getId());
String keyPairName = createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, template.getOptions()); String keyPairName = createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, template.getOptions());
addSecurityGroups(region, tag, template, instanceOptions); addSecurityGroups(region, group, template, instanceOptions);
if (template.getOptions() instanceof EC2TemplateOptions) { if (template.getOptions() instanceof EC2TemplateOptions) {
if (keyPairName != null) if (keyPairName != null)
@ -90,72 +91,83 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
instanceOptions.withUserData(userData); instanceOptions.withUserData(userData);
Set<BlockDeviceMapping> blockDeviceMappings = EC2TemplateOptions.class.cast(template.getOptions()) Set<BlockDeviceMapping> blockDeviceMappings = EC2TemplateOptions.class.cast(template.getOptions())
.getBlockDeviceMappings(); .getBlockDeviceMappings();
if (blockDeviceMappings.size() > 0) { if (blockDeviceMappings.size() > 0) {
checkState("ebs".equals(template.getImage().getUserMetadata().get("rootDeviceType")), checkState("ebs".equals(template.getImage().getUserMetadata().get("rootDeviceType")),
"BlockDeviceMapping only available on ebs boot"); "BlockDeviceMapping only available on ebs boot");
instanceOptions.withBlockDeviceMappings(blockDeviceMappings); instanceOptions.withBlockDeviceMappings(blockDeviceMappings);
} }
} }
return instanceOptions; return instanceOptions;
} }
protected void addSecurityGroups(String region, String tag, Template template, RunInstancesOptions instanceOptions) { protected void addSecurityGroups(String region, String group, Template template, RunInstancesOptions instanceOptions) {
Set<String> groups = getSecurityGroupsForTagAndOptions(region, tag, template.getOptions()); Set<String> groups = getSecurityGroupsForTagAndOptions(region, group, template.getOptions());
instanceOptions.withSecurityGroups(groups); instanceOptions.withSecurityGroups(groups);
} }
@VisibleForTesting @VisibleForTesting
public String createNewKeyPairUnlessUserSpecifiedOtherwise(String region, String tag, TemplateOptions options) { public String createNewKeyPairUnlessUserSpecifiedOtherwise(String region, String group, TemplateOptions options) {
String keyPairName = null; String keyPairName = null;
boolean shouldAutomaticallyCreateKeyPair = true; boolean shouldAutomaticallyCreateKeyPair = true;
if (options instanceof EC2TemplateOptions) { if (options instanceof EC2TemplateOptions) {
keyPairName = EC2TemplateOptions.class.cast(options).getKeyPair(); keyPairName = EC2TemplateOptions.class.cast(options).getKeyPair();
if (keyPairName == null) if (keyPairName == null)
shouldAutomaticallyCreateKeyPair = EC2TemplateOptions.class.cast(options) shouldAutomaticallyCreateKeyPair = EC2TemplateOptions.class.cast(options)
.shouldAutomaticallyCreateKeyPair(); .shouldAutomaticallyCreateKeyPair();
} }
if (keyPairName == null && shouldAutomaticallyCreateKeyPair) { if (keyPairName == null && shouldAutomaticallyCreateKeyPair) {
RegionAndName regionAndName = new RegionAndName(region, tag); keyPairName = createOrImportKeyPair(region, group, options);
KeyPair keyPair = createUniqueKeyPair.apply(regionAndName);
// 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(region, keyPair.getKeyName()), keyPair);
keyPairName = keyPair.getKeyName();
} }
return keyPairName; return keyPairName;
} }
@VisibleForTesting // base EC2 driver currently does not support key import
public Set<String> getSecurityGroupsForTagAndOptions(String region, @Nullable String tag, TemplateOptions options) { protected String createOrImportKeyPair(String region, String group, TemplateOptions options) {
Set<String> groups = Sets.newLinkedHashSet(); return createUniqueKeyPairAndPutIntoMap(region, group);
}
if (tag != null) { protected String createUniqueKeyPairAndPutIntoMap(String region, String group) {
String markerGroup = String.format("jclouds#%s#%s", tag, region); String keyPairName;
RegionAndName regionAndName = new RegionAndName(region, group);
KeyPair keyPair = createUniqueKeyPair.apply(regionAndName);
keyPairName = keyPair.getKeyName();
// 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(regionAndName.getRegion(), keyPairName), keyPair);
return keyPairName;
}
@VisibleForTesting
public Set<String> getSecurityGroupsForTagAndOptions(String region, @Nullable String group, TemplateOptions options) {
Builder<String> groups = ImmutableSet.<String> builder();
if (group != null) {
String markerGroup = String.format("jclouds#%s#%s", group, region);
groups.add(markerGroup); groups.add(markerGroup);
RegionNameAndIngressRules regionNameAndIngessRulesForMarkerGroup; RegionNameAndIngressRules regionNameAndIngessRulesForMarkerGroup;
if (options instanceof EC2TemplateOptions && EC2TemplateOptions.class.cast(options).getGroupIds().size() > 0) { if (options instanceof EC2TemplateOptions && EC2TemplateOptions.class.cast(options).getGroupIds().size() > 0) {
regionNameAndIngessRulesForMarkerGroup = new RegionNameAndIngressRules(region, markerGroup, new int[] {}, regionNameAndIngessRulesForMarkerGroup = new RegionNameAndIngressRules(region, markerGroup, new int[] {},
false); false);
groups.addAll(EC2TemplateOptions.class.cast(options).getGroupIds()); groups.addAll(EC2TemplateOptions.class.cast(options).getGroupIds());
} else { } else {
regionNameAndIngessRulesForMarkerGroup = new RegionNameAndIngressRules(region, markerGroup, options regionNameAndIngessRulesForMarkerGroup = new RegionNameAndIngressRules(region, markerGroup,
.getInboundPorts(), true); options.getInboundPorts(), true);
} }
if (!securityGroupMap.containsKey(regionNameAndIngessRulesForMarkerGroup)) { if (!securityGroupMap.containsKey(regionNameAndIngessRulesForMarkerGroup)) {
securityGroupMap.put(regionNameAndIngessRulesForMarkerGroup, createSecurityGroupIfNeeded securityGroupMap.put(regionNameAndIngessRulesForMarkerGroup,
.apply(regionNameAndIngessRulesForMarkerGroup)); createSecurityGroupIfNeeded.apply(regionNameAndIngessRulesForMarkerGroup));
} }
} }
return groups; return groups.build();
} }
// allows us to mock this method // allows us to mock this method

View File

@ -31,12 +31,14 @@ import java.util.concurrent.Future;
import javax.annotation.Resource; import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.aws.util.AWSUtils; import org.jclouds.aws.util.AWSUtils;
import org.jclouds.compute.config.CustomizationResponse; import org.jclouds.compute.config.CustomizationResponse;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.reference.ComputeServiceConstants; import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet; import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.util.ComputeUtils; import org.jclouds.compute.util.ComputeUtils;
@ -77,16 +79,19 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
final Predicate<RunningInstance> instancePresent; final Predicate<RunningInstance> instancePresent;
final Function<RunningInstance, Credentials> instanceToCredentials; final Function<RunningInstance, Credentials> instanceToCredentials;
final Map<String, Credentials> credentialStore; final Map<String, Credentials> credentialStore;
final Provider<TemplateBuilder> templateBuilderProvider;
@Inject @Inject
EC2CreateNodesInGroupThenAddToSet( EC2CreateNodesInGroupThenAddToSet(
EC2Client client, EC2Client client,
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize, Provider<TemplateBuilder> templateBuilderProvider,
@Named("PRESENT") Predicate<RunningInstance> instancePresent, CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata, @Named("PRESENT") Predicate<RunningInstance> instancePresent,
Function<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore, Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
ComputeUtils utils) { Function<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore,
ComputeUtils utils) {
this.client = client; this.client = client;
this.templateBuilderProvider = templateBuilderProvider;
this.instancePresent = instancePresent; this.instancePresent = instancePresent;
this.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = createKeyPairAndSecurityGroupsAsNeededAndReturncustomize; this.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = createKeyPairAndSecurityGroupsAsNeededAndReturncustomize;
this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata; this.runningInstanceToNodeMetadata = runningInstanceToNodeMetadata;
@ -97,10 +102,11 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
@Override @Override
public Map<?, Future<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes, public Map<?, Future<Void>> execute(String group, int count, Template template, Set<NodeMetadata> goodNodes,
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) { Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
// ensure we don't mutate the input template
Iterable<? extends RunningInstance> started = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(group, count, template = templateBuilderProvider.get().fromTemplate(template).build();
template); Iterable<? extends RunningInstance> started = createKeyPairAndSecurityGroupsAsNeededThenRunInstances(group,
count, template);
Iterable<String> ids = transform(started, instanceToId); Iterable<String> ids = transform(started, instanceToId);
String idsString = Joiner.on(',').join(ids); String idsString = Joiner.on(',').join(ids);
@ -111,8 +117,8 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
populateCredentials(started); populateCredentials(started);
} }
return utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(template.getOptions(), transform(started, return utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(template.getOptions(),
runningInstanceToNodeMetadata), goodNodes, badNodes, customizationResponses); transform(started, runningInstanceToNodeMetadata), goodNodes, badNodes, customizationResponses);
} }
protected void populateCredentials(Iterable<? extends RunningInstance> started) { protected void populateCredentials(Iterable<? extends RunningInstance> started) {
@ -131,12 +137,12 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
// TODO write test for this // TODO write test for this
@VisibleForTesting @VisibleForTesting
Iterable<? extends RunningInstance> createKeyPairAndSecurityGroupsAsNeededThenRunInstances(String group, int count, Iterable<? extends RunningInstance> createKeyPairAndSecurityGroupsAsNeededThenRunInstances(String group, int count,
Template template) { Template template) {
String region = AWSUtils.getRegionFromLocationOrNull(template.getLocation()); String region = AWSUtils.getRegionFromLocationOrNull(template.getLocation());
String zone = getZoneFromLocationOrNull(template.getLocation()); String zone = getZoneFromLocationOrNull(template.getLocation());
RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturncustomize.execute(region, RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturncustomize.execute(region,
group, template); group, template);
int countStarted = 0; int countStarted = 0;
int tries = 0; int tries = 0;
@ -145,10 +151,12 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
while (countStarted < count && tries++ < count) { while (countStarted < count && tries++ < count) {
if (logger.isDebugEnabled()) if (logger.isDebugEnabled())
logger.debug(">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", count - countStarted, region, logger.debug(">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", count - countStarted, region,
zone, template.getImage().getProviderId(), instanceOptions.buildFormParameters()); zone, template.getImage().getProviderId(), instanceOptions.buildFormParameters());
started = Iterables.concat(started, client.getInstanceServices().runInstancesInRegion(region, zone, started = Iterables.concat(
template.getImage().getProviderId(), 1, count - countStarted, instanceOptions)); started,
client.getInstanceServices().runInstancesInRegion(region, zone, template.getImage().getProviderId(), 1,
count - countStarted, instanceOptions));
countStarted = Iterables.size(started); countStarted = Iterables.size(started);
if (countStarted < count) if (countStarted < count)

View File

@ -31,6 +31,52 @@ import javax.annotation.Nullable;
* @author Adrian Cole * @author Adrian Cole
*/ */
public class KeyPair implements Comparable<KeyPair> { public class KeyPair implements Comparable<KeyPair> {
@Override
public String toString() {
return "[region=" + region + ", keyName=" + keyName + ", keyFingerprint=" + keyFingerprint + ", keyMaterial?="
+ (keyMaterial != null) + "]";
}
public static Builder builder() {
return new Builder();
}
public static class Builder {
private String region;
private String keyName;
private String keyFingerprint;
private String keyMaterial;
public Builder region(String region) {
this.region = region;
return this;
}
public Builder keyName(String keyName) {
this.keyName = keyName;
return this;
}
public Builder keyFingerprint(String keyFingerprint) {
this.keyFingerprint = keyFingerprint;
return this;
}
public Builder keyMaterial(String keyMaterial) {
this.keyMaterial = keyMaterial;
return this;
}
public KeyPair build() {
return new KeyPair(region, keyName, keyFingerprint, keyMaterial);
}
public static Builder fromKeyPair(KeyPair in) {
return new Builder().region(in.getRegion()).keyName(in.getKeyName()).keyFingerprint(in.getKeyFingerprint())
.keyMaterial(in.getKeyMaterial());
}
}
private final String region; private final String region;
private final String keyName; private final String keyName;
private final String keyFingerprint; private final String keyFingerprint;
@ -122,4 +168,7 @@ public class KeyPair implements Comparable<KeyPair> {
return true; return true;
} }
public Builder toBuilder() {
return Builder.fromKeyPair(this);
}
} }

View File

@ -19,7 +19,6 @@
package org.jclouds.ec2.compute; package org.jclouds.ec2.compute;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue; import static org.testng.Assert.assertTrue;
@ -28,7 +27,6 @@ import java.util.Set;
import org.jclouds.compute.BaseComputeServiceLiveTest; import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.predicates.NodePredicates; import org.jclouds.compute.predicates.NodePredicates;
@ -83,19 +81,6 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
assertEquals(byId.getImage(), defaultTemplate.getImage()); assertEquals(byId.getImage(), defaultTemplate.getImage());
} }
@Test(enabled = true, dependsOnMethods = "testImagesResolveCorrectly")
public void testDefaultTemplateBuilder() {
assertDefaultWorks();
}
protected void assertDefaultWorks() {
Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getVersion(), "2010.11.1-beta");
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.AMZN_LINUX);
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
}
@Test(enabled = true, dependsOnMethods = "testCompareSizes") @Test(enabled = true, dependsOnMethods = "testCompareSizes")
public void testExtendedOptionsAndLogin() throws Exception { public void testExtendedOptionsAndLogin() throws Exception {
SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi()) SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())

View File

@ -47,6 +47,7 @@ import org.jclouds.ec2.options.RunInstancesOptions;
import org.jclouds.encryption.internal.Base64; import org.jclouds.encryption.internal.Base64;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
@ -426,10 +427,10 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class); Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
Map<RegionAndName, String> securityGroupMap = createMock(Map.class); Map<RegionAndName, String> securityGroupMap = createMock(Map.class);
CreateUniqueKeyPair createUniqueKeyPair = createMock(CreateUniqueKeyPair.class); CreateUniqueKeyPair createUniqueKeyPair = createMock(CreateUniqueKeyPair.class);
CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded = createMock(CreateSecurityGroupIfNeeded.class); Function<RegionNameAndIngressRules, String> createSecurityGroupIfNeeded = createMock(CreateSecurityGroupIfNeeded.class);
return new CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions(credentialsMap, securityGroupMap, return new CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions(credentialsMap, securityGroupMap,
createUniqueKeyPair, createSecurityGroupIfNeeded, OPTIONS_PROVIDER); createUniqueKeyPair, createSecurityGroupIfNeeded, OPTIONS_PROVIDER);
} }
private void replayStrategy(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy) { private void replayStrategy(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy) {

View File

@ -35,6 +35,7 @@ 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;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.util.ComputeUtils; import org.jclouds.compute.util.ComputeUtils;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
@ -54,6 +55,7 @@ import com.google.common.base.Predicate;
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;
import com.google.inject.util.Providers;
/** /**
* @author Adrian Cole * @author Adrian Cole
@ -97,25 +99,29 @@ public class EC2RunNodesAndAddToSetStrategyTest {
String imageId = "ami1"; String imageId = "ami1";
String instanceCreatedId = "instance1"; String instanceCreatedId = "instance1";
// setup mocks // setup mocks
EC2CreateNodesInGroupThenAddToSet strategy = setupStrategy(); TemplateBuilder templateBuilder = createMock(TemplateBuilder.class);
EC2CreateNodesInGroupThenAddToSet strategy = setupStrategy(templateBuilder);
InputParams input = new InputParams(location); InputParams input = new InputParams(location);
InstanceClient instanceClient = createMock(InstanceClient.class); InstanceClient instanceClient = createMock(InstanceClient.class);
RunInstancesOptions ec2Options = createMock(RunInstancesOptions.class); RunInstancesOptions ec2Options = createMock(RunInstancesOptions.class);
RunningInstance instance = createMock(RunningInstance.class); RunningInstance instance = createMock(RunningInstance.class);
Reservation<? extends RunningInstance> reservation = new Reservation<RunningInstance>(region, ImmutableSet Reservation<? extends RunningInstance> reservation = new Reservation<RunningInstance>(region,
.<String> of(), ImmutableSet.<RunningInstance> of(instance), "ownerId", "requesterId", "reservationId"); ImmutableSet.<String> of(), ImmutableSet.<RunningInstance> of(instance), "ownerId", "requesterId",
"reservationId");
NodeMetadata nodeMetadata = createMock(NodeMetadata.class); NodeMetadata nodeMetadata = createMock(NodeMetadata.class);
// setup expectations // setup expectations
expect(templateBuilder.fromTemplate(input.template)).andReturn(templateBuilder);
expect(templateBuilder.build()).andReturn(input.template);
expect(strategy.client.getInstanceServices()).andReturn(instanceClient).atLeastOnce(); expect(strategy.client.getInstanceServices()).andReturn(instanceClient).atLeastOnce();
expect( expect(
strategy.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize.execute(region, input.tag, strategy.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize
input.template)).andReturn(ec2Options); .execute(region, input.tag, input.template)).andReturn(ec2Options);
expect(input.template.getLocation()).andReturn(input.location).atLeastOnce(); expect(input.template.getLocation()).andReturn(input.location).atLeastOnce();
expect(input.template.getImage()).andReturn(input.image).atLeastOnce(); expect(input.template.getImage()).andReturn(input.image).atLeastOnce();
expect(input.image.getProviderId()).andReturn(imageId).atLeastOnce(); expect(input.image.getProviderId()).andReturn(imageId).atLeastOnce();
expect(instanceClient.runInstancesInRegion(region, zone, imageId, 1, input.count, ec2Options)).andReturn( expect(instanceClient.runInstancesInRegion(region, zone, imageId, 1, input.count, ec2Options)).andReturn(
(Reservation) reservation); (Reservation) reservation);
expect(instance.getId()).andReturn(instanceCreatedId).atLeastOnce(); expect(instance.getId()).andReturn(instanceCreatedId).atLeastOnce();
// simulate a lazy credentials fetch // simulate a lazy credentials fetch
Credentials creds = new Credentials("foo", "bar"); Credentials creds = new Credentials("foo", "bar");
@ -128,11 +134,12 @@ public class EC2RunNodesAndAddToSetStrategyTest {
expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn(nodeMetadata); expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn(nodeMetadata);
expect( expect(
strategy.utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(eq(input.options), strategy.utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(eq(input.options),
containsNodeMetadata(nodeMetadata), eq(input.nodes), eq(input.badNodes), containsNodeMetadata(nodeMetadata), eq(input.nodes), eq(input.badNodes), eq(input.customization)))
eq(input.customization))).andReturn(null); .andReturn(null);
// replay mocks // replay mocks
replay(templateBuilder);
replay(instanceClient); replay(instanceClient);
replay(ec2Options); replay(ec2Options);
replay(instance); replay(instance);
@ -144,6 +151,7 @@ public class EC2RunNodesAndAddToSetStrategyTest {
strategy.execute(input.tag, input.count, input.template, input.nodes, input.badNodes, input.customization); strategy.execute(input.tag, input.count, input.template, input.nodes, input.badNodes, input.customization);
// verify mocks // verify mocks
verify(templateBuilder);
verify(instanceClient); verify(instanceClient);
verify(ec2Options); verify(ec2Options);
verify(instance); verify(instance);
@ -152,12 +160,12 @@ public class EC2RunNodesAndAddToSetStrategyTest {
verifyStrategy(strategy); verifyStrategy(strategy);
} }
private static final Location REGION_AP_SOUTHEAST_1 = new LocationBuilder().scope(LocationScope.REGION).id( private static final Location REGION_AP_SOUTHEAST_1 = new LocationBuilder().scope(LocationScope.REGION)
"ap-southeast-1").description("ap-southeast-1").parent( .id("ap-southeast-1").description("ap-southeast-1")
new LocationBuilder().scope(LocationScope.PROVIDER).id("aws-ec2").description("aws-ec2").build()).build(); .parent(new LocationBuilder().scope(LocationScope.PROVIDER).id("aws-ec2").description("aws-ec2").build())
private static final Location ZONE_AP_SOUTHEAST_1A = new LocationBuilder().scope(LocationScope.ZONE).id( .build();
"ap-southeast-1a").description("ap-southeast-1a").parent( private static final Location ZONE_AP_SOUTHEAST_1A = new LocationBuilder().scope(LocationScope.ZONE)
REGION_AP_SOUTHEAST_1).build(); .id("ap-southeast-1a").description("ap-southeast-1a").parent(REGION_AP_SOUTHEAST_1).build();
// ///////////////////////////////////////////////////////////////////// // /////////////////////////////////////////////////////////////////////
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
@ -209,7 +217,7 @@ public class EC2RunNodesAndAddToSetStrategyTest {
} }
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private EC2CreateNodesInGroupThenAddToSet setupStrategy() { private EC2CreateNodesInGroupThenAddToSet setupStrategy(TemplateBuilder template) {
EC2Client client = createMock(EC2Client.class); EC2Client client = createMock(EC2Client.class);
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = createMock(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class); CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = createMock(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class);
Predicate<RunningInstance> instanceStateRunning = createMock(Predicate.class); Predicate<RunningInstance> instanceStateRunning = createMock(Predicate.class);
@ -217,8 +225,9 @@ public class EC2RunNodesAndAddToSetStrategyTest {
Function<RunningInstance, Credentials> instanceToCredentials = createMock(Function.class); Function<RunningInstance, Credentials> instanceToCredentials = createMock(Function.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, createKeyPairAndSecurityGroupsAsNeededAndReturncustomize, return new EC2CreateNodesInGroupThenAddToSet(client, Providers.<TemplateBuilder> of(template),
instanceStateRunning, runningInstanceToNodeMetadata, instanceToCredentials, credentialStore, utils); createKeyPairAndSecurityGroupsAsNeededAndReturncustomize, instanceStateRunning,
runningInstanceToNodeMetadata, instanceToCredentials, credentialStore, utils);
} }
private void replayStrategy(EC2CreateNodesInGroupThenAddToSet strategy) { private void replayStrategy(EC2CreateNodesInGroupThenAddToSet strategy) {

View File

@ -19,11 +19,6 @@
package org.jclouds.eucalyptus.compute; package org.jclouds.eucalyptus.compute;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.ec2.compute.EC2ComputeServiceLiveTest; import org.jclouds.ec2.compute.EC2ComputeServiceLiveTest;
import org.jclouds.http.HttpResponseException; import org.jclouds.http.HttpResponseException;
import org.testng.annotations.Test; import org.testng.annotations.Test;
@ -41,14 +36,6 @@ public class EucalyptusComputeServiceLiveTest extends EC2ComputeServiceLiveTest
group = "eu"; group = "eu";
} }
@Override
protected void assertDefaultWorks() {
Template defaultTemplate = client.templateBuilder().build();
assertEquals(defaultTemplate.getImage().getOperatingSystem().is64Bit(), true);
assertEquals(defaultTemplate.getImage().getOperatingSystem().getFamily(), OsFamily.CENTOS);
assertEquals(getCores(defaultTemplate.getHardware()), 1.0d);
}
@Override @Override
@Test(enabled = true, dependsOnMethods = "testReboot") @Test(enabled = true, dependsOnMethods = "testReboot")
public void testSuspendResume() throws Exception { public void testSuspendResume() throws Exception {

View File

@ -26,6 +26,26 @@ import org.jclouds.vcloud.terremark.domain.KeyPair;
*/ */
public class KeyPairCredentials extends Credentials { public class KeyPairCredentials extends Credentials {
public static class Builder<T extends KeyPairCredentials> extends Credentials.Builder<T> {
private String identity;
private KeyPair keyPair;
public Builder<T> identity(String identity) {
this.identity = identity;
return this;
}
public Builder<T> keyPair(KeyPair keyPair) {
this.keyPair = keyPair;
return this;
}
@SuppressWarnings("unchecked")
public T build() {
return (T) new KeyPairCredentials(identity, keyPair);
}
}
public KeyPair getKeyPair() { public KeyPair getKeyPair() {
return keyPair; return keyPair;
} }
@ -37,4 +57,8 @@ public class KeyPairCredentials extends Credentials {
this.keyPair = keyPair; this.keyPair = keyPair;
} }
public Builder<? extends KeyPairCredentials> toBuilder() {
return new Builder<KeyPairCredentials>().identity(identity).keyPair(keyPair);
}
} }

View File

@ -70,16 +70,17 @@ import org.jclouds.compute.options.RunScriptOptions;
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.compute.reference.ComputeServiceConstants.Timeouts; import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.DestroyNodeStrategy; import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy; import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap; import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy; import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy; import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy; import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.RunScriptOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap; import org.jclouds.compute.strategy.RunScriptOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
import org.jclouds.compute.strategy.SuspendNodeStrategy; import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Credentials.Builder;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
import org.jclouds.io.Payload; import org.jclouds.io.Payload;
import org.jclouds.logging.Logger; import org.jclouds.logging.Logger;
@ -132,18 +133,17 @@ public class BaseComputeService implements ComputeService {
@Inject @Inject
protected BaseComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore, protected BaseComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> hardwareProfiles,
@Memoized Supplier<Set<? extends Hardware>> hardwareProfiles, @Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy, ResumeNodeStrategy resumeNodeStrategy, SuspendNodeStrategy suspendNodeStrategy,
ResumeNodeStrategy resumeNodeStrategy, SuspendNodeStrategy suspendNodeStrategy, Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning, @Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated, @Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended, InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, Timeouts timeouts,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, Timeouts timeouts, @Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.context = checkNotNull(context, "context"); this.context = checkNotNull(context, "context");
this.credentialStore = checkNotNull(credentialStore, "credentialStore"); this.credentialStore = checkNotNull(credentialStore, "credentialStore");
this.images = checkNotNull(images, "images"); this.images = checkNotNull(images, "images");
@ -179,7 +179,7 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Set<? extends NodeMetadata> runNodesWithTag(String group, int count, Template template) public Set<? extends NodeMetadata> runNodesWithTag(String group, int count, Template template)
throws RunNodesException { throws RunNodesException {
return createNodesInGroup(group, count, template); return createNodesInGroup(group, count, template);
} }
@ -188,7 +188,7 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Set<? extends NodeMetadata> runNodesWithTag(String group, int count, TemplateOptions templateOptions) public Set<? extends NodeMetadata> runNodesWithTag(String group, int count, TemplateOptions templateOptions)
throws RunNodesException { throws RunNodesException {
return createNodesInGroup(group, count, templateBuilder().any().options(templateOptions).build()); return createNodesInGroup(group, count, templateBuilder().any().options(templateOptions).build());
} }
@ -202,20 +202,20 @@ public class BaseComputeService implements ComputeService {
@Override @Override
public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, Template template) public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, Template template)
throws RunNodesException { throws RunNodesException {
checkNotNull(group, "group cannot be null"); checkNotNull(group, "group cannot be null");
checkNotNull(template.getLocation(), "location"); checkNotNull(template.getLocation(), "location");
logger.debug(">> running %d node%s group(%s) location(%s) image(%s) hardwareProfile(%s) options(%s)", count, logger.debug(">> running %d node%s group(%s) location(%s) image(%s) hardwareProfile(%s) options(%s)", count,
count > 1 ? "s" : "", group, template.getLocation().getId(), template.getImage().getId(), template count > 1 ? "s" : "", group, template.getLocation().getId(), template.getImage().getId(), template
.getHardware().getId(), template.getOptions()); .getHardware().getId(), template.getOptions());
Set<NodeMetadata> goodNodes = newLinkedHashSet(); Set<NodeMetadata> goodNodes = newLinkedHashSet();
Map<NodeMetadata, Exception> badNodes = newLinkedHashMap(); Map<NodeMetadata, Exception> badNodes = newLinkedHashMap();
Multimap<NodeMetadata, CustomizationResponse> customizationResponses = LinkedHashMultimap.create(); Multimap<NodeMetadata, CustomizationResponse> customizationResponses = LinkedHashMultimap.create();
Map<?, Future<Void>> responses = runNodesAndAddToSetStrategy.execute(group, count, template, goodNodes, badNodes, Map<?, Future<Void>> responses = runNodesAndAddToSetStrategy.execute(group, count, template, goodNodes, badNodes,
customizationResponses); customizationResponses);
Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger, "runNodesWithTag(" Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger, "runNodesWithTag("
+ group + ")"); + group + ")");
for (NodeMetadata node : concat(goodNodes, badNodes.keySet())) for (NodeMetadata node : concat(goodNodes, badNodes.keySet()))
if (node.getCredentials() != null) if (node.getCredentials() != null)
credentialStore.put("node#" + node.getId(), node.getCredentials()); credentialStore.put("node#" + node.getId(), node.getCredentials());
@ -227,7 +227,7 @@ public class BaseComputeService implements ComputeService {
@Override @Override
public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, TemplateOptions templateOptions) public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, TemplateOptions templateOptions)
throws RunNodesException { throws RunNodesException {
return createNodesInGroup(group, count, templateBuilder().any().options(templateOptions).build()); return createNodesInGroup(group, count, templateBuilder().any().options(templateOptions).build());
} }
@ -274,23 +274,23 @@ public class BaseComputeService implements ComputeService {
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) { public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> destroying nodes matching(%s)", filter); logger.debug(">> destroying nodes matching(%s)", filter);
Set<NodeMetadata> set = newLinkedHashSet(transformParallel(nodesMatchingFilterAndNotTerminated(filter), Set<NodeMetadata> set = newLinkedHashSet(transformParallel(nodesMatchingFilterAndNotTerminated(filter),
new Function<NodeMetadata, Future<NodeMetadata>>() { new Function<NodeMetadata, Future<NodeMetadata>>() {
// TODO make an async interface instead of re-wrapping // TODO make an async interface instead of re-wrapping
@Override @Override
public Future<NodeMetadata> apply(final NodeMetadata from) { public Future<NodeMetadata> apply(final NodeMetadata from) {
return executor.submit(new Callable<NodeMetadata>() { return executor.submit(new Callable<NodeMetadata>() {
@Override @Override
public NodeMetadata call() throws Exception { public NodeMetadata call() throws Exception {
destroyNode(from.getId()); destroyNode(from.getId());
return from; return from;
} }
}); });
} }
}, executor, null, logger, "destroyNodesMatching(" + filter + ")")); }, executor, null, logger, "destroyNodesMatching(" + filter + ")"));
logger.debug("<< destroyed(%d)", set.size()); logger.debug("<< destroyed(%d)", set.size());
return set; return set;
} }
@ -304,7 +304,7 @@ public class BaseComputeService implements ComputeService {
* if none found * if none found
*/ */
Iterable<? extends NodeMetadata> nodesMatchingFilterAndNotTerminatedExceptionIfNotFound( Iterable<? extends NodeMetadata> nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(
Predicate<NodeMetadata> filter) { Predicate<NodeMetadata> filter) {
Iterable<? extends NodeMetadata> nodes = nodesMatchingFilterAndNotTerminated(filter); Iterable<? extends NodeMetadata> nodes = nodesMatchingFilterAndNotTerminated(filter);
if (Iterables.size(nodes) == 0) if (Iterables.size(nodes) == 0)
throw new NoSuchElementException("no nodes matched filter: " + filter); throw new NoSuchElementException("no nodes matched filter: " + filter);
@ -394,15 +394,15 @@ public class BaseComputeService implements ComputeService {
public void rebootNodesMatching(Predicate<NodeMetadata> filter) { public void rebootNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> rebooting nodes matching(%s)", filter); logger.debug(">> rebooting nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter), transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter),
new Function<NodeMetadata, Future<Void>>() { new Function<NodeMetadata, Future<Void>>() {
// TODO use native async // TODO use native async
@Override @Override
public Future<Void> apply(NodeMetadata from) { public Future<Void> apply(NodeMetadata from) {
rebootNode(from.getId()); rebootNode(from.getId());
return immediateFuture(null); return immediateFuture(null);
} }
}, executor, null, logger, "rebootNodesMatching(" + filter + ")"); }, executor, null, logger, "rebootNodesMatching(" + filter + ")");
logger.debug("<< rebooted"); logger.debug("<< rebooted");
} }
@ -425,15 +425,15 @@ public class BaseComputeService implements ComputeService {
public void resumeNodesMatching(Predicate<NodeMetadata> filter) { public void resumeNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> resuming nodes matching(%s)", filter); logger.debug(">> resuming nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter), transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter),
new Function<NodeMetadata, Future<Void>>() { new Function<NodeMetadata, Future<Void>>() {
// TODO use native async // TODO use native async
@Override @Override
public Future<Void> apply(NodeMetadata from) { public Future<Void> apply(NodeMetadata from) {
resumeNode(from.getId()); resumeNode(from.getId());
return immediateFuture(null); return immediateFuture(null);
} }
}, executor, null, logger, "resumeNodesMatching(" + filter + ")"); }, executor, null, logger, "resumeNodesMatching(" + filter + ")");
logger.debug("<< resumed"); logger.debug("<< resumed");
} }
@ -456,15 +456,15 @@ public class BaseComputeService implements ComputeService {
public void suspendNodesMatching(Predicate<NodeMetadata> filter) { public void suspendNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> suspending nodes matching(%s)", filter); logger.debug(">> suspending nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter), transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter),
new Function<NodeMetadata, Future<Void>>() { new Function<NodeMetadata, Future<Void>>() {
// TODO use native async // TODO use native async
@Override @Override
public Future<Void> apply(NodeMetadata from) { public Future<Void> apply(NodeMetadata from) {
suspendNode(from.getId()); suspendNode(from.getId());
return immediateFuture(null); return immediateFuture(null);
} }
}, executor, null, logger, "suspendNodesMatching(" + filter + ")"); }, executor, null, logger, "suspendNodesMatching(" + filter + ")");
logger.debug("<< suspended"); logger.debug("<< suspended");
} }
@ -473,7 +473,7 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript) public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript)
throws RunScriptOnNodesException { throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE); return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE);
} }
@ -482,10 +482,10 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript, public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript,
RunScriptOptions options) throws RunScriptOnNodesException { RunScriptOptions options) throws RunScriptOnNodesException {
try { try {
return runScriptOnNodesMatching(filter, Statements.exec(Strings2.toStringAndClose(checkNotNull(runScript, return runScriptOnNodesMatching(filter,
"runScript").getInput())), options); Statements.exec(Strings2.toStringAndClose(checkNotNull(runScript, "runScript").getInput())), options);
} catch (IOException e) { } catch (IOException e) {
Throwables.propagate(e); Throwables.propagate(e);
return null; return null;
@ -497,7 +497,7 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, String runScript) public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, String runScript)
throws RunScriptOnNodesException { throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, Statements.exec(checkNotNull(runScript, "runScript"))); return runScriptOnNodesMatching(filter, Statements.exec(checkNotNull(runScript, "runScript")));
} }
@ -506,15 +506,15 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript) public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript)
throws RunScriptOnNodesException { throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE); return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE);
} }
@Override @Override
public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
String runScript, RunScriptOptions options) throws RunScriptOnNodesException { String runScript, RunScriptOptions options) throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, Statements.exec(checkNotNull(runScript, "runScript")), return runScriptOnNodesMatching(filter, Statements.exec(checkNotNull(runScript, "runScript")),
RunScriptOptions.NONE); RunScriptOptions.NONE);
} }
/** /**
@ -522,7 +522,7 @@ public class BaseComputeService implements ComputeService {
*/ */
@Override @Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript, public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript,
RunScriptOptions options) throws RunScriptOnNodesException { RunScriptOptions options) throws RunScriptOnNodesException {
checkNotNull(filter, "filter"); checkNotNull(filter, "filter");
checkNotNull(runScript, "runScript"); checkNotNull(runScript, "runScript");
@ -534,11 +534,11 @@ public class BaseComputeService implements ComputeService {
Map<?, Exception> exceptions = ImmutableMap.<Object, Exception> of(); Map<?, Exception> exceptions = ImmutableMap.<Object, Exception> of();
Iterable<? extends RunScriptOnNode> scriptRunners = transformNodesIntoInitializedScriptRunners( Iterable<? extends RunScriptOnNode> scriptRunners = transformNodesIntoInitializedScriptRunners(
nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter), runScript, options, badNodes); nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter), runScript, options, badNodes);
if (Iterables.size(scriptRunners) > 0) { if (Iterables.size(scriptRunners) > 0) {
for (RunScriptOnNode runner : scriptRunners) { for (RunScriptOnNode runner : scriptRunners) {
responses.put(runner.getNode(), executor.submit(new RunScriptOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap( responses.put(runner.getNode(), executor.submit(new RunScriptOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap(
runner, goodNodes, badNodes))); runner, goodNodes, badNodes)));
} }
exceptions = awaitCompletion(responses, executor, null, logger, "runScriptOnNodesMatching(" + filter + ")"); exceptions = awaitCompletion(responses, executor, null, logger, "runScriptOnNodesMatching(" + filter + ")");
} }
@ -550,10 +550,11 @@ public class BaseComputeService implements ComputeService {
} }
private Iterable<? extends RunScriptOnNode> transformNodesIntoInitializedScriptRunners( private Iterable<? extends RunScriptOnNode> transformNodesIntoInitializedScriptRunners(
Iterable<? extends NodeMetadata> nodes, Statement script, RunScriptOptions options, Iterable<? extends NodeMetadata> nodes, Statement script, RunScriptOptions options,
Map<NodeMetadata, Exception> badNodes) { Map<NodeMetadata, Exception> badNodes) {
return filter(transformParallel(nodes, new TransformNodesIntoInitializedScriptRunners(script, options, badNodes), return filter(
executor, null, logger, "initialize script runners"), notNull()); transformParallel(nodes, new TransformNodesIntoInitializedScriptRunners(script, options, badNodes),
executor, null, logger, "initialize script runners"), notNull());
} }
private Set<? extends NodeMetadata> detailsOnAllNodes() { private Set<? extends NodeMetadata> detailsOnAllNodes() {
@ -566,13 +567,13 @@ public class BaseComputeService implements ComputeService {
} }
private final class TransformNodesIntoInitializedScriptRunners implements private final class TransformNodesIntoInitializedScriptRunners implements
Function<NodeMetadata, Future<RunScriptOnNode>> { Function<NodeMetadata, Future<RunScriptOnNode>> {
private final Map<NodeMetadata, Exception> badNodes; private final Map<NodeMetadata, Exception> badNodes;
private final Statement script; private final Statement script;
private final RunScriptOptions options; private final RunScriptOptions options;
private TransformNodesIntoInitializedScriptRunners(Statement script, RunScriptOptions options, private TransformNodesIntoInitializedScriptRunners(Statement script, RunScriptOptions options,
Map<NodeMetadata, Exception> badNodes) { Map<NodeMetadata, Exception> badNodes) {
this.badNodes = checkNotNull(badNodes, "badNodes"); this.badNodes = checkNotNull(badNodes, "badNodes");
this.script = checkNotNull(script, "script"); this.script = checkNotNull(script, "script");
this.options = checkNotNull(options, "options"); this.options = checkNotNull(options, "options");
@ -581,8 +582,14 @@ public class BaseComputeService implements ComputeService {
@Override @Override
public Future<RunScriptOnNode> apply(NodeMetadata node) { public Future<RunScriptOnNode> apply(NodeMetadata node) {
checkNotNull(node, "node"); checkNotNull(node, "node");
if (options.getOverrideCredentials() != null) { if (options.getOverridingCredentials() != null) {
node = NodeMetadataBuilder.fromNodeMetadata(node).credentials(options.getOverrideCredentials()).build(); Builder<? extends Credentials> builder = node.getCredentials() != null ? node.getCredentials().toBuilder()
: new Credentials.Builder<Credentials>();
if (options.getOverridingCredentials().identity != null)
builder.identity(options.getOverridingCredentials().identity);
if (options.getOverridingCredentials().credential != null)
builder.credential(options.getOverridingCredentials().credential);
node = NodeMetadataBuilder.fromNodeMetadata(node).credentials(builder.build()).build();
} }
return executor.submit(initScriptRunnerFactory.create(node, script, options, badNodes)); return executor.submit(initScriptRunnerFactory.create(node, script, options, badNodes));
} }

View File

@ -34,6 +34,26 @@ import com.google.common.collect.Lists;
*/ */
public class Credentials { public class Credentials {
public static class Builder<T extends Credentials> {
private String identity;
private String credential;
public Builder<T> identity(String identity) {
this.identity = identity;
return this;
}
public Builder<T> credential(String credential) {
this.credential = credential;
return this;
}
@SuppressWarnings("unchecked")
public T build() {
return (T) new Credentials(identity, credential);
}
}
public final String identity; public final String identity;
public final String credential; public final String credential;
@ -45,7 +65,7 @@ public class Credentials {
public static Credentials parse(URI uri) { public static Credentials parse(URI uri) {
checkNotNull(uri, "uri"); checkNotNull(uri, "uri");
List<String> userInfo = Lists.newArrayList(Splitter.on(':').split( List<String> userInfo = Lists.newArrayList(Splitter.on(':').split(
checkNotNull(uri.getUserInfo(), "no userInfo in " + uri))); checkNotNull(uri.getUserInfo(), "no userInfo in " + uri)));
String identity = checkNotNull(userInfo.get(0), "no username in " + uri.getUserInfo()); String identity = checkNotNull(userInfo.get(0), "no username in " + uri.getUserInfo());
if (Strings2.isUrlEncoded(identity)) { if (Strings2.isUrlEncoded(identity)) {
identity = Strings2.urlDecode(identity); identity = Strings2.urlDecode(identity);
@ -57,6 +77,10 @@ public class Credentials {
return new Credentials(identity, credential); return new Credentials(identity, credential);
} }
public Builder<? extends Credentials> toBuilder() {
return new Builder<Credentials>().identity(identity).credential(credential);
}
@Override @Override
public int hashCode() { public int hashCode() {
final int prime = 31; final int prime = 31;

View File

@ -22,8 +22,8 @@ package org.jclouds.aws.ec2.compute;
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.Set;
import java.util.Map.Entry; import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ExecutorService; import java.util.concurrent.ExecutorService;
import javax.inject.Inject; import javax.inject.Inject;
@ -43,13 +43,13 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts; import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.DestroyNodeStrategy; import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy; import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap; import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy; import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy; import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy; import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.SuspendNodeStrategy; import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.domain.Credentials; import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location; import org.jclouds.domain.Location;
@ -75,44 +75,47 @@ public class AWSEC2ComputeService extends EC2ComputeService {
@Inject @Inject
protected AWSEC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore, protected AWSEC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes, @Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy, @Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy, GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy, RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy, ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider, Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning, @Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated, @Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended, @Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, Timeouts timeouts, InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, 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, Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap,
@Named("PLACEMENT") Map<RegionAndName, String> placementGroupMap, @Named("PLACEMENT") Map<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, runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy,
stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, nodeSuspended,
nodeSuspended, initScriptRunnerFactory, timeouts, executor, ec2Client, credentialsMap, securityGroupMap); initScriptRunnerFactory, timeouts, executor, ec2Client, credentialsMap, securityGroupMap);
this.ec2Client = ec2Client; this.ec2Client = ec2Client;
this.placementGroupMap = placementGroupMap; this.placementGroupMap = placementGroupMap;
this.placementGroupDeleted = placementGroupDeleted; this.placementGroupDeleted = placementGroupDeleted;
} }
@VisibleForTesting @VisibleForTesting
void deletePlacementGroup(String region, String tag) { void deletePlacementGroup(String region, String group) {
Preconditions2.checkNotEmpty(tag, "tag"); Preconditions2.checkNotEmpty(group, "group");
String group = String.format("jclouds#%s#%s", tag, region); // placementGroupName must be unique within an account per
// http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?using_cluster_computing.html
String placementGroup = String.format("jclouds#%s#%s", group, region);
try { try {
if (ec2Client.getPlacementGroupServices().describePlacementGroupsInRegion(region, group).size() > 0) { if (ec2Client.getPlacementGroupServices().describePlacementGroupsInRegion(region, placementGroup).size() > 0) {
logger.debug(">> deleting placementGroup(%s)", group); logger.debug(">> deleting placementGroup(%s)", placementGroup);
try { try {
ec2Client.getPlacementGroupServices().deletePlacementGroupInRegion(region, group); ec2Client.getPlacementGroupServices().deletePlacementGroupInRegion(region, placementGroup);
checkState(placementGroupDeleted.apply(new PlacementGroup(region, group, "cluster", State.PENDING)), checkState(
String.format("placementGroup region(%s) name(%s) failed to delete", region, group)); placementGroupDeleted.apply(new PlacementGroup(region, placementGroup, "cluster", State.PENDING)),
placementGroupMap.remove(new RegionAndName(region, group)); String.format("placementGroup region(%s) name(%s) failed to delete", region, placementGroup));
logger.debug("<< deleted placementGroup(%s)", group); placementGroupMap.remove(new RegionAndName(region, placementGroup));
logger.debug("<< deleted placementGroup(%s)", placementGroup);
} catch (IllegalStateException e) { } catch (IllegalStateException e) {
logger.debug("<< inUse placementGroup(%s)", group); logger.debug("<< inUse placementGroup(%s)", placementGroup);
} }
} }
} catch (UnsupportedOperationException e) { } catch (UnsupportedOperationException e) {
@ -120,6 +123,7 @@ public class AWSEC2ComputeService extends EC2ComputeService {
} }
} }
@Override
protected void cleanUpIncidentalResources(Entry<String, String> regionTag) { protected void cleanUpIncidentalResources(Entry<String, String> regionTag) {
super.cleanUpIncidentalResources(regionTag); super.cleanUpIncidentalResources(regionTag);
deletePlacementGroup(regionTag.getKey(), regionTag.getValue()); deletePlacementGroup(regionTag.getKey(), regionTag.getValue());

View File

@ -34,10 +34,13 @@ import org.jclouds.aws.ec2.AWSEC2Client;
import org.jclouds.aws.ec2.compute.AWSEC2ComputeService; import org.jclouds.aws.ec2.compute.AWSEC2ComputeService;
import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions; import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
import org.jclouds.aws.ec2.domain.PlacementGroup; import org.jclouds.aws.ec2.domain.PlacementGroup;
import org.jclouds.aws.ec2.domain.RegionNameAndPublicKeyMaterial;
import org.jclouds.aws.ec2.functions.ImportOrReturnExistingKeypair;
import org.jclouds.aws.ec2.predicates.PlacementGroupAvailable; import org.jclouds.aws.ec2.predicates.PlacementGroupAvailable;
import org.jclouds.aws.ec2.predicates.PlacementGroupDeleted; import org.jclouds.aws.ec2.predicates.PlacementGroupDeleted;
import org.jclouds.compute.ComputeService; import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext; import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata; import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder; import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.internal.ComputeServiceContextImpl; import org.jclouds.compute.internal.ComputeServiceContextImpl;
@ -45,10 +48,14 @@ 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.CredentialsForInstance; import org.jclouds.ec2.compute.functions.CredentialsForInstance;
import org.jclouds.ec2.compute.functions.RegionAndIdToImage;
import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata; import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl; import org.jclouds.ec2.compute.internal.EC2TemplateBuilderImpl;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.domain.RunningInstance; import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.predicates.RetryablePredicate; import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
@ -75,6 +82,14 @@ public class AWSEC2ComputeServiceDependenciesModule extends EC2ComputeServiceDep
}).to(RunningInstanceToNodeMetadata.class); }).to(RunningInstanceToNodeMetadata.class);
bind(new TypeLiteral<Function<RunningInstance, Credentials>>() { bind(new TypeLiteral<Function<RunningInstance, Credentials>>() {
}).to(CredentialsForInstance.class); }).to(CredentialsForInstance.class);
bind(new TypeLiteral<Function<RegionNameAndIngressRules, String>>() {
}).to(CreateSecurityGroupIfNeeded.class);
bind(new TypeLiteral<Function<RegionAndName, KeyPair>>() {
}).to(CreateUniqueKeyPair.class);
bind(new TypeLiteral<Function<RegionNameAndPublicKeyMaterial, KeyPair>>() {
}).to(ImportOrReturnExistingKeypair.class);
bind(new TypeLiteral<Function<RegionAndName, Image>>() {
}).to(RegionAndIdToImage.class);
bind(new TypeLiteral<ComputeServiceContext>() { bind(new TypeLiteral<ComputeServiceContext>() {
}).to(new TypeLiteral<ComputeServiceContextImpl<AWSEC2Client, AWSEC2AsyncClient>>() { }).to(new TypeLiteral<ComputeServiceContextImpl<AWSEC2Client, AWSEC2AsyncClient>>() {
}).in(Scopes.SINGLETON); }).in(Scopes.SINGLETON);

View File

@ -100,7 +100,7 @@ public class AWSEC2ReviseParsedImage implements ReviseParsedImage {
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
logger.debug("<< didn't match os(%s)", from.getImageLocation()); logger.debug("<< didn't match os(%s)", from.getImageLocation());
} catch (NoSuchElementException e) { } catch (NoSuchElementException e) {
logger.debug("<< didn't match at all(%s)", from.getImageLocation()); logger.trace("<< didn't match at all(%s)", from.getImageLocation());
} }
} }

View File

@ -19,26 +19,35 @@
package org.jclouds.aws.ec2.compute.strategy; package org.jclouds.aws.ec2.compute.strategy;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.or;
import java.util.Map; import java.util.Map;
import javax.annotation.Resource;
import javax.inject.Inject; import javax.inject.Inject;
import javax.inject.Named; import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton; import javax.inject.Singleton;
import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions; import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
import org.jclouds.aws.ec2.domain.RegionNameAndPublicKeyMaterial;
import org.jclouds.aws.ec2.functions.CreatePlacementGroupIfNeeded; import org.jclouds.aws.ec2.functions.CreatePlacementGroupIfNeeded;
import org.jclouds.aws.ec2.options.AWSRunInstancesOptions; import org.jclouds.aws.ec2.options.AWSRunInstancesOptions;
import org.jclouds.compute.domain.Template; 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.ec2.compute.domain.RegionAndName; import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.functions.CreateSecurityGroupIfNeeded; import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
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.compute.strategy.CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions; import org.jclouds.ec2.compute.strategy.CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
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.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.Predicate;
/** /**
* *
@ -46,31 +55,37 @@ import com.google.common.annotations.VisibleForTesting;
*/ */
@Singleton @Singleton
public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions extends public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions extends
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions { CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@VisibleForTesting @VisibleForTesting
final Map<RegionAndName, String> placementGroupMap; final Map<RegionAndName, String> placementGroupMap;
@VisibleForTesting @VisibleForTesting
final CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded; final CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded;
@VisibleForTesting
final Function<RegionNameAndPublicKeyMaterial, KeyPair> importExistingKeyPair;
@Inject @Inject
public CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions( public CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions(
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap, Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap,
@Named("PLACEMENT") Map<RegionAndName, String> placementGroupMap, CreateUniqueKeyPair createUniqueKeyPair, @Named("PLACEMENT") Map<RegionAndName, String> placementGroupMap,
CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded, Function<RegionAndName, KeyPair> createUniqueKeyPair,
javax.inject.Provider<RunInstancesOptions> optionsProvider, Function<RegionNameAndIngressRules, String> createSecurityGroupIfNeeded,
CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded) { Provider<RunInstancesOptions> optionsProvider, CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded,
Function<RegionNameAndPublicKeyMaterial, KeyPair> importExistingKeyPair) {
super(credentialsMap, securityGroupMap, createUniqueKeyPair, createSecurityGroupIfNeeded, optionsProvider); super(credentialsMap, securityGroupMap, createUniqueKeyPair, createSecurityGroupIfNeeded, optionsProvider);
this.placementGroupMap = placementGroupMap; this.placementGroupMap = placementGroupMap;
this.createPlacementGroupIfNeeded = createPlacementGroupIfNeeded; this.createPlacementGroupIfNeeded = createPlacementGroupIfNeeded;
this.importExistingKeyPair = importExistingKeyPair;
} }
public AWSRunInstancesOptions execute(String region, String tag, Template template) { public AWSRunInstancesOptions execute(String region, String group, Template template) {
AWSRunInstancesOptions instanceOptions = AWSRunInstancesOptions.class.cast(super.execute(region, tag, template)); AWSRunInstancesOptions instanceOptions = AWSRunInstancesOptions.class
.cast(super.execute(region, group, template));
String placementGroupName = template.getHardware().getId().startsWith("cc") ? createNewPlacementGroupUnlessUserSpecifiedOtherwise( String placementGroupName = template.getHardware().getId().startsWith("cc") ? createNewPlacementGroupUnlessUserSpecifiedOtherwise(
region, tag, template.getOptions()) region, group, template.getOptions()) : null;
: null;
if (placementGroupName != null) if (placementGroupName != null)
instanceOptions.inPlacementGroup(placementGroupName); instanceOptions.inPlacementGroup(placementGroupName);
@ -82,17 +97,19 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions
} }
@VisibleForTesting @VisibleForTesting
String createNewPlacementGroupUnlessUserSpecifiedOtherwise(String region, String tag, TemplateOptions options) { String createNewPlacementGroupUnlessUserSpecifiedOtherwise(String region, String group, TemplateOptions options) {
String placementGroupName = null; String placementGroupName = null;
boolean shouldAutomaticallyCreatePlacementGroup = true; boolean shouldAutomaticallyCreatePlacementGroup = true;
if (options instanceof EC2TemplateOptions) { if (options instanceof EC2TemplateOptions) {
placementGroupName = AWSEC2TemplateOptions.class.cast(options).getPlacementGroup(); placementGroupName = AWSEC2TemplateOptions.class.cast(options).getPlacementGroup();
if (placementGroupName == null) if (placementGroupName == null)
shouldAutomaticallyCreatePlacementGroup = AWSEC2TemplateOptions.class.cast(options) shouldAutomaticallyCreatePlacementGroup = AWSEC2TemplateOptions.class.cast(options)
.shouldAutomaticallyCreatePlacementGroup(); .shouldAutomaticallyCreatePlacementGroup();
} }
if (placementGroupName == null && shouldAutomaticallyCreatePlacementGroup) { if (placementGroupName == null && shouldAutomaticallyCreatePlacementGroup) {
placementGroupName = String.format("jclouds#%s#%s", tag, region); // placementGroupName must be unique within an account per
// http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?using_cluster_computing.html
placementGroupName = String.format("jclouds#%s#%s", group, region);
RegionAndName regionAndName = new RegionAndName(region, placementGroupName); RegionAndName regionAndName = new RegionAndName(region, placementGroupName);
if (!placementGroupMap.containsKey(regionAndName)) { if (!placementGroupMap.containsKey(regionAndName)) {
placementGroupMap.put(regionAndName, createPlacementGroupIfNeeded.apply(regionAndName)); placementGroupMap.put(regionAndName, createPlacementGroupIfNeeded.apply(regionAndName));
@ -102,12 +119,60 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions
} }
@Override @Override
protected void addSecurityGroups(String region, String tag, Template template, RunInstancesOptions instanceOptions) { protected String createOrImportKeyPair(String region, String group, TemplateOptions options) {
RegionAndName key = new RegionAndName(region, "jclouds#" + group);
KeyPair pair = credentialsMap.get(key);
if (pair != null)
return pair.getKeyName();
if (and(hasPublicKeyMaterial, or(doesntNeedSshAfterImportingPublicKey, hasLoginCredential)).apply(options)) {
pair = importExistingKeyPair.apply(new RegionNameAndPublicKeyMaterial(region, group, options.getPublicKey()));
options.dontAuthorizePublicKey();
if (hasLoginCredential.apply(options))
pair = pair.toBuilder().keyMaterial(options.getOverridingCredentials().credential).build();
credentialsMap.put(key, pair);
} else {
if (hasPublicKeyMaterial.apply(options)) {
logger.warn("to avoid creating extra keys in aws-ec2, use templateOption overrideLoginCredentialWith(id_rsa)");
}
return createUniqueKeyPairAndPutIntoMap(region, group);
}
return pair.getKeyName();
}
public static final Predicate<TemplateOptions> hasPublicKeyMaterial = new Predicate<TemplateOptions>() {
@Override
public boolean apply(TemplateOptions options) {
return options.getPublicKey() != null;
}
};
public static final Predicate<TemplateOptions> doesntNeedSshAfterImportingPublicKey = new Predicate<TemplateOptions>() {
@Override
public boolean apply(TemplateOptions options) {
return (options.getRunScript() == null && options.getPrivateKey() == null);
}
};
public static final Predicate<TemplateOptions> hasLoginCredential = new Predicate<TemplateOptions>() {
@Override
public boolean apply(TemplateOptions options) {
return options.getOverridingCredentials() != null && options.getOverridingCredentials().credential != null;
}
};
@Override
protected void addSecurityGroups(String region, String group, Template template, RunInstancesOptions instanceOptions) {
String subnetId = AWSEC2TemplateOptions.class.cast(template.getOptions()).getSubnetId(); String subnetId = AWSEC2TemplateOptions.class.cast(template.getOptions()).getSubnetId();
if (subnetId != null) { if (subnetId != null) {
AWSRunInstancesOptions.class.cast(instanceOptions).withSubnetId(subnetId); AWSRunInstancesOptions.class.cast(instanceOptions).withSubnetId(subnetId);
} else { } else {
super.addSecurityGroups(region, tag, template, instanceOptions); super.addSecurityGroups(region, group, template, instanceOptions);
} }
} }
} }

View File

@ -0,0 +1,43 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.aws.ec2.domain;
import org.jclouds.ec2.compute.domain.RegionAndName;
/**
*
* @author Adrian Cole
*/
public class RegionNameAndPublicKeyMaterial extends RegionAndName {
private final String publicKeyMaterial;
public RegionNameAndPublicKeyMaterial(String region, String tag, String publicKeyMaterial) {
super(region, tag);
this.publicKeyMaterial = publicKeyMaterial;
}
// intentionally not overriding equals or hash-code so that we can search only by region/tag in a
// map
public String getPublicKeyMaterial() {
return publicKeyMaterial;
}
}

View File

@ -0,0 +1,83 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.aws.ec2.functions;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.AWSEC2Client;
import org.jclouds.aws.ec2.domain.RegionNameAndPublicKeyMaterial;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.logging.Logger;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.collect.Iterables;
/**
*
* @author Adrian Cole
*/
@Singleton
public class ImportOrReturnExistingKeypair implements Function<RegionNameAndPublicKeyMaterial, KeyPair> {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final AWSEC2Client ec2Client;
@Inject
public ImportOrReturnExistingKeypair(AWSEC2Client ec2Client) {
this.ec2Client = ec2Client;
}
@Override
public KeyPair apply(RegionNameAndPublicKeyMaterial from) {
return importOrReturnExistingKeypair(from.getRegion(), from.getName(), from.getPublicKeyMaterial());
}
@VisibleForTesting
KeyPair importOrReturnExistingKeypair(String region, String group, String publicKeyMaterial) {
checkNotNull(region, "region");
checkNotNull(group, "group");
checkNotNull(publicKeyMaterial, "publicKeyMaterial");
logger.debug(">> importing keyPair region(%s) group(%s)", region, group);
KeyPair keyPair = null;
// loop for eventual consistency or race condition.
// as this command is idempotent, it should be ok
while (keyPair == null)
try {
keyPair = ec2Client.getKeyPairServices().importKeyPairInRegion(region, "jclouds#" + group,
publicKeyMaterial);
logger.debug("<< imported keyPair(%s)", keyPair.getKeyName());
} catch (IllegalStateException e) {
keyPair = Iterables.getFirst(
ec2Client.getKeyPairServices().describeKeyPairsInRegion(region, "jclouds#" + group), null);
if (keyPair != null)
logger.debug("<< retrieved existing keyPair(%s)", keyPair.getKeyName());
}
return keyPair;
}
}

View File

@ -59,13 +59,13 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCompareSizes") @Test(enabled = true, dependsOnMethods = "testCompareSizes")
public void testExtendedOptionsAndLogin() throws Exception { public void testExtendedOptionsAndLogin() throws Exception {
SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi()) SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getSecurityGroupServices(); .getSecurityGroupServices();
KeyPairClient keyPairClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi()) KeyPairClient keyPairClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getKeyPairServices(); .getKeyPairServices();
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi()) InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices(); .getInstanceServices();
String group = this.group + "o"; String group = this.group + "o";
@ -117,17 +117,17 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
// } // }
// make sure we made our dummy group and also let in the user's group // make sure we made our dummy group and also let in the user's group
assertEquals(Sets.newTreeSet(instance.getGroupIds()), ImmutableSortedSet.<String> of("jclouds#" + group + "#" assertEquals(Sets.newTreeSet(instance.getGroupIds()),
+ instance.getRegion(), group)); ImmutableSortedSet.<String> of("jclouds#" + group + "#" + instance.getRegion(), group));
// make sure our dummy group has no rules // make sure our dummy group has no rules
SecurityGroup secgroup = Iterables.getOnlyElement(securityGroupClient.describeSecurityGroupsInRegion(null, SecurityGroup secgroup = Iterables.getOnlyElement(securityGroupClient.describeSecurityGroupsInRegion(null,
"jclouds#" +group + "#" + instance.getRegion())); "jclouds#" + group + "#" + instance.getRegion()));
assert secgroup.getIpPermissions().size() == 0 : secgroup; assert secgroup.getIpPermissions().size() == 0 : secgroup;
// try to run a script with the original keyPair // try to run a script with the original keyPair
runScriptWithCreds(group, first.getOperatingSystem(), new Credentials(first.getCredentials().identity, result runScriptWithCreds(group, first.getOperatingSystem(),
.getKeyMaterial())); new Credentials(first.getCredentials().identity, result.getKeyMaterial()));
} finally { } finally {
client.destroyNodesMatching(NodePredicates.inGroup(group)); client.destroyNodesMatching(NodePredicates.inGroup(group));
@ -140,19 +140,15 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
} }
} }
@Test(enabled = true, dependsOnMethods = "testCompareSizes") @Test(enabled = true, dependsOnMethods = "testCompareSizes")
public void testExtendedOptionsWithSubnetId() throws Exception { public void testSubnetId() throws Exception {
String subnetId = System.getProperty("test.subnetId"); String subnetId = System.getProperty("test.subnetId");
if (subnetId == null) { if (subnetId == null) {
// Skip test and return // Skip test and return
return; return;
} }
SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getSecurityGroupServices();
KeyPairClient keyPairClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getKeyPairServices();
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi()) InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices(); .getInstanceServices();
@ -161,20 +157,11 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
TemplateOptions options = client.templateOptions(); TemplateOptions options = client.templateOptions();
// options.as(AWSEC2TemplateOptions.class).securityGroups(group);
options.as(AWSEC2TemplateOptions.class).keyPair(group);
options.as(AWSEC2TemplateOptions.class).subnetId(subnetId); options.as(AWSEC2TemplateOptions.class).subnetId(subnetId);
String startedId = null; String startedId = null;
String nodeId = null; String nodeId = null;
try { try {
cleanupExtendedStuff(securityGroupClient, keyPairClient, group);
// create the security group
// securityGroupClient.createSecurityGroupInRegion(null, group, group);
// create a keypair to pass in as well
keyPairClient.createKeyPairInRegion(null, group);
Set<? extends NodeMetadata> nodes = client.createNodesInGroup(group, 1, options); Set<? extends NodeMetadata> nodes = client.createNodesInGroup(group, 1, options);
@ -192,11 +179,6 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
} finally { } finally {
if (nodeId != null) if (nodeId != null)
client.destroyNode(nodeId); client.destroyNode(nodeId);
if (startedId != null) {
// ensure we didn't delete these resources!
assertEquals(keyPairClient.describeKeyPairsInRegion(null, group).size(), 1);
}
cleanupExtendedStuff(securityGroupClient, keyPairClient, group);
} }
} }

View File

@ -34,17 +34,17 @@ import javax.inject.Provider;
import org.jclouds.aws.domain.Region; import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions; import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
import org.jclouds.aws.ec2.domain.PlacementGroup; import org.jclouds.aws.ec2.domain.PlacementGroup;
import org.jclouds.aws.ec2.domain.RegionNameAndPublicKeyMaterial;
import org.jclouds.aws.ec2.functions.CreatePlacementGroupIfNeeded; import org.jclouds.aws.ec2.functions.CreatePlacementGroupIfNeeded;
import org.jclouds.aws.ec2.options.AWSRunInstancesOptions; import org.jclouds.aws.ec2.options.AWSRunInstancesOptions;
import org.jclouds.compute.domain.Hardware; import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Template; import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions; import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Credentials;
import org.jclouds.ec2.compute.EC2TemplateBuilderTest; import org.jclouds.ec2.compute.EC2TemplateBuilderTest;
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.strategy.CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions; import org.jclouds.ec2.compute.strategy.CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
import org.jclouds.ec2.domain.BlockDeviceMapping; import org.jclouds.ec2.domain.BlockDeviceMapping;
import org.jclouds.ec2.domain.KeyPair; import org.jclouds.ec2.domain.KeyPair;
@ -52,6 +52,7 @@ import org.jclouds.ec2.options.RunInstancesOptions;
import org.jclouds.encryption.internal.Base64; import org.jclouds.encryption.internal.Base64;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMultimap; import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
@ -72,7 +73,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testExecuteWithDefaultOptionsEC2() throws SecurityException, NoSuchMethodException { public void testExecuteWithDefaultOptionsEC2() throws SecurityException, NoSuchMethodException {
// setup constants // setup constants
String region = Region.AP_SOUTHEAST_1; String region = Region.AP_SOUTHEAST_1;
String tag = "tag"; String group = "group";
Hardware size = EC2HardwareBuilder.m1_small().build(); Hardware size = EC2HardwareBuilder.m1_small().build();
String systemGeneratedKeyPairName = "systemGeneratedKeyPair"; String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
String generatedGroup = "group"; String generatedGroup = "group";
@ -80,18 +81,18 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// create mocks // create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock( CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock(
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class, new Method[] { CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class,
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class new Method[] {
.getDeclaredMethod("getOptionsProvider"), CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod( .getDeclaredMethod("getOptionsProvider"),
"createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class, CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
TemplateOptions.class), "createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class,
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod( TemplateOptions.class),
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class, CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
TemplateOptions.class), "createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class,
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class TemplateOptions.class),
.getDeclaredMethod("getSecurityGroupsForTagAndOptions", String.class, String.class, CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
TemplateOptions.class) }); "getSecurityGroupsForTagAndOptions", String.class, String.class, TemplateOptions.class) });
AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class); AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class);
Template template = createMock(Template.class); Template template = createMock(Template.class);
@ -101,9 +102,9 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(template.getHardware()).andReturn(size).atLeastOnce(); expect(template.getHardware()).andReturn(size).atLeastOnce();
expect(template.getOptions()).andReturn(options).atLeastOnce(); expect(template.getOptions()).andReturn(options).atLeastOnce();
expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce(); expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce();
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn( expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
systemGeneratedKeyPairName); systemGeneratedKeyPairName);
expect(strategy.getSecurityGroupsForTagAndOptions(region, tag, options)).andReturn(generatedGroups); expect(strategy.getSecurityGroupsForTagAndOptions(region, group, options)).andReturn(generatedGroups);
expect(options.getSubnetId()).andReturn(null); expect(options.getSubnetId()).andReturn(null);
expect(options.getUserData()).andReturn(null); expect(options.getUserData()).andReturn(null);
expect(options.isMonitoringEnabled()).andReturn(false); expect(options.isMonitoringEnabled()).andReturn(false);
@ -114,11 +115,12 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replay(strategy); replay(strategy);
// run // run
RunInstancesOptions customize = strategy.execute(region, tag, template); RunInstancesOptions customize = strategy.execute(region, group, template);
assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of()); assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildFormParameters().entries(), ImmutableMultimap.<String, String> of("InstanceType", assertEquals(
size.getProviderId(), "SecurityGroup.1", generatedGroup, "KeyName", systemGeneratedKeyPairName) customize.buildFormParameters().entries(),
.entries()); ImmutableMultimap.<String, String> of("InstanceType", size.getProviderId(), "SecurityGroup.1",
generatedGroup, "KeyName", systemGeneratedKeyPairName).entries());
assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of()); assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of()); assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildStringPayload(), null); assertEquals(customize.buildStringPayload(), null);
@ -132,7 +134,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testExecuteForCCAutomatic() throws SecurityException, NoSuchMethodException { public void testExecuteForCCAutomatic() throws SecurityException, NoSuchMethodException {
// setup constants // setup constants
String region = Region.US_EAST_1; String region = Region.US_EAST_1;
String tag = "tag"; String group = "group";
Hardware size = EC2TemplateBuilderTest.CC1_4XLARGE; Hardware size = EC2TemplateBuilderTest.CC1_4XLARGE;
String systemGeneratedKeyPairName = "systemGeneratedKeyPair"; String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
String generatedGroup = "group"; String generatedGroup = "group";
@ -140,18 +142,18 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// create mocks // create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock( CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock(
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class, new Method[] { CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class,
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class new Method[] {
.getDeclaredMethod("getOptionsProvider"), CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod( .getDeclaredMethod("getOptionsProvider"),
"createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class, CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
TemplateOptions.class), "createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class,
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod( TemplateOptions.class),
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class, CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
TemplateOptions.class), "createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class,
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class TemplateOptions.class),
.getDeclaredMethod("getSecurityGroupsForTagAndOptions", String.class, String.class, CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
TemplateOptions.class) }); "getSecurityGroupsForTagAndOptions", String.class, String.class, TemplateOptions.class) });
AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class); AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class);
Template template = createMock(Template.class); Template template = createMock(Template.class);
@ -161,11 +163,11 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(template.getHardware()).andReturn(size).atLeastOnce(); expect(template.getHardware()).andReturn(size).atLeastOnce();
expect(template.getOptions()).andReturn(options).atLeastOnce(); expect(template.getOptions()).andReturn(options).atLeastOnce();
expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce(); expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce();
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn( expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
systemGeneratedKeyPairName); systemGeneratedKeyPairName);
expect(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn( expect(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
generatedGroup); generatedGroup);
expect(strategy.getSecurityGroupsForTagAndOptions(region, tag, options)).andReturn(generatedGroups); expect(strategy.getSecurityGroupsForTagAndOptions(region, group, options)).andReturn(generatedGroups);
expect(options.getSubnetId()).andReturn(null); expect(options.getSubnetId()).andReturn(null);
expect(options.getUserData()).andReturn(null); expect(options.getUserData()).andReturn(null);
expect(options.isMonitoringEnabled()).andReturn(false); expect(options.isMonitoringEnabled()).andReturn(false);
@ -176,11 +178,13 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replay(strategy); replay(strategy);
// run // run
RunInstancesOptions customize = strategy.execute(region, tag, template); RunInstancesOptions customize = strategy.execute(region, group, template);
assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of()); assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildFormParameters().entries(), ImmutableMultimap.<String, String> of("InstanceType", assertEquals(
size.getProviderId(), "SecurityGroup.1", generatedGroup, "KeyName", systemGeneratedKeyPairName, customize.buildFormParameters().entries(),
"Placement.GroupName", generatedGroup).entries()); ImmutableMultimap.<String, String> of("InstanceType", size.getProviderId(), "SecurityGroup.1",
generatedGroup, "KeyName", systemGeneratedKeyPairName, "Placement.GroupName", generatedGroup)
.entries());
assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of()); assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of()); assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildStringPayload(), null); assertEquals(customize.buildStringPayload(), null);
@ -194,7 +198,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testExecuteForCCUserSpecified() throws SecurityException, NoSuchMethodException { public void testExecuteForCCUserSpecified() throws SecurityException, NoSuchMethodException {
// setup constants // setup constants
String region = Region.US_EAST_1; String region = Region.US_EAST_1;
String tag = "tag"; String group = "group";
Hardware size = EC2TemplateBuilderTest.CC1_4XLARGE; Hardware size = EC2TemplateBuilderTest.CC1_4XLARGE;
String systemGeneratedKeyPairName = "systemGeneratedKeyPair"; String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
String generatedGroup = "group"; String generatedGroup = "group";
@ -202,18 +206,18 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// create mocks // create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock( CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock(
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class, new Method[] { CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class,
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class new Method[] {
.getDeclaredMethod("getOptionsProvider"), CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod( .getDeclaredMethod("getOptionsProvider"),
"createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class, CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
TemplateOptions.class), "createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class,
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod( TemplateOptions.class),
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class, CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
TemplateOptions.class), "createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class,
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class TemplateOptions.class),
.getDeclaredMethod("getSecurityGroupsForTagAndOptions", String.class, String.class, CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
TemplateOptions.class) }); "getSecurityGroupsForTagAndOptions", String.class, String.class, TemplateOptions.class) });
AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class); AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class);
Template template = createMock(Template.class); Template template = createMock(Template.class);
@ -223,11 +227,11 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(template.getHardware()).andReturn(size).atLeastOnce(); expect(template.getHardware()).andReturn(size).atLeastOnce();
expect(template.getOptions()).andReturn(options).atLeastOnce(); expect(template.getOptions()).andReturn(options).atLeastOnce();
expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce(); expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce();
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn( expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
systemGeneratedKeyPairName); systemGeneratedKeyPairName);
expect(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn( expect(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
generatedGroup); generatedGroup);
expect(strategy.getSecurityGroupsForTagAndOptions(region, tag, options)).andReturn(generatedGroups); expect(strategy.getSecurityGroupsForTagAndOptions(region, group, options)).andReturn(generatedGroups);
expect(options.getSubnetId()).andReturn(null); expect(options.getSubnetId()).andReturn(null);
expect(options.getUserData()).andReturn(null); expect(options.getUserData()).andReturn(null);
expect(options.isMonitoringEnabled()).andReturn(false); expect(options.isMonitoringEnabled()).andReturn(false);
@ -238,11 +242,13 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replay(strategy); replay(strategy);
// run // run
RunInstancesOptions customize = strategy.execute(region, tag, template); RunInstancesOptions customize = strategy.execute(region, group, template);
assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of()); assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildFormParameters().entries(), ImmutableMultimap.<String, String> of("InstanceType", assertEquals(
size.getProviderId(), "SecurityGroup.1", generatedGroup, "KeyName", systemGeneratedKeyPairName, customize.buildFormParameters().entries(),
"Placement.GroupName", generatedGroup).entries()); ImmutableMultimap.<String, String> of("InstanceType", size.getProviderId(), "SecurityGroup.1",
generatedGroup, "KeyName", systemGeneratedKeyPairName, "Placement.GroupName", generatedGroup)
.entries());
assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of()); assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of()); assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildStringPayload(), null); assertEquals(customize.buildStringPayload(), null);
@ -256,24 +262,24 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testExecuteWithSubnet() throws SecurityException, NoSuchMethodException { public void testExecuteWithSubnet() throws SecurityException, NoSuchMethodException {
// setup constants // setup constants
String region = Region.AP_SOUTHEAST_1; String region = Region.AP_SOUTHEAST_1;
String tag = "tag"; String group = "group";
Hardware size = EC2HardwareBuilder.m1_small().build(); Hardware size = EC2HardwareBuilder.m1_small().build();
String systemGeneratedKeyPairName = "systemGeneratedKeyPair"; String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
// create mocks // create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock( CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock(
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class, new Method[] { CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class,
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class new Method[] {
.getDeclaredMethod("getOptionsProvider"), CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod( .getDeclaredMethod("getOptionsProvider"),
"createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class, CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
TemplateOptions.class), "createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class,
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod( TemplateOptions.class),
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class, CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
TemplateOptions.class), "createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class,
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class TemplateOptions.class),
.getDeclaredMethod("getSecurityGroupsForTagAndOptions", String.class, String.class, CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
TemplateOptions.class) }); "getSecurityGroupsForTagAndOptions", String.class, String.class, TemplateOptions.class) });
AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class); AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class);
Template template = createMock(Template.class); Template template = createMock(Template.class);
@ -283,8 +289,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(template.getHardware()).andReturn(size).atLeastOnce(); expect(template.getHardware()).andReturn(size).atLeastOnce();
expect(template.getOptions()).andReturn(options).atLeastOnce(); expect(template.getOptions()).andReturn(options).atLeastOnce();
expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce(); expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce();
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn( expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
systemGeneratedKeyPairName); systemGeneratedKeyPairName);
expect(options.getSubnetId()).andReturn("1"); expect(options.getSubnetId()).andReturn("1");
expect(options.getUserData()).andReturn(null); expect(options.getUserData()).andReturn(null);
expect(options.isMonitoringEnabled()).andReturn(false); expect(options.isMonitoringEnabled()).andReturn(false);
@ -295,10 +301,12 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replay(strategy); replay(strategy);
// run // run
RunInstancesOptions customize = strategy.execute(region, tag, template); RunInstancesOptions customize = strategy.execute(region, group, template);
assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of()); assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildFormParameters().entries(), ImmutableMultimap.<String, String> of("InstanceType", assertEquals(
size.getProviderId(), "SubnetId", "1", "KeyName", systemGeneratedKeyPairName).entries()); customize.buildFormParameters().entries(),
ImmutableMultimap.<String, String> of("InstanceType", size.getProviderId(), "SubnetId", "1", "KeyName",
systemGeneratedKeyPairName).entries());
assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of()); assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of()); assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildStringPayload(), null); assertEquals(customize.buildStringPayload(), null);
@ -312,7 +320,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testExecuteWithUserData() throws SecurityException, NoSuchMethodException { public void testExecuteWithUserData() throws SecurityException, NoSuchMethodException {
// setup constants // setup constants
String region = Region.AP_SOUTHEAST_1; String region = Region.AP_SOUTHEAST_1;
String tag = "tag"; String group = "group";
Hardware size = EC2HardwareBuilder.m1_small().build(); Hardware size = EC2HardwareBuilder.m1_small().build();
String systemGeneratedKeyPairName = "systemGeneratedKeyPair"; String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
String generatedGroup = "group"; String generatedGroup = "group";
@ -320,18 +328,18 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// create mocks // create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock( CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock(
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class, new Method[] { CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class,
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class new Method[] {
.getDeclaredMethod("getOptionsProvider"), CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod( .getDeclaredMethod("getOptionsProvider"),
"createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class, CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
TemplateOptions.class), "createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class,
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod( TemplateOptions.class),
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class, CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
TemplateOptions.class), "createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class,
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class TemplateOptions.class),
.getDeclaredMethod("getSecurityGroupsForTagAndOptions", String.class, String.class, CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
TemplateOptions.class) }); "getSecurityGroupsForTagAndOptions", String.class, String.class, TemplateOptions.class) });
AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class); AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class);
Template template = createMock(Template.class); Template template = createMock(Template.class);
@ -341,9 +349,9 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(template.getHardware()).andReturn(size).atLeastOnce(); expect(template.getHardware()).andReturn(size).atLeastOnce();
expect(template.getOptions()).andReturn(options).atLeastOnce(); expect(template.getOptions()).andReturn(options).atLeastOnce();
expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce(); expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce();
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn( expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
systemGeneratedKeyPairName); systemGeneratedKeyPairName);
expect(strategy.getSecurityGroupsForTagAndOptions(region, tag, options)).andReturn(generatedGroups); expect(strategy.getSecurityGroupsForTagAndOptions(region, group, options)).andReturn(generatedGroups);
expect(options.getSubnetId()).andReturn(null); expect(options.getSubnetId()).andReturn(null);
expect(options.getUserData()).andReturn("hello".getBytes()); expect(options.getUserData()).andReturn("hello".getBytes());
expect(options.isMonitoringEnabled()).andReturn(false); expect(options.isMonitoringEnabled()).andReturn(false);
@ -354,11 +362,12 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replay(strategy); replay(strategy);
// run // run
RunInstancesOptions customize = strategy.execute(region, tag, template); RunInstancesOptions customize = strategy.execute(region, group, template);
assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of()); assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildFormParameters().entries(), ImmutableMultimap.<String, String> of("InstanceType", assertEquals(
size.getProviderId(), "SecurityGroup.1", "group", "KeyName", systemGeneratedKeyPairName, "UserData", customize.buildFormParameters().entries(),
Base64.encodeBytes("hello".getBytes())).entries()); ImmutableMultimap.<String, String> of("InstanceType", size.getProviderId(), "SecurityGroup.1", "group",
"KeyName", systemGeneratedKeyPairName, "UserData", Base64.encodeBytes("hello".getBytes())).entries());
assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of()); assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of()); assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildStringPayload(), null); assertEquals(customize.buildStringPayload(), null);
@ -372,7 +381,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_reusesKeyWhenToldTo() { public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_reusesKeyWhenToldTo() {
// setup constants // setup constants
String region = Region.AP_SOUTHEAST_1; String region = Region.AP_SOUTHEAST_1;
String tag = "tag"; String group = "group";
String userSuppliedKeyPair = "myKeyPair"; String userSuppliedKeyPair = "myKeyPair";
// create mocks // create mocks
@ -389,7 +398,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy); replayStrategy(strategy);
// run // run
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options), userSuppliedKeyPair); assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options), userSuppliedKeyPair);
// verify mocks // verify mocks
verify(options); verify(options);
@ -397,10 +406,86 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
verifyStrategy(strategy); verifyStrategy(strategy);
} }
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_createsNewKeyPairAndReturnsItsNameByDefault() { public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_importsKeyPairAndUnsetsTemplateInstructionWhenPublicKeySuppliedAndAddsCredentialToMapWhenOverridingCredsAreSet() {
// setup constants // setup constants
String region = Region.AP_SOUTHEAST_1; String region = Region.AP_SOUTHEAST_1;
String tag = "tag"; String group = "group";
String userSuppliedKeyPair = null;
boolean shouldAutomaticallyCreateKeyPair = true;
// create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = setupStrategy();
AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class);
KeyPair keyPair = new KeyPair(region, "jclouds#" + group, "fingerprint", null);
// setup expectations
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
expect(options.shouldAutomaticallyCreateKeyPair()).andReturn(shouldAutomaticallyCreateKeyPair);
expect(strategy.credentialsMap.get(new RegionAndName(region, "jclouds#" + group))).andReturn(null);
expect(options.getPublicKey()).andReturn("ssh-rsa").times(2);
expect(strategy.importExistingKeyPair.apply(new RegionNameAndPublicKeyMaterial(region, group, "ssh-rsa")))
.andReturn(keyPair);
expect(options.dontAuthorizePublicKey()).andReturn(options);
expect(options.getOverridingCredentials()).andReturn(new Credentials("foo", "bar")).times(3);
expect(options.getRunScript()).andReturn(null);
expect(options.getPrivateKey()).andReturn(null);
expect(
strategy.credentialsMap.put(new RegionAndName(region, "jclouds#" + group),
keyPair.toBuilder().keyMaterial("bar").build())).andReturn(null);
// replay mocks
replay(options);
replayStrategy(strategy);
// run
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options), "jclouds#" + group);
// verify mocks
verify(options);
verifyStrategy(strategy);
}
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_importsKeyPairAndUnsetsTemplateInstructionWhenPublicKeySupplied() {
// setup constants
String region = Region.AP_SOUTHEAST_1;
String group = "group";
String userSuppliedKeyPair = null;
boolean shouldAutomaticallyCreateKeyPair = true;
// create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = setupStrategy();
AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class);
KeyPair keyPair = new KeyPair(region, "jclouds#" + group, "fingerprint", null);
// setup expectations
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
expect(options.shouldAutomaticallyCreateKeyPair()).andReturn(shouldAutomaticallyCreateKeyPair);
expect(strategy.credentialsMap.get(new RegionAndName(region, "jclouds#" + group))).andReturn(null);
expect(options.getPublicKey()).andReturn("ssh-rsa").times(2);
expect(strategy.importExistingKeyPair.apply(new RegionNameAndPublicKeyMaterial(region, group, "ssh-rsa")))
.andReturn(keyPair);
expect(options.dontAuthorizePublicKey()).andReturn(options);
expect(options.getOverridingCredentials()).andReturn(null);
expect(options.getRunScript()).andReturn(null);
expect(options.getPrivateKey()).andReturn(null);
expect(strategy.credentialsMap.put(new RegionAndName(region, "jclouds#" + group), keyPair)).andReturn(null);
// replay mocks
replay(options);
replayStrategy(strategy);
// run
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options), "jclouds#" + group);
// verify mocks
verify(options);
verifyStrategy(strategy);
}
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_createsNewKeyPairAndReturnsItsNameWhenNoPublicKeySupplied() {
// setup constants
String region = Region.AP_SOUTHEAST_1;
String group = "group";
String userSuppliedKeyPair = null; String userSuppliedKeyPair = null;
boolean shouldAutomaticallyCreateKeyPair = true; boolean shouldAutomaticallyCreateKeyPair = true;
String systemGeneratedKeyPairName = "systemGeneratedKeyPair"; String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
@ -413,10 +498,12 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// 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(strategy.credentialsMap.get(new RegionAndName(region, "jclouds#" + group))).andReturn(null);
expect(options.getPublicKey()).andReturn(null).times(2);
expect(strategy.createUniqueKeyPair.apply(new RegionAndName(region, group))).andReturn(keyPair);
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.put(new RegionAndName(region, systemGeneratedKeyPairName), keyPair)).andReturn(
null); null);
// replay mocks // replay mocks
replay(options); replay(options);
@ -424,8 +511,41 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy); replayStrategy(strategy);
// run // run
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options), assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options),
systemGeneratedKeyPairName); systemGeneratedKeyPairName);
// verify mocks
verify(options);
verify(keyPair);
verifyStrategy(strategy);
}
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_returnsExistingKeyIfAlreadyPresent() {
// setup constants
String region = Region.AP_SOUTHEAST_1;
String group = "group";
String userSuppliedKeyPair = null;
boolean shouldAutomaticallyCreateKeyPair = true;
String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
// create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = setupStrategy();
AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class);
KeyPair keyPair = createMock(KeyPair.class);
// setup expectations
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
expect(options.shouldAutomaticallyCreateKeyPair()).andReturn(shouldAutomaticallyCreateKeyPair);
expect(strategy.credentialsMap.get(new RegionAndName(region, "jclouds#" + group))).andReturn(keyPair);
expect(keyPair.getKeyName()).andReturn(systemGeneratedKeyPairName).atLeastOnce();
// replay mocks
replay(options);
replay(keyPair);
replayStrategy(strategy);
// run
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options),
systemGeneratedKeyPairName);
// verify mocks // verify mocks
verify(options); verify(options);
@ -436,7 +556,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_doesntCreateAKeyPairAndReturnsNullWhenToldNotTo() { public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_doesntCreateAKeyPairAndReturnsNullWhenToldNotTo() {
// setup constants // setup constants
String region = Region.AP_SOUTHEAST_1; String region = Region.AP_SOUTHEAST_1;
String tag = "tag"; String group = "group";
String userSuppliedKeyPair = null; String userSuppliedKeyPair = null;
boolean shouldAutomaticallyCreateKeyPair = false; // here's the important boolean shouldAutomaticallyCreateKeyPair = false; // here's the important
// part! // part!
@ -456,7 +576,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy); replayStrategy(strategy);
// run // run
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options), null); assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options), null);
// verify mocks // verify mocks
verify(options); verify(options);
@ -467,8 +587,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testGetSecurityGroupsForTagAndOptions_createsNewGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesntExist() { public void testGetSecurityGroupsForTagAndOptions_createsNewGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesntExist() {
// setup constants // setup constants
String region = Region.AP_SOUTHEAST_1; String region = Region.AP_SOUTHEAST_1;
String tag = "tag"; String group = "group";
String generatedMarkerGroup = "jclouds#tag#" + Region.AP_SOUTHEAST_1; String generatedMarkerGroup = "jclouds#group#" + Region.AP_SOUTHEAST_1;
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;
@ -483,7 +603,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(options.getGroupIds()).andReturn(groupIds).atLeastOnce(); expect(options.getGroupIds()).andReturn(groupIds).atLeastOnce();
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.containsKey(regionNameAndIngressRules)).andReturn(groupExisted);
expect(strategy.createSecurityGroupIfNeeded.apply(regionNameAndIngressRules)).andReturn(generatedMarkerGroup); expect(strategy.createSecurityGroupIfNeeded.apply(regionNameAndIngressRules)).andReturn(generatedMarkerGroup);
expect(strategy.securityGroupMap.put(regionNameAndIngressRules, generatedMarkerGroup)).andReturn(null); expect(strategy.securityGroupMap.put(regionNameAndIngressRules, generatedMarkerGroup)).andReturn(null);
@ -493,7 +613,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy); replayStrategy(strategy);
// run // run
assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, tag, options), returnVal); assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, group, options), returnVal);
// verify mocks // verify mocks
verify(options); verify(options);
@ -503,8 +623,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testGetSecurityGroupsForTagAndOptions_createsNewGroupByDefaultWhenPortsAreSpecifiedWhenDoesntExist() { public void testGetSecurityGroupsForTagAndOptions_createsNewGroupByDefaultWhenPortsAreSpecifiedWhenDoesntExist() {
// setup constants // setup constants
String region = Region.AP_SOUTHEAST_1; String region = Region.AP_SOUTHEAST_1;
String tag = "tag"; String group = "group";
String generatedMarkerGroup = "jclouds#tag#" + Region.AP_SOUTHEAST_1; String generatedMarkerGroup = "jclouds#group#" + Region.AP_SOUTHEAST_1;
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;
@ -519,7 +639,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(options.getGroupIds()).andReturn(groupIds).atLeastOnce(); expect(options.getGroupIds()).andReturn(groupIds).atLeastOnce();
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.containsKey(regionNameAndIngressRules)).andReturn(groupExisted);
expect(strategy.createSecurityGroupIfNeeded.apply(regionNameAndIngressRules)).andReturn(generatedMarkerGroup); expect(strategy.createSecurityGroupIfNeeded.apply(regionNameAndIngressRules)).andReturn(generatedMarkerGroup);
expect(strategy.securityGroupMap.put(regionNameAndIngressRules, generatedMarkerGroup)).andReturn(null); expect(strategy.securityGroupMap.put(regionNameAndIngressRules, generatedMarkerGroup)).andReturn(null);
@ -529,7 +649,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy); replayStrategy(strategy);
// run // run
assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, tag, options), returnVal); assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, group, options), returnVal);
// verify mocks // verify mocks
verify(options); verify(options);
@ -539,8 +659,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testGetSecurityGroupsForTagAndOptions_reusesGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesExist() { public void testGetSecurityGroupsForTagAndOptions_reusesGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesExist() {
// setup constants // setup constants
String region = Region.AP_SOUTHEAST_1; String region = Region.AP_SOUTHEAST_1;
String tag = "tag"; String group = "group";
String generatedMarkerGroup = "jclouds#tag#" + Region.AP_SOUTHEAST_1; String generatedMarkerGroup = "jclouds#group#" + Region.AP_SOUTHEAST_1;
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;
@ -555,7 +675,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(options.getGroupIds()).andReturn(groupIds).atLeastOnce(); expect(options.getGroupIds()).andReturn(groupIds).atLeastOnce();
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.containsKey(regionNameAndIngressRules)).andReturn(groupExisted);
// replay mocks // replay mocks
@ -563,7 +683,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy); replayStrategy(strategy);
// run // run
assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, tag, options), returnVal); assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, group, options), returnVal);
// verify mocks // verify mocks
verify(options); verify(options);
@ -573,8 +693,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testGetSecurityGroupsForTagAndOptions_reusesGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesExistAndAcceptsUserSuppliedGroups() { public void testGetSecurityGroupsForTagAndOptions_reusesGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesExistAndAcceptsUserSuppliedGroups() {
// setup constants // setup constants
String region = Region.AP_SOUTHEAST_1; String region = Region.AP_SOUTHEAST_1;
String tag = "tag"; String group = "group";
String generatedMarkerGroup = "jclouds#tag#" + Region.AP_SOUTHEAST_1; String generatedMarkerGroup = "jclouds#group#" + Region.AP_SOUTHEAST_1;
Set<String> groupIds = ImmutableSet.<String> of("group1", "group2"); Set<String> groupIds = ImmutableSet.<String> of("group1", "group2");
int[] ports = new int[] {}; int[] ports = new int[] {};
boolean shouldAuthorizeSelf = true; boolean shouldAuthorizeSelf = true;
@ -588,7 +708,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// setup expectations // setup expectations
expect(options.getGroupIds()).andReturn(groupIds).atLeastOnce(); expect(options.getGroupIds()).andReturn(groupIds).atLeastOnce();
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup, RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
ports, shouldAuthorizeSelf); // note ports, shouldAuthorizeSelf); // note
// this // this
// works // works
// since // since
@ -601,7 +721,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy); replayStrategy(strategy);
// run // run
assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, tag, options), returnVal); assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, group, options), returnVal);
// verify mocks // verify mocks
verify(options); verify(options);
@ -611,7 +731,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testCreateNewPlacementGroupUnlessUserSpecifiedOtherwise_reusesKeyWhenToldTo() { public void testCreateNewPlacementGroupUnlessUserSpecifiedOtherwise_reusesKeyWhenToldTo() {
// setup constants // setup constants
String region = Region.AP_SOUTHEAST_1; String region = Region.AP_SOUTHEAST_1;
String tag = "tag"; String group = "group";
String userSuppliedPlacementGroup = "myPlacementGroup"; String userSuppliedPlacementGroup = "myPlacementGroup";
// create mocks // create mocks
@ -628,8 +748,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy); replayStrategy(strategy);
// run // run
assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, tag, options), assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, group, options),
userSuppliedPlacementGroup); userSuppliedPlacementGroup);
// verify mocks // verify mocks
verify(options); verify(options);
@ -640,10 +760,10 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testCreateNewPlacementGroupUnlessUserSpecifiedOtherwise_createsNewPlacementGroupAndReturnsItsNameByDefault() { public void testCreateNewPlacementGroupUnlessUserSpecifiedOtherwise_createsNewPlacementGroupAndReturnsItsNameByDefault() {
// setup constants // setup constants
String region = Region.AP_SOUTHEAST_1; String region = Region.AP_SOUTHEAST_1;
String tag = "tag"; String group = "group";
String userSuppliedPlacementGroup = null; String userSuppliedPlacementGroup = null;
boolean shouldAutomaticallyCreatePlacementGroup = true; boolean shouldAutomaticallyCreatePlacementGroup = true;
String generatedMarkerGroup = "jclouds#tag#" + Region.AP_SOUTHEAST_1; String generatedMarkerGroup = "jclouds#group#" + Region.AP_SOUTHEAST_1;
// create mocks // create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = setupStrategy(); CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = setupStrategy();
@ -654,17 +774,17 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(options.shouldAutomaticallyCreatePlacementGroup()).andReturn(shouldAutomaticallyCreatePlacementGroup); expect(options.shouldAutomaticallyCreatePlacementGroup()).andReturn(shouldAutomaticallyCreatePlacementGroup);
expect(strategy.placementGroupMap.containsKey(new RegionAndName(region, generatedMarkerGroup))).andReturn(false); expect(strategy.placementGroupMap.containsKey(new RegionAndName(region, generatedMarkerGroup))).andReturn(false);
expect(strategy.createPlacementGroupIfNeeded.apply(new RegionAndName(region, generatedMarkerGroup))).andReturn( expect(strategy.createPlacementGroupIfNeeded.apply(new RegionAndName(region, generatedMarkerGroup))).andReturn(
generatedMarkerGroup); generatedMarkerGroup);
expect(strategy.placementGroupMap.put(new RegionAndName(region, generatedMarkerGroup), generatedMarkerGroup)) expect(strategy.placementGroupMap.put(new RegionAndName(region, generatedMarkerGroup), generatedMarkerGroup))
.andReturn(null); .andReturn(null);
// replay mocks // replay mocks
replay(options); replay(options);
replayStrategy(strategy); replayStrategy(strategy);
// run // run
assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, tag, options), assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, group, options),
generatedMarkerGroup); generatedMarkerGroup);
// verify mocks // verify mocks
verify(options); verify(options);
@ -674,7 +794,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testCreateNewPlacementGroupUnlessUserSpecifiedOtherwise_doesntCreateAPlacementGroupAndReturnsNullWhenToldNotTo() { public void testCreateNewPlacementGroupUnlessUserSpecifiedOtherwise_doesntCreateAPlacementGroupAndReturnsNullWhenToldNotTo() {
// setup constants // setup constants
String region = Region.AP_SOUTHEAST_1; String region = Region.AP_SOUTHEAST_1;
String tag = "tag"; String group = "group";
String userSuppliedPlacementGroup = null; String userSuppliedPlacementGroup = null;
boolean shouldAutomaticallyCreatePlacementGroup = false; // here's the important boolean shouldAutomaticallyCreatePlacementGroup = false; // here's the important
// part! // part!
@ -694,7 +814,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy); replayStrategy(strategy);
// run // run
assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, tag, options), null); assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, group, options), null);
// verify mocks // verify mocks
verify(options); verify(options);
@ -707,6 +827,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
verify(strategy.securityGroupMap); verify(strategy.securityGroupMap);
verify(strategy.placementGroupMap); verify(strategy.placementGroupMap);
verify(strategy.createUniqueKeyPair); verify(strategy.createUniqueKeyPair);
verify(strategy.importExistingKeyPair);
verify(strategy.createSecurityGroupIfNeeded); verify(strategy.createSecurityGroupIfNeeded);
verify(strategy.createPlacementGroupIfNeeded); verify(strategy.createPlacementGroupIfNeeded);
} }
@ -716,13 +837,14 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class); Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
Map<RegionAndName, String> securityGroupMap = createMock(Map.class); Map<RegionAndName, String> securityGroupMap = createMock(Map.class);
Map<RegionAndName, String> placementGroupMap = createMock(Map.class); Map<RegionAndName, String> placementGroupMap = createMock(Map.class);
CreateUniqueKeyPair createUniqueKeyPair = createMock(CreateUniqueKeyPair.class); Function<RegionAndName, KeyPair> createOrGetKeyPair = createMock(Function.class);
CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded = createMock(CreateSecurityGroupIfNeeded.class); Function<RegionNameAndIngressRules, String> createSecurityGroupIfNeeded = 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(credentialsMap, securityGroupMap,
placementGroupMap, createUniqueKeyPair, createSecurityGroupIfNeeded, OPTIONS_PROVIDER, placementGroupMap, createOrGetKeyPair, createSecurityGroupIfNeeded, OPTIONS_PROVIDER,
createPlacementGroupIfNeeded); createPlacementGroupIfNeeded, importExistingKeyPair);
} }
private void replayStrategy(CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy) { private void replayStrategy(CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy) {
@ -730,6 +852,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replay(strategy.securityGroupMap); replay(strategy.securityGroupMap);
replay(strategy.placementGroupMap); replay(strategy.placementGroupMap);
replay(strategy.createUniqueKeyPair); replay(strategy.createUniqueKeyPair);
replay(strategy.importExistingKeyPair);
replay(strategy.createSecurityGroupIfNeeded); replay(strategy.createSecurityGroupIfNeeded);
replay(strategy.createPlacementGroupIfNeeded); replay(strategy.createPlacementGroupIfNeeded);
} }

View File

@ -0,0 +1,116 @@
/**
*
* Copyright (C) 2010 Cloud Conscious, LLC. <info@cloudconscious.com>
*
* ====================================================================
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
* ====================================================================
*/
package org.jclouds.aws.ec2.functions;
import static org.easymock.EasyMock.expect;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import static org.testng.Assert.assertEquals;
import java.net.UnknownHostException;
import org.jclouds.aws.ec2.AWSEC2Client;
import org.jclouds.aws.ec2.services.AWSKeyPairClient;
import org.jclouds.ec2.domain.KeyPair;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
/**
* @author Adrian Cole
*/
@Test(groups = "unit")
public class ImportOrReturnExistingKeypairTest {
@Test
public void testApply() throws UnknownHostException {
AWSEC2Client client = createMock(AWSEC2Client.class);
AWSKeyPairClient keyClient = createMock(AWSKeyPairClient.class);
KeyPair pair = createMock(KeyPair.class);
expect(client.getKeyPairServices()).andReturn(keyClient).atLeastOnce();
expect(keyClient.importKeyPairInRegion("region", "jclouds#group", "ssh-rsa")).andReturn(pair);
replay(client);
replay(keyClient);
ImportOrReturnExistingKeypair parser = new ImportOrReturnExistingKeypair(client);
assertEquals(parser.importOrReturnExistingKeypair("region", "group", "ssh-rsa"), pair);
verify(client);
verify(keyClient);
}
@Test
public void testApplyWithIllegalStateExceptionReturnsExistingKey() throws UnknownHostException {
AWSEC2Client client = createMock(AWSEC2Client.class);
AWSKeyPairClient keyClient = createMock(AWSKeyPairClient.class);
KeyPair pair = createMock(KeyPair.class);
expect(client.getKeyPairServices()).andReturn(keyClient).atLeastOnce();
expect(keyClient.importKeyPairInRegion("region", "jclouds#group", "ssh-rsa")).andThrow(
new IllegalStateException());
expect(keyClient.describeKeyPairsInRegion("region", "jclouds#group")).andReturn(ImmutableSet.of(pair));
replay(client);
replay(keyClient);
ImportOrReturnExistingKeypair parser = new ImportOrReturnExistingKeypair(client);
assertEquals(parser.importOrReturnExistingKeypair("region", "group", "ssh-rsa"), pair);
verify(client);
verify(keyClient);
}
@Test
public void testApplyWithIllegalStateExceptionRetriesWhenExistingKeyNotFound() throws UnknownHostException {
AWSEC2Client client = createMock(AWSEC2Client.class);
AWSKeyPairClient keyClient = createMock(AWSKeyPairClient.class);
KeyPair pair = createMock(KeyPair.class);
expect(client.getKeyPairServices()).andReturn(keyClient).atLeastOnce();
expect(keyClient.importKeyPairInRegion("region", "jclouds#group", "ssh-rsa")).andThrow(
new IllegalStateException());
expect(keyClient.describeKeyPairsInRegion("region", "jclouds#group")).andReturn(ImmutableSet.<KeyPair> of());
expect(keyClient.importKeyPairInRegion("region", "jclouds#group", "ssh-rsa")).andThrow(
new IllegalStateException());
expect(keyClient.describeKeyPairsInRegion("region", "jclouds#group")).andReturn(ImmutableSet.<KeyPair> of(pair));
replay(client);
replay(keyClient);
ImportOrReturnExistingKeypair parser = new ImportOrReturnExistingKeypair(client);
assertEquals(parser.importOrReturnExistingKeypair("region", "group", "ssh-rsa"), pair);
verify(client);
verify(keyClient);
}
}

View File

@ -20,6 +20,13 @@
package org.jclouds.aws.ec2.services; package org.jclouds.aws.ec2.services;
import static com.google.common.base.Preconditions.checkNotNull; import static com.google.common.base.Preconditions.checkNotNull;
import static com.google.common.collect.Iterables.get;
import static com.google.common.collect.Iterables.getOnlyElement;
import static com.google.common.collect.Sets.newTreeSet;
import static org.jclouds.compute.options.TemplateOptions.Builder.overrideCredentialsWith;
import static org.jclouds.compute.predicates.NodePredicates.inGroup;
import static org.jclouds.compute.predicates.NodePredicates.runningInGroup;
import static org.jclouds.scriptbuilder.domain.Statements.exec;
import static org.testng.Assert.assertEquals; import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull; import static org.testng.Assert.assertNotNull;
@ -34,17 +41,26 @@ import org.jclouds.Constants;
import org.jclouds.aws.domain.Region; import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.AWSEC2AsyncClient; import org.jclouds.aws.ec2.AWSEC2AsyncClient;
import org.jclouds.aws.ec2.AWSEC2Client; import org.jclouds.aws.ec2.AWSEC2Client;
import org.jclouds.aws.ec2.domain.AWSRunningInstance;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.ComputeServiceContextFactory; import org.jclouds.compute.ComputeServiceContextFactory;
import org.jclouds.compute.ComputeTestUtils; import org.jclouds.compute.ComputeTestUtils;
import org.jclouds.compute.domain.ExecResponse;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Credentials;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.domain.KeyPair; import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.ec2.services.InstanceClient;
import org.jclouds.logging.log4j.config.Log4JLoggingModule; import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext; import org.jclouds.rest.RestContext;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.AfterTest; import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeGroups; import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test; import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet; import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.inject.Module; import com.google.inject.Module;
/** /**
@ -63,6 +79,7 @@ public class AWSKeyPairClientLiveTest {
protected String credential; protected String credential;
protected String endpoint; protected String endpoint;
protected String apiversion; protected String apiversion;
private ComputeServiceContext computeContext;
protected void setupCredentials() { protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity"); identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
@ -89,20 +106,67 @@ public class AWSKeyPairClientLiveTest {
public void setupClient() { public void setupClient() {
setupCredentials(); setupCredentials();
Properties overrides = setupProperties(); Properties overrides = setupProperties();
context = new ComputeServiceContextFactory().createContext(provider, computeContext = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule()), overrides).getProviderSpecificContext(); ImmutableSet.<Module> of(new Log4JLoggingModule(), new JschSshClientModule()), overrides);
context = computeContext.getProviderSpecificContext();
client = context.getApi().getKeyPairServices(); client = context.getApi().getKeyPairServices();
} }
public void testNoSsh() throws Exception {
Map<String, String> keyPair = ComputeTestUtils.setupKeyPair();
InstanceClient instanceClient = EC2Client.class.cast(context.getApi()).getInstanceServices();
String group = PREFIX + "unssh";
computeContext.getComputeService().destroyNodesMatching(inGroup(group));
TemplateOptions options = computeContext.getComputeService().templateOptions();
options.authorizePublicKey(keyPair.get("public"));
ComputeServiceContext noSshContext = null;
try {
noSshContext = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.of(new Log4JLoggingModule()), setupProperties());
Set<? extends NodeMetadata> nodes = noSshContext.getComputeService().createNodesInGroup(group, 1, options);
NodeMetadata first = get(nodes, 0);
assert first.getCredentials() != null : first;
assert first.getCredentials().identity != null : first;
AWSRunningInstance instance = AWSRunningInstance.class
.cast(getInstance(instanceClient, first.getProviderId()));
assertEquals(instance.getKeyName(), "jclouds#" + group);
assertEquals(first.getCredentials().credential, null);
Map<? extends NodeMetadata, ExecResponse> responses = computeContext.getComputeService()
.runScriptOnNodesMatching(
runningInGroup(group),
exec("echo hello"),
overrideCredentialsWith(new Credentials(first.getCredentials().identity, keyPair.get("private")))
.wrapInInitScript(false).runAsRoot(false));
ExecResponse hello = getOnlyElement(responses.values());
assertEquals(hello.getOutput().trim(), "hello");
} finally {
noSshContext.close();
computeContext.getComputeService().destroyNodesMatching(inGroup(group));
}
}
@Test @Test
void testDescribeAWSKeyPairs() { void testDescribeAWSKeyPairs() {
for (String region : Region.DEFAULT_REGIONS) { for (String region : Region.DEFAULT_REGIONS) {
SortedSet<KeyPair> allResults = Sets.newTreeSet(client.describeKeyPairsInRegion(region)); SortedSet<KeyPair> allResults = newTreeSet(client.describeKeyPairsInRegion(region));
assertNotNull(allResults); assertNotNull(allResults);
if (allResults.size() >= 1) { if (allResults.size() >= 1) {
KeyPair pair = allResults.last(); KeyPair pair = allResults.last();
SortedSet<KeyPair> result = Sets.newTreeSet(client.describeKeyPairsInRegion(region, pair.getKeyName())); SortedSet<KeyPair> result = newTreeSet(client.describeKeyPairsInRegion(region, pair.getKeyName()));
assertNotNull(result); assertNotNull(result);
KeyPair compare = result.last(); KeyPair compare = result.last();
assertEquals(compare, pair); assertEquals(compare, pair);
@ -163,7 +227,7 @@ public class AWSKeyPairClientLiveTest {
assertNotNull(keyPair.getKeyFingerprint()); assertNotNull(keyPair.getKeyFingerprint());
assertEquals(keyPair.getKeyName(), keyName); assertEquals(keyPair.getKeyName(), keyName);
Set<KeyPair> twoResults = Sets.newLinkedHashSet(client.describeKeyPairsInRegion(null, keyName)); Set<KeyPair> twoResults = client.describeKeyPairsInRegion(null, keyName);
assertNotNull(twoResults); assertNotNull(twoResults);
assertEquals(twoResults.size(), 1); assertEquals(twoResults.size(), 1);
KeyPair listPair = twoResults.iterator().next(); KeyPair listPair = twoResults.iterator().next();
@ -171,6 +235,11 @@ public class AWSKeyPairClientLiveTest {
assertEquals(listPair.getKeyFingerprint(), keyPair.getKeyFingerprint()); assertEquals(listPair.getKeyFingerprint(), keyPair.getKeyFingerprint());
} }
protected RunningInstance getInstance(InstanceClient instanceClient, String id) {
RunningInstance instance = getOnlyElement(getOnlyElement(instanceClient.describeInstancesInRegion(null, id)));
return instance;
}
@AfterTest @AfterTest
public void shutdown() { public void shutdown() {
context.close(); context.close();

View File

@ -197,8 +197,8 @@ public class PlacementGroupClientLiveTest {
assertEquals(template.getHardware().getProviderId(), InstanceType.CC1_4XLARGE); assertEquals(template.getHardware().getProviderId(), InstanceType.CC1_4XLARGE);
assertEquals(template.getImage().getId(), "us-east-1/ami-7ea24a17"); assertEquals(template.getImage().getId(), "us-east-1/ami-7ea24a17");
template.getOptions().installPrivateKey(keyPair.get("private")).authorizePublicKey(keyPair.get("public")) template.getOptions().overrideLoginCredentialWith(keyPair.get("private"))
.runScript(buildScript(template.getImage().getOperatingSystem())); .authorizePublicKey(keyPair.get("public")).runScript(buildScript(template.getImage().getOperatingSystem()));
String group = PREFIX + "cccluster"; String group = PREFIX + "cccluster";
context.getComputeService().destroyNodesMatching(NodePredicates.inGroup(group)); context.getComputeService().destroyNodesMatching(NodePredicates.inGroup(group));