mirror of https://github.com/apache/jclouds.git
JCLOUDS-450. Adding support for EC2 MaxCount option.
Note - no live test for this, because it's very hard to guarantee a situation where it would be relevant.
This commit is contained in:
parent
f9d4ac6a27
commit
bf4626016b
|
@ -16,6 +16,16 @@
|
|||
*/
|
||||
package org.jclouds.ec2.compute.options;
|
||||
|
||||
import static com.google.common.base.Objects.equal;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Strings.emptyToNull;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Objects;
|
||||
import com.google.common.base.Objects.ToStringHelper;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
@ -32,16 +42,6 @@ import org.jclouds.ec2.domain.BlockDeviceMapping.UnmapDeviceNamed;
|
|||
import org.jclouds.javax.annotation.Nullable;
|
||||
import org.jclouds.scriptbuilder.domain.Statement;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import static com.google.common.base.Objects.equal;
|
||||
import static com.google.common.base.Preconditions.checkArgument;
|
||||
import static com.google.common.base.Preconditions.checkNotNull;
|
||||
import static com.google.common.base.Preconditions.checkState;
|
||||
import static com.google.common.base.Strings.emptyToNull;
|
||||
|
||||
/**
|
||||
* Contains options supported in the {@code ComputeService#runNode} operation on
|
||||
* the "ec2" provider. <h2>
|
||||
|
@ -82,6 +82,10 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
|
|||
eTo.noKeyPair();
|
||||
if (getUserData() != null)
|
||||
eTo.userData(getUserData());
|
||||
if (getMaxCount() > 0)
|
||||
eTo.maxCount(getMaxCount());
|
||||
if (getClientToken() != null)
|
||||
eTo.clientToken(getClientToken());
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -90,6 +94,8 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
|
|||
private boolean noKeyPair;
|
||||
private List<Byte> userData;
|
||||
private ImmutableSet.Builder<BlockDeviceMapping> blockDeviceMappings = ImmutableSet.builder();
|
||||
private Integer maxCount;
|
||||
private String clientToken = null;
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
|
@ -99,14 +105,17 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
|
|||
return false;
|
||||
EC2TemplateOptions that = EC2TemplateOptions.class.cast(o);
|
||||
return super.equals(that) && equal(this.groupNames, that.groupNames) && equal(this.keyPair, that.keyPair)
|
||||
&& equal(this.noKeyPair, that.noKeyPair) && equal(this.userData, that.userData)
|
||||
&& equal(this.blockDeviceMappings, that.blockDeviceMappings);
|
||||
&& equal(this.noKeyPair, that.noKeyPair) && equal(this.userData, that.userData)
|
||||
&& equal(this.blockDeviceMappings, that.blockDeviceMappings)
|
||||
&& equal(this.maxCount, that.maxCount)
|
||||
&& equal(this.clientToken, that.clientToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Objects
|
||||
.hashCode(super.hashCode(), groupNames, keyPair, noKeyPair, userData, userData, blockDeviceMappings);
|
||||
.hashCode(super.hashCode(), groupNames, keyPair, noKeyPair, userData, userData, blockDeviceMappings,
|
||||
maxCount, clientToken);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -122,6 +131,10 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
|
|||
ImmutableSet<BlockDeviceMapping> mappings = blockDeviceMappings.build();
|
||||
if (mappings.size() != 0)
|
||||
toString.add("blockDeviceMappings", mappings);
|
||||
if (maxCount != null && maxCount.intValue() > 0)
|
||||
toString.add("maxCount", maxCount);
|
||||
if (clientToken != null)
|
||||
toString.add("clientToken", clientToken);
|
||||
return toString;
|
||||
}
|
||||
|
||||
|
@ -200,6 +213,16 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
|
|||
return this;
|
||||
}
|
||||
|
||||
public EC2TemplateOptions maxCount(Integer maxCount) {
|
||||
this.maxCount = maxCount;
|
||||
return this;
|
||||
}
|
||||
|
||||
public EC2TemplateOptions clientToken(String clientToken) {
|
||||
this.clientToken = checkNotNull(clientToken, "clientToken");
|
||||
return this;
|
||||
}
|
||||
|
||||
public static class Builder extends TemplateOptions.Builder {
|
||||
/**
|
||||
* @see EC2TemplateOptions#blockDeviceMappings
|
||||
|
@ -404,6 +427,16 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
|
|||
EC2TemplateOptions options = new EC2TemplateOptions();
|
||||
return options.blockOnComplete(value);
|
||||
}
|
||||
|
||||
public static EC2TemplateOptions maxCount(Integer maxCount) {
|
||||
EC2TemplateOptions options = new EC2TemplateOptions();
|
||||
return options.maxCount(maxCount);
|
||||
}
|
||||
|
||||
public static EC2TemplateOptions clientToken(String clientToken) {
|
||||
EC2TemplateOptions options = new EC2TemplateOptions();
|
||||
return options.clientToken(clientToken);
|
||||
}
|
||||
}
|
||||
|
||||
// methods that only facilitate returning the correct object type
|
||||
|
@ -621,4 +654,20 @@ public class EC2TemplateOptions extends TemplateOptions implements Cloneable {
|
|||
return blockDeviceMappings.build();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return the maximum number of instances to create
|
||||
*/
|
||||
public int getMaxCount() {
|
||||
return maxCount != null ? maxCount.intValue() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* See <a href="http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Run_Instance_Idempotency.html">here</a> for more information.
|
||||
*
|
||||
* @return the optional client token string, used for idempotency
|
||||
*/
|
||||
public String getClientToken() {
|
||||
return clientToken;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -22,13 +22,18 @@ import static com.google.common.base.Preconditions.checkState;
|
|||
import static org.jclouds.ssh.SshKeys.fingerprintPrivateKey;
|
||||
import static org.jclouds.ssh.SshKeys.sha1PrivateKey;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Provider;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSet.Builder;
|
||||
import com.google.inject.Inject;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
import org.jclouds.compute.functions.GroupNamingConvention;
|
||||
import org.jclouds.compute.functions.GroupNamingConvention.Factory;
|
||||
|
@ -41,13 +46,6 @@ import org.jclouds.ec2.domain.KeyPair;
|
|||
import org.jclouds.ec2.options.RunInstancesOptions;
|
||||
import org.jclouds.javax.annotation.Nullable;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableSet.Builder;
|
||||
import com.google.inject.Inject;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Adrian Cole
|
||||
|
@ -101,6 +99,12 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions {
|
|||
"BlockDeviceMapping only available on ebs boot");
|
||||
instanceOptions.withBlockDeviceMappings(blockDeviceMappings);
|
||||
}
|
||||
|
||||
String clientToken = EC2TemplateOptions.class.cast(template.getOptions()).getClientToken();
|
||||
|
||||
if (clientToken != null) {
|
||||
instanceOptions.withClientToken(clientToken);
|
||||
}
|
||||
}
|
||||
return instanceOptions;
|
||||
}
|
||||
|
|
|
@ -26,15 +26,24 @@ import static org.jclouds.compute.config.ComputeServiceProperties.TIMEOUT_NODE_R
|
|||
import static org.jclouds.compute.functions.DefaultCredentialsFromImageOrOverridingCredentials.overrideDefaultCredentialsWithOptionsIfPresent;
|
||||
import static org.jclouds.ec2.compute.util.EC2ComputeUtils.getZoneFromLocationOrNull;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import javax.annotation.Resource;
|
||||
import javax.inject.Inject;
|
||||
import javax.inject.Named;
|
||||
import javax.inject.Singleton;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
import org.jclouds.aws.util.AWSUtils;
|
||||
import org.jclouds.compute.config.CustomizationResponse;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
|
@ -48,22 +57,12 @@ import org.jclouds.domain.LoginCredentials;
|
|||
import org.jclouds.ec2.EC2Api;
|
||||
import org.jclouds.ec2.compute.domain.RegionAndName;
|
||||
import org.jclouds.ec2.compute.functions.PresentInstances;
|
||||
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
||||
import org.jclouds.ec2.domain.RunningInstance;
|
||||
import org.jclouds.ec2.options.RunInstancesOptions;
|
||||
import org.jclouds.ec2.reference.EC2Constants;
|
||||
import org.jclouds.logging.Logger;
|
||||
|
||||
import com.google.common.annotations.VisibleForTesting;
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.base.Predicate;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Maps;
|
||||
import com.google.common.collect.Multimap;
|
||||
import com.google.common.util.concurrent.ListenableFuture;
|
||||
|
||||
/**
|
||||
* creates futures that correlate to
|
||||
*
|
||||
|
@ -218,12 +217,23 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
|
|||
return createNodesInRegionAndZone(region, zone, group, count, template, instanceOptions);
|
||||
}
|
||||
|
||||
protected Set<RunningInstance> createNodesInRegionAndZone(String region, String zone, String group, int count,
|
||||
Template template, RunInstancesOptions instanceOptions) {
|
||||
protected Set<RunningInstance> createNodesInRegionAndZone(String region, String zone, String group,
|
||||
int count, Template template,
|
||||
RunInstancesOptions instanceOptions) {
|
||||
int countStarted = 0;
|
||||
int tries = 0;
|
||||
Set<RunningInstance> started = ImmutableSet.<RunningInstance> of();
|
||||
|
||||
int maxCount = EC2TemplateOptions.class.cast(template.getOptions()).getMaxCount();
|
||||
int countToProvision;
|
||||
|
||||
if (maxCount == 0) {
|
||||
maxCount = count;
|
||||
countToProvision = 1;
|
||||
} else {
|
||||
countToProvision = count;
|
||||
}
|
||||
|
||||
while (countStarted < count && tries++ < count) {
|
||||
if (logger.isDebugEnabled())
|
||||
logger.debug(">> running %d instance region(%s) zone(%s) ami(%s) params(%s)", count - countStarted, region,
|
||||
|
@ -231,8 +241,8 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
|
|||
|
||||
started = ImmutableSet.copyOf(concat(
|
||||
started,
|
||||
client.getInstanceApi().get().runInstancesInRegion(region, zone, template.getImage().getProviderId(), 1,
|
||||
count - countStarted, instanceOptions)));
|
||||
client.getInstanceApi().get().runInstancesInRegion(region, zone, template.getImage().getProviderId(),
|
||||
countToProvision, maxCount - countStarted, instanceOptions)));
|
||||
|
||||
countStarted = size(started);
|
||||
if (countStarted < count)
|
||||
|
|
|
@ -145,6 +145,15 @@ public class RunInstancesOptions extends BaseEC2RequestOptions {
|
|||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Specifies the optional ClientToken field, which triggers idempotent RunInstances calls.
|
||||
* See <a href="http://docs.aws.amazon.com/AWSEC2/latest/UserGuide/Run_Instance_Idempotency.html">here</a> for more details.
|
||||
*/
|
||||
public RunInstancesOptions withClientToken(String clientToken) {
|
||||
formParameters.put("ClientToken", checkNotNull(clientToken, "clientToken"));
|
||||
return this;
|
||||
}
|
||||
|
||||
public static class Builder {
|
||||
/**
|
||||
* @see RunInstancesOptions#withKeyName(String)
|
||||
|
@ -202,5 +211,13 @@ public class RunInstancesOptions extends BaseEC2RequestOptions {
|
|||
return options.withBlockDeviceMappings(mappings);
|
||||
}
|
||||
|
||||
/**
|
||||
* @see RunInstancesOptions#withClientToken(String)
|
||||
*/
|
||||
public static RunInstancesOptions withClientToken(String clientToken) {
|
||||
RunInstancesOptions options = new RunInstancesOptions();
|
||||
return options.withClientToken(clientToken);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -17,23 +17,24 @@
|
|||
package org.jclouds.ec2.compute;
|
||||
|
||||
import static org.jclouds.ec2.compute.options.EC2TemplateOptions.Builder.blockUntilRunning;
|
||||
import static org.jclouds.ec2.compute.options.EC2TemplateOptions.Builder.maxCount;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNotNull;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMap.Builder;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import org.jclouds.compute.ComputeService;
|
||||
import org.jclouds.compute.domain.NodeMetadata;
|
||||
import org.jclouds.ec2.compute.internal.BaseEC2ComputeServiceExpectTest;
|
||||
import org.jclouds.http.HttpRequest;
|
||||
import org.jclouds.http.HttpResponse;
|
||||
import org.testng.annotations.BeforeClass;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableMap.Builder;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
|
||||
/**
|
||||
* Tests the compute service abstraction of the EC2 api.
|
||||
*
|
||||
|
@ -41,6 +42,74 @@ import com.google.common.collect.Iterables;
|
|||
*/
|
||||
@Test(groups = "unit", testName = "EC2ComputeServiceExpectTest")
|
||||
public class EC2ComputeServiceExpectTest extends BaseEC2ComputeServiceExpectTest {
|
||||
protected HttpRequest createFirstTagRequest;
|
||||
protected HttpRequest createSecondTagRequest;
|
||||
protected HttpRequest createThirdTagRequest;
|
||||
|
||||
@BeforeClass
|
||||
@Override
|
||||
protected void setupDefaultRequests() {
|
||||
super.setupDefaultRequests();
|
||||
createFirstTagRequest =
|
||||
formSigner.filter(HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://ec2.us-east-1.amazonaws.com/")
|
||||
.addHeader("Host", "ec2.us-east-1.amazonaws.com")
|
||||
.payload(
|
||||
payloadFromStringWithContentType(
|
||||
"Action=CreateTags" +
|
||||
"&ResourceId.1=i-2ba64342" +
|
||||
"&Signature=Trp5e5%2BMqeBeBZbLYa9s9gxahQ9nkx6ETfsGl82IV8Y%3D" +
|
||||
"&SignatureMethod=HmacSHA256" +
|
||||
"&SignatureVersion=2" +
|
||||
"&Tag.1.Key=Name" +
|
||||
"&Tag.1.Value=test-2ba64342" +
|
||||
"&Timestamp=2012-04-16T15%3A54%3A08.897Z" +
|
||||
"&Version=2010-08-31" +
|
||||
"&AWSAccessKeyId=identity",
|
||||
"application/x-www-form-urlencoded"))
|
||||
.build());
|
||||
|
||||
createSecondTagRequest =
|
||||
formSigner.filter(HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://ec2.us-east-1.amazonaws.com/")
|
||||
.addHeader("Host", "ec2.us-east-1.amazonaws.com")
|
||||
.payload(
|
||||
payloadFromStringWithContentType(
|
||||
"Action=CreateTags" +
|
||||
"&ResourceId.1=i-2bc64242" +
|
||||
"&Signature=Trp5e5%2BMqeBeBZbLYa9s9gxahQ9nkx6ETfsGl82IV8Y%3D" +
|
||||
"&SignatureMethod=HmacSHA256" +
|
||||
"&SignatureVersion=2" +
|
||||
"&Tag.1.Key=Name" +
|
||||
"&Tag.1.Value=test-2bc64242" +
|
||||
"&Timestamp=2012-04-16T15%3A54%3A08.897Z" +
|
||||
"&Version=2010-08-31" +
|
||||
"&AWSAccessKeyId=identity",
|
||||
"application/x-www-form-urlencoded"))
|
||||
.build());
|
||||
|
||||
createThirdTagRequest =
|
||||
formSigner.filter(HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://ec2.us-east-1.amazonaws.com/")
|
||||
.addHeader("Host", "ec2.us-east-1.amazonaws.com")
|
||||
.payload(
|
||||
payloadFromStringWithContentType(
|
||||
"Action=CreateTags" +
|
||||
"&ResourceId.1=i-2be64332" +
|
||||
"&Signature=Trp5e5%2BMqeBeBZbLYa9s9gxahQ9nkx6ETfsGl82IV8Y%3D" +
|
||||
"&SignatureMethod=HmacSHA256" +
|
||||
"&SignatureVersion=2" +
|
||||
"&Tag.1.Key=Name" +
|
||||
"&Tag.1.Value=test-2be64332" +
|
||||
"&Timestamp=2012-04-16T15%3A54%3A08.897Z" +
|
||||
"&Version=2010-08-31" +
|
||||
"&AWSAccessKeyId=identity",
|
||||
"application/x-www-form-urlencoded"))
|
||||
.build());
|
||||
}
|
||||
|
||||
public void testCreateNodeWithGeneratedKeyPairAndOverriddenLoginUser() throws Exception {
|
||||
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
|
||||
|
@ -67,6 +136,60 @@ public class EC2ComputeServiceExpectTest extends BaseEC2ComputeServiceExpectTest
|
|||
assertNotNull(node.getCredentials().getPrivateKey());
|
||||
}
|
||||
|
||||
public void testCreateThreeNodesWithMaxCountThree() throws Exception {
|
||||
|
||||
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
|
||||
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
|
||||
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
|
||||
requestResponseMap.put(describeImagesRequest, describeImagesResponse);
|
||||
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
|
||||
requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
|
||||
requestResponseMap.put(describeSecurityGroupRequest, describeSecurityGroupResponse);
|
||||
requestResponseMap.put(authorizeSecurityGroupIngressRequest22, authorizeSecurityGroupIngressResponse);
|
||||
requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, authorizeSecurityGroupIngressResponse);
|
||||
requestResponseMap.put(runThreeInstancesRequest, runThreeInstancesResponse);
|
||||
requestResponseMap.put(describeInstanceRequest, describeInstanceResponse);
|
||||
requestResponseMap.put(describeInstanceThreeIdsRequest, describeInstanceThreeIdsResponse);
|
||||
requestResponseMap.put(describeImageRequest, describeImagesResponse);
|
||||
requestResponseMap.put(createFirstTagRequest, createTagsResponse);
|
||||
requestResponseMap.put(createSecondTagRequest, createTagsResponse);
|
||||
requestResponseMap.put(createThirdTagRequest, createTagsResponse);
|
||||
|
||||
ComputeService apiThatCreatesNode = requestsSendResponses(requestResponseMap.build());
|
||||
|
||||
NodeMetadata node = Iterables.getFirst(apiThatCreatesNode.createNodesInGroup("test", 3,
|
||||
maxCount(3).blockUntilRunning(false).overrideLoginUser("ec2-user")), null);
|
||||
assertNotNull(node, "Node should exist");
|
||||
assertEquals(node.getCredentials().getUser(), "ec2-user", "User should be ec2-user");
|
||||
}
|
||||
|
||||
public void testCreateThreeNodesWithMaxCountFourGetThreeNodes() throws Exception {
|
||||
|
||||
Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
|
||||
requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
|
||||
requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
|
||||
requestResponseMap.put(describeImagesRequest, describeImagesResponse);
|
||||
requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
|
||||
requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
|
||||
requestResponseMap.put(describeSecurityGroupRequest, describeSecurityGroupResponse);
|
||||
requestResponseMap.put(authorizeSecurityGroupIngressRequest22, authorizeSecurityGroupIngressResponse);
|
||||
requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, authorizeSecurityGroupIngressResponse);
|
||||
requestResponseMap.put(runThreeToFourInstancesRequest, runThreeInstancesResponse);
|
||||
requestResponseMap.put(describeInstanceRequest, describeInstanceResponse);
|
||||
requestResponseMap.put(describeInstanceThreeIdsRequest, describeInstanceThreeIdsResponse);
|
||||
requestResponseMap.put(describeImageRequest, describeImagesResponse);
|
||||
requestResponseMap.put(createFirstTagRequest, createTagsResponse);
|
||||
requestResponseMap.put(createSecondTagRequest, createTagsResponse);
|
||||
requestResponseMap.put(createThirdTagRequest, createTagsResponse);
|
||||
|
||||
ComputeService apiThatCreatesNode = requestsSendResponses(requestResponseMap.build());
|
||||
|
||||
NodeMetadata node = Iterables.getFirst(apiThatCreatesNode.createNodesInGroup("test", 3,
|
||||
maxCount(4).blockUntilRunning(false).overrideLoginUser("ec2-user")), null);
|
||||
assertNotNull(node, "Node should exist");
|
||||
assertEquals(node.getCredentials().getUser(), "ec2-user", "User should be ec2-user");
|
||||
}
|
||||
|
||||
public void testCreateNodeWithSpecifiedName() throws Exception {
|
||||
HttpRequest createNamedTagsRequest =
|
||||
formSigner.filter(HttpRequest.builder()
|
||||
|
|
|
@ -20,6 +20,7 @@ import static org.testng.Assert.assertEquals;
|
|||
import static org.testng.Assert.assertFalse;
|
||||
import static org.testng.Assert.assertTrue;
|
||||
|
||||
import java.security.SecureRandom;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
import java.util.Set;
|
||||
|
@ -111,6 +112,8 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
|||
|
||||
@Test(enabled = true, dependsOnMethods = "testCompareSizes")
|
||||
public void testExtendedOptionsAndLogin() throws Exception {
|
||||
final SecureRandom random = new SecureRandom();
|
||||
|
||||
SecurityGroupApi securityGroupClient = view.unwrapApi(EC2Api.class)
|
||||
.getSecurityGroupApi().get();
|
||||
|
||||
|
@ -125,6 +128,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
|||
TemplateOptions options = client.templateOptions();
|
||||
|
||||
options.as(EC2TemplateOptions.class).securityGroups(group);
|
||||
options.as(EC2TemplateOptions.class).clientToken(Integer.toHexString(random.nextInt(65536 * 1024)));
|
||||
|
||||
String startedId = null;
|
||||
try {
|
||||
|
@ -151,6 +155,9 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
|
|||
assert first.getCredentials() != null : first;
|
||||
assert first.getCredentials().identity != null : first;
|
||||
|
||||
// Verify that the output of createNodesInGroup is the same.
|
||||
assertEquals(client.createNodesInGroup(group, 1, options), nodes, "Idempotency failing - got different instances");
|
||||
|
||||
startedId = Iterables.getOnlyElement(nodes).getProviderId();
|
||||
|
||||
RunningInstance instance = getInstance(instanceClient, startedId);
|
||||
|
|
|
@ -18,9 +18,8 @@ package org.jclouds.ec2.compute.internal;
|
|||
|
||||
import static org.jclouds.location.reference.LocationConstants.PROPERTY_REGIONS;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.ws.rs.core.MediaType;
|
||||
import java.util.Properties;
|
||||
|
||||
import org.jclouds.compute.ComputeService;
|
||||
import org.jclouds.compute.ComputeServiceContext;
|
||||
|
@ -54,10 +53,15 @@ public abstract class BaseEC2ComputeServiceExpectTest extends BaseEC2ComputeServ
|
|||
protected HttpRequest authorizeSecurityGroupIngressRequestGroup;
|
||||
protected HttpRequest runInstancesRequest;
|
||||
protected HttpResponse runInstancesResponse;
|
||||
protected HttpRequest runThreeInstancesRequest;
|
||||
protected HttpRequest runThreeToFourInstancesRequest;
|
||||
protected HttpResponse runThreeInstancesResponse;
|
||||
protected HttpRequest describeInstanceRequest;
|
||||
protected HttpResponse describeInstanceResponse;
|
||||
protected HttpRequest describeInstanceMultiIdsRequest;
|
||||
protected HttpResponse describeInstanceMultiIdsResponse;
|
||||
protected HttpRequest describeInstanceThreeIdsRequest;
|
||||
protected HttpResponse describeInstanceThreeIdsResponse;
|
||||
protected HttpRequest describeImageRequest;
|
||||
protected HttpRequest createTagsRequest;
|
||||
protected HttpResponse createTagsResponse;
|
||||
|
@ -177,14 +181,45 @@ public abstract class BaseEC2ComputeServiceExpectTest extends BaseEC2ComputeServ
|
|||
HttpResponse.builder().statusCode(200)
|
||||
.payload(payloadFromResourceWithContentType(
|
||||
"/new_instance.xml", MediaType.APPLICATION_XML)).build();
|
||||
|
||||
describeInstanceRequest =
|
||||
|
||||
runThreeInstancesRequest =
|
||||
formSigner.filter(HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://ec2." + region + ".amazonaws.com/")
|
||||
.addHeader("Host", "ec2." + region + ".amazonaws.com")
|
||||
.addFormParam("Action", "RunInstances")
|
||||
.addFormParam("ImageId", "ami-be3adfd7")
|
||||
.addFormParam("InstanceType", "m1.small")
|
||||
.addFormParam("KeyName", "jclouds#test#0")
|
||||
.addFormParam("MaxCount", "3")
|
||||
.addFormParam("MinCount", "3")
|
||||
.addFormParam("SecurityGroup.1", "jclouds#test").build());
|
||||
|
||||
runThreeToFourInstancesRequest =
|
||||
formSigner.filter(HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://ec2." + region + ".amazonaws.com/")
|
||||
.addHeader("Host", "ec2." + region + ".amazonaws.com")
|
||||
.addFormParam("Action", "RunInstances")
|
||||
.addFormParam("ImageId", "ami-be3adfd7")
|
||||
.addFormParam("InstanceType", "m1.small")
|
||||
.addFormParam("KeyName", "jclouds#test#0")
|
||||
.addFormParam("MaxCount", "4")
|
||||
.addFormParam("MinCount", "3")
|
||||
.addFormParam("SecurityGroup.1", "jclouds#test").build());
|
||||
|
||||
runThreeInstancesResponse =
|
||||
HttpResponse.builder().statusCode(200)
|
||||
.payload(payloadFromResourceWithContentType(
|
||||
"/run_instances_three.xml", MediaType.APPLICATION_XML)).build();
|
||||
|
||||
describeInstanceRequest =
|
||||
formSigner.filter(HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://ec2." + region + ".amazonaws.com/")
|
||||
.addHeader("Host", "ec2." + region + ".amazonaws.com")
|
||||
.addFormParam("Action", "DescribeInstances")
|
||||
.addFormParam("InstanceId.1", "i-2baa5550").build());
|
||||
.method("POST")
|
||||
.endpoint("https://ec2." + region + ".amazonaws.com/")
|
||||
.addHeader("Host", "ec2." + region + ".amazonaws.com")
|
||||
.addFormParam("Action", "DescribeInstances")
|
||||
.addFormParam("InstanceId.1", "i-2baa5550").build());
|
||||
|
||||
describeInstanceResponse =
|
||||
HttpResponse.builder().statusCode(200)
|
||||
|
@ -205,6 +240,21 @@ public abstract class BaseEC2ComputeServiceExpectTest extends BaseEC2ComputeServ
|
|||
.payload(payloadFromResourceWithContentType(
|
||||
"/describe_instances_multiple.xml", MediaType.APPLICATION_XML)).build();
|
||||
|
||||
describeInstanceThreeIdsRequest =
|
||||
formSigner.filter(HttpRequest.builder()
|
||||
.method("POST")
|
||||
.endpoint("https://ec2." + region + ".amazonaws.com/")
|
||||
.addHeader("Host", "ec2." + region + ".amazonaws.com")
|
||||
.addFormParam("Action", "DescribeInstances")
|
||||
.addFormParam("InstanceId.1", "i-2ba64342")
|
||||
.addFormParam("InstanceId.2", "i-2bc64242")
|
||||
.addFormParam("InstanceId.3", "i-2be64332").build());
|
||||
|
||||
describeInstanceThreeIdsResponse =
|
||||
HttpResponse.builder().statusCode(200)
|
||||
.payload(payloadFromResourceWithContentType(
|
||||
"/describe_instances_multiple.xml", MediaType.APPLICATION_XML)).build();
|
||||
|
||||
//TODO: duplicate.. shouldn't need this
|
||||
describeImageRequest =
|
||||
formSigner.filter(HttpRequest.builder()
|
||||
|
|
|
@ -24,14 +24,14 @@ import static org.jclouds.ec2.compute.options.EC2TemplateOptions.Builder.keyPair
|
|||
import static org.jclouds.ec2.compute.options.EC2TemplateOptions.Builder.noKeyPair;
|
||||
import static org.jclouds.ec2.compute.options.EC2TemplateOptions.Builder.securityGroups;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
import static org.testng.Assert.assertNull;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.jclouds.compute.options.TemplateOptions;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* Tests possible uses of EC2TemplateOptions and EC2TemplateOptions.Builder.*
|
||||
*
|
||||
|
@ -285,4 +285,43 @@ public class EC2TemplateOptionsTest {
|
|||
assertEquals(options.getInboundPorts()[0], 22);
|
||||
assertEquals(options.getInboundPorts()[1], 30);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxCountDefault() {
|
||||
EC2TemplateOptions options = new EC2TemplateOptions();
|
||||
assertEquals(options.getMaxCount(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxCount() {
|
||||
EC2TemplateOptions options = new EC2TemplateOptions();
|
||||
options.maxCount(2);
|
||||
assertEquals(options.getMaxCount(), 2);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testMaxCountNull() {
|
||||
EC2TemplateOptions options = new EC2TemplateOptions();
|
||||
options.maxCount(null);
|
||||
assertEquals(options.getMaxCount(), 0);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientTokenDefault() {
|
||||
EC2TemplateOptions options = new EC2TemplateOptions();
|
||||
assertNull(options.getClientToken());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testClientToken() {
|
||||
EC2TemplateOptions options = new EC2TemplateOptions();
|
||||
options.clientToken("some-token");
|
||||
assertEquals(options.getClientToken(), "some-token");
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void testClientTokenNPE() {
|
||||
EC2TemplateOptions options = new EC2TemplateOptions();
|
||||
options.clientToken(null);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -23,13 +23,16 @@ import static org.easymock.EasyMock.replay;
|
|||
import static org.easymock.EasyMock.verify;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import javax.inject.Provider;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentMap;
|
||||
import java.util.concurrent.ExecutionException;
|
||||
|
||||
import javax.inject.Provider;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.jclouds.aws.domain.Region;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
import org.jclouds.compute.domain.Template;
|
||||
|
@ -46,11 +49,6 @@ import org.jclouds.ec2.options.RunInstancesOptions;
|
|||
import org.jclouds.scriptbuilder.domain.Statements;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Function;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableMultimap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
|
@ -130,6 +128,7 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
|||
systemGeneratedKeyPairName);
|
||||
expect(strategy.getSecurityGroupsForTagAndOptions(region, group, options)).andReturn(generatedGroups);
|
||||
expect(options.getUserData()).andReturn(null);
|
||||
expect(options.getClientToken()).andReturn(null);
|
||||
|
||||
// replay mocks
|
||||
replay(options);
|
||||
|
@ -181,6 +180,7 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
|||
expect(template.getHardware()).andReturn(size).atLeastOnce();
|
||||
expect(template.getOptions()).andReturn(options).atLeastOnce();
|
||||
expect(options.getBlockDeviceMappings()).andReturn(ImmutableSet.<BlockDeviceMapping> of()).atLeastOnce();
|
||||
expect(options.getClientToken()).andReturn("some-token");
|
||||
expect(strategy.createNewKeyPairUnlessUserSpecifiedOtherwise(region, group, options)).andReturn(
|
||||
systemGeneratedKeyPairName);
|
||||
expect(strategy.getSecurityGroupsForTagAndOptions(region, group, options)).andReturn(generatedGroups);
|
||||
|
@ -197,7 +197,8 @@ public class CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptionsTest {
|
|||
assertEquals(
|
||||
customize.buildFormParameters().entries(),
|
||||
ImmutableMultimap.<String, String> of("InstanceType", size.getProviderId(), "SecurityGroup.1", "group",
|
||||
"KeyName", systemGeneratedKeyPairName, "UserData", base64().encode("hello".getBytes())).entries());
|
||||
"KeyName", systemGeneratedKeyPairName, "UserData", base64().encode("hello".getBytes()),
|
||||
"ClientToken", "some-token").entries());
|
||||
|
||||
assertEquals(customize.buildRequestHeaders(), ImmutableMultimap.<String, String> of());
|
||||
assertEquals(customize.buildStringPayload(), null);
|
||||
|
|
|
@ -26,6 +26,11 @@ import static org.easymock.EasyMock.verify;
|
|||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Multimap;
|
||||
import org.easymock.IArgumentMatcher;
|
||||
import org.jclouds.compute.config.CustomizationResponse;
|
||||
import org.jclouds.compute.domain.Hardware;
|
||||
|
@ -49,18 +54,12 @@ import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
|
|||
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
|
||||
import org.jclouds.ec2.domain.Reservation;
|
||||
import org.jclouds.ec2.domain.RunningInstance;
|
||||
import org.jclouds.ec2.options.RunInstancesOptions;
|
||||
import org.jclouds.ec2.features.ElasticIPAddressApi;
|
||||
import org.jclouds.ec2.features.InstanceApi;
|
||||
import org.jclouds.ec2.options.RunInstancesOptions;
|
||||
import org.testng.Assert;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.base.Optional;
|
||||
import com.google.common.cache.LoadingCache;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.Iterables;
|
||||
import com.google.common.collect.Multimap;
|
||||
|
||||
/**
|
||||
* @author Adrian Cole
|
||||
*/
|
||||
|
@ -124,6 +123,7 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
|
|||
expect(input.options.getLoginPassword()).andReturn(null);
|
||||
expect(input.options.getLoginPrivateKey()).andReturn(null);
|
||||
expect(input.options.shouldAuthenticateSudo()).andReturn(null);
|
||||
expect(input.options.getMaxCount()).andReturn(0);
|
||||
|
||||
expect(
|
||||
strategy.utils.customizeNodesAndAddToGoodMapOrPutExceptionIntoBadMap(eq(input.options),
|
||||
|
@ -222,7 +222,7 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
|
|||
expect(input.options.getLoginPassword()).andReturn(null);
|
||||
expect(input.options.getLoginPrivateKey()).andReturn(null);
|
||||
expect(input.options.shouldAuthenticateSudo()).andReturn(null);
|
||||
|
||||
expect(input.options.getMaxCount()).andReturn(0);
|
||||
|
||||
expect(strategy.runningInstanceToNodeMetadata.apply(instance)).andReturn(nodeMetadata);
|
||||
expect(
|
||||
|
|
|
@ -18,6 +18,7 @@ package org.jclouds.ec2.options;
|
|||
|
||||
import static org.jclouds.ec2.options.RunInstancesOptions.Builder.asType;
|
||||
import static org.jclouds.ec2.options.RunInstancesOptions.Builder.withBlockDeviceMappings;
|
||||
import static org.jclouds.ec2.options.RunInstancesOptions.Builder.withClientToken;
|
||||
import static org.jclouds.ec2.options.RunInstancesOptions.Builder.withKernelId;
|
||||
import static org.jclouds.ec2.options.RunInstancesOptions.Builder.withKeyName;
|
||||
import static org.jclouds.ec2.options.RunInstancesOptions.Builder.withRamdisk;
|
||||
|
@ -25,14 +26,13 @@ import static org.jclouds.ec2.options.RunInstancesOptions.Builder.withSecurityGr
|
|||
import static org.jclouds.ec2.options.RunInstancesOptions.Builder.withUserData;
|
||||
import static org.testng.Assert.assertEquals;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import org.jclouds.ec2.domain.BlockDeviceMapping;
|
||||
import org.jclouds.ec2.domain.InstanceType;
|
||||
import org.jclouds.http.options.HttpRequestOptions;
|
||||
import org.testng.annotations.Test;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
|
||||
/**
|
||||
* Tests possible uses of RunInstancesOptions and RunInstancesOptions.Builder.*
|
||||
*
|
||||
|
@ -244,4 +244,15 @@ public class RunInstancesOptionsTest {
|
|||
withBlockDeviceMappings(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testWithClientToken() {
|
||||
RunInstancesOptions options = withClientToken("some-token");
|
||||
assertEquals(options.buildFormParameters().get("ClientToken"), ImmutableList.of("some-token"));
|
||||
}
|
||||
|
||||
@Test(expectedExceptions = NullPointerException.class)
|
||||
public void testWithClientTokenNPE() {
|
||||
withClientToken(null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -0,0 +1,74 @@
|
|||
<DescribeInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
|
||||
<reservationId>r-47a5402e</reservationId>
|
||||
<ownerId>AIDADH4IGTRXXKCD</ownerId>
|
||||
<groupSet>
|
||||
<item>
|
||||
<groupId>default</groupId>
|
||||
</item>
|
||||
</groupSet>
|
||||
<instancesSet>
|
||||
<item>
|
||||
<instanceId>i-2ba64342</instanceId>
|
||||
<imageId>ami-aecd60c7</imageId>
|
||||
<instanceState>
|
||||
<code>0</code>
|
||||
<name>pending</name>
|
||||
</instanceState>
|
||||
<privateDnsName></privateDnsName>
|
||||
<dnsName></dnsName>
|
||||
<keyName>example-key-name</keyName>
|
||||
<amiLaunchIndex>0</amiLaunchIndex>
|
||||
<instanceType>m1.small</instanceType>
|
||||
<launchTime>2007-08-07T11:51:50.000Z</launchTime>
|
||||
<placement>
|
||||
<availabilityZone>us-east-1b</availabilityZone>
|
||||
</placement>
|
||||
<monitoring>
|
||||
<state>enabled</state>
|
||||
</monitoring>
|
||||
<hypervisor>xen</hypervisor>
|
||||
</item>
|
||||
<item>
|
||||
<instanceId>i-2bc64242</instanceId>
|
||||
<imageId>ami-aecd60c7</imageId>
|
||||
<instanceState>
|
||||
<code>0</code>
|
||||
<name>pending</name>
|
||||
</instanceState>
|
||||
<privateDnsName></privateDnsName>
|
||||
<dnsName></dnsName>
|
||||
<keyName>example-key-name</keyName>
|
||||
<amiLaunchIndex>1</amiLaunchIndex>
|
||||
<instanceType>m1.small</instanceType>
|
||||
<launchTime>2007-08-07T11:51:50.000Z</launchTime>
|
||||
<placement>
|
||||
<availabilityZone>us-east-1b</availabilityZone>
|
||||
</placement>
|
||||
<monitoring>
|
||||
<state>enabled</state>
|
||||
</monitoring>
|
||||
<hypervisor>xen</hypervisor>
|
||||
</item>
|
||||
<item>
|
||||
<instanceId>i-2be64332</instanceId>
|
||||
<imageId>ami-aecd60c7</imageId>
|
||||
<instanceState>
|
||||
<code>0</code>
|
||||
<name>pending</name>
|
||||
</instanceState>
|
||||
<privateDnsName></privateDnsName>
|
||||
<dnsName></dnsName>
|
||||
<keyName>example-key-name</keyName>
|
||||
<amiLaunchIndex>2</amiLaunchIndex>
|
||||
<instanceType>m1.small</instanceType>
|
||||
<launchTime>2007-08-07T11:51:50.000Z</launchTime>
|
||||
<placement>
|
||||
<availabilityZone>us-east-1b</availabilityZone>
|
||||
</placement>
|
||||
<monitoring>
|
||||
<state>enabled</state>
|
||||
</monitoring>
|
||||
<hypervisor>xen</hypervisor>
|
||||
</item>
|
||||
</instancesSet>
|
||||
</DescribeInstancesResponse>
|
|
@ -0,0 +1,74 @@
|
|||
<RunInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
|
||||
<reservationId>r-47a5402e</reservationId>
|
||||
<ownerId>AIDADH4IGTRXXKCD</ownerId>
|
||||
<groupSet>
|
||||
<item>
|
||||
<groupId>default</groupId>
|
||||
</item>
|
||||
</groupSet>
|
||||
<instancesSet>
|
||||
<item>
|
||||
<instanceId>i-2ba64342</instanceId>
|
||||
<imageId>ami-aecd60c7</imageId>
|
||||
<instanceState>
|
||||
<code>0</code>
|
||||
<name>pending</name>
|
||||
</instanceState>
|
||||
<privateDnsName></privateDnsName>
|
||||
<dnsName></dnsName>
|
||||
<keyName>example-key-name</keyName>
|
||||
<amiLaunchIndex>0</amiLaunchIndex>
|
||||
<instanceType>m1.small</instanceType>
|
||||
<launchTime>2007-08-07T11:51:50.000Z</launchTime>
|
||||
<placement>
|
||||
<availabilityZone>us-east-1b</availabilityZone>
|
||||
</placement>
|
||||
<monitoring>
|
||||
<state>enabled</state>
|
||||
</monitoring>
|
||||
<hypervisor>xen</hypervisor>
|
||||
</item>
|
||||
<item>
|
||||
<instanceId>i-2bc64242</instanceId>
|
||||
<imageId>ami-aecd60c7</imageId>
|
||||
<instanceState>
|
||||
<code>0</code>
|
||||
<name>pending</name>
|
||||
</instanceState>
|
||||
<privateDnsName></privateDnsName>
|
||||
<dnsName></dnsName>
|
||||
<keyName>example-key-name</keyName>
|
||||
<amiLaunchIndex>1</amiLaunchIndex>
|
||||
<instanceType>m1.small</instanceType>
|
||||
<launchTime>2007-08-07T11:51:50.000Z</launchTime>
|
||||
<placement>
|
||||
<availabilityZone>us-east-1b</availabilityZone>
|
||||
</placement>
|
||||
<monitoring>
|
||||
<state>enabled</state>
|
||||
</monitoring>
|
||||
<hypervisor>xen</hypervisor>
|
||||
</item>
|
||||
<item>
|
||||
<instanceId>i-2be64332</instanceId>
|
||||
<imageId>ami-aecd60c7</imageId>
|
||||
<instanceState>
|
||||
<code>0</code>
|
||||
<name>pending</name>
|
||||
</instanceState>
|
||||
<privateDnsName></privateDnsName>
|
||||
<dnsName></dnsName>
|
||||
<keyName>example-key-name</keyName>
|
||||
<amiLaunchIndex>2</amiLaunchIndex>
|
||||
<instanceType>m1.small</instanceType>
|
||||
<launchTime>2007-08-07T11:51:50.000Z</launchTime>
|
||||
<placement>
|
||||
<availabilityZone>us-east-1b</availabilityZone>
|
||||
</placement>
|
||||
<monitoring>
|
||||
<state>enabled</state>
|
||||
</monitoring>
|
||||
<hypervisor>xen</hypervisor>
|
||||
</item>
|
||||
</instancesSet>
|
||||
</RunInstancesResponse>
|
Loading…
Reference in New Issue