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;
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.Set;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
@ -40,13 +45,13 @@ import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.internal.BaseComputeService;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.domain.Credentials;
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.options.EC2TemplateOptions;
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.base.Function;
import com.google.common.base.Predicate;
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
@ -86,18 +94,17 @@ public class EC2ComputeService extends BaseComputeService {
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy,
stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated,
nodeSuspended, initScriptRunnerFactory, timeouts, executor);
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy,
templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, nodeSuspended,
initScriptRunnerFactory, timeouts, executor);
this.ec2Client = ec2Client;
this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap;
}
@VisibleForTesting
void deleteSecurityGroup(String region, String group) {
Preconditions2.checkNotEmpty(group, "group");
checkNotEmpty(group, "group");
String groupName = String.format("jclouds#%s#%s", group, region);
if (ec2Client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, groupName).size() > 0) {
logger.debug(">> deleting securityGroup(%s)", groupName);
@ -115,7 +122,17 @@ public class EC2ComputeService extends BaseComputeService {
@VisibleForTesting
void deleteKeyPair(String region, String group) {
for (KeyPair keyPair : ec2Client.getKeyPairServices().describeKeyPairsInRegion(region)) {
if (keyPair.getKeyName().matches(String.format("jclouds#%s#%s#%s", group, region, "[0-9a-f]+"))) {
if (
// when the keypair is unique per group
keyPair.getKeyName().equals("jclouds#" + group)
|| keyPair.getKeyName().matches(String.format("jclouds#%s#%s", group, "[0-9a-f]+"))
// old keypair pattern too verbose as it has an unnecessary region qualifier
|| 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
@ -124,6 +141,34 @@ public class EC2ComputeService extends BaseComputeService {
}
}
}
}
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
@ -132,20 +177,20 @@ public class EC2ComputeService extends BaseComputeService {
@Override
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> 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) {
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()) {
cleanUpIncidentalResources(regionTag);
for (Entry<String, String> regionGroup : regionGroups.build().entrySet()) {
cleanUpIncidentalResources(regionGroup);
}
return deadOnes;
}
protected void cleanUpIncidentalResources(Entry<String, String> regionTag) {
deleteKeyPair(regionTag.getKey(), regionTag.getValue());
deleteSecurityGroup(regionTag.getKey(), regionTag.getValue());
protected void cleanUpIncidentalResources(Entry<String, String> regionGroup) {
deleteKeyPair(regionGroup.getKey(), regionGroup.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.compute.EC2ComputeService;
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.CreateUniqueKeyPair;
import org.jclouds.ec2.compute.functions.CredentialsForInstance;
@ -76,9 +77,9 @@ import com.google.inject.TypeLiteral;
public class EC2ComputeServiceDependenciesModule extends AbstractModule {
public static final Map<InstanceState, NodeState> instanceToNodeState = ImmutableMap
.<InstanceState, NodeState> builder().put(InstanceState.PENDING, NodeState.PENDING).put(
InstanceState.RUNNING, NodeState.RUNNING).put(InstanceState.SHUTTING_DOWN, NodeState.PENDING).put(
InstanceState.TERMINATED, NodeState.TERMINATED).put(InstanceState.STOPPING, NodeState.PENDING)
.<InstanceState, NodeState> builder().put(InstanceState.PENDING, NodeState.PENDING)
.put(InstanceState.RUNNING, NodeState.RUNNING).put(InstanceState.SHUTTING_DOWN, NodeState.PENDING)
.put(InstanceState.TERMINATED, NodeState.TERMINATED).put(InstanceState.STOPPING, NodeState.PENDING)
.put(InstanceState.STOPPED, NodeState.SUSPENDED).put(InstanceState.UNRECOGNIZED, NodeState.UNRECOGNIZED)
.build();
@ -104,6 +105,12 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
}).to(RunningInstanceToNodeMetadata.class);
bind(new TypeLiteral<Function<RunningInstance, Credentials>>() {
}).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>() {
}).to(new TypeLiteral<ComputeServiceContextImpl<EC2Client, EC2AsyncClient>>() {
}).in(Scopes.SINGLETON);
@ -128,7 +135,7 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
@Provides
@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)
// return new MapMaker().makeComputingMap(in);
return newLinkedHashMap();
@ -137,13 +144,12 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
@Provides
@Singleton
@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)
// return new MapMaker().makeComputingMap(in);
return newLinkedHashMap();
}
@Provides
@Singleton
@Named(PROPERTY_EC2_AMI_OWNERS)
@ -153,10 +159,9 @@ public class EC2ComputeServiceDependenciesModule extends AbstractModule {
return toArray(Splitter.on(',').split(amiOwners), String.class);
}
@Provides
@Singleton
protected Map<RegionAndName, Image> provideImageMap(RegionAndIdToImage regionAndIdToImage) {
protected Map<RegionAndName, Image> provideImageMap(Function<RegionAndName, Image> regionAndIdToImage) {
return new MapMaker().makeComputingMap(regionAndIdToImage);
}

View File

@ -73,7 +73,7 @@ public class RegionAndName {
@Override
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.Singleton;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.ec2.EC2Client;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.logging.Logger;
import com.google.common.annotations.VisibleForTesting;
@ -46,7 +46,7 @@ public class CreateUniqueKeyPair implements Function<RegionAndName, KeyPair> {
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
protected final EC2Client ec2Client;
protected Supplier<String> randomSuffix;
protected final Supplier<String> randomSuffix;
@Inject
public CreateUniqueKeyPair(EC2Client ec2Client, Supplier<String> randomSuffix) {
@ -60,14 +60,14 @@ public class CreateUniqueKeyPair implements Function<RegionAndName, KeyPair> {
}
@VisibleForTesting
KeyPair createNewKeyPairInRegion(String region, String tag) {
KeyPair createNewKeyPairInRegion(String region, String group) {
checkNotNull(region, "region");
checkNotNull(tag, "tag");
logger.debug(">> creating keyPair region(%s) tag(%s)", region, tag);
checkNotNull(group, "group");
logger.debug(">> creating keyPair region(%s) group(%s)", region, group);
KeyPair keyPair = null;
while (keyPair == null) {
try {
keyPair = ec2Client.getKeyPairServices().createKeyPairInRegion(region, getNextName(region, tag));
keyPair = ec2Client.getKeyPairServices().createKeyPairInRegion(region, getNextName(region, group));
logger.debug("<< created keyPair(%s)", keyPair.getKeyName());
} catch (IllegalStateException e) {
@ -76,7 +76,7 @@ public class CreateUniqueKeyPair implements Function<RegionAndName, KeyPair> {
return keyPair;
}
private String getNextName(String region, String tag) {
return String.format("jclouds#%s#%s#%s", tag, region, randomSuffix.get());
private String getNextName(String region, String group) {
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
public Image apply(final org.jclouds.ec2.domain.Image from) {
if (from.getImageType() != ImageType.MACHINE) {
logger.trace("skipping as not a machine image(%s)", from.getId());
return null;
}
ImageBuilder builder = new ImageBuilder();

View File

@ -27,21 +27,22 @@ import java.util.Set;
import javax.annotation.Nullable;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions;
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.CreateUniqueKeyPair;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.domain.BlockDeviceMapping;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.options.RunInstancesOptions;
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
public final Map<RegionAndName, String> securityGroupMap;
@VisibleForTesting
public final CreateUniqueKeyPair createUniqueKeyPair;
public final Function<RegionAndName, KeyPair> createUniqueKeyPair;
@VisibleForTesting
public final CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded;
private final javax.inject.Provider<RunInstancesOptions> optionsProvider;
public final Function<RegionNameAndIngressRules, String> createSecurityGroupIfNeeded;
protected final Provider<RunInstancesOptions> optionsProvider;
@Inject
public CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions(Map<RegionAndName, KeyPair> credentialsMap,
@Named("SECURITY") Map<RegionAndName, String> securityGroupMap, CreateUniqueKeyPair createUniqueKeyPair,
CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded,
javax.inject.Provider<RunInstancesOptions> optionsProvider) {
@Named("SECURITY") Map<RegionAndName, String> securityGroupMap, Function<RegionAndName, KeyPair> createUniqueKeyPair,
Function<RegionNameAndIngressRules, String> createSecurityGroupIfNeeded,
Provider<RunInstancesOptions> optionsProvider) {
this.credentialsMap = credentialsMap;
this.securityGroupMap = securityGroupMap;
this.createUniqueKeyPair = createUniqueKeyPair;
@ -72,13 +73,13 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
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());
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 (keyPairName != null)
@ -100,13 +101,13 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
return instanceOptions;
}
protected void addSecurityGroups(String region, String tag, Template template, RunInstancesOptions instanceOptions) {
Set<String> groups = getSecurityGroupsForTagAndOptions(region, tag, template.getOptions());
protected void addSecurityGroups(String region, String group, Template template, RunInstancesOptions instanceOptions) {
Set<String> groups = getSecurityGroupsForTagAndOptions(region, group, template.getOptions());
instanceOptions.withSecurityGroups(groups);
}
@VisibleForTesting
public String createNewKeyPairUnlessUserSpecifiedOtherwise(String region, String tag, TemplateOptions options) {
public String createNewKeyPairUnlessUserSpecifiedOtherwise(String region, String group, TemplateOptions options) {
String keyPairName = null;
boolean shouldAutomaticallyCreateKeyPair = true;
if (options instanceof EC2TemplateOptions) {
@ -116,26 +117,37 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
.shouldAutomaticallyCreateKeyPair();
}
if (keyPairName == null && shouldAutomaticallyCreateKeyPair) {
RegionAndName regionAndName = new RegionAndName(region, tag);
keyPairName = createOrImportKeyPair(region, group, options);
}
return keyPairName;
}
// base EC2 driver currently does not support key import
protected String createOrImportKeyPair(String region, String group, TemplateOptions options) {
return createUniqueKeyPairAndPutIntoMap(region, group);
}
protected String createUniqueKeyPairAndPutIntoMap(String region, String group) {
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(region, keyPair.getKeyName()), keyPair);
keyPairName = keyPair.getKeyName();
}
credentialsMap.put(new RegionAndName(regionAndName.getRegion(), keyPairName), keyPair);
return keyPairName;
}
@VisibleForTesting
public Set<String> getSecurityGroupsForTagAndOptions(String region, @Nullable String tag, TemplateOptions options) {
Set<String> groups = Sets.newLinkedHashSet();
public Set<String> getSecurityGroupsForTagAndOptions(String region, @Nullable String group, TemplateOptions options) {
Builder<String> groups = ImmutableSet.<String> builder();
if (tag != null) {
String markerGroup = String.format("jclouds#%s#%s", tag, region);
if (group != null) {
String markerGroup = String.format("jclouds#%s#%s", group, region);
groups.add(markerGroup);
RegionNameAndIngressRules regionNameAndIngessRulesForMarkerGroup;
@ -146,16 +158,16 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
groups.addAll(EC2TemplateOptions.class.cast(options).getGroupIds());
} else {
regionNameAndIngessRulesForMarkerGroup = new RegionNameAndIngressRules(region, markerGroup, options
.getInboundPorts(), true);
regionNameAndIngessRulesForMarkerGroup = new RegionNameAndIngressRules(region, markerGroup,
options.getInboundPorts(), true);
}
if (!securityGroupMap.containsKey(regionNameAndIngessRulesForMarkerGroup)) {
securityGroupMap.put(regionNameAndIngessRulesForMarkerGroup, createSecurityGroupIfNeeded
.apply(regionNameAndIngessRulesForMarkerGroup));
securityGroupMap.put(regionNameAndIngessRulesForMarkerGroup,
createSecurityGroupIfNeeded.apply(regionNameAndIngessRulesForMarkerGroup));
}
}
return groups;
return groups.build();
}
// allows us to mock this method

View File

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

View File

@ -31,6 +31,52 @@ import javax.annotation.Nullable;
* @author Adrian Cole
*/
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 keyName;
private final String keyFingerprint;
@ -122,4 +168,7 @@ public class KeyPair implements Comparable<KeyPair> {
return true;
}
public Builder toBuilder() {
return Builder.fromKeyPair(this);
}
}

View File

@ -19,7 +19,6 @@
package org.jclouds.ec2.compute;
import static org.jclouds.compute.util.ComputeServiceUtils.getCores;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
@ -28,7 +27,6 @@ import java.util.Set;
import org.jclouds.compute.BaseComputeServiceLiveTest;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.OsFamily;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.predicates.NodePredicates;
@ -83,19 +81,6 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
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")
public void testExtendedOptionsAndLogin() throws Exception {
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.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
@ -426,7 +427,7 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
Map<RegionAndName, String> securityGroupMap = createMock(Map.class);
CreateUniqueKeyPair createUniqueKeyPair = createMock(CreateUniqueKeyPair.class);
CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded = createMock(CreateSecurityGroupIfNeeded.class);
Function<RegionNameAndIngressRules, String> createSecurityGroupIfNeeded = createMock(CreateSecurityGroupIfNeeded.class);
return new CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions(credentialsMap, securityGroupMap,
createUniqueKeyPair, createSecurityGroupIfNeeded, OPTIONS_PROVIDER);

View File

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

View File

@ -19,11 +19,6 @@
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.http.HttpResponseException;
import org.testng.annotations.Test;
@ -41,14 +36,6 @@ public class EucalyptusComputeServiceLiveTest extends EC2ComputeServiceLiveTest
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
@Test(enabled = true, dependsOnMethods = "testReboot")
public void testSuspendResume() throws Exception {

View File

@ -26,6 +26,26 @@ import org.jclouds.vcloud.terremark.domain.KeyPair;
*/
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() {
return keyPair;
}
@ -37,4 +57,8 @@ public class KeyPairCredentials extends Credentials {
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.reference.ComputeServiceConstants;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.RunScriptOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Credentials.Builder;
import org.jclouds.domain.Location;
import org.jclouds.io.Payload;
import org.jclouds.logging.Logger;
@ -132,8 +133,7 @@ public class BaseComputeService implements ComputeService {
@Inject
protected BaseComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images,
@Memoized Supplier<Set<? extends Hardware>> hardwareProfiles,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> hardwareProfiles,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
@ -484,8 +484,8 @@ public class BaseComputeService implements ComputeService {
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript,
RunScriptOptions options) throws RunScriptOnNodesException {
try {
return runScriptOnNodesMatching(filter, Statements.exec(Strings2.toStringAndClose(checkNotNull(runScript,
"runScript").getInput())), options);
return runScriptOnNodesMatching(filter,
Statements.exec(Strings2.toStringAndClose(checkNotNull(runScript, "runScript").getInput())), options);
} catch (IOException e) {
Throwables.propagate(e);
return null;
@ -552,7 +552,8 @@ public class BaseComputeService implements ComputeService {
private Iterable<? extends RunScriptOnNode> transformNodesIntoInitializedScriptRunners(
Iterable<? extends NodeMetadata> nodes, Statement script, RunScriptOptions options,
Map<NodeMetadata, Exception> badNodes) {
return filter(transformParallel(nodes, new TransformNodesIntoInitializedScriptRunners(script, options, badNodes),
return filter(
transformParallel(nodes, new TransformNodesIntoInitializedScriptRunners(script, options, badNodes),
executor, null, logger, "initialize script runners"), notNull());
}
@ -581,8 +582,14 @@ public class BaseComputeService implements ComputeService {
@Override
public Future<RunScriptOnNode> apply(NodeMetadata node) {
checkNotNull(node, "node");
if (options.getOverrideCredentials() != null) {
node = NodeMetadataBuilder.fromNodeMetadata(node).credentials(options.getOverrideCredentials()).build();
if (options.getOverridingCredentials() != null) {
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));
}

View File

@ -34,6 +34,26 @@ import com.google.common.collect.Lists;
*/
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 credential;
@ -57,6 +77,10 @@ public class Credentials {
return new Credentials(identity, credential);
}
public Builder<? extends Credentials> toBuilder() {
return new Builder<Credentials>().identity(identity).credential(credential);
}
@Override
public int hashCode() {
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 java.util.Map;
import java.util.Set;
import java.util.Map.Entry;
import java.util.Set;
import java.util.concurrent.ExecutorService;
import javax.inject.Inject;
@ -43,13 +43,13 @@ import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants.Timeouts;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.DestroyNodeStrategy;
import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
import org.jclouds.compute.strategy.InitializeRunScriptOnNodeOrPlaceInBadMap;
import org.jclouds.compute.strategy.ListNodesStrategy;
import org.jclouds.compute.strategy.RebootNodeStrategy;
import org.jclouds.compute.strategy.ResumeNodeStrategy;
import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
import org.jclouds.compute.strategy.SuspendNodeStrategy;
import org.jclouds.domain.Credentials;
import org.jclouds.domain.Location;
@ -90,29 +90,32 @@ public class AWSEC2ComputeService extends EC2ComputeService {
@Named("PLACEMENT") Map<RegionAndName, String> placementGroupMap,
@Named("DELETED") Predicate<PlacementGroup> placementGroupDeleted) {
super(context, credentialStore, images, sizes, locations, listNodesStrategy, getNodeMetadataStrategy,
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy,
stopNodeStrategy, templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated,
nodeSuspended, initScriptRunnerFactory, timeouts, executor, ec2Client, credentialsMap, securityGroupMap);
runNodesAndAddToSetStrategy, rebootNodeStrategy, destroyNodeStrategy, startNodeStrategy, stopNodeStrategy,
templateBuilderProvider, templateOptionsProvider, nodeRunning, nodeTerminated, nodeSuspended,
initScriptRunnerFactory, timeouts, executor, ec2Client, credentialsMap, securityGroupMap);
this.ec2Client = ec2Client;
this.placementGroupMap = placementGroupMap;
this.placementGroupDeleted = placementGroupDeleted;
}
@VisibleForTesting
void deletePlacementGroup(String region, String tag) {
Preconditions2.checkNotEmpty(tag, "tag");
String group = String.format("jclouds#%s#%s", tag, region);
void deletePlacementGroup(String region, String group) {
Preconditions2.checkNotEmpty(group, "group");
// 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 {
if (ec2Client.getPlacementGroupServices().describePlacementGroupsInRegion(region, group).size() > 0) {
logger.debug(">> deleting placementGroup(%s)", group);
if (ec2Client.getPlacementGroupServices().describePlacementGroupsInRegion(region, placementGroup).size() > 0) {
logger.debug(">> deleting placementGroup(%s)", placementGroup);
try {
ec2Client.getPlacementGroupServices().deletePlacementGroupInRegion(region, group);
checkState(placementGroupDeleted.apply(new PlacementGroup(region, group, "cluster", State.PENDING)),
String.format("placementGroup region(%s) name(%s) failed to delete", region, group));
placementGroupMap.remove(new RegionAndName(region, group));
logger.debug("<< deleted placementGroup(%s)", group);
ec2Client.getPlacementGroupServices().deletePlacementGroupInRegion(region, placementGroup);
checkState(
placementGroupDeleted.apply(new PlacementGroup(region, placementGroup, "cluster", State.PENDING)),
String.format("placementGroup region(%s) name(%s) failed to delete", region, placementGroup));
placementGroupMap.remove(new RegionAndName(region, placementGroup));
logger.debug("<< deleted placementGroup(%s)", placementGroup);
} catch (IllegalStateException e) {
logger.debug("<< inUse placementGroup(%s)", group);
logger.debug("<< inUse placementGroup(%s)", placementGroup);
}
}
} catch (UnsupportedOperationException e) {
@ -120,6 +123,7 @@ public class AWSEC2ComputeService extends EC2ComputeService {
}
}
@Override
protected void cleanUpIncidentalResources(Entry<String, String> regionTag) {
super.cleanUpIncidentalResources(regionTag);
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.AWSEC2TemplateOptions;
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.PlacementGroupDeleted;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.ComputeServiceContext;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.TemplateBuilder;
import org.jclouds.compute.internal.ComputeServiceContextImpl;
@ -45,10 +48,14 @@ import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Credentials;
import org.jclouds.ec2.compute.config.EC2ComputeServiceDependenciesModule;
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.CreateUniqueKeyPair;
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.internal.EC2TemplateBuilderImpl;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.domain.RunningInstance;
import org.jclouds.predicates.RetryablePredicate;
import org.jclouds.rest.RestContext;
@ -75,6 +82,14 @@ public class AWSEC2ComputeServiceDependenciesModule extends EC2ComputeServiceDep
}).to(RunningInstanceToNodeMetadata.class);
bind(new TypeLiteral<Function<RunningInstance, Credentials>>() {
}).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>() {
}).to(new TypeLiteral<ComputeServiceContextImpl<AWSEC2Client, AWSEC2AsyncClient>>() {
}).in(Scopes.SINGLETON);

View File

@ -100,7 +100,7 @@ public class AWSEC2ReviseParsedImage implements ReviseParsedImage {
} catch (IllegalArgumentException e) {
logger.debug("<< didn't match os(%s)", from.getImageLocation());
} 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;
import static com.google.common.base.Predicates.and;
import static com.google.common.base.Predicates.or;
import java.util.Map;
import javax.annotation.Resource;
import javax.inject.Inject;
import javax.inject.Named;
import javax.inject.Provider;
import javax.inject.Singleton;
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.options.AWSRunInstancesOptions;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.compute.reference.ComputeServiceConstants;
import org.jclouds.ec2.compute.domain.RegionAndName;
import org.jclouds.ec2.compute.functions.CreateSecurityGroupIfNeeded;
import org.jclouds.ec2.compute.functions.CreateUniqueKeyPair;
import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
import org.jclouds.ec2.compute.strategy.CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
import org.jclouds.ec2.domain.KeyPair;
import org.jclouds.ec2.options.RunInstancesOptions;
import org.jclouds.logging.Logger;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Function;
import com.google.common.base.Predicate;
/**
*
@ -47,30 +56,36 @@ import com.google.common.annotations.VisibleForTesting;
@Singleton
public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions extends
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
@Resource
@Named(ComputeServiceConstants.COMPUTE_LOGGER)
protected Logger logger = Logger.NULL;
@VisibleForTesting
final Map<RegionAndName, String> placementGroupMap;
@VisibleForTesting
final CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded;
@VisibleForTesting
final Function<RegionNameAndPublicKeyMaterial, KeyPair> importExistingKeyPair;
@Inject
public CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions(
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap,
@Named("PLACEMENT") Map<RegionAndName, String> placementGroupMap, CreateUniqueKeyPair createUniqueKeyPair,
CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded,
javax.inject.Provider<RunInstancesOptions> optionsProvider,
CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded) {
@Named("PLACEMENT") Map<RegionAndName, String> placementGroupMap,
Function<RegionAndName, KeyPair> createUniqueKeyPair,
Function<RegionNameAndIngressRules, String> createSecurityGroupIfNeeded,
Provider<RunInstancesOptions> optionsProvider, CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded,
Function<RegionNameAndPublicKeyMaterial, KeyPair> importExistingKeyPair) {
super(credentialsMap, securityGroupMap, createUniqueKeyPair, createSecurityGroupIfNeeded, optionsProvider);
this.placementGroupMap = placementGroupMap;
this.createPlacementGroupIfNeeded = createPlacementGroupIfNeeded;
this.importExistingKeyPair = importExistingKeyPair;
}
public AWSRunInstancesOptions execute(String region, String tag, Template template) {
AWSRunInstancesOptions instanceOptions = AWSRunInstancesOptions.class.cast(super.execute(region, tag, template));
public AWSRunInstancesOptions execute(String region, String group, Template template) {
AWSRunInstancesOptions instanceOptions = AWSRunInstancesOptions.class
.cast(super.execute(region, group, template));
String placementGroupName = template.getHardware().getId().startsWith("cc") ? createNewPlacementGroupUnlessUserSpecifiedOtherwise(
region, tag, template.getOptions())
: null;
region, group, template.getOptions()) : null;
if (placementGroupName != null)
instanceOptions.inPlacementGroup(placementGroupName);
@ -82,7 +97,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions
}
@VisibleForTesting
String createNewPlacementGroupUnlessUserSpecifiedOtherwise(String region, String tag, TemplateOptions options) {
String createNewPlacementGroupUnlessUserSpecifiedOtherwise(String region, String group, TemplateOptions options) {
String placementGroupName = null;
boolean shouldAutomaticallyCreatePlacementGroup = true;
if (options instanceof EC2TemplateOptions) {
@ -92,7 +107,9 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions
.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);
if (!placementGroupMap.containsKey(regionAndName)) {
placementGroupMap.put(regionAndName, createPlacementGroupIfNeeded.apply(regionAndName));
@ -102,12 +119,60 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions
}
@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();
if (subnetId != null) {
AWSRunInstancesOptions.class.cast(instanceOptions).withSubnetId(subnetId);
} 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

@ -117,8 +117,8 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
// }
// 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 + "#"
+ instance.getRegion(), group));
assertEquals(Sets.newTreeSet(instance.getGroupIds()),
ImmutableSortedSet.<String> of("jclouds#" + group + "#" + instance.getRegion(), group));
// make sure our dummy group has no rules
SecurityGroup secgroup = Iterables.getOnlyElement(securityGroupClient.describeSecurityGroupsInRegion(null,
@ -126,8 +126,8 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
assert secgroup.getIpPermissions().size() == 0 : secgroup;
// try to run a script with the original keyPair
runScriptWithCreds(group, first.getOperatingSystem(), new Credentials(first.getCredentials().identity, result
.getKeyMaterial()));
runScriptWithCreds(group, first.getOperatingSystem(),
new Credentials(first.getCredentials().identity, result.getKeyMaterial()));
} finally {
client.destroyNodesMatching(NodePredicates.inGroup(group));
@ -140,19 +140,15 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
}
}
@Test(enabled = true, dependsOnMethods = "testCompareSizes")
public void testExtendedOptionsWithSubnetId() throws Exception {
public void testSubnetId() throws Exception {
String subnetId = System.getProperty("test.subnetId");
if (subnetId == null) {
// Skip test and 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())
.getInstanceServices();
@ -161,20 +157,11 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
TemplateOptions options = client.templateOptions();
// options.as(AWSEC2TemplateOptions.class).securityGroups(group);
options.as(AWSEC2TemplateOptions.class).keyPair(group);
options.as(AWSEC2TemplateOptions.class).subnetId(subnetId);
String startedId = null;
String nodeId = null;
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);
@ -192,11 +179,6 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
} finally {
if (nodeId != null)
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.ec2.compute.AWSEC2TemplateOptions;
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.options.AWSRunInstancesOptions;
import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Template;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.Credentials;
import org.jclouds.ec2.compute.EC2TemplateBuilderTest;
import org.jclouds.ec2.compute.domain.EC2HardwareBuilder;
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.CreateUniqueKeyPair;
import org.jclouds.ec2.compute.strategy.CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions;
import org.jclouds.ec2.domain.BlockDeviceMapping;
import org.jclouds.ec2.domain.KeyPair;
@ -52,6 +52,7 @@ import org.jclouds.ec2.options.RunInstancesOptions;
import org.jclouds.encryption.internal.Base64;
import org.testng.annotations.Test;
import com.google.common.base.Function;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.ImmutableSet;
@ -72,7 +73,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testExecuteWithDefaultOptionsEC2() throws SecurityException, NoSuchMethodException {
// setup constants
String region = Region.AP_SOUTHEAST_1;
String tag = "tag";
String group = "group";
Hardware size = EC2HardwareBuilder.m1_small().build();
String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
String generatedGroup = "group";
@ -80,7 +81,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock(
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class, new Method[] {
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class,
new Method[] {
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getOptionsProvider"),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
@ -89,9 +91,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getSecurityGroupsForTagAndOptions", String.class, String.class,
TemplateOptions.class) });
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"getSecurityGroupsForTagAndOptions", String.class, String.class, TemplateOptions.class) });
AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class);
Template template = createMock(Template.class);
@ -101,9 +102,9 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(template.getHardware()).andReturn(size).atLeastOnce();
expect(template.getOptions()).andReturn(options).atLeastOnce();
expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce();
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn(
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
systemGeneratedKeyPairName);
expect(strategy.getSecurityGroupsForTagAndOptions(region, tag, options)).andReturn(generatedGroups);
expect(strategy.getSecurityGroupsForTagAndOptions(region, group, options)).andReturn(generatedGroups);
expect(options.getSubnetId()).andReturn(null);
expect(options.getUserData()).andReturn(null);
expect(options.isMonitoringEnabled()).andReturn(false);
@ -114,11 +115,12 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replay(strategy);
// run
RunInstancesOptions customize = strategy.execute(region, tag, template);
RunInstancesOptions customize = strategy.execute(region, group, template);
assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildFormParameters().entries(), ImmutableMultimap.<String, String> of("InstanceType",
size.getProviderId(), "SecurityGroup.1", generatedGroup, "KeyName", systemGeneratedKeyPairName)
.entries());
assertEquals(
customize.buildFormParameters().entries(),
ImmutableMultimap.<String, String> of("InstanceType", size.getProviderId(), "SecurityGroup.1",
generatedGroup, "KeyName", systemGeneratedKeyPairName).entries());
assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildStringPayload(), null);
@ -132,7 +134,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testExecuteForCCAutomatic() throws SecurityException, NoSuchMethodException {
// setup constants
String region = Region.US_EAST_1;
String tag = "tag";
String group = "group";
Hardware size = EC2TemplateBuilderTest.CC1_4XLARGE;
String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
String generatedGroup = "group";
@ -140,7 +142,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock(
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class, new Method[] {
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class,
new Method[] {
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getOptionsProvider"),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
@ -149,9 +152,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getSecurityGroupsForTagAndOptions", String.class, String.class,
TemplateOptions.class) });
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"getSecurityGroupsForTagAndOptions", String.class, String.class, TemplateOptions.class) });
AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class);
Template template = createMock(Template.class);
@ -161,11 +163,11 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(template.getHardware()).andReturn(size).atLeastOnce();
expect(template.getOptions()).andReturn(options).atLeastOnce();
expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce();
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn(
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
systemGeneratedKeyPairName);
expect(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn(
expect(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
generatedGroup);
expect(strategy.getSecurityGroupsForTagAndOptions(region, tag, options)).andReturn(generatedGroups);
expect(strategy.getSecurityGroupsForTagAndOptions(region, group, options)).andReturn(generatedGroups);
expect(options.getSubnetId()).andReturn(null);
expect(options.getUserData()).andReturn(null);
expect(options.isMonitoringEnabled()).andReturn(false);
@ -176,11 +178,13 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replay(strategy);
// run
RunInstancesOptions customize = strategy.execute(region, tag, template);
RunInstancesOptions customize = strategy.execute(region, group, template);
assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildFormParameters().entries(), ImmutableMultimap.<String, String> of("InstanceType",
size.getProviderId(), "SecurityGroup.1", generatedGroup, "KeyName", systemGeneratedKeyPairName,
"Placement.GroupName", generatedGroup).entries());
assertEquals(
customize.buildFormParameters().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.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildStringPayload(), null);
@ -194,7 +198,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testExecuteForCCUserSpecified() throws SecurityException, NoSuchMethodException {
// setup constants
String region = Region.US_EAST_1;
String tag = "tag";
String group = "group";
Hardware size = EC2TemplateBuilderTest.CC1_4XLARGE;
String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
String generatedGroup = "group";
@ -202,7 +206,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock(
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class, new Method[] {
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class,
new Method[] {
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getOptionsProvider"),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
@ -211,9 +216,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getSecurityGroupsForTagAndOptions", String.class, String.class,
TemplateOptions.class) });
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"getSecurityGroupsForTagAndOptions", String.class, String.class, TemplateOptions.class) });
AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class);
Template template = createMock(Template.class);
@ -223,11 +227,11 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(template.getHardware()).andReturn(size).atLeastOnce();
expect(template.getOptions()).andReturn(options).atLeastOnce();
expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce();
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn(
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
systemGeneratedKeyPairName);
expect(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn(
expect(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
generatedGroup);
expect(strategy.getSecurityGroupsForTagAndOptions(region, tag, options)).andReturn(generatedGroups);
expect(strategy.getSecurityGroupsForTagAndOptions(region, group, options)).andReturn(generatedGroups);
expect(options.getSubnetId()).andReturn(null);
expect(options.getUserData()).andReturn(null);
expect(options.isMonitoringEnabled()).andReturn(false);
@ -238,11 +242,13 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replay(strategy);
// run
RunInstancesOptions customize = strategy.execute(region, tag, template);
RunInstancesOptions customize = strategy.execute(region, group, template);
assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildFormParameters().entries(), ImmutableMultimap.<String, String> of("InstanceType",
size.getProviderId(), "SecurityGroup.1", generatedGroup, "KeyName", systemGeneratedKeyPairName,
"Placement.GroupName", generatedGroup).entries());
assertEquals(
customize.buildFormParameters().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.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildStringPayload(), null);
@ -256,13 +262,14 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testExecuteWithSubnet() throws SecurityException, NoSuchMethodException {
// setup constants
String region = Region.AP_SOUTHEAST_1;
String tag = "tag";
String group = "group";
Hardware size = EC2HardwareBuilder.m1_small().build();
String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
// create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock(
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class, new Method[] {
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class,
new Method[] {
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getOptionsProvider"),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
@ -271,9 +278,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getSecurityGroupsForTagAndOptions", String.class, String.class,
TemplateOptions.class) });
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"getSecurityGroupsForTagAndOptions", String.class, String.class, TemplateOptions.class) });
AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class);
Template template = createMock(Template.class);
@ -283,7 +289,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(template.getHardware()).andReturn(size).atLeastOnce();
expect(template.getOptions()).andReturn(options).atLeastOnce();
expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce();
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn(
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
systemGeneratedKeyPairName);
expect(options.getSubnetId()).andReturn("1");
expect(options.getUserData()).andReturn(null);
@ -295,10 +301,12 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replay(strategy);
// run
RunInstancesOptions customize = strategy.execute(region, tag, template);
RunInstancesOptions customize = strategy.execute(region, group, template);
assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildFormParameters().entries(), ImmutableMultimap.<String, String> of("InstanceType",
size.getProviderId(), "SubnetId", "1", "KeyName", systemGeneratedKeyPairName).entries());
assertEquals(
customize.buildFormParameters().entries(),
ImmutableMultimap.<String, String> of("InstanceType", size.getProviderId(), "SubnetId", "1", "KeyName",
systemGeneratedKeyPairName).entries());
assertEquals(customize.buildMatrixParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildStringPayload(), null);
@ -312,7 +320,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testExecuteWithUserData() throws SecurityException, NoSuchMethodException {
// setup constants
String region = Region.AP_SOUTHEAST_1;
String tag = "tag";
String group = "group";
Hardware size = EC2HardwareBuilder.m1_small().build();
String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
String generatedGroup = "group";
@ -320,7 +328,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock(
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class, new Method[] {
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class,
new Method[] {
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getOptionsProvider"),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
@ -329,9 +338,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getSecurityGroupsForTagAndOptions", String.class, String.class,
TemplateOptions.class) });
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"getSecurityGroupsForTagAndOptions", String.class, String.class, TemplateOptions.class) });
AWSEC2TemplateOptions options = createMock(AWSEC2TemplateOptions.class);
Template template = createMock(Template.class);
@ -341,9 +349,9 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(template.getHardware()).andReturn(size).atLeastOnce();
expect(template.getOptions()).andReturn(options).atLeastOnce();
expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce();
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn(
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
systemGeneratedKeyPairName);
expect(strategy.getSecurityGroupsForTagAndOptions(region, tag, options)).andReturn(generatedGroups);
expect(strategy.getSecurityGroupsForTagAndOptions(region, group, options)).andReturn(generatedGroups);
expect(options.getSubnetId()).andReturn(null);
expect(options.getUserData()).andReturn("hello".getBytes());
expect(options.isMonitoringEnabled()).andReturn(false);
@ -354,11 +362,12 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replay(strategy);
// run
RunInstancesOptions customize = strategy.execute(region, tag, template);
RunInstancesOptions customize = strategy.execute(region, group, template);
assertEquals(customize.buildQueryParameters(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildFormParameters().entries(), ImmutableMultimap.<String, String> of("InstanceType",
size.getProviderId(), "SecurityGroup.1", "group", "KeyName", systemGeneratedKeyPairName, "UserData",
Base64.encodeBytes("hello".getBytes())).entries());
assertEquals(
customize.buildFormParameters().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.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
assertEquals(customize.buildStringPayload(), null);
@ -372,7 +381,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_reusesKeyWhenToldTo() {
// setup constants
String region = Region.AP_SOUTHEAST_1;
String tag = "tag";
String group = "group";
String userSuppliedKeyPair = "myKeyPair";
// create mocks
@ -389,7 +398,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy);
// run
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options), userSuppliedKeyPair);
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options), userSuppliedKeyPair);
// verify mocks
verify(options);
@ -397,10 +406,86 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
verifyStrategy(strategy);
}
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_createsNewKeyPairAndReturnsItsNameByDefault() {
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_importsKeyPairAndUnsetsTemplateInstructionWhenPublicKeySuppliedAndAddsCredentialToMapWhenOverridingCredsAreSet() {
// setup constants
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;
boolean shouldAutomaticallyCreateKeyPair = true;
String systemGeneratedKeyPairName = "systemGeneratedKeyPair";
@ -413,7 +498,9 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// setup expectations
expect(options.getKeyPair()).andReturn(userSuppliedKeyPair);
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(strategy.credentialsMap.put(new RegionAndName(region, systemGeneratedKeyPairName), keyPair)).andReturn(
null);
@ -424,7 +511,40 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy);
// run
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options),
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options),
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
@ -436,7 +556,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testCreateNewKeyPairUnlessUserSpecifiedOtherwise_doesntCreateAKeyPairAndReturnsNullWhenToldNotTo() {
// setup constants
String region = Region.AP_SOUTHEAST_1;
String tag = "tag";
String group = "group";
String userSuppliedKeyPair = null;
boolean shouldAutomaticallyCreateKeyPair = false; // here's the important
// part!
@ -456,7 +576,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy);
// run
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options), null);
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options), null);
// verify mocks
verify(options);
@ -467,8 +587,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testGetSecurityGroupsForTagAndOptions_createsNewGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesntExist() {
// setup constants
String region = Region.AP_SOUTHEAST_1;
String tag = "tag";
String generatedMarkerGroup = "jclouds#tag#" + Region.AP_SOUTHEAST_1;
String group = "group";
String generatedMarkerGroup = "jclouds#group#" + Region.AP_SOUTHEAST_1;
Set<String> groupIds = ImmutableSet.<String> of();
int[] ports = new int[] {};
boolean shouldAuthorizeSelf = true;
@ -493,7 +613,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy);
// run
assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, tag, options), returnVal);
assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, group, options), returnVal);
// verify mocks
verify(options);
@ -503,8 +623,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testGetSecurityGroupsForTagAndOptions_createsNewGroupByDefaultWhenPortsAreSpecifiedWhenDoesntExist() {
// setup constants
String region = Region.AP_SOUTHEAST_1;
String tag = "tag";
String generatedMarkerGroup = "jclouds#tag#" + Region.AP_SOUTHEAST_1;
String group = "group";
String generatedMarkerGroup = "jclouds#group#" + Region.AP_SOUTHEAST_1;
Set<String> groupIds = ImmutableSet.<String> of();
int[] ports = new int[] { 22, 80 };
boolean shouldAuthorizeSelf = true;
@ -529,7 +649,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy);
// run
assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, tag, options), returnVal);
assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, group, options), returnVal);
// verify mocks
verify(options);
@ -539,8 +659,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testGetSecurityGroupsForTagAndOptions_reusesGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesExist() {
// setup constants
String region = Region.AP_SOUTHEAST_1;
String tag = "tag";
String generatedMarkerGroup = "jclouds#tag#" + Region.AP_SOUTHEAST_1;
String group = "group";
String generatedMarkerGroup = "jclouds#group#" + Region.AP_SOUTHEAST_1;
Set<String> groupIds = ImmutableSet.<String> of();
int[] ports = new int[] {};
boolean shouldAuthorizeSelf = true;
@ -563,7 +683,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy);
// run
assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, tag, options), returnVal);
assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, group, options), returnVal);
// verify mocks
verify(options);
@ -573,8 +693,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testGetSecurityGroupsForTagAndOptions_reusesGroupByDefaultWhenNoPortsAreSpecifiedWhenDoesExistAndAcceptsUserSuppliedGroups() {
// setup constants
String region = Region.AP_SOUTHEAST_1;
String tag = "tag";
String generatedMarkerGroup = "jclouds#tag#" + Region.AP_SOUTHEAST_1;
String group = "group";
String generatedMarkerGroup = "jclouds#group#" + Region.AP_SOUTHEAST_1;
Set<String> groupIds = ImmutableSet.<String> of("group1", "group2");
int[] ports = new int[] {};
boolean shouldAuthorizeSelf = true;
@ -601,7 +721,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy);
// run
assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, tag, options), returnVal);
assertEquals(strategy.getSecurityGroupsForTagAndOptions(region, group, options), returnVal);
// verify mocks
verify(options);
@ -611,7 +731,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testCreateNewPlacementGroupUnlessUserSpecifiedOtherwise_reusesKeyWhenToldTo() {
// setup constants
String region = Region.AP_SOUTHEAST_1;
String tag = "tag";
String group = "group";
String userSuppliedPlacementGroup = "myPlacementGroup";
// create mocks
@ -628,7 +748,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy);
// run
assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, tag, options),
assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, group, options),
userSuppliedPlacementGroup);
// verify mocks
@ -640,10 +760,10 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testCreateNewPlacementGroupUnlessUserSpecifiedOtherwise_createsNewPlacementGroupAndReturnsItsNameByDefault() {
// setup constants
String region = Region.AP_SOUTHEAST_1;
String tag = "tag";
String group = "group";
String userSuppliedPlacementGroup = null;
boolean shouldAutomaticallyCreatePlacementGroup = true;
String generatedMarkerGroup = "jclouds#tag#" + Region.AP_SOUTHEAST_1;
String generatedMarkerGroup = "jclouds#group#" + Region.AP_SOUTHEAST_1;
// create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = setupStrategy();
@ -663,7 +783,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy);
// run
assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, tag, options),
assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, group, options),
generatedMarkerGroup);
// verify mocks
@ -674,7 +794,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
public void testCreateNewPlacementGroupUnlessUserSpecifiedOtherwise_doesntCreateAPlacementGroupAndReturnsNullWhenToldNotTo() {
// setup constants
String region = Region.AP_SOUTHEAST_1;
String tag = "tag";
String group = "group";
String userSuppliedPlacementGroup = null;
boolean shouldAutomaticallyCreatePlacementGroup = false; // here's the important
// part!
@ -694,7 +814,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy);
// run
assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, tag, options), null);
assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, group, options), null);
// verify mocks
verify(options);
@ -707,6 +827,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
verify(strategy.securityGroupMap);
verify(strategy.placementGroupMap);
verify(strategy.createUniqueKeyPair);
verify(strategy.importExistingKeyPair);
verify(strategy.createSecurityGroupIfNeeded);
verify(strategy.createPlacementGroupIfNeeded);
}
@ -716,13 +837,14 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
Map<RegionAndName, KeyPair> credentialsMap = createMock(Map.class);
Map<RegionAndName, String> securityGroupMap = createMock(Map.class);
Map<RegionAndName, String> placementGroupMap = createMock(Map.class);
CreateUniqueKeyPair createUniqueKeyPair = createMock(CreateUniqueKeyPair.class);
CreateSecurityGroupIfNeeded createSecurityGroupIfNeeded = createMock(CreateSecurityGroupIfNeeded.class);
Function<RegionAndName, KeyPair> createOrGetKeyPair = createMock(Function.class);
Function<RegionNameAndIngressRules, String> createSecurityGroupIfNeeded = createMock(Function.class);
Function<RegionNameAndPublicKeyMaterial, KeyPair> importExistingKeyPair = createMock(Function.class);
CreatePlacementGroupIfNeeded createPlacementGroupIfNeeded = createMock(CreatePlacementGroupIfNeeded.class);
return new CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions(credentialsMap, securityGroupMap,
placementGroupMap, createUniqueKeyPair, createSecurityGroupIfNeeded, OPTIONS_PROVIDER,
createPlacementGroupIfNeeded);
placementGroupMap, createOrGetKeyPair, createSecurityGroupIfNeeded, OPTIONS_PROVIDER,
createPlacementGroupIfNeeded, importExistingKeyPair);
}
private void replayStrategy(CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy) {
@ -730,6 +852,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replay(strategy.securityGroupMap);
replay(strategy.placementGroupMap);
replay(strategy.createUniqueKeyPair);
replay(strategy.importExistingKeyPair);
replay(strategy.createSecurityGroupIfNeeded);
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;
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.assertNotNull;
@ -34,17 +41,26 @@ import org.jclouds.Constants;
import org.jclouds.aws.domain.Region;
import org.jclouds.aws.ec2.AWSEC2AsyncClient;
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.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.RunningInstance;
import org.jclouds.ec2.services.InstanceClient;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
import org.jclouds.rest.RestContext;
import org.jclouds.ssh.jsch.config.JschSshClientModule;
import org.testng.annotations.AfterTest;
import org.testng.annotations.BeforeGroups;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Sets;
import com.google.inject.Module;
/**
@ -63,6 +79,7 @@ public class AWSKeyPairClientLiveTest {
protected String credential;
protected String endpoint;
protected String apiversion;
private ComputeServiceContext computeContext;
protected void setupCredentials() {
identity = checkNotNull(System.getProperty("test." + provider + ".identity"), "test." + provider + ".identity");
@ -89,20 +106,67 @@ public class AWSKeyPairClientLiveTest {
public void setupClient() {
setupCredentials();
Properties overrides = setupProperties();
context = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule()), overrides).getProviderSpecificContext();
computeContext = new ComputeServiceContextFactory().createContext(provider,
ImmutableSet.<Module> of(new Log4JLoggingModule(), new JschSshClientModule()), overrides);
context = computeContext.getProviderSpecificContext();
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
void testDescribeAWSKeyPairs() {
for (String region : Region.DEFAULT_REGIONS) {
SortedSet<KeyPair> allResults = Sets.newTreeSet(client.describeKeyPairsInRegion(region));
SortedSet<KeyPair> allResults = newTreeSet(client.describeKeyPairsInRegion(region));
assertNotNull(allResults);
if (allResults.size() >= 1) {
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);
KeyPair compare = result.last();
assertEquals(compare, pair);
@ -163,7 +227,7 @@ public class AWSKeyPairClientLiveTest {
assertNotNull(keyPair.getKeyFingerprint());
assertEquals(keyPair.getKeyName(), keyName);
Set<KeyPair> twoResults = Sets.newLinkedHashSet(client.describeKeyPairsInRegion(null, keyName));
Set<KeyPair> twoResults = client.describeKeyPairsInRegion(null, keyName);
assertNotNull(twoResults);
assertEquals(twoResults.size(), 1);
KeyPair listPair = twoResults.iterator().next();
@ -171,6 +235,11 @@ public class AWSKeyPairClientLiveTest {
assertEquals(listPair.getKeyFingerprint(), keyPair.getKeyFingerprint());
}
protected RunningInstance getInstance(InstanceClient instanceClient, String id) {
RunningInstance instance = getOnlyElement(getOnlyElement(instanceClient.describeInstancesInRegion(null, id)));
return instance;
}
@AfterTest
public void shutdown() {
context.close();

View File

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