Issue 29: completed instance commands

git-svn-id: http://jclouds.googlecode.com/svn/trunk@2561 3d8758e0-26b5-11de-8745-db77d3ebf521
This commit is contained in:
adrian.f.cole 2010-01-01 01:38:23 +00:00
parent 9d1ef9bdf5
commit 7e34f51cc4
25 changed files with 1035 additions and 194 deletions

View File

@ -21,6 +21,8 @@ package org.jclouds.aws.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
@ -30,8 +32,8 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
* Binds the String [] to query parameters named with GroupName.index
*
* @author Adrian Cole
* @since 4.0
*/
@Singleton
public class BindGroupNameToIndexedFormParams implements Binder {
@SuppressWarnings("unchecked")

View File

@ -23,6 +23,8 @@ import static com.google.common.base.Preconditions.checkNotNull;
import java.net.InetAddress;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
@ -32,8 +34,8 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
* Binds the String [] to form parameters named with InstanceId.index
*
* @author Adrian Cole
* @since 4.0
*/
@Singleton
public class BindInetAddressesToIndexedFormParams implements Binder {
@SuppressWarnings("unchecked")

View File

@ -21,6 +21,8 @@ package org.jclouds.aws.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
@ -30,8 +32,8 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
* Binds the String [] to form parameters named with InstanceId.index
*
* @author Adrian Cole
* @since 4.0
*/
@Singleton
public class BindInstanceIdsToIndexedFormParams implements Binder {
@SuppressWarnings("unchecked")

View File

@ -21,6 +21,8 @@ package org.jclouds.aws.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
@ -30,8 +32,8 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
* Binds the String [] to query parameters named with KeyName.index
*
* @author Adrian Cole
* @since 4.0
*/
@Singleton
public class BindKeyNameToIndexedFormParams implements Binder {
@SuppressWarnings("unchecked")

View File

@ -21,6 +21,8 @@ package org.jclouds.aws.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
@ -30,8 +32,8 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
* Binds the String [] to form parameters named with ProductCode.index
*
* @author Adrian Cole
* @since 4.0
*/
@Singleton
public class BindProductCodesToIndexedFormParams implements Binder {
@SuppressWarnings("unchecked")

View File

@ -21,6 +21,8 @@ package org.jclouds.aws.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
@ -33,6 +35,7 @@ import com.google.common.collect.Iterables;
*
* @author Adrian Cole
*/
@Singleton
public class BindUserGroupsToIndexedFormParams implements Binder {
@SuppressWarnings("unchecked")

View File

@ -21,6 +21,8 @@ package org.jclouds.aws.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.domain.UserIdGroupPair;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
@ -30,8 +32,8 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
* Binds the String [] to query parameters named with GroupName.index
*
* @author Adrian Cole
* @since 4.0
*/
@Singleton
public class BindUserIdGroupPairToSourceSecurityGroupFormParams implements Binder {
@SuppressWarnings("unchecked")

View File

@ -21,6 +21,8 @@ package org.jclouds.aws.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
@ -31,6 +33,7 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
*
* @author Adrian Cole
*/
@Singleton
public class BindUserIdsToIndexedFormParams implements Binder {
@SuppressWarnings("unchecked")

View File

@ -21,6 +21,8 @@ package org.jclouds.aws.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.util.EC2Utils;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
@ -31,6 +33,7 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
*
* @author Adrian Cole
*/
@Singleton
public class BindVolumeIdsToIndexedFormParams implements Binder {
@SuppressWarnings("unchecked")

View File

@ -21,6 +21,8 @@ package org.jclouds.aws.ec2.binders;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Singleton;
import org.jclouds.aws.ec2.domain.AvailabilityZone;
import org.jclouds.http.HttpRequest;
import org.jclouds.rest.Binder;
@ -31,6 +33,7 @@ import org.jclouds.rest.internal.GeneratedHttpRequest;
*
* @author Adrian Cole
*/
@Singleton
public class IfNotNullBindAvailabilityZoneToFormParam implements Binder {
@SuppressWarnings("unchecked")

View File

@ -503,5 +503,19 @@ public class RunningInstance implements Comparable<RunningInstance> {
return true;
}
@Override
public String toString() {
return "RunningInstance [amiLaunchIndex=" + amiLaunchIndex + ", availabilityZone="
+ availabilityZone + ", dnsName=" + dnsName + ", ebsBlockDevices=" + ebsBlockDevices
+ ", imageId=" + imageId + ", instanceId=" + instanceId + ", instanceState="
+ instanceState + ", instanceType=" + instanceType + ", ipAddress=" + ipAddress
+ ", kernelId=" + kernelId + ", keyName=" + keyName + ", launchTime=" + launchTime
+ ", monitoring=" + monitoring + ", platform=" + platform + ", privateDnsName="
+ privateDnsName + ", privateIpAddress=" + privateIpAddress + ", productCodes="
+ productCodes + ", ramdiskId=" + ramdiskId + ", reason=" + reason + ", region="
+ region + ", rootDeviceName=" + rootDeviceName + ", rootDeviceType="
+ rootDeviceType + ", subnetId=" + subnetId + ", vpcId=" + vpcId + "]";
}
}

View File

@ -0,0 +1,52 @@
/**
*
* Copyright (C) 2009 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.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import javax.inject.Inject;
import javax.inject.Singleton;
import org.jclouds.encryption.EncryptionService;
import com.google.common.base.Function;
/**
* Binds base64 encodes the byte [] input
*
* @author Adrian Cole
*/
@Singleton
public class ConvertUnencodedBytesToBase64EncodedString implements Function<Object, String> {
@Inject
EncryptionService encryptionService;
@Override
public String apply(Object from) {
checkArgument(checkNotNull(from, "input") instanceof byte[],
"this binder is only valid for byte []!");
byte[] unencodedData = (byte[]) from;
checkArgument(checkNotNull(unencodedData, "unencodedData").length <= 16 * 1024,
"userData cannot be larger than 16kb");
return encryptionService.toBase64String(unencodedData);
}
}

View File

@ -18,6 +18,7 @@
*/
package org.jclouds.aws.ec2.options;
import static com.google.common.base.Preconditions.checkArgument;
import static com.google.common.base.Preconditions.checkNotNull;
import org.jclouds.aws.ec2.domain.InstanceType;
@ -84,8 +85,10 @@ public class RunInstancesOptions extends BaseEC2RequestOptions {
/**
* Unencoded data
*/
public RunInstancesOptions withUserData(byte[] data) {
formParameters.put("UserData", Base64.encodeBytes(checkNotNull(data, "data")));
public RunInstancesOptions withUserData(byte[] unencodedData) {
checkArgument(checkNotNull(unencodedData, "unencodedData").length <= 16 * 1024,
"userData cannot be larger than 16kb");
formParameters.put("UserData", Base64.encodeBytes(unencodedData));
return this;
}
@ -210,9 +213,9 @@ public class RunInstancesOptions extends BaseEC2RequestOptions {
/**
* @see RunInstancesOptions#withUserData(byte [])
*/
public static RunInstancesOptions withUserData(byte[] userData) {
public static RunInstancesOptions withUserData(byte[] unencodedData) {
RunInstancesOptions options = new RunInstancesOptions();
return options.withUserData(userData);
return options.withUserData(unencodedData);
}
/**

View File

@ -0,0 +1,69 @@
/**
*
* Copyright (C) 2009 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.predicates;
import javax.annotation.Resource;
import javax.inject.Singleton;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.ec2.domain.Region;
import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.aws.ec2.services.InstanceClient;
import org.jclouds.logging.Logger;
import com.google.common.base.Predicate;
import com.google.common.collect.Iterables;
import com.google.inject.Inject;
/**
*
* Tests to see if a task succeeds.
*
* @author Adrian Cole
*/
@Singleton
public class InstanceHasIpAddress implements Predicate<RunningInstance> {
private final InstanceClient client;
@Resource
protected Logger logger = Logger.NULL;
@Inject
public InstanceHasIpAddress(InstanceClient client) {
this.client = client;
}
public boolean apply(RunningInstance instance) {
logger.trace("looking for ipAddress on instance %s", instance);
try {
instance = refresh(instance.getId());
return instance.getIpAddress() != null;
} catch (AWSResponseException e) {
if (e.getError().getCode().equals("InvalidInstanceID.NotFound"))
return false;
throw e;
}
}
private RunningInstance refresh(String instanceId) {
return Iterables.getLast(Iterables.getLast(
client.describeInstancesInRegion(Region.DEFAULT, instanceId)).getRunningInstances());
}
}

View File

@ -40,6 +40,7 @@ import org.jclouds.aws.ec2.domain.Reservation;
import org.jclouds.aws.ec2.domain.Image.EbsBlockDevice;
import org.jclouds.aws.ec2.domain.Volume.InstanceInitiatedShutdownBehavior;
import org.jclouds.aws.ec2.filters.FormSigner;
import org.jclouds.aws.ec2.functions.ConvertUnencodedBytesToBase64EncodedString;
import org.jclouds.aws.ec2.functions.RegionToEndpoint;
import org.jclouds.aws.ec2.options.RunInstancesOptions;
import org.jclouds.aws.ec2.xml.BlockDeviceMappingHandler;
@ -54,6 +55,7 @@ import org.jclouds.aws.ec2.xml.UnencodeStringValueHandler;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.FormParams;
import org.jclouds.rest.annotations.ParamParser;
import org.jclouds.rest.annotations.RequestFilters;
import org.jclouds.rest.annotations.VirtualHost;
import org.jclouds.rest.annotations.XMLResponseParser;
@ -93,6 +95,16 @@ public interface InstanceAsyncClient {
@FormParam("ImageId") String imageId, @FormParam("MinCount") int minCount,
@FormParam("MaxCount") int maxCount, RunInstancesOptions... options);
/**
* @see InstanceClient#rebootInstancesInRegion
*/
@POST
@Path("/")
@FormParams(keys = ACTION, values = "RebootInstances")
Future<Void> rebootInstancesInRegion(
@EndpointParam(parser = RegionToEndpoint.class) Region region,
@BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
/**
* @see InstanceClient#terminateInstancesInRegion
*/
@ -161,18 +173,6 @@ public interface InstanceAsyncClient {
@EndpointParam(parser = RegionToEndpoint.class) Region region,
@FormParam("InstanceId") String instanceId);
/**
* @see AMIClient#getDisableApiTerminationForInstanceInRegion
*/
@POST
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute",
"disableApiTermination" })
@XMLResponseParser(BooleanValueHandler.class)
Future<Boolean> getDisableApiTerminationForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) Region region,
@FormParam("InstanceId") String instanceId);
/**
* @see AMIClient#getKernelForInstanceInRegion
*/
@ -184,6 +184,18 @@ public interface InstanceAsyncClient {
@EndpointParam(parser = RegionToEndpoint.class) Region region,
@FormParam("InstanceId") String instanceId);
/**
* @see AMIClient#isApiTerminationDisabledForInstanceInRegion
*/
@POST
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute",
"disableApiTermination" })
@XMLResponseParser(BooleanValueHandler.class)
Future<Boolean> isApiTerminationDisabledForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) Region region,
@FormParam("InstanceId") String instanceId);
/**
* @see AMIClient#getInstanceTypeForInstanceInRegion
*/
@ -220,4 +232,102 @@ public interface InstanceAsyncClient {
@EndpointParam(parser = RegionToEndpoint.class) Region region,
@FormParam("InstanceId") String instanceId);
/**
* @see AMIClient#resetRamdiskForInstanceInRegion
*/
@POST
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ResetInstanceAttribute", "ramdisk" })
Future<Void> resetRamdiskForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) Region region,
@FormParam("InstanceId") String instanceId);
/**
* @see AMIClient#resetKernelForInstanceInRegion
*/
@POST
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ResetInstanceAttribute", "kernel" })
Future<Void> resetKernelForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) Region region,
@FormParam("InstanceId") String instanceId);
/**
* @see AMIClient#setUserDataForInstanceInRegion
*/
@POST
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "userData" })
Future<Void> setUserDataForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) Region region,
@FormParam("InstanceId") String instanceId,
@FormParam("Value") @ParamParser(ConvertUnencodedBytesToBase64EncodedString.class) byte[] unencodedData);
/**
* @see AMIClient#setRamdiskForInstanceInRegion
*/
@POST
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "ramdisk" })
Future<Void> setRamdiskForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) Region region,
@FormParam("InstanceId") String instanceId, @FormParam("Value") String ramdisk);
/**
* @see AMIClient#setKernelForInstanceInRegion
*/
@POST
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "kernel" })
Future<Void> setKernelForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) Region region,
@FormParam("InstanceId") String instanceId, @FormParam("Value") String kernel);
/**
* @see AMIClient#setApiTerminationDisabledForInstanceInRegion
*/
@POST
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute",
"disableApiTermination" })
Future<Void> setApiTerminationDisabledForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) Region region,
@FormParam("InstanceId") String instanceId,
@FormParam("Value") boolean apiTerminationDisabled);
/**
* @see AMIClient#setInstanceTypeForInstanceInRegion
*/
@POST
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "instanceType" })
Future<Void> setInstanceTypeForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) Region region,
@FormParam("InstanceId") String instanceId,
@FormParam("Value") InstanceType instanceType);
/**
* @see AMIClient#setInstanceInitiatedShutdownBehaviorForInstanceInRegion
*/
@POST
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute",
"instanceInitiatedShutdownBehavior" })
Future<Void> setInstanceInitiatedShutdownBehaviorForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) Region region,
@FormParam("InstanceId") String instanceId,
@FormParam("Value") InstanceInitiatedShutdownBehavior instanceInitiatedShutdownBehavior);
/**
* @see AMIClient#setBlockDeviceMappingForInstanceInRegion
*/
@POST
@Path("/")
@FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute",
"blockDeviceMapping" })
Future<Void> setBlockDeviceMappingForInstanceInRegion(
@EndpointParam(parser = RegionToEndpoint.class) Region region,
@FormParam("InstanceId") String instanceId,
@FormParam("Value") String blockDeviceMapping);
}

