Using the AWS EC2 API in Flex
Welcome! This month I'm going to give a quick tutorial elucidating some basic and very useful AWS EC2 API calls from within Flex. At the end, you can download some example code which you can use as a starting point in building your own AWS API library for Flex! For this tutorial you'll need an AWS account, if you haven't already got one then you can sign up here you can then create and configure an EC2 micro instance using the free usage tier.
In the name of Iron Maiden! Let's begin!
Amazon Web Services provides two types of API for controlling our EC2 instances one is SOAP based the other is REST based, we'll be using the latter in this tutorial
Let's assume we have our EC2 instance set up. Now in your AWS account navigate to your EC2 dashboard. You should see your list of configured EC2 instances. In my test I'm using the server below named 'ec2-server'

Notice the Instance column above, this field contains the instance id that is used to identify our EC2 instance. We'll be using this in the code that follows.
Let's look at how we can programmatically examine the status of any our instances. For this we're going to use the DescribeInstances API call which takes an optional instance id. Supplying the instance id returns information on just that particular instance, while supplying no instance id returns the status of *all* of our instances.
Below is the xml returned in my test set up as a result of the DescribeInstances call ...
<DescribeInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2012-12-01/">
<requestId>2050b11e-2a9a-419a-b8ae-73249f0a7878</requestId>
<reservationSet>
<item>
<reservationId>r-52ef3136</reservationId>
<ownerId>393619079936</ownerId>
<groupSet>
<item>
<groupId>sg-b08914d8</groupId>
<groupName>quick-start-1</groupName>
</item>
</groupSet>
<instancesSet>
<item>
<instanceId>i-eaedd492</instanceId>
<imageId>ami-aecd60c7</imageId>
<instanceState>
<code>80</code>
<name>stopped</name>
</instanceState>
<privateDnsName/>
<dnsName/>
<reason>User initiated (2013-02-01 18:31:16 GMT)</reason>
<keyName>test_server</keyName>
<amiLaunchIndex>0</amiLaunchIndex>
<productCodes/>
<instanceType>t1.micro</instanceType>
<launchTime>2013-02-01T18:24:26.000Z</launchTime>
<placement>
<availabilityZone>us-east-1c</availabilityZone>
<groupName/>
<tenancy>default</tenancy>
</placement>
<kernelId>aki-88aa75e1</kernelId>
<monitoring>
<state>disabled</state>
</monitoring>
<groupSet>
<item>
<groupId>sg-b08914d8</groupId>
<groupName>quick-start-1</groupName>
</item>
</groupSet>
<stateReason>
<code>Client.UserInitiatedShutdown</code>
<message>Client.UserInitiatedShutdown: User initiated shutdown</message>
</stateReason>
<architecture>x86_64</architecture>
<rootDeviceType>ebs</rootDeviceType>
<rootDeviceName>/dev/sda1</rootDeviceName>
<blockDeviceMapping>
<item>
<deviceName>/dev/sda1</deviceName>
<ebs>
<volumeId>vol-08cee669</volumeId>
<status>attached</status>
<attachTime>2012-07-25T13:50:11.000Z</attachTime>
<deleteOnTermination>true</deleteOnTermination>
</ebs>
</item>
</blockDeviceMapping>
<virtualizationType>paravirtual</virtualizationType>
<clientToken>ozLCT1343224207944</clientToken>
<tagSet>
<item>
<key>Name</key>
<value>ec2-server</value>
</item>
</tagSet>
<hypervisor>xen</hypervisor>
<networkInterfaceSet/>
<ebsOptimized>false</ebsOptimized>
</item>
</instancesSet>
</item>
</reservationSet>
</DescribeInstancesResponse>
Notice the instanceState block wtihin the instanceSet showing the instance status.
<instanceState>
<code>80</code>
<name>stopped</name>
</instanceState>
Let's look at the code, our demo library contains an EC2 class which handles the execution of the various API calls using the RESTful interface. In the calling class EC2APIDemo below we instantiate the EC2 class and set up the handler to process the results.
public function EC2APIDemo()
{
var AWS_ACCESS_ID:String = "YOUR_AWS_ACCESS_KEY";
var AWS_SECRET_KEY:String = "YOUR_AWS_SECRET_ACCESS_KEY";
var AWS_EC2_SERVER_INSTANCE_ID:String = "i-eaedd492";
var ec2Interface:EC2 = new EC2(EC2.US_EAST_1);
ec2Interface.setAWSCredentials(AWS_ACCESS_ID,
AWS_SECRET_KEY);
var parameterArray:Array = new Array();
parameterArray.push(new Parameter("InstanceId.1",
AWS_EC2_SERVER_INSTANCE_ID));
ec2Interface.addEventListener(AWSEvent.RESULT, handler);
ec2Interface.executeRequest(EC2.DESCRIBE_INSTANCES, parameterArray);
}
Here's the handler, all we're doing for now is iterating over the ids and the associated state
public function handler(event:AWSEvent):void
{
var xmlData:XML = new XML(event.data);
trace("handler " + xmlData);
for each(var item:* in xmlData.*::reservationSet.*::item.*::instancesSet.*::item)
{
trace(" item.*::instanceState.*::name " + item.*::instanceState.*::name);
trace(" item.*::instanceId " + item.*::instanceId);
}
}
This brings us to our next EC2 API call: Having examined the instance state and finding that it's stopped, we can make use of the StartInstances API calL to get the instance running. As you can see looking at the docs, this expects one or more instance ids so you can start up a whole cluster of them if you want!
public function startInstances():void
{
var parameterArray:Array = new Array();
parameterArray.push(new Parameter("InstanceId.1", AWS_EC2_SERVER_INSTANCE_ID));
this.ec2Interface.addEventListener(AWSEvent.RESULT, handlerStartInstances);
this.ec2Interface.executeRequest(EC2.START_INSTANCES, parameterArray);
}
public function handlerStartInstances(event:AWSEvent):void
{
var xmlData:XML = new XML(event.data);
trace("handlerStartInstances " + xmlData);
//Do stuff ...
//Error handling ...
}
The response from the StartInstances call as described in the API, results in a list of instance state changes. In this case the state is changed to 'pending' i.e. startup is in progress ...
<StartInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2012-12-01/">
<requestId>ef28014b-4fbc-408f-85b9-3d09b9e655d4</requestId>
<instancesSet>
<item>
<instanceId>i-eaedd492</instanceId>
<currentState>
<code>0</code>
<name>pending</name>
</currentState>
<previousState>
<code>80</code>
<name>stopped</name>
</previousState>
</item>
</instancesSet>
</StartInstancesResponse>
Taking a look under the hood in the demo Flex EC2 API library we have the method executeRequest. Here we can see the url request constructed using the given EC2 API action e.g. DescribeInstances, StartInstances, StopInstances ...
public function executeRequest(action:String, urlVariablesArr:Array=null, requestMethod:String="POST"):void
{
this.action = action;
if(!urlVariablesArr)
{
urlVariablesArr = new Array();
}
urlVariablesArr.push(new Parameter("Version", "2012-12-01"));
urlVariablesArr.push(new Parameter("Action", action));
urlVariablesArr.push(new Parameter("AWSAccessKeyId", awsAccessKey_));
urlVariablesArr.push(new Parameter("Timestamp",
AWSDateUtil.generateRequestTimeStamp(new Date())));
var urlVariables:URLVariables=generateSignature(urlVariablesArr,
signatureVersionToUse,
requestMethod);
for each (var item:Parameter in urlVariablesArr)
{
urlVariables[item.key]=item.value;
}
var request:URLRequest=new URLRequest(remoteRequestURL);
request.data=urlVariables;
request.method=requestMethod;
var urlLoader:URLLoader=new URLLoader();
urlLoader.addEventListener(Event.COMPLETE, handleRequest);
urlLoader.addEventListener(IOErrorEvent.IO_ERROR, handleRequestIOError);
urlLoader.load(request);
}
We've looked here at some very useful EC2 API commands that can be used to programmatically start EC2 services on demand and to monitor the status of sets of EC2 instances. I've packaged up the complete example code which you can download here. You can use this as a starting point for developing your own Flex based AWS API library and using it in your own applications.