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
@ -73,31 +81,30 @@ public class EC2ComputeService extends BaseComputeService {
@Inject
protected EC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, EC2Client ec2Client,
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap) {
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, Timeouts timeouts,
@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,16 +122,54 @@ 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]+"))) {
logger.debug(">> deleting keyPair(%s)", keyPair.getKeyName());
ec2Client.getKeyPairServices().deleteKeyPairInRegion(region, keyPair.getKeyName());
// TODO: test this clear happens
credentialsMap.remove(new RegionAndName(region, keyPair.getKeyName()));
logger.debug("<< deleted keyPair(%s)", keyPair.getKeyName());
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
credentialsMap.remove(new RegionAndName(region, keyPair.getKeyName()));
logger.debug("<< deleted keyPair(%s)", keyPair.getKeyName());
}
}
}
}
protected ImmutableSet<String> extractIdsFromInstances(Iterable<? extends RunningInstance> deadOnes) {
return ImmutableSet.copyOf(transform(deadOnes, new Function<RunningInstance, String>() {
@Override
public String apply(RunningInstance input) {
return input.getId();
}
}));
}
protected Predicate<RunningInstance> usingKeyPairAndNotDead(final KeyPair keyPair) {
return new Predicate<RunningInstance>() {
@Override
public boolean apply(RunningInstance input) {
switch (input.getInstanceState()) {
case TERMINATED:
case SHUTTING_DOWN:
return false;
}
return keyPair.getKeyName().equals(input.getKeyName());
}
};
}
/**
* like {@link BaseComputeService#destroyNodesMatching} except that this will clean implicit
* keypairs and security groups.
@ -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,11 +77,11 @@ 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)
.put(InstanceState.STOPPED, NodeState.SUSPENDED).put(InstanceState.UNRECOGNIZED, NodeState.UNRECOGNIZED)
.build();
.<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();
@Singleton
@Provides
@ -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)
@ -90,72 +91,83 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
instanceOptions.withUserData(userData);
Set<BlockDeviceMapping> blockDeviceMappings = EC2TemplateOptions.class.cast(template.getOptions())
.getBlockDeviceMappings();
.getBlockDeviceMappings();
if (blockDeviceMappings.size() > 0) {
checkState("ebs".equals(template.getImage().getUserMetadata().get("rootDeviceType")),
"BlockDeviceMapping only available on ebs boot");
"BlockDeviceMapping only available on ebs boot");
instanceOptions.withBlockDeviceMappings(blockDeviceMappings);
}
}
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) {
keyPairName = EC2TemplateOptions.class.cast(options).getKeyPair();
if (keyPairName == null)
shouldAutomaticallyCreateKeyPair = EC2TemplateOptions.class.cast(options)
.shouldAutomaticallyCreateKeyPair();
.shouldAutomaticallyCreateKeyPair();
}
if (keyPairName == null && shouldAutomaticallyCreateKeyPair) {
RegionAndName regionAndName = new RegionAndName(region, tag);
KeyPair keyPair = createUniqueKeyPair.apply(regionAndName);
// get or create incidental resources
// TODO race condition. we were using MapMaker, but it doesn't seem to
// refresh properly
// when
// another thread
// deletes a key
credentialsMap.put(new RegionAndName(region, keyPair.getKeyName()), keyPair);
keyPairName = keyPair.getKeyName();
keyPairName = createOrImportKeyPair(region, group, options);
}
return keyPairName;
}
@VisibleForTesting
public Set<String> getSecurityGroupsForTagAndOptions(String region, @Nullable String tag, TemplateOptions options) {
Set<String> groups = Sets.newLinkedHashSet();
// base EC2 driver currently does not support key import
protected String createOrImportKeyPair(String region, String group, TemplateOptions options) {
return createUniqueKeyPairAndPutIntoMap(region, group);
}
if (tag != null) {
String markerGroup = String.format("jclouds#%s#%s", tag, region);
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(regionAndName.getRegion(), keyPairName), keyPair);
return keyPairName;
}
@VisibleForTesting
public Set<String> getSecurityGroupsForTagAndOptions(String region, @Nullable String group, TemplateOptions options) {
Builder<String> groups = ImmutableSet.<String> builder();
if (group != null) {
String markerGroup = String.format("jclouds#%s#%s", group, region);
groups.add(markerGroup);
RegionNameAndIngressRules regionNameAndIngessRulesForMarkerGroup;
if (options instanceof EC2TemplateOptions && EC2TemplateOptions.class.cast(options).getGroupIds().size() > 0) {
regionNameAndIngessRulesForMarkerGroup = new RegionNameAndIngressRules(region, markerGroup, new int[] {},
false);
false);
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,
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
@Named("PRESENT") Predicate<RunningInstance> instancePresent,
Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
Function<RunningInstance, Credentials> instanceToCredentials, Map<String, Credentials> credentialStore,
ComputeUtils utils) {
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;
@ -97,10 +102,11 @@ 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);
Map<NodeMetadata, Exception> badNodes, Multimap<NodeMetadata, CustomizationResponse> customizationResponses) {
// 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) {
@ -131,12 +137,12 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
// TODO write test for this
@VisibleForTesting
Iterable<? extends RunningInstance> createKeyPairAndSecurityGroupsAsNeededThenRunInstances(String group, int count,
Template template) {
Template template) {
String region = AWSUtils.getRegionFromLocationOrNull(template.getLocation());
String zone = getZoneFromLocationOrNull(template.getLocation());
RunInstancesOptions instanceOptions = createKeyPairAndSecurityGroupsAsNeededAndReturncustomize.execute(region,
group, template);
group, template);
int countStarted = 0;
int tries = 0;
@ -145,10 +151,12 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
while (countStarted < count && tries++ < count) {
if (logger.isDebugEnabled())
logger.debug(">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", count - countStarted, region,
zone, template.getImage().getProviderId(), instanceOptions.buildFormParameters());
zone, template.getImage().getProviderId(), instanceOptions.buildFormParameters());
started = Iterables.concat(started, client.getInstanceServices().runInstancesInRegion(region, zone,
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,10 +427,10 @@ 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);
createUniqueKeyPair, createSecurityGroupIfNeeded, OPTIONS_PROVIDER);
}
private void replayStrategy(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions strategy) {

View File

@ -35,6 +35,7 @@ import org.jclouds.compute.domain.Hardware;
import org.jclouds.compute.domain.Image;
import org.jclouds.compute.domain.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,25 +99,29 @@ 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();
expect(instanceClient.runInstancesInRegion(region, zone, imageId, 1, input.count, ec2Options)).andReturn(
(Reservation) reservation);
(Reservation) reservation);
expect(instance.getId()).andReturn(instanceCreatedId).atLeastOnce();
// simulate a lazy credentials fetch
Credentials creds = new Credentials("foo", "bar");
@ -128,11 +134,12 @@ 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);
strategy.utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(eq(input.options),
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,18 +133,17 @@ 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 Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
ResumeNodeStrategy resumeNodeStrategy, SuspendNodeStrategy suspendNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
@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,
ResumeNodeStrategy resumeNodeStrategy, SuspendNodeStrategy suspendNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor) {
this.context = checkNotNull(context, "context");
this.credentialStore = checkNotNull(credentialStore, "credentialStore");
this.images = checkNotNull(images, "images");
@ -179,7 +179,7 @@ public class BaseComputeService implements ComputeService {
*/
@Override
public Set<? extends NodeMetadata> runNodesWithTag(String group, int count, Template template)
throws RunNodesException {
throws RunNodesException {
return createNodesInGroup(group, count, template);
}
@ -188,7 +188,7 @@ public class BaseComputeService implements ComputeService {
*/
@Override
public Set<? extends NodeMetadata> runNodesWithTag(String group, int count, TemplateOptions templateOptions)
throws RunNodesException {
throws RunNodesException {
return createNodesInGroup(group, count, templateBuilder().any().options(templateOptions).build());
}
@ -202,20 +202,20 @@ public class BaseComputeService implements ComputeService {
@Override
public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, Template template)
throws RunNodesException {
throws RunNodesException {
checkNotNull(group, "group cannot be null");
checkNotNull(template.getLocation(), "location");
logger.debug(">> running %d node%s group(%s) location(%s) image(%s) hardwareProfile(%s) options(%s)", count,
count > 1 ? "s" : "", group, template.getLocation().getId(), template.getImage().getId(), template
.getHardware().getId(), template.getOptions());
count > 1 ? "s" : "", group, template.getLocation().getId(), template.getImage().getId(), template
.getHardware().getId(), template.getOptions());
Set<NodeMetadata> goodNodes = newLinkedHashSet();
Map<NodeMetadata, Exception> badNodes = newLinkedHashMap();
Multimap<NodeMetadata, CustomizationResponse> customizationResponses = LinkedHashMultimap.create();
Map<?, Future<Void>> responses = runNodesAndAddToSetStrategy.execute(group, count, template, goodNodes, badNodes,
customizationResponses);
customizationResponses);
Map<?, Exception> executionExceptions = awaitCompletion(responses, executor, null, logger, "runNodesWithTag("
+ group + ")");
+ group + ")");
for (NodeMetadata node : concat(goodNodes, badNodes.keySet()))
if (node.getCredentials() != null)
credentialStore.put("node#" + node.getId(), node.getCredentials());
@ -227,7 +227,7 @@ public class BaseComputeService implements ComputeService {
@Override
public Set<? extends NodeMetadata> createNodesInGroup(String group, int count, TemplateOptions templateOptions)
throws RunNodesException {
throws RunNodesException {
return createNodesInGroup(group, count, templateBuilder().any().options(templateOptions).build());
}
@ -274,23 +274,23 @@ public class BaseComputeService implements ComputeService {
public Set<? extends NodeMetadata> destroyNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> destroying nodes matching(%s)", filter);
Set<NodeMetadata> set = newLinkedHashSet(transformParallel(nodesMatchingFilterAndNotTerminated(filter),
new Function<NodeMetadata, Future<NodeMetadata>>() {
new Function<NodeMetadata, Future<NodeMetadata>>() {
// TODO make an async interface instead of re-wrapping
@Override
public Future<NodeMetadata> apply(final NodeMetadata from) {
return executor.submit(new Callable<NodeMetadata>() {
// TODO make an async interface instead of re-wrapping
@Override
public Future<NodeMetadata> apply(final NodeMetadata from) {
return executor.submit(new Callable<NodeMetadata>() {
@Override
public NodeMetadata call() throws Exception {
destroyNode(from.getId());
return from;
}
@Override
public NodeMetadata call() throws Exception {
destroyNode(from.getId());
return from;
}
});
}
});
}
}, executor, null, logger, "destroyNodesMatching(" + filter + ")"));
}, executor, null, logger, "destroyNodesMatching(" + filter + ")"));
logger.debug("<< destroyed(%d)", set.size());
return set;
}
@ -304,7 +304,7 @@ public class BaseComputeService implements ComputeService {
* if none found
*/
Iterable<? extends NodeMetadata> nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(
Predicate<NodeMetadata> filter) {
Predicate<NodeMetadata> filter) {
Iterable<? extends NodeMetadata> nodes = nodesMatchingFilterAndNotTerminated(filter);
if (Iterables.size(nodes) == 0)
throw new NoSuchElementException("no nodes matched filter: " + filter);
@ -394,15 +394,15 @@ public class BaseComputeService implements ComputeService {
public void rebootNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> rebooting nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter),
new Function<NodeMetadata, Future<Void>>() {
// TODO use native async
@Override
public Future<Void> apply(NodeMetadata from) {
rebootNode(from.getId());
return immediateFuture(null);
}
new Function<NodeMetadata, Future<Void>>() {
// TODO use native async
@Override
public Future<Void> apply(NodeMetadata from) {
rebootNode(from.getId());
return immediateFuture(null);
}
}, executor, null, logger, "rebootNodesMatching(" + filter + ")");
}, executor, null, logger, "rebootNodesMatching(" + filter + ")");
logger.debug("<< rebooted");
}
@ -425,15 +425,15 @@ public class BaseComputeService implements ComputeService {
public void resumeNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> resuming nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter),
new Function<NodeMetadata, Future<Void>>() {
// TODO use native async
@Override
public Future<Void> apply(NodeMetadata from) {
resumeNode(from.getId());
return immediateFuture(null);
}
new Function<NodeMetadata, Future<Void>>() {
// TODO use native async
@Override
public Future<Void> apply(NodeMetadata from) {
resumeNode(from.getId());
return immediateFuture(null);
}
}, executor, null, logger, "resumeNodesMatching(" + filter + ")");
}, executor, null, logger, "resumeNodesMatching(" + filter + ")");
logger.debug("<< resumed");
}
@ -456,15 +456,15 @@ public class BaseComputeService implements ComputeService {
public void suspendNodesMatching(Predicate<NodeMetadata> filter) {
logger.debug(">> suspending nodes matching(%s)", filter);
transformParallel(nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter),
new Function<NodeMetadata, Future<Void>>() {
// TODO use native async
@Override
public Future<Void> apply(NodeMetadata from) {
suspendNode(from.getId());
return immediateFuture(null);
}
new Function<NodeMetadata, Future<Void>>() {
// TODO use native async
@Override
public Future<Void> apply(NodeMetadata from) {
suspendNode(from.getId());
return immediateFuture(null);
}
}, executor, null, logger, "suspendNodesMatching(" + filter + ")");
}, executor, null, logger, "suspendNodesMatching(" + filter + ")");
logger.debug("<< suspended");
}
@ -473,7 +473,7 @@ public class BaseComputeService implements ComputeService {
*/
@Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript)
throws RunScriptOnNodesException {
throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE);
}
@ -482,10 +482,10 @@ public class BaseComputeService implements ComputeService {
*/
@Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Payload runScript,
RunScriptOptions options) throws RunScriptOnNodesException {
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;
@ -497,7 +497,7 @@ public class BaseComputeService implements ComputeService {
*/
@Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, String runScript)
throws RunScriptOnNodesException {
throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, Statements.exec(checkNotNull(runScript, "runScript")));
}
@ -506,15 +506,15 @@ public class BaseComputeService implements ComputeService {
*/
@Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript)
throws RunScriptOnNodesException {
throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, runScript, RunScriptOptions.NONE);
}
@Override
public Map<? extends NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter,
String runScript, RunScriptOptions options) throws RunScriptOnNodesException {
String runScript, RunScriptOptions options) throws RunScriptOnNodesException {
return runScriptOnNodesMatching(filter, Statements.exec(checkNotNull(runScript, "runScript")),
RunScriptOptions.NONE);
RunScriptOptions.NONE);
}
/**
@ -522,7 +522,7 @@ public class BaseComputeService implements ComputeService {
*/
@Override
public Map<NodeMetadata, ExecResponse> runScriptOnNodesMatching(Predicate<NodeMetadata> filter, Statement runScript,
RunScriptOptions options) throws RunScriptOnNodesException {
RunScriptOptions options) throws RunScriptOnNodesException {
checkNotNull(filter, "filter");
checkNotNull(runScript, "runScript");
@ -534,11 +534,11 @@ public class BaseComputeService implements ComputeService {
Map<?, Exception> exceptions = ImmutableMap.<Object, Exception> of();
Iterable<? extends RunScriptOnNode> scriptRunners = transformNodesIntoInitializedScriptRunners(
nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter), runScript, options, badNodes);
nodesMatchingFilterAndNotTerminatedExceptionIfNotFound(filter), runScript, options, badNodes);
if (Iterables.size(scriptRunners) > 0) {
for (RunScriptOnNode runner : scriptRunners) {
responses.put(runner.getNode(), executor.submit(new RunScriptOnNodeAndAddToGoodMapOrPutExceptionIntoBadMap(
runner, goodNodes, badNodes)));
runner, goodNodes, badNodes)));
}
exceptions = awaitCompletion(responses, executor, null, logger, "runScriptOnNodesMatching(" + filter + ")");
}
@ -550,10 +550,11 @@ 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),
executor, null, logger, "initialize script runners"), notNull());
Iterable<? extends NodeMetadata> nodes, Statement script, RunScriptOptions options,
Map<NodeMetadata, Exception> badNodes) {
return filter(
transformParallel(nodes, new TransformNodesIntoInitializedScriptRunners(script, options, badNodes),
executor, null, logger, "initialize script runners"), notNull());
}
private Set<? extends NodeMetadata> detailsOnAllNodes() {
@ -566,13 +567,13 @@ public class BaseComputeService implements ComputeService {
}
private final class TransformNodesIntoInitializedScriptRunners implements
Function<NodeMetadata, Future<RunScriptOnNode>> {
Function<NodeMetadata, Future<RunScriptOnNode>> {
private final Map<NodeMetadata, Exception> badNodes;
private final Statement script;
private final RunScriptOptions options;
private TransformNodesIntoInitializedScriptRunners(Statement script, RunScriptOptions options,
Map<NodeMetadata, Exception> badNodes) {
Map<NodeMetadata, Exception> badNodes) {
this.badNodes = checkNotNull(badNodes, "badNodes");
this.script = checkNotNull(script, "script");
this.options = checkNotNull(options, "options");
@ -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;
@ -45,7 +65,7 @@ public class Credentials {
public static Credentials parse(URI uri) {
checkNotNull(uri, "uri");
List<String> userInfo = Lists.newArrayList(Splitter.on(':').split(
checkNotNull(uri.getUserInfo(), "no userInfo in " + uri)));
checkNotNull(uri.getUserInfo(), "no userInfo in " + uri)));
String identity = checkNotNull(userInfo.get(0), "no username in " + uri.getUserInfo());
if (Strings2.isUrlEncoded(identity)) {
identity = Strings2.urlDecode(identity);
@ -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;
@ -75,44 +75,47 @@ public class AWSEC2ComputeService extends EC2ComputeService {
@Inject
protected AWSEC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, AWSEC2Client ec2Client,
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap,
@Named("PLACEMENT") Map<RegionAndName, String> placementGroupMap,
@Named("DELETED") Predicate<PlacementGroup> placementGroupDeleted) {
@Memoized Supplier<Set<? extends Image>> images, @Memoized Supplier<Set<? extends Hardware>> sizes,
@Memoized Supplier<Set<? extends Location>> locations, ListNodesStrategy listNodesStrategy,
GetNodeMetadataStrategy getNodeMetadataStrategy, CreateNodesInGroupThenAddToSet runNodesAndAddToSetStrategy,
RebootNodeStrategy rebootNodeStrategy, DestroyNodeStrategy destroyNodeStrategy,
ResumeNodeStrategy startNodeStrategy, SuspendNodeStrategy stopNodeStrategy,
Provider<TemplateBuilder> templateBuilderProvider, Provider<TemplateOptions> templateOptionsProvider,
@Named("NODE_RUNNING") Predicate<NodeMetadata> nodeRunning,
@Named("NODE_TERMINATED") Predicate<NodeMetadata> nodeTerminated,
@Named("NODE_SUSPENDED") Predicate<NodeMetadata> nodeSuspended,
InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory, Timeouts timeouts,
@Named(Constants.PROPERTY_USER_THREADS) ExecutorService executor, AWSEC2Client ec2Client,
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap,
@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;
/**
*
@ -46,31 +55,37 @@ import com.google.common.annotations.VisibleForTesting;
*/
@Singleton
public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions extends
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
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) {
Map<RegionAndName, KeyPair> credentialsMap, @Named("SECURITY") Map<RegionAndName, String> securityGroupMap,
@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,17 +97,19 @@ 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) {
placementGroupName = AWSEC2TemplateOptions.class.cast(options).getPlacementGroup();
if (placementGroupName == null)
shouldAutomaticallyCreatePlacementGroup = AWSEC2TemplateOptions.class.cast(options)
.shouldAutomaticallyCreatePlacementGroup();
.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

@ -59,13 +59,13 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
@Test(enabled = true, dependsOnMethods = "testCompareSizes")
public void testExtendedOptionsAndLogin() throws Exception {
SecurityGroupClient securityGroupClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getSecurityGroupServices();
.getSecurityGroupServices();
KeyPairClient keyPairClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getKeyPairServices();
.getKeyPairServices();
InstanceClient instanceClient = EC2Client.class.cast(context.getProviderSpecificContext().getApi())
.getInstanceServices();
.getInstanceServices();
String group = this.group + "o";
@ -117,17 +117,17 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
// }
// make sure we made our dummy group and also let in the user's group
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,
"jclouds#" +group + "#" + instance.getRegion()));
"jclouds#" + group + "#" + instance.getRegion()));
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));
@ -138,21 +138,17 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
}
cleanupExtendedStuff(securityGroupClient, keyPairClient, group);
}
}
@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,18 +81,18 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock(
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class, new Method[] {
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getOptionsProvider"),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getSecurityGroupsForTagAndOptions", String.class, String.class,
TemplateOptions.class) });
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class,
new Method[] {
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getOptionsProvider"),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", 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(
systemGeneratedKeyPairName);
expect(strategy.getSecurityGroupsForTagAndOptions(region, tag, options)).andReturn(generatedGroups);
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
systemGeneratedKeyPairName);
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,18 +142,18 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock(
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class, new Method[] {
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getOptionsProvider"),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getSecurityGroupsForTagAndOptions", String.class, String.class,
TemplateOptions.class) });
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class,
new Method[] {
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getOptionsProvider"),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", 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(
systemGeneratedKeyPairName);
expect(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn(
generatedGroup);
expect(strategy.getSecurityGroupsForTagAndOptions(region, tag, options)).andReturn(generatedGroups);
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
systemGeneratedKeyPairName);
expect(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
generatedGroup);
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,18 +206,18 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock(
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class, new Method[] {
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getOptionsProvider"),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getSecurityGroupsForTagAndOptions", String.class, String.class,
TemplateOptions.class) });
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class,
new Method[] {
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getOptionsProvider"),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", 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(
systemGeneratedKeyPairName);
expect(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, tag, options)).andReturn(
generatedGroup);
expect(strategy.getSecurityGroupsForTagAndOptions(region, tag, options)).andReturn(generatedGroups);
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
systemGeneratedKeyPairName);
expect(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
generatedGroup);
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,24 +262,24 @@ 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[] {
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getOptionsProvider"),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getSecurityGroupsForTagAndOptions", String.class, String.class,
TemplateOptions.class) });
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class,
new Method[] {
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getOptionsProvider"),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", 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,8 +289,8 @@ 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(
systemGeneratedKeyPairName);
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
systemGeneratedKeyPairName);
expect(options.getSubnetId()).andReturn("1");
expect(options.getUserData()).andReturn(null);
expect(options.isMonitoringEnabled()).andReturn(false);
@ -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,18 +328,18 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// create mocks
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions strategy = createMock(
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class, new Method[] {
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getOptionsProvider"),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getSecurityGroupsForTagAndOptions", String.class, String.class,
TemplateOptions.class) });
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class,
new Method[] {
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class
.getDeclaredMethod("getOptionsProvider"),
CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewKeyPairUnlessUserSpecifiedOtherwise", String.class, String.class,
TemplateOptions.class),
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.class.getDeclaredMethod(
"createNewPlacementGroupUnlessUserSpecifiedOtherwise", 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(
systemGeneratedKeyPairName);
expect(strategy.getSecurityGroupsForTagAndOptions(region, tag, options)).andReturn(generatedGroups);
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
systemGeneratedKeyPairName);
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,10 +498,12 @@ 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);
null);
// replay mocks
replay(options);
@ -424,8 +511,41 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy);
// run
assertEquals(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, tag, options),
systemGeneratedKeyPairName);
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
verify(options);
@ -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;
@ -483,7 +603,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(options.getGroupIds()).andReturn(groupIds).atLeastOnce();
expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
ports, shouldAuthorizeSelf);
ports, shouldAuthorizeSelf);
expect(strategy.securityGroupMap.containsKey(regionNameAndIngressRules)).andReturn(groupExisted);
expect(strategy.createSecurityGroupIfNeeded.apply(regionNameAndIngressRules)).andReturn(generatedMarkerGroup);
expect(strategy.securityGroupMap.put(regionNameAndIngressRules, generatedMarkerGroup)).andReturn(null);
@ -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;
@ -519,7 +639,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(options.getGroupIds()).andReturn(groupIds).atLeastOnce();
expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
ports, shouldAuthorizeSelf);
ports, shouldAuthorizeSelf);
expect(strategy.securityGroupMap.containsKey(regionNameAndIngressRules)).andReturn(groupExisted);
expect(strategy.createSecurityGroupIfNeeded.apply(regionNameAndIngressRules)).andReturn(generatedMarkerGroup);
expect(strategy.securityGroupMap.put(regionNameAndIngressRules, generatedMarkerGroup)).andReturn(null);
@ -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;
@ -555,7 +675,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(options.getGroupIds()).andReturn(groupIds).atLeastOnce();
expect(options.getInboundPorts()).andReturn(ports).atLeastOnce();
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
ports, shouldAuthorizeSelf);
ports, shouldAuthorizeSelf);
expect(strategy.securityGroupMap.containsKey(regionNameAndIngressRules)).andReturn(groupExisted);
// replay mocks
@ -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;
@ -588,7 +708,7 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
// setup expectations
expect(options.getGroupIds()).andReturn(groupIds).atLeastOnce();
RegionNameAndIngressRules regionNameAndIngressRules = new RegionNameAndIngressRules(region, generatedMarkerGroup,
ports, shouldAuthorizeSelf); // note
ports, shouldAuthorizeSelf); // note
// this
// works
// since
@ -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,8 +748,8 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
replayStrategy(strategy);
// run
assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, tag, options),
userSuppliedPlacementGroup);
assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, group, options),
userSuppliedPlacementGroup);
// verify mocks
verify(options);
@ -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();
@ -654,17 +774,17 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
expect(options.shouldAutomaticallyCreatePlacementGroup()).andReturn(shouldAutomaticallyCreatePlacementGroup);
expect(strategy.placementGroupMap.containsKey(new RegionAndName(region, generatedMarkerGroup))).andReturn(false);
expect(strategy.createPlacementGroupIfNeeded.apply(new RegionAndName(region, generatedMarkerGroup))).andReturn(
generatedMarkerGroup);
generatedMarkerGroup);
expect(strategy.placementGroupMap.put(new RegionAndName(region, generatedMarkerGroup), generatedMarkerGroup))
.andReturn(null);
.andReturn(null);
// replay mocks
replay(options);
replayStrategy(strategy);
// run
assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, tag, options),
generatedMarkerGroup);
assertEquals(strategy.createNewPlacementGroupUnlessUserSpecifiedOtherwise(region, group, options),
generatedMarkerGroup);
// verify mocks
verify(options);
@ -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));