View File

@ -25,6 +25,7 @@ import java.util.concurrent.TimeUnit;
import javax.annotation.Nullable;
import org.jclouds.aws.ec2.domain.AvailabilityZone;
import org.jclouds.aws.ec2.domain.InstanceState;
import org.jclouds.aws.ec2.domain.InstanceStateChange;
import org.jclouds.aws.ec2.domain.InstanceType;
import org.jclouds.aws.ec2.domain.Region;
@ -187,7 +188,7 @@ public interface InstanceClient {
* @see #startInstancesInRegion
* @see #runInstancesInRegion
* @see #describeInstancesInRegion
* @see #terminateeInstancesInRegion
* @see #terminateInstancesInRegion
* @see <a href=
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StopInstances.html"
* />
@ -195,6 +196,30 @@ public interface InstanceClient {
Set<InstanceStateChange> stopInstancesInRegion(Region region, boolean force,
String... instanceIds);
/**
* Requests a reboot of one or more instances. This operation is asynchronous; it only queues a
* request to reboot the specified instance(s). The operation will succeed if the instances are
* valid and belong to you. Requests to reboot terminated instances are ignored. <h3>Note</h3> If
* a Linux/UNIX instance does not cleanly shut down within four minutes, Amazon EC2 will perform
* a hard reboot.
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
*
* @param instanceIds
* Instance ID to reboot.
*
* @see #startInstancesInRegion
* @see #runInstancesInRegion
* @see #describeInstancesInRegion
* @see #terminateInstancesInRegion
* @see <a href=
* "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StopInstances.html"
* />
*/
void rebootInstancesInRegion(Region region, String... instanceIds);
/**
* Starts an instance that uses an Amazon EBS volume as its root device.
* <p/>
@ -219,7 +244,7 @@ public interface InstanceClient {
* @see #stopInstancesInRegion
* @see #runInstancesInRegion
* @see #describeInstancesInRegion
* @see #terminateeInstancesInRegion
* @see #terminateInstancesInRegion
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StartInstances.html"
* />
*/
@ -265,10 +290,9 @@ public interface InstanceClient {
* Region.
* @param instanceId
* which instance to describe the attribute of
* @return Specifies whether the instance can be terminated using the APIs. You must modify this
* attribute before you can terminate any "locked" instances from the APIs.
* @return the ID of the kernel associated with the AMI.
*/
boolean getDisableApiTerminationForInstanceInRegion(Region region, String instanceId);
String getKernelForInstanceInRegion(Region region, String instanceId);
/**
*
@ -277,9 +301,10 @@ public interface InstanceClient {
* Region.
* @param instanceId
* which instance to describe the attribute of
* @return the ID of the kernel associated with the AMI.
* @return Specifies whether the instance can be terminated using the APIs. You must modify this
* attribute before you can terminate any "locked" instances from the APIs.
*/
String getKernelForInstanceInRegion(Region region, String instanceId);
boolean isApiTerminationDisabledForInstanceInRegion(Region region, String instanceId);
/**
*
@ -318,4 +343,181 @@ public interface InstanceClient {
Map<String, EbsBlockDevice> getBlockDeviceMappingForInstanceInRegion(Region region,
String instanceId);
/**
* Resets an attribute of an instance to its default value.
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* @param instanceId
* which instance to reset the attribute of
* @return the ID of the RAM disk associated with the AMI.
*/
String resetRamdiskForInstanceInRegion(Region region, String instanceId);
/**
* Resets an attribute of an instance to its default value.
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* @param instanceId
* which instance to reset the attribute of
* @return the ID of the kernel associated with the AMI.
*/
String resetKernelForInstanceInRegion(Region region, String instanceId);
/**
* Sets the userData used for starting the instance.
* <p/>
* The instance needs to be in a {@link InstanceState#STOPPED} state, which implies two things:
* <ol>
* <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
* <li>You have stopped and waited for the instance to transition from
* {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
* </ol>
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* @param instanceId
* which instance to change the attribute of
* @param unencodedData
* unencoded data to set as userData
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
* />
*/
void setUserDataForInstanceInRegion(Region region, String instanceId, byte[] unencodedData);
/**
* Sets the ramdisk used for starting the instance.
* <p/>
* The instance needs to be in a {@link InstanceState#STOPPED} state, which implies two things:
* <ol>
* <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
* <li>You have stopped and waited for the instance to transition from
* {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
* </ol>
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* @param instanceId
* which instance to change the attribute of
* @param ramdisk
* ramdisk used to start the instance
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
* />
*/
void setRamdiskForInstanceInRegion(Region region, String instanceId, String ramdisk);
/**
* Sets the kernelId used for starting the instance.
* <p/>
* The instance needs to be in a {@link InstanceState#STOPPED} state, which implies two things:
* <ol>
* <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
* <li>You have stopped and waited for the instance to transition from
* {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
* </ol>
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* @param instanceId
* which instance to change the attribute of
* @param kernel
* kernelId used to start the instance
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
* />
*/
void setKernelForInstanceInRegion(Region region, String instanceId, String kernel);
/**
* This command works while the instance is running and controls whether or not the api can be
* used to terminate the instance.
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* @param instanceId
* which instance to reset the attribute of
* @param apiTerminationDisabled
* true to disable api termination
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
* />
*/
void setApiTerminationDisabledForInstanceInRegion(Region region, String instanceId,
boolean apiTerminationDisabled);
/**
* Sets the instanceType used for starting the instance.
* <p/>
* The instance needs to be in a {@link InstanceState#STOPPED} state, which implies two things:
* <ol>
* <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
* <li>You have stopped and waited for the instance to transition from
* {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
* </ol>
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* @param instanceId
* which instance to change the attribute of
* @param instanceType
* instanceType used to start the instance
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
* />
*/
void setInstanceTypeForInstanceInRegion(Region region, String instanceId,
InstanceType instanceType);
/**
* Specifies whether the instance's Amazon EBS volumes are stopped or terminated when the
* instance is shut down.
* <p/>
* The instance needs to be in a {@link InstanceState#STOPPED} state, which implies two things:
* <ol>
* <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
* <li>You have stopped and waited for the instance to transition from
* {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
* </ol>
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* @param instanceId
* which instance to change the attribute of
* @param instanceInitiatedShutdownBehavior
* whether the instance's Amazon EBS volumes are stopped or terminated when the
* instance is shut down.
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
* />
*/
void setInstanceInitiatedShutdownBehaviorForInstanceInRegion(Region region, String instanceId,
InstanceInitiatedShutdownBehavior instanceInitiatedShutdownBehavior);
/**
* Sets the blockDeviceMapping used for starting the instance.
* <p/>
* The instance needs to be in a {@link InstanceState#STOPPED} state, which implies two things:
* <ol>
* <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
* <li>You have stopped and waited for the instance to transition from
* {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
* </ol>
*
* @param region
* Instances are tied to Availability Zones. However, the instance ID is tied to the
* Region.
* @param instanceId
* which instance to change the attribute of
* @param blockDeviceMapping
* blockDeviceMapping used to start the instance
* @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
* />
*/
void setBlockDeviceMappingForInstanceInRegion(Region region, String instanceId,
String blockDeviceMapping);
}

View File

@ -34,6 +34,7 @@ import java.util.concurrent.ExecutionException;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;
import org.jclouds.aws.AWSResponseException;
import org.jclouds.aws.ec2.domain.InstanceState;
import org.jclouds.aws.ec2.domain.InstanceType;
import org.jclouds.aws.ec2.domain.IpProtocol;
@ -44,6 +45,7 @@ import org.jclouds.aws.ec2.domain.Reservation;
import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.aws.ec2.domain.Image.EbsBlockDevice;
import org.jclouds.aws.ec2.domain.Volume.InstanceInitiatedShutdownBehavior;
import org.jclouds.aws.ec2.predicates.InstanceHasIpAddress;
import org.jclouds.aws.ec2.predicates.InstanceStateRunning;
import org.jclouds.http.HttpResponseException;
import org.jclouds.logging.log4j.config.Log4JLoggingModule;
@ -72,7 +74,7 @@ import com.google.inject.Injector;
*
* @author Adrian Cole
*/
@Test(groups = "live", enabled = true, sequential = true, testName = "ec2.CloudApplicationArchitecturesEC2ClientLiveTest")
@Test(groups = "live", enabled = false, sequential = true, testName = "ec2.CloudApplicationArchitecturesEC2ClientLiveTest")
public class CloudApplicationArchitecturesEC2ClientLiveTest {
private EC2Client client;
@ -84,6 +86,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
private InetAddress address;
private RetryablePredicate<InetSocketAddress> socketTester;
private RetryablePredicate<RunningInstance> hasIpTester;
private RetryablePredicate<RunningInstance> runningTester;
@BeforeGroups(groups = { "live" })
@ -96,11 +99,13 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
sshFactory = injector.getInstance(SshClient.Factory.class);
runningTester = new RetryablePredicate<RunningInstance>(new InstanceStateRunning(client
.getInstanceServices()), 180, 5, TimeUnit.SECONDS);
hasIpTester = new RetryablePredicate<RunningInstance>(new InstanceHasIpAddress(client
.getInstanceServices()), 180, 5, TimeUnit.SECONDS);
socketTester = new RetryablePredicate<InetSocketAddress>(new SocketOpen(), 180, 1,
TimeUnit.SECONDS);
}
@Test(enabled = true)
@Test(enabled = false)
void testCreateSecurityGroupIngressCidr() throws InterruptedException, ExecutionException,
TimeoutException {
securityGroupName = instancePrefix + "ingress";
@ -119,7 +124,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
}
}
@Test(enabled = true)
@Test(enabled = false)
void testCreateKeyPair() throws InterruptedException, ExecutionException, TimeoutException {
String keyName = instancePrefix + "1";
try {
@ -136,7 +141,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
assertEquals(keyPair.getKeyName(), keyName);
}
@Test(enabled = true, dependsOnMethods = { "testCreateKeyPair",
@Test(enabled = false, dependsOnMethods = { "testCreateKeyPair",
"testCreateSecurityGroupIngressCidr" })
public void testCreateRunningInstance() throws Exception {
String script = new ScriptBuilder() // lamp install script
@ -173,7 +178,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
instance = blockUntilWeCanSshIntoInstance(instance);
verifyInstanceProperties(script);
tryToChangeStuff();
sshPing(instance);
System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instanceId);
@ -189,7 +194,7 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
assert client.getInstanceServices().getRamdiskForInstanceInRegion(Region.DEFAULT, instanceId)
.startsWith("ari-");
assertEquals(false, client.getInstanceServices().getDisableApiTerminationForInstanceInRegion(
assertEquals(false, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion(
Region.DEFAULT, instanceId));
assert client.getInstanceServices().getKernelForInstanceInRegion(Region.DEFAULT, instanceId)
@ -205,7 +210,112 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
.getBlockDeviceMappingForInstanceInRegion(Region.DEFAULT, instanceId));
}
@Test(enabled = true, dependsOnMethods = "testCreateRunningInstance")
private void setApiTerminationDisabledForInstanceInRegion() {
client.getInstanceServices().setApiTerminationDisabledForInstanceInRegion(Region.DEFAULT,
instanceId, true);
assertEquals(true, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion(
Region.DEFAULT, instanceId));
client.getInstanceServices().setApiTerminationDisabledForInstanceInRegion(Region.DEFAULT,
instanceId, false);
assertEquals(false, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion(
Region.DEFAULT, instanceId));
}
private void tryToChangeStuff() {
setApiTerminationDisabledForInstanceInRegion();
setUserDataForInstanceInRegion();
setRamdiskForInstanceInRegion();
setKernelForInstanceInRegion();
setInstanceTypeForInstanceInRegion();
setInstanceInitiatedShutdownBehaviorForInstanceInRegion();
setBlockDeviceMappingForInstanceInRegion();
}
private void setUserDataForInstanceInRegion() {
try {
client.getInstanceServices().setUserDataForInstanceInRegion(Region.DEFAULT, instanceId,
"test".getBytes());
assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode());
}
}
private void setRamdiskForInstanceInRegion() {
try {
String ramdisk = client.getInstanceServices().getRamdiskForInstanceInRegion(
Region.DEFAULT, instanceId);
client.getInstanceServices().setRamdiskForInstanceInRegion(Region.DEFAULT, instanceId,
ramdisk);
assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode());
}
}
private void setKernelForInstanceInRegion() {
try {
String oldKernel = client.getInstanceServices().getKernelForInstanceInRegion(
Region.DEFAULT, instanceId);
client.getInstanceServices().setKernelForInstanceInRegion(Region.DEFAULT, instanceId,
oldKernel);
assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode());
}
}
private void setInstanceTypeForInstanceInRegion() {
try {
client.getInstanceServices().setInstanceTypeForInstanceInRegion(Region.DEFAULT,
instanceId, InstanceType.C1_MEDIUM);
assert false : "shouldn't be allowed, as instance needs to be stopped";
} catch (AWSResponseException e) {
assertEquals("IncorrectInstanceState", e.getError().getCode());
}
}
private void setBlockDeviceMappingForInstanceInRegion() {
try {
client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(Region.DEFAULT,
instanceId, "whoopie");
assert false : "shouldn't be allowed, as instance needs to be ebs based-ami";
} catch (AWSResponseException e) {
assertEquals("InvalidParameterCombination", e.getError().getCode());
}
}
private void setInstanceInitiatedShutdownBehaviorForInstanceInRegion() {
try {
client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(
Region.DEFAULT, instanceId, InstanceInitiatedShutdownBehavior.STOP);
assert false : "shouldn't be allowed, as instance needs to be ebs based-ami";
} catch (AWSResponseException e) {
assertEquals("UnsupportedInstanceAttribute", e.getError().getCode());
}
}
@Test(enabled = false, dependsOnMethods = "testCreateRunningInstance")
void testReboot() throws InterruptedException, ExecutionException, TimeoutException, IOException {
RunningInstance instance = getInstance(instanceId);
System.out.printf("%d: %s rebooting instance %n", System.currentTimeMillis(), instanceId);
client.getInstanceServices().rebootInstancesInRegion(Region.DEFAULT, instanceId);
Thread.sleep(1000);
instance = getInstance(instanceId);
blockUntilWeCanSshIntoInstance(instance);
SshClient ssh = sshFactory.create(new InetSocketAddress(instance.getIpAddress(), 22), "root",
keyPair.getKeyMaterial().getBytes());
try {
ssh.connect();
ExecResponse uptime = ssh.exec("uptime");
assert uptime.getOutput().indexOf("0 min") != -1 : "reboot didn't work: " + uptime;
} finally {
if (ssh != null)
ssh.disconnect();
}
}
@Test(enabled = false, dependsOnMethods = "testReboot")
void testElasticIpAddress() throws InterruptedException, ExecutionException, TimeoutException,
IOException {
address = client.getElasticIPAddressServices().allocateAddressInRegion(Region.DEFAULT);
@ -254,12 +364,11 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
.getId());
assert runningTester.apply(instance);
// search my account for the instance I just created
Set<Reservation> reservations = client.getInstanceServices().describeInstancesInRegion(
instance.getRegion(), instance.getId()); // last parameter (ids) narrows the search
instance = getInstance(instance.getId());
instance = Iterables.getOnlyElement(Iterables.getOnlyElement(reservations)
.getRunningInstances());
System.out.printf("%d: %s awaiting instance to have ip assigned %n", System
.currentTimeMillis(), instance.getId());
assert hasIpTester.apply(instance);
System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(),
instance.getIpAddress());
@ -279,6 +388,14 @@ public class CloudApplicationArchitecturesEC2ClientLiveTest {
return instance;
}
private RunningInstance getInstance(String instanceId) {
// search my account for the instance I just created
Set<Reservation> reservations = client.getInstanceServices().describeInstancesInRegion(
Region.DEFAULT, instanceId); // last parameter (ids) narrows the search
return Iterables.getOnlyElement(Iterables.getOnlyElement(reservations).getRunningInstances());
}
/**
* this tests "personality" as the file looked up was sent during instance creation
*

View File

@ -49,7 +49,9 @@ import org.jclouds.aws.ec2.domain.RunningInstance;
import org.jclouds.aws.ec2.domain.Snapshot;
import org.jclouds.aws.ec2.domain.Volume;
import org.jclouds.aws.ec2.domain.Image.Architecture;
import org.jclouds.aws.ec2.domain.Image.EbsBlockDevice;
import org.jclouds.aws.ec2.domain.Image.ImageType;
import org.jclouds.aws.ec2.domain.Volume.InstanceInitiatedShutdownBehavior;
import org.jclouds.aws.ec2.predicates.InstanceStateRunning;
import org.jclouds.aws.ec2.predicates.InstanceStateStopped;
import org.jclouds.aws.ec2.predicates.InstanceStateTerminated;
@ -186,7 +188,8 @@ public class EBSBootEC2ClientLiveTest {
assertEquals(keyPair.getKeyName(), keyName);
}
@Test(enabled = false, dependsOnMethods = { "testCreateKeyPair", "testCreateSecurityGroupIngressCidr" })
@Test(enabled = false, dependsOnMethods = { "testCreateKeyPair",
"testCreateSecurityGroupIngressCidr" })
public void testCreateRunningInstance() throws Exception {
instance = createInstance(IMAGE_ID);
}
@ -237,6 +240,7 @@ public class EBSBootEC2ClientLiveTest {
.getId());
}
// TODO use userData to do this, and make initbuilder an example for something else.
@BeforeTest
void makeScript() {
@ -393,7 +397,7 @@ public class EBSBootEC2ClientLiveTest {
System.out.printf("%d: %s awaiting instance to stop %n", System.currentTimeMillis(),
ebsInstance.getId());
stoppedTester.apply(ebsInstance);
tryToChangeStuff();
System.out.printf("%d: %s awaiting instance to start %n", System.currentTimeMillis(),
ebsInstance.getId());
client.getInstanceServices().startInstancesInRegion(ebsInstance.getRegion(),
@ -409,6 +413,90 @@ public class EBSBootEC2ClientLiveTest {
new Image.EbsBlockDevice(snapshot.getId(), VOLUME_SIZE, true)).entrySet());
}
private void tryToChangeStuff() {
setUserDataForInstanceInRegion();
setRamdiskForInstanceInRegion();
setKernelForInstanceInRegion();
setInstanceTypeForInstanceInRegion();
setInstanceInitiatedShutdownBehaviorForInstanceInRegion();
setBlockDeviceMappingForInstanceInRegion();
}
private void setUserDataForInstanceInRegion() {
client.getInstanceServices().setUserDataForInstanceInRegion(Region.DEFAULT,
ebsInstance.getId(), "test".getBytes());
assertEquals("test", client.getInstanceServices().getUserDataForInstanceInRegion(
Region.DEFAULT, ebsInstance.getId()));
}
private void setRamdiskForInstanceInRegion() {
String ramdisk = client.getInstanceServices().getRamdiskForInstanceInRegion(Region.DEFAULT,
ebsInstance.getId());
client.getInstanceServices().setRamdiskForInstanceInRegion(Region.DEFAULT,
ebsInstance.getId(), ramdisk);
assertEquals(ramdisk, client.getInstanceServices().getRamdiskForInstanceInRegion(
Region.DEFAULT, ebsInstance.getId()));
}
private void setKernelForInstanceInRegion() {
String oldKernel = client.getInstanceServices().getKernelForInstanceInRegion(Region.DEFAULT,
ebsInstance.getId());
client.getInstanceServices().setKernelForInstanceInRegion(Region.DEFAULT,
ebsInstance.getId(), oldKernel);
assertEquals(oldKernel, client.getInstanceServices().getKernelForInstanceInRegion(
Region.DEFAULT, ebsInstance.getId()));
}
private void setInstanceTypeForInstanceInRegion() {
client.getInstanceServices().setInstanceTypeForInstanceInRegion(Region.DEFAULT,
ebsInstance.getId(), InstanceType.C1_MEDIUM);
assertEquals(InstanceType.C1_MEDIUM, client.getInstanceServices()
.getInstanceTypeForInstanceInRegion(Region.DEFAULT, ebsInstance.getId()));
client.getInstanceServices().setInstanceTypeForInstanceInRegion(Region.DEFAULT,
ebsInstance.getId(), InstanceType.M1_SMALL);
assertEquals(InstanceType.M1_SMALL, client.getInstanceServices()
.getInstanceTypeForInstanceInRegion(Region.DEFAULT, ebsInstance.getId()));
}
private void setBlockDeviceMappingForInstanceInRegion() { // TODO: determine the correct
// blockDeviceMapping format
try {
client.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(Region.DEFAULT,
ebsInstance.getId(), "whoopie");
assertEquals(ImmutableMap.<String, EbsBlockDevice> of("whoopie", null), client
.getInstanceServices().getBlockDeviceMappingForInstanceInRegion(Region.DEFAULT,
ebsInstance.getId()));
System.out.println("OK: setBlockDeviceMappingForInstanceInRegion");
} catch (Exception e) {
System.err.println("setBlockDeviceMappingForInstanceInRegion");
e.printStackTrace();
}
}
private void setInstanceInitiatedShutdownBehaviorForInstanceInRegion() {
try {
client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(
Region.DEFAULT, ebsInstance.getId(), InstanceInitiatedShutdownBehavior.STOP);
assertEquals(InstanceInitiatedShutdownBehavior.STOP, client.getInstanceServices()
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(Region.DEFAULT,
ebsInstance.getId()));
client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(
Region.DEFAULT, ebsInstance.getId(), InstanceInitiatedShutdownBehavior.TERMINATE);
assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client.getInstanceServices()
.getInstanceInitiatedShutdownBehaviorForInstanceInRegion(Region.DEFAULT,
ebsInstance.getId()));
System.out.println("OK: setInstanceInitiatedShutdownBehaviorForInstanceInRegion");
} catch (Exception e) {
System.err.println("setInstanceInitiatedShutdownBehaviorForInstanceInRegion");
e.printStackTrace();
}
}
/**
* this tests "personality" as the file looked up was sent during instance creation
*

View File

@ -0,0 +1,28 @@
package org.jclouds.aws.ec2.functions;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import org.testng.annotations.Test;
import com.google.inject.Guice;
import com.google.inject.Injector;
/**
* Tests behavior of {@code ConvertUnencodedBytesToBase64EncodedString}
*
* @author Adrian Cole
*/
@Test(groups = "unit", testName = "ec2.ConvertUnencodedBytesToBase64EncodedStringTest")
public class ConvertUnencodedBytesToBase64EncodedStringTest {
Injector injector = Guice.createInjector();
public void testDefault() throws IOException {
ConvertUnencodedBytesToBase64EncodedString function = injector
.getInstance(ConvertUnencodedBytesToBase64EncodedString.class);
assertEquals("dGVzdA==", function.apply("test".getBytes()));
}
}

View File

@ -30,7 +30,9 @@ import javax.inject.Singleton;
import org.jclouds.aws.ec2.EC2;
import org.jclouds.aws.ec2.domain.AvailabilityZone;
import org.jclouds.aws.ec2.domain.InstanceType;
import org.jclouds.aws.ec2.domain.Region;
import org.jclouds.aws.ec2.domain.Volume.InstanceInitiatedShutdownBehavior;
import org.jclouds.aws.ec2.filters.FormSigner;
import org.jclouds.aws.ec2.options.RunInstancesOptions;
import org.jclouds.aws.ec2.xml.BlockDeviceMappingHandler;
@ -45,12 +47,14 @@ import org.jclouds.aws.ec2.xml.UnencodeStringValueHandler;
import org.jclouds.aws.reference.AWSConstants;
import org.jclouds.date.TimeStamp;
import org.jclouds.http.functions.ParseSax;
import org.jclouds.http.functions.ReturnVoidIf2xx;
import org.jclouds.logging.Logger;
import org.jclouds.logging.Logger.LoggerFactory;
import org.jclouds.rest.RestClientTest;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import org.jclouds.rest.internal.RestAnnotationProcessor;
import org.jclouds.util.Jsr330;
import org.testng.annotations.BeforeTest;
import org.testng.annotations.Test;
import com.google.common.collect.ImmutableMap;
@ -187,6 +191,25 @@ public class InstanceAsyncClientTest extends RestClientTest<InstanceAsyncClient>
checkFilters(httpMethod);
}
public void testRebootInstances() throws SecurityException, NoSuchMethodException, IOException {
Method method = InstanceAsyncClient.class.getMethod("rebootInstancesInRegion", Region.class,
Array.newInstance(String.class, 0).getClass());
GeneratedHttpRequest<InstanceAsyncClient> httpMethod = processor.createRequest(method,
Region.DEFAULT, "1", "2");
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod,
"Content-Length: 41\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
assertPayloadEquals(httpMethod,
"Version=2009-11-30&Action=RebootInstances&InstanceId.1=1&InstanceId.2=2");
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
public void testStartInstances() throws SecurityException, NoSuchMethodException, IOException {
Method method = InstanceAsyncClient.class.getMethod("startInstancesInRegion", Region.class,
Array.newInstance(String.class, 0).getClass());
@ -269,7 +292,7 @@ public class InstanceAsyncClientTest extends RestClientTest<InstanceAsyncClient>
public void testGetDisableApiTerminationForInstanceInRegion() throws SecurityException,
NoSuchMethodException, IOException {
Method method = InstanceAsyncClient.class.getMethod(
"getDisableApiTerminationForInstanceInRegion", Region.class, String.class);
"isApiTerminationDisabledForInstanceInRegion", Region.class, String.class);
GeneratedHttpRequest<InstanceAsyncClient> httpMethod = processor.createRequest(method,
Region.DEFAULT, "1");
@ -368,6 +391,160 @@ public class InstanceAsyncClientTest extends RestClientTest<InstanceAsyncClient>
checkFilters(httpMethod);
}
public void testSetUserDataForInstanceInRegion() throws SecurityException,
NoSuchMethodException, IOException {
Method method = InstanceAsyncClient.class.getMethod("setUserDataForInstanceInRegion",
Region.class, String.class, Array.newInstance(byte.class, 0).getClass());
GeneratedHttpRequest<InstanceAsyncClient> httpMethod = processor.createRequest(method,
Region.DEFAULT, "1", "test".getBytes());
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod,
"Content-Length: 100\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
assertPayloadEquals(
httpMethod,
"Version=2009-11-30&Action=ModifyInstanceAttribute&Attribute=userData&Value=dGVzdA%3D%3D&InstanceId=1");
filter.filter(httpMethod);// ensure encoding worked properly
assertPayloadEquals(
httpMethod,
"Action=ModifyInstanceAttribute&Attribute=userData&InstanceId=1&Signature=LyanxPcmESLrkIIFu9RX2yGN1rSQmyF489LYcoszbFE%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2009-11-08T15%3A54%3A08.897Z&Value=dGVzdA%3D%3D&Version=2009-11-30&AWSAccessKeyId=user");
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
public void testSetRamdiskForInstanceInRegion() throws SecurityException, NoSuchMethodException,
IOException {
Method method = InstanceAsyncClient.class.getMethod("setRamdiskForInstanceInRegion",
Region.class, String.class, String.class);
GeneratedHttpRequest<InstanceAsyncClient> httpMethod = processor.createRequest(method,
Region.DEFAULT, "1", "test");
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod,
"Content-Length: 91\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
assertPayloadEquals(httpMethod,
"Version=2009-11-30&Action=ModifyInstanceAttribute&Attribute=ramdisk&Value=test&InstanceId=1");
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
public void testSetKernelForInstanceInRegion() throws SecurityException, NoSuchMethodException,
IOException {
Method method = InstanceAsyncClient.class.getMethod("setKernelForInstanceInRegion",
Region.class, String.class, String.class);
GeneratedHttpRequest<InstanceAsyncClient> httpMethod = processor.createRequest(method,
Region.DEFAULT, "1", "test");
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod,
"Content-Length: 90\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
assertPayloadEquals(httpMethod,
"Version=2009-11-30&Action=ModifyInstanceAttribute&Attribute=kernel&Value=test&InstanceId=1");
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
public void testSetApiTerminationDisabledForInstanceInRegion() throws SecurityException,
NoSuchMethodException, IOException {
Method method = InstanceAsyncClient.class.getMethod(
"setApiTerminationDisabledForInstanceInRegion", Region.class, String.class,
boolean.class);
GeneratedHttpRequest<InstanceAsyncClient> httpMethod = processor.createRequest(method,
Region.DEFAULT, "1", true);
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod,
"Content-Length: 105\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
assertPayloadEquals(
httpMethod,
"Version=2009-11-30&Action=ModifyInstanceAttribute&Attribute=disableApiTermination&Value=true&InstanceId=1");
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
public void testSetInstanceTypeForInstanceInRegion() throws SecurityException,
NoSuchMethodException, IOException {
Method method = InstanceAsyncClient.class.getMethod("setInstanceTypeForInstanceInRegion",
Region.class, String.class, InstanceType.class);
GeneratedHttpRequest<InstanceAsyncClient> httpMethod = processor.createRequest(method,
Region.DEFAULT, "1", InstanceType.C1_MEDIUM);
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod,
"Content-Length: 101\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
assertPayloadEquals(
httpMethod,
"Version=2009-11-30&Action=ModifyInstanceAttribute&Attribute=instanceType&Value=c1.medium&InstanceId=1");
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
public void testSetInstanceInitiatedShutdownBehaviorForInstanceInRegion()
throws SecurityException, NoSuchMethodException, IOException {
Method method = InstanceAsyncClient.class.getMethod(
"setInstanceInitiatedShutdownBehaviorForInstanceInRegion", Region.class,
String.class, InstanceInitiatedShutdownBehavior.class);
GeneratedHttpRequest<InstanceAsyncClient> httpMethod = processor.createRequest(method,
Region.DEFAULT, "1", InstanceInitiatedShutdownBehavior.TERMINATE);
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod,
"Content-Length: 122\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
assertPayloadEquals(
httpMethod,
"Version=2009-11-30&Action=ModifyInstanceAttribute&Attribute=instanceInitiatedShutdownBehavior&Value=terminate&InstanceId=1");
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
public void testSetBlockDeviceMappingForInstanceInRegion() throws SecurityException,
NoSuchMethodException, IOException {
Method method = InstanceAsyncClient.class
.getMethod("setBlockDeviceMappingForInstanceInRegion", Region.class, String.class,
String.class);
GeneratedHttpRequest<InstanceAsyncClient> httpMethod = processor.createRequest(method,
Region.DEFAULT, "1", "test");
assertRequestLineEquals(httpMethod, "POST https://ec2.amazonaws.com/ HTTP/1.1");
assertHeadersEqual(httpMethod,
"Content-Length: 102\nContent-Type: application/x-www-form-urlencoded\nHost: ec2.amazonaws.com\n");
assertPayloadEquals(
httpMethod,
"Version=2009-11-30&Action=ModifyInstanceAttribute&Attribute=blockDeviceMapping&Value=test&InstanceId=1");
filter.filter(httpMethod);// ensure encoding worked properly
assertPayloadEquals(
httpMethod,
"Action=ModifyInstanceAttribute&Attribute=blockDeviceMapping&InstanceId=1&Signature=KNCKfLATSmpXGuIBpXOx3lBmHv9tyu17Cxrfi%2FTzQHE%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2009-11-08T15%3A54%3A08.897Z&Value=test&Version=2009-11-30&AWSAccessKeyId=user");
assertResponseParserClassEquals(method, httpMethod, ReturnVoidIf2xx.class);
assertSaxResponseParserClassEquals(method, null);
assertExceptionParserClassEquals(method, null);
checkFilters(httpMethod);
}
@Override
protected void checkFilters(GeneratedHttpRequest<InstanceAsyncClient> httpMethod) {
assertEquals(httpMethod.getFilters().size(), 1);
@ -380,6 +557,15 @@ public class InstanceAsyncClientTest extends RestClientTest<InstanceAsyncClient>
};
}
private FormSigner filter;
@Override
@BeforeTest
protected void setupFactory() {
super.setupFactory();
this.filter = injector.getInstance(FormSigner.class);
}
@Override
protected Module createModule() {
return new AbstractModule() {

View File

@ -1,109 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<!--
Copyright (C) 2009 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.
====================================================================
-->
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<!--
For more configuration infromation and examples see the Apache Log4j
website: http://logging.apache.org/log4j/
-->
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false">
<!-- A time/date based rolling appender -->
<appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-wire.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category] (Thread:NDC) Message\n
<param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x)
%m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category] (Thread:NDC) Message\n
<param name="ConversionPattern" value="%d %-5r %-5p [%c] (%t:%x)
%m%n"/>
-->
</layout>
</appender>
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="WIREFILE" />
</appender>
<!-- ================ -->
<!-- Limit categories -->
<!-- ================ -->
<category name="org.jclouds">
<priority value="DEBUG" />
<appender-ref ref="ASYNC" />
</category>
<category name="jclouds.http.headers">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category><!--
<category name="jclouds.http.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
--><!-- ======================= -->
<!-- Setup the Root category -->
<!-- ======================= -->
<root>
<priority value="WARN" />
</root>
</log4j:configuration>

View File

@ -1,21 +1,83 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE log4j:configuration SYSTEM "log4j.dtd">
<log4j:configuration xmlns:log4j="http://jakarta.apache.org/log4j/"
debug="false">
<!-- A time/date based rolling appender -->
<appender name="WIREFILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds-wire.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
Copyright (C) 2009 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.
====================================================================
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<!-- A time/date based rolling appender -->
<appender name="FILE" class="org.apache.log4j.DailyRollingFileAppender">
<param name="File" value="target/test-data/jclouds.log" />
<param name="Append" value="true" />
<!-- Rollover at midnight each day -->
<param name="DatePattern" value="'.'yyyy-MM-dd" />
<param name="Threshold" value="TRACE" />
<layout class="org.apache.log4j.PatternLayout">
<!-- The default pattern: Date Priority [Category] Message\n -->
<param name="ConversionPattern" value="%d %-5p [%c] (%t) %m%n" />
<!--
The full pattern: Date MS Priority [Category]
(Thread:NDC) Message\n <param name="ConversionPattern"
value="%d %-5r %-5p [%c] (%t:%x) %m%n"/>
-->
</layout>
</appender>
<appender name="ASYNC" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="FILE" />
</appender>
<appender name="ASYNCWIRE" class="org.apache.log4j.AsyncAppender">
<appender-ref ref="WIREFILE" />
</appender>
<!-- ================ -->
<!-- Limit categories -->
<!-- ================ -->
<category name="org.jclouds">
<priority value="DEBUG" />
<appender-ref ref="ASYNC" />
</category>
<category name="jclouds.http.headers">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
<category name="jclouds.http.wire">
<priority value="DEBUG" />
<appender-ref ref="ASYNCWIRE" />
</category>
<!--======================= -->
<!-- Setup the Root category -->
<!-- ======================= -->
<root>
<priority value="WARN" />
</root>
</log4j:configuration>

View File

@ -1,24 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<projectDescription>
<name>jclouds-aws-demo-createlamp</name>
<comment>jclouds ec2 sample that creates an instance and all you need to access it</comment>
<projects>
<project>jclouds-aws</project>
<project>jclouds-blobstore</project>
<project>jclouds-core</project>
<project>jclouds-jsch</project>
<project>jclouds-log4j</project>
<project>jclouds-scriptbuilder</project>
<project>resteasy-jaxrs-client</project>
</projects>
<buildSpec>
<buildCommand>
<name>org.eclipse.jdt.core.javabuilder</name>
<arguments>
</arguments>
</buildCommand>
</buildSpec>
<natures>
<nature>org.eclipse.jdt.core.javanature</nature>
</natures>
</projectDescription>

View File

@ -431,8 +431,13 @@ public class RestAnnotationProcessor<T> {
} else {
String[] parts = HttpUtils.urlDecode(in).split("&");
for (int partIndex = 0; partIndex < parts.length; partIndex++) {
String[] keyValue = parts[partIndex].split("=");
map.put(keyValue[0], keyValue.length == 2 ? keyValue[1] : null);
// note that '=' can be a valid part of the value
int indexOfFirstEquals = parts[partIndex].indexOf('=');
String key = indexOfFirstEquals == -1 ? parts[partIndex] : parts[partIndex].substring(
0, indexOfFirstEquals);
String value = indexOfFirstEquals == -1 ? null : parts[partIndex]
.substring(indexOfFirstEquals+1);
map.put(key, value);
}
}
return map;

View File

@ -108,6 +108,7 @@ import com.google.common.base.Function;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.LinkedHashMultimap;
import com.google.common.collect.LinkedListMultimap;
import com.google.common.collect.Multimap;
import com.google.inject.AbstractModule;
import com.google.inject.Guice;
@ -838,6 +839,19 @@ public class RestAnnotationProcessorTest {
assertEquals(httpMethod.getHeaders().size(), 0);
}
public void testParseBase64InForm() {
Multimap<String, String> expects = LinkedListMultimap.create();
expects.put("Version", "2009-11-30");
expects.put("Action", "ModifyInstanceAttribute");
expects.put("Attribute", "userData");
expects.put("Value", "dGVzdA==");
expects.put("InstanceId", "1");
assertEquals(
expects,
RestAnnotationProcessor
.parseQueryToMap("Version=2009-11-30&Action=ModifyInstanceAttribute&Attribute=userData&Value=dGVzdA%3D%3D&InstanceId=1"));
}
@Endpoint(Localhost.class)
@SkipEncoding('/')
public class TestQueryReplace {