You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@stratos.apache.org by ni...@apache.org on 2014/04/02 11:14:24 UTC

[12/25] forking jclouds ec2 api

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/CloudApplicationArchitecturesEC2ApiLiveTest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/CloudApplicationArchitecturesEC2ApiLiveTest.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/CloudApplicationArchitecturesEC2ApiLiveTest.java
new file mode 100644
index 0000000..2a999da
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/CloudApplicationArchitecturesEC2ApiLiveTest.java
@@ -0,0 +1,427 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.ec2.options.RunInstancesOptions.Builder.asType;
+import static org.jclouds.util.Predicates2.retry;
+import static org.jclouds.scriptbuilder.domain.Statements.exec;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.fail;
+
+import java.io.IOException;
+import java.net.UnknownHostException;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
+import org.jclouds.aws.AWSResponseException;
+import org.jclouds.compute.domain.ExecResponse;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.ec2.domain.BlockDevice;
+import org.jclouds.ec2.domain.Image.EbsBlockDevice;
+import org.jclouds.ec2.domain.InstanceState;
+import org.jclouds.ec2.domain.InstanceType;
+import org.jclouds.ec2.domain.KeyPair;
+import org.jclouds.ec2.domain.PublicIpInstanceIdPair;
+import org.jclouds.ec2.domain.Reservation;
+import org.jclouds.ec2.domain.RunningInstance;
+import org.jclouds.ec2.domain.Volume.InstanceInitiatedShutdownBehavior;
+import org.jclouds.ec2.predicates.InstanceHasIpAddress;
+import org.jclouds.ec2.predicates.InstanceStateRunning;
+import org.jclouds.http.HttpResponseException;
+import org.jclouds.net.domain.IpProtocol;
+import org.jclouds.predicates.SocketOpen;
+import org.jclouds.scriptbuilder.ScriptBuilder;
+import org.jclouds.scriptbuilder.domain.OsFamily;
+import org.jclouds.ssh.SshClient;
+import org.jclouds.ssh.SshException;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import com.google.common.net.HostAndPort;
+import com.google.inject.Injector;
+
+/**
+ * Follows the book Cloud Application Architectures ISBN: 978-0-596-15636-7
+ * <p/>
+ * adds in functionality to boot a lamp instance: http://alestic.com/2009/06/ec2-user-data-scripts
+ * <p/>
+ * Generally disabled, as it incurs higher fees.
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", enabled = false, singleThreaded = true, testName = "CloudApplicationArchitecturesEC2ApiLiveTest")
+public class CloudApplicationArchitecturesEC2ApiLiveTest extends BaseComputeServiceContextLiveTest {
+   public CloudApplicationArchitecturesEC2ApiLiveTest() {
+      provider = "ec2";
+   }
+
+   private EC2Api client;
+   protected SshClient.Factory sshFactory;
+   private String instancePrefix = System.getProperty("user.name") + ".ec2";
+   private KeyPair keyPair;
+   private String securityGroupName;
+   private String instanceId;
+   private String address;
+
+   private Predicate<HostAndPort> socketTester;
+   private Predicate<RunningInstance> hasIpTester;
+   private Predicate<RunningInstance> runningTester;
+
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      Injector injector = view.utils().injector();
+      client = injector.getInstance(EC2Api.class);
+      sshFactory = injector.getInstance(SshClient.Factory.class);
+      runningTester = retry(new InstanceStateRunning(client), 180, 5,SECONDS);
+      hasIpTester = retry(new InstanceHasIpAddress(client), 180, 5, SECONDS);
+      SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
+      socketTester = retry(socketOpen, 180, 1, SECONDS);
+   }
+
+   @Test(enabled = false)
+   void testCreateSecurityGroupIngressCidr() throws InterruptedException, ExecutionException, TimeoutException {
+      securityGroupName = instancePrefix + "ingress";
+
+      try {
+         client.getSecurityGroupApi().get().deleteSecurityGroupInRegion(null, securityGroupName);
+      } catch (Exception e) {
+      }
+
+      client.getSecurityGroupApi().get().createSecurityGroupInRegion(null, securityGroupName, securityGroupName);
+      for (int port : new int[] { 80, 443, 22 }) {
+         client.getSecurityGroupApi().get().authorizeSecurityGroupIngressInRegion(null, securityGroupName,
+               IpProtocol.TCP, port, port, "0.0.0.0/0");
+      }
+   }
+
+   @Test(enabled = false)
+   void testCreateKeyPair() throws InterruptedException, ExecutionException, TimeoutException {
+      String keyName = instancePrefix + "1";
+      try {
+         client.getKeyPairApi().get().deleteKeyPairInRegion(null, keyName);
+      } catch (Exception e) {
+
+      }
+      client.getKeyPairApi().get().deleteKeyPairInRegion(null, keyName);
+
+      keyPair = client.getKeyPairApi().get().createKeyPairInRegion(null, keyName);
+      assertNotNull(keyPair);
+      assertNotNull(keyPair.getKeyMaterial());
+      assertNotNull(keyPair.getSha1OfPrivateKey());
+      assertEquals(keyPair.getKeyName(), keyName);
+   }
+
+   @Test(enabled = false, dependsOnMethods = { "testCreateKeyPair", "testCreateSecurityGroupIngressCidr" })
+   public void testCreateRunningInstance() throws Exception {
+      String script = new ScriptBuilder() // lamp install script
+            .addStatement(exec("runurl run.alestic.com/apt/upgrade"))//
+            .addStatement(exec("runurl run.alestic.com/install/lamp"))//
+            .render(OsFamily.UNIX);
+
+      RunningInstance instance = null;
+      while (instance == null) {
+         try {
+
+            System.out.printf("%d: running instance%n", System.currentTimeMillis());
+            Reservation<? extends RunningInstance> reservation = client.getInstanceApi().get().runInstancesInRegion(
+                  null, null, // allow
+                  // ec2
+                  // to
+                  // chose
+                  // an
+                  // availability
+                  // zone
+                  "ami-ccf615a5", // alestic ami allows auto-invoke of
+                  // user data scripts
+                  1, // minimum instances
+                  1, // maximum instances
+                  asType(InstanceType.M1_SMALL) // smallest instance size
+                        .withKeyName(keyPair.getKeyName()) // key I
+                        // created
+                        // above
+                        .withSecurityGroup(securityGroupName) // group I
+                        // created
+                        // above
+                        .withUserData(script.getBytes())); // script to
+            // run as root
+
+            instance = Iterables.getOnlyElement(reservation);
+
+         } catch (HttpResponseException htpe) {
+            if (htpe.getResponse().getStatusCode() == 400)
+               continue;
+            throw htpe;
+         }
+      }
+      assertNotNull(instance.getId());
+      instanceId = instance.getId();
+      assertEquals(instance.getInstanceState(), InstanceState.PENDING);
+      instance = blockUntilWeCanSshIntoInstance(instance);
+
+      verifyInstanceProperties(script);
+      tryToChangeStuff();
+      sshPing(instance);
+      System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instanceId);
+
+   }
+
+   private void verifyInstanceProperties(String script) {
+      assertEquals(script, client.getInstanceApi().get().getUserDataForInstanceInRegion(null, instanceId));
+
+      assertEquals(null, client.getInstanceApi().get().getRootDeviceNameForInstanceInRegion(null, instanceId));
+
+      assert client.getInstanceApi().get().getRamdiskForInstanceInRegion(null, instanceId).startsWith("ari-");
+
+      assertEquals(false, client.getInstanceApi().get().isApiTerminationDisabledForInstanceInRegion(null, instanceId));
+
+      assert client.getInstanceApi().get().getKernelForInstanceInRegion(null, instanceId).startsWith("aki-");
+
+      assertEquals(InstanceType.M1_SMALL,
+            client.getInstanceApi().get().getInstanceTypeForInstanceInRegion(null, instanceId));
+
+      assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client.getInstanceApi().get()
+            .getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, instanceId));
+
+      assertEquals(ImmutableMap.<String, EbsBlockDevice> of(), client.getInstanceApi().get()
+            .getBlockDeviceMappingForInstanceInRegion(null, instanceId));
+   }
+
+   private void setApiTerminationDisabledForInstanceInRegion() {
+      client.getInstanceApi().get().setApiTerminationDisabledForInstanceInRegion(null, instanceId, true);
+      assertEquals(true, client.getInstanceApi().get().isApiTerminationDisabledForInstanceInRegion(null, instanceId));
+      client.getInstanceApi().get().setApiTerminationDisabledForInstanceInRegion(null, instanceId, false);
+      assertEquals(false, client.getInstanceApi().get().isApiTerminationDisabledForInstanceInRegion(null, instanceId));
+   }
+
+   private void tryToChangeStuff() {
+      setApiTerminationDisabledForInstanceInRegion();
+      setUserDataForInstanceInRegion();
+      setRamdiskForInstanceInRegion();
+      setKernelForInstanceInRegion();
+      setInstanceTypeForInstanceInRegion();
+      setInstanceInitiatedShutdownBehaviorForInstanceInRegion();
+      setBlockDeviceMappingForInstanceInRegion();
+   }
+
+   private void setUserDataForInstanceInRegion() {
+      try {
+         client.getInstanceApi().get().setUserDataForInstanceInRegion(null, instanceId, "test".getBytes());
+         fail("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.getInstanceApi().get().getRamdiskForInstanceInRegion(null, instanceId);
+         client.getInstanceApi().get().setRamdiskForInstanceInRegion(null, instanceId, ramdisk);
+         fail("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.getInstanceApi().get().getKernelForInstanceInRegion(null, instanceId);
+         client.getInstanceApi().get().setKernelForInstanceInRegion(null, instanceId, oldKernel);
+         fail("shouldn't be allowed, as instance needs to be stopped");
+      } catch (AWSResponseException e) {
+         assertEquals("IncorrectInstanceState", e.getError().getCode());
+      }
+   }
+
+   private void setInstanceTypeForInstanceInRegion() {
+      try {
+         client.getInstanceApi().get().setInstanceTypeForInstanceInRegion(null, instanceId, InstanceType.C1_MEDIUM);
+         fail("shouldn't be allowed, as instance needs to be stopped");
+      } catch (AWSResponseException e) {
+         assertEquals("IncorrectInstanceState", e.getError().getCode());
+      }
+   }
+
+   private void setBlockDeviceMappingForInstanceInRegion() {
+      Map<String, BlockDevice> mapping = Maps.newLinkedHashMap();
+      try {
+         client.getInstanceApi().get().setBlockDeviceMappingForInstanceInRegion(null, instanceId, mapping);
+         fail("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.getInstanceApi().get().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, instanceId,
+               InstanceInitiatedShutdownBehavior.STOP);
+         fail("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.getInstanceApi().get().rebootInstancesInRegion(null, instanceId);
+      Thread.sleep(1000);
+      instance = getInstance(instanceId);
+      blockUntilWeCanSshIntoInstance(instance);
+      SshClient ssh = sshFactory.create(HostAndPort.fromParts(instance.getIpAddress(), 22),
+            LoginCredentials.builder().user("root").privateKey(keyPair.getKeyMaterial()).build());
+      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.getElasticIPAddressApi().get().allocateAddressInRegion(null);
+      assertNotNull(address);
+
+      PublicIpInstanceIdPair compare = Iterables.getLast(client.getElasticIPAddressApi().get()
+            .describeAddressesInRegion(null, address));
+
+      assertEquals(compare.getPublicIp(), address);
+      assert compare.getInstanceId() == null;
+
+      client.getElasticIPAddressApi().get().associateAddressInRegion(null, address, instanceId);
+
+      compare = Iterables.getLast(client.getElasticIPAddressApi().get().describeAddressesInRegion(null, address));
+
+      assertEquals(compare.getPublicIp(), address);
+      assertEquals(compare.getInstanceId(), instanceId);
+
+      Reservation<? extends RunningInstance> reservation = Iterables.getOnlyElement(client.getInstanceApi().get()
+            .describeInstancesInRegion(null, instanceId));
+
+      assertNotNull(Iterables.getOnlyElement(reservation).getIpAddress());
+      assertNotEquals(address, Iterables.getOnlyElement(reservation).getIpAddress());
+
+      doCheckKey(address);
+
+      client.getElasticIPAddressApi().get().disassociateAddressInRegion(null, address);
+
+      compare = Iterables.getLast(client.getElasticIPAddressApi().get().describeAddressesInRegion(null, address));
+
+      assertEquals(compare.getPublicIp(), address);
+      assert compare.getInstanceId() == null;
+
+      reservation = Iterables.getOnlyElement(client.getInstanceApi().get().describeInstancesInRegion(null, instanceId));
+      // assert reservation.getRunningInstances().last().getIpAddress() == null;
+      // TODO
+   }
+
+   private RunningInstance blockUntilWeCanSshIntoInstance(RunningInstance instance) throws UnknownHostException {
+      System.out.printf("%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance.getId());
+      assert runningTester.apply(instance);
+
+      instance = getInstance(instance.getId());
+
+      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());
+      assert socketTester.apply(HostAndPort.fromParts(instance.getIpAddress(), 22));
+
+      System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), instance.getDnsName());
+      sshPing(instance);
+      System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instance.getId());
+
+      System.out.printf("%d: %s awaiting http service to start%n", System.currentTimeMillis(), instance.getIpAddress());
+      assert socketTester.apply(HostAndPort.fromParts(instance.getIpAddress(), 80));
+      System.out.printf("%d: %s http service started%n", System.currentTimeMillis(), instance.getDnsName());
+      return instance;
+   }
+
+   private RunningInstance getInstance(String instanceId) {
+      // search my identity for the instance I just created
+      Set<? extends Reservation<? extends RunningInstance>> reservations = client.getInstanceApi().get()
+            .describeInstancesInRegion(null, instanceId); // last parameter
+      // (ids) narrows the
+      // search
+
+      return Iterables.getOnlyElement(Iterables.getOnlyElement(reservations));
+   }
+
+   /**
+    * this tests "personality" as the file looked up was sent during instance creation
+    * 
+    * @throws UnknownHostException
+    */
+   private void sshPing(RunningInstance newDetails) throws UnknownHostException {
+      try {
+         doCheckKey(newDetails);
+      } catch (SshException e) {// try twice in case there is a network timeout
+         try {
+            Thread.sleep(10 * 1000);
+         } catch (InterruptedException e1) {
+         }
+         doCheckKey(newDetails);
+      }
+   }
+
+   private void doCheckKey(RunningInstance newDetails) throws UnknownHostException {
+      doCheckKey(newDetails.getIpAddress());
+   }
+
+   private void doCheckKey(String address) {
+      SshClient ssh = sshFactory.create(HostAndPort.fromParts(address, 22),
+            LoginCredentials.builder().user("root").privateKey(keyPair.getKeyMaterial()).build());
+      try {
+         ssh.connect();
+         ExecResponse hello = ssh.exec("echo hello");
+         assertEquals(hello.getOutput().trim(), "hello");
+      } finally {
+         if (ssh != null)
+            ssh.disconnect();
+      }
+   }
+
+   @AfterTest
+   void cleanup() throws InterruptedException, ExecutionException, TimeoutException {
+      if (address != null)
+         client.getElasticIPAddressApi().get().releaseAddressInRegion(null, address);
+      if (instanceId != null)
+         client.getInstanceApi().get().terminateInstancesInRegion(null, instanceId);
+      if (keyPair != null)
+         client.getKeyPairApi().get().deleteKeyPairInRegion(null, keyPair.getKeyName());
+      if (securityGroupName != null)
+         client.getSecurityGroupApi().get().deleteSecurityGroupInRegion(null, securityGroupName);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/EBSBootEC2ApiLiveTest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/EBSBootEC2ApiLiveTest.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/EBSBootEC2ApiLiveTest.java
new file mode 100644
index 0000000..3cff3f2
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/EBSBootEC2ApiLiveTest.java
@@ -0,0 +1,607 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2;
+
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.ec2.options.CreateSnapshotOptions.Builder.withDescription;
+import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.imageIds;
+import static org.jclouds.ec2.options.RegisterImageBackedByEbsOptions.Builder.withKernelId;
+import static org.jclouds.ec2.options.RunInstancesOptions.Builder.withKeyName;
+import static org.jclouds.util.Predicates2.retry;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.net.UnknownHostException;
+import java.util.Map;
+import java.util.Set;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeoutException;
+
+import org.jclouds.aws.AWSResponseException;
+import org.jclouds.compute.domain.ExecResponse;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.ec2.domain.Attachment;
+import org.jclouds.ec2.domain.BlockDevice;
+import org.jclouds.ec2.domain.Image;
+import org.jclouds.ec2.domain.Image.Architecture;
+import org.jclouds.ec2.domain.Image.ImageType;
+import org.jclouds.ec2.domain.InstanceState;
+import org.jclouds.ec2.domain.InstanceType;
+import org.jclouds.ec2.domain.KeyPair;
+import org.jclouds.ec2.domain.Reservation;
+import org.jclouds.ec2.domain.RootDeviceType;
+import org.jclouds.ec2.domain.RunningInstance;
+import org.jclouds.ec2.domain.Snapshot;
+import org.jclouds.ec2.domain.Volume;
+import org.jclouds.ec2.domain.Volume.InstanceInitiatedShutdownBehavior;
+import org.jclouds.ec2.predicates.InstanceStateRunning;
+import org.jclouds.ec2.predicates.InstanceStateStopped;
+import org.jclouds.ec2.predicates.InstanceStateTerminated;
+import org.jclouds.ec2.predicates.SnapshotCompleted;
+import org.jclouds.ec2.predicates.VolumeAttached;
+import org.jclouds.ec2.predicates.VolumeAvailable;
+import org.jclouds.http.HttpResponseException;
+import org.jclouds.io.Payloads;
+import org.jclouds.net.domain.IpProtocol;
+import org.jclouds.predicates.SocketOpen;
+import org.jclouds.scriptbuilder.InitScript;
+import org.jclouds.scriptbuilder.domain.OsFamily;
+import org.jclouds.scriptbuilder.domain.Statements;
+import org.jclouds.ssh.SshClient;
+import org.jclouds.ssh.SshException;
+import org.testng.annotations.AfterTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Maps;
+import com.google.common.net.HostAndPort;
+import com.google.inject.Injector;
+
+/**
+ * Adapted from the following sources: {@link http://gist.github.com/249915}, {@link http
+ * ://www.capsunlock.net/2009/12/create-ebs-boot-ami.html}
+ * <p/>
+ * 
+ * Generally disabled, as it incurs higher fees.
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", enabled = false, singleThreaded = true, testName = "EBSBootEC2ApiLiveTest")
+public class EBSBootEC2ApiLiveTest extends BaseComputeServiceContextLiveTest {
+   public EBSBootEC2ApiLiveTest() {
+      provider = "ec2";
+   }
+
+   // TODO: parameterize
+   private static final String IMAGE_ID = "ami-7e28ca17";
+
+   // don't need a lot of space. 2GB should be more than enough for testing
+   private static final int VOLUME_SIZE = 2;
+   private static final String SCRIPT_END = "----COMPLETE----";
+   private static final String INSTANCE_PREFIX = System.getProperty("user.name") + ".ec2ebs";
+
+   private EC2Api client;
+   private SshClient.Factory sshFactory;
+
+   private KeyPair keyPair;
+   private String securityGroupName;
+
+   private Predicate<HostAndPort> socketTester;
+   private Predicate<Attachment> attachTester;
+   private Predicate<Volume> volumeTester;
+   private RunningInstance instance;
+   private Predicate<RunningInstance> runningTester;
+   private Predicate<RunningInstance> stoppedTester;
+   private Predicate<RunningInstance> terminatedTester;
+   private Volume volume;
+   private Predicate<Snapshot> snapshotTester;
+   private Snapshot snapshot;
+   private Image ebsImage;
+   private RunningInstance ebsInstance;
+   private Attachment attachment;
+   private String mkEbsBoot;
+
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      Injector injector = view.utils().injector();
+      client = injector.getInstance(EC2Api.class);
+      sshFactory = injector.getInstance(SshClient.Factory.class);
+      SocketOpen socketOpen = injector.getInstance(SocketOpen.class);
+      socketTester = retry(socketOpen, 120, 1, SECONDS);
+
+      VolumeAvailable volumeAvailable = injector.getInstance(VolumeAvailable.class);
+      volumeTester = retry(volumeAvailable, 60, 1, SECONDS);
+
+      SnapshotCompleted snapshotCompleted = injector.getInstance(SnapshotCompleted.class);
+      snapshotTester = retry(snapshotCompleted, 120, 3, SECONDS);
+
+      VolumeAttached volumeAttached = injector.getInstance(VolumeAttached.class);
+      attachTester = retry(volumeAttached, 60, 1, SECONDS);
+
+      runningTester = retry(new InstanceStateRunning(client), 180, 5, SECONDS);
+
+      InstanceStateStopped instanceStateStopped = injector.getInstance(InstanceStateStopped.class);
+      stoppedTester = retry(instanceStateStopped, 60, 1, SECONDS);
+
+      InstanceStateTerminated instanceStateTerminated = injector.getInstance(InstanceStateTerminated.class);
+      terminatedTester = retry(instanceStateTerminated, 60, 1, SECONDS);
+
+      injector.injectMembers(socketOpen); // add logger
+   }
+
+   @Test(enabled = false)
+   void testCreateSecurityGroupIngressCidr() throws InterruptedException, ExecutionException, TimeoutException {
+      securityGroupName = INSTANCE_PREFIX + "ingress";
+
+      try {
+         client.getSecurityGroupApi().get().deleteSecurityGroupInRegion(null, securityGroupName);
+      } catch (Exception e) {
+      }
+
+      client.getSecurityGroupApi().get().createSecurityGroupInRegion(null, securityGroupName, securityGroupName);
+      client.getSecurityGroupApi().get().authorizeSecurityGroupIngressInRegion(null, securityGroupName, IpProtocol.TCP,
+            80, 80, "0.0.0.0/0");
+      client.getSecurityGroupApi().get().authorizeSecurityGroupIngressInRegion(null, securityGroupName, IpProtocol.TCP,
+            443, 443, "0.0.0.0/0");
+      client.getSecurityGroupApi().get().authorizeSecurityGroupIngressInRegion(null, securityGroupName, IpProtocol.TCP,
+            22, 22, "0.0.0.0/0");
+   }
+
+   @Test(enabled = false)
+   void testCreateKeyPair() {
+      String keyName = INSTANCE_PREFIX + "1";
+      try {
+         client.getKeyPairApi().get().deleteKeyPairInRegion(null, keyName);
+      } catch (Exception e) {
+
+      }
+
+      keyPair = client.getKeyPairApi().get().createKeyPairInRegion(null, keyName);
+      assertNotNull(keyPair);
+      assertNotNull(keyPair.getKeyMaterial());
+      assertNotNull(keyPair.getSha1OfPrivateKey());
+      assertEquals(keyPair.getKeyName(), keyName);
+   }
+
+   @Test(enabled = false, dependsOnMethods = { "testCreateKeyPair", "testCreateSecurityGroupIngressCidr" })
+   public void testCreateRunningInstance() throws Exception {
+      instance = createInstance(IMAGE_ID);
+   }
+
+   private RunningInstance createInstance(String imageId) throws UnknownHostException {
+      RunningInstance instance = null;
+      while (instance == null) {
+         try {
+            System.out.printf("%d: running instance%n", System.currentTimeMillis());
+            Reservation<? extends RunningInstance> reservation = client.getInstanceApi().get().runInstancesInRegion(
+                  null, null, // allow
+                  // ec2
+                  // to
+                  // chose
+                  // an
+                  // availability
+                  // zone
+                  imageId, 1, // minimum instances
+                  1, // maximum instances
+                  withKeyName(keyPair.getKeyName())// key I created above
+                        .asType(InstanceType.M1_SMALL)// smallest instance
+                        // size
+                        .withSecurityGroup(securityGroupName));// group I
+            // created
+            // above
+            instance = Iterables.getOnlyElement(reservation);
+         } catch (HttpResponseException htpe) {
+            if (htpe.getResponse().getStatusCode() == 400)
+               continue;
+            throw htpe;
+         }
+      }
+      assertNotNull(instance.getId());
+      assertEquals(instance.getInstanceState(), InstanceState.PENDING);
+      instance = blockUntilWeCanSshIntoInstance(instance);
+      return instance;
+   }
+
+   @Test(enabled = false, dependsOnMethods = "testCreateRunningInstance")
+   void testCreateAndAttachVolume() {
+      volume = client.getElasticBlockStoreApi().get().createVolumeInAvailabilityZone(instance.getAvailabilityZone(),
+            VOLUME_SIZE);
+      System.out.printf("%d: %s awaiting volume to become available%n", System.currentTimeMillis(), volume.getId());
+
+      assert volumeTester.apply(volume);
+
+      Attachment attachment = client.getElasticBlockStoreApi().get().attachVolumeInRegion(instance.getRegion(),
+            volume.getId(), instance.getId(), "/dev/sdh");
+
+      System.out.printf("%d: %s awaiting attachment to complete%n", System.currentTimeMillis(), attachment.getId());
+
+      assert attachTester.apply(attachment);
+      System.out.printf("%d: %s attachment complete%n", System.currentTimeMillis(), attachment.getId());
+   }
+
+   // TODO use userData to do this, and make initbuilder an example for
+   // something else.
+   @BeforeTest
+   void makeScript() {
+
+      mkEbsBoot = InitScript.builder()
+            .name("mkebsboot")
+            .home("/tmp")
+            .logDir("/tmp/logs")
+            .exportVariables(ImmutableMap.of("imageDir", "/mnt/tmp", "ebsDevice", "/dev/sdh", "ebsMountPoint", "/mnt/ebs"))
+            .run(Statements
+                  .interpret(
+                        "echo creating a filesystem and mounting the ebs volume",
+                        "{md} {varl}IMAGE_DIR{varr} {varl}EBS_MOUNT_POINT{varr}",
+                        "rm -rf {varl}IMAGE_DIR{varr}/*",
+                        "yes| mkfs -t ext3 {varl}EBS_DEVICE{varr} 2>&-",
+                        "mount {varl}EBS_DEVICE{varr} {varl}EBS_MOUNT_POINT{varr}",
+                        "echo making a local working copy of the boot disk",
+                        "rsync -ax --exclude /ubuntu/.bash_history --exclude /home/*/.bash_history --exclude /etc/ssh/ssh_host_* --exclude /etc/ssh/moduli --exclude /etc/udev/rules.d/*persistent-net.rules --exclude /var/lib/* --exclude=/mnt/* --exclude=/proc/* --exclude=/tmp/* --exclude=/dev/log / {varl}IMAGE_DIR{varr}",
+                        "echo preparing the local working copy",
+                        "touch {varl}IMAGE_DIR{varr}/etc/init.d/ec2-init-user-data",
+                        "echo copying the local working copy to the ebs mount", "{cd} {varl}IMAGE_DIR{varr}",
+                        "tar -cSf - * | tar xf - -C {varl}EBS_MOUNT_POINT{varr}", "echo size of ebs",
+                        "du -sk {varl}EBS_MOUNT_POINT{varr}", "echo size of source", "du -sk {varl}IMAGE_DIR{varr}",
+                        "rm -rf {varl}IMAGE_DIR{varr}/*", "umount {varl}EBS_MOUNT_POINT{varr}", "echo " + SCRIPT_END)).build()
+            .render(OsFamily.UNIX);
+   }
+
+   @Test(enabled = false, dependsOnMethods = "testCreateAndAttachVolume")
+   void testBundleInstance() {
+      SshClient ssh = sshFactory.create(HostAndPort.fromParts(instance.getIpAddress(), 22),
+            LoginCredentials.builder().user("ubuntu").privateKey(keyPair.getKeyMaterial()).build());
+      try {
+         ssh.connect();
+      } catch (SshException e) {// try twice in case there is a network timeout
+         try {
+            Thread.sleep(10 * 1000);
+         } catch (InterruptedException e1) {
+         }
+         ssh.connect();
+      }
+      try {
+         System.out.printf("%d: %s writing ebs script%n", System.currentTimeMillis(), instance.getId());
+         String script = "/tmp/mkebsboot-init.sh";
+         ssh.put(script, Payloads.newStringPayload(mkEbsBoot));
+
+         System.out.printf("%d: %s launching ebs script%n", System.currentTimeMillis(), instance.getId());
+         ssh.exec("chmod 755 " + script);
+         ssh.exec(script + " init");
+         ExecResponse output = ssh.exec("sudo " + script + " start");
+         System.out.println(output);
+         output = ssh.exec(script + " status");
+
+         assert !output.getOutput().trim().equals("") : output;
+         Predicate<String> scriptTester = retry(new ScriptTester(ssh, SCRIPT_END), 600, 10, SECONDS);
+         scriptTester.apply(script);
+      } finally {
+         if (ssh != null)
+            ssh.disconnect();
+      }
+   }
+
+   public static class ScriptTester implements Predicate<String> {
+      private final SshClient ssh;
+      private final String endMatches;
+
+      public ScriptTester(SshClient ssh, String endMatches) {
+         this.ssh = ssh;
+         this.endMatches = endMatches;
+      }
+
+      @Override
+      public boolean apply(String script) {
+         System.out.printf("%d: %s testing status%n", System.currentTimeMillis(), script);
+         ExecResponse output = ssh.exec(script + " status");
+         if (output.getOutput().trim().equals("")) {
+            output = ssh.exec(script + " tail");
+            String stdout = output.getOutput().trim();
+            if (stdout.contains(endMatches)) {
+               return true;
+            } else {
+               output = ssh.exec(script + " tailerr");
+               String stderr = output.getOutput().trim();
+               throw new RuntimeException(String.format(
+                     "script %s ended without token: stdout.log: [%s]; stderr.log: [%s]; ", script, stdout, stderr));
+            }
+         }
+         return false;
+      }
+
+   }
+
+   @Test(enabled = false, dependsOnMethods = "testBundleInstance")
+   void testAMIFromBundle() {
+      volume = Iterables.getOnlyElement(client.getElasticBlockStoreApi().get().describeVolumesInRegion(
+            volume.getRegion(), volume.getId()));
+      if (volume.getAttachments().size() > 0) {
+         // should be cleanly unmounted, so force is not necessary.
+         client.getElasticBlockStoreApi().get().detachVolumeInRegion(instance.getRegion(), volume.getId(), false);
+         System.out.printf("%d: %s awaiting detachment to complete%n", System.currentTimeMillis(), volume.getId());
+         assert volumeTester.apply(volume);
+      } else {
+         attachment = null; // protect test closer so that it doesn't try to
+         // detach
+      }
+      snapshot = client.getElasticBlockStoreApi().get().createSnapshotInRegion(volume.getRegion(), volume.getId(),
+            withDescription("EBS Ubuntu Hardy"));
+
+      System.out.printf("%d: %s awaiting snapshot to complete%n", System.currentTimeMillis(), snapshot.getId());
+
+      assert snapshotTester.apply(snapshot);
+      Image image = Iterables.getOnlyElement(client.getAMIApi().get().describeImagesInRegion(snapshot.getRegion(),
+            imageIds(IMAGE_ID)));
+      String description = image.getDescription() == null ? "jclouds" : image.getDescription();
+
+      System.out.printf("%d: %s creating ami from snapshot%n", System.currentTimeMillis(), snapshot.getId());
+
+      String amiId = client.getAMIApi().get().registerUnixImageBackedByEbsInRegion(
+            snapshot.getRegion(),
+            "ebsboot-" + image.getId(),
+            snapshot.getId(),
+            withKernelId(image.getKernelId()).withRamdisk(image.getRamdiskId()).withDescription(description)
+                  .asArchitecture(Architecture.I386));
+      try {
+         ebsImage = Iterables.getOnlyElement(client.getAMIApi().get().describeImagesInRegion(snapshot.getRegion(),
+               imageIds(amiId)));
+      } catch (AWSResponseException e) {
+         // TODO add a retry handler for this HTTP code 400 and the below error
+         if (e.getError().getClass().equals("InvalidAMIID.NotFound"))
+            ebsImage = Iterables.getOnlyElement(client.getAMIApi().get().describeImagesInRegion(snapshot.getRegion(),
+                  imageIds(amiId)));
+         else
+            throw e;
+      }
+      verifyImage();
+   }
+
+   @Test(enabled = false, dependsOnMethods = { "testAMIFromBundle" })
+   public void testInstanceFromEBS() throws Exception {
+      System.out.printf("%d: %s creating instance from ebs-backed ami%n", System.currentTimeMillis(), ebsImage.getId());
+
+      ebsInstance = createInstance(ebsImage.getId());
+
+      client.getInstanceApi().get().stopInstancesInRegion(ebsInstance.getRegion(), true, ebsInstance.getId());
+
+      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.getInstanceApi().get().startInstancesInRegion(ebsInstance.getRegion(), ebsInstance.getId());
+      ebsInstance = blockUntilWeCanSshIntoInstance(ebsInstance);
+   }
+
+   private void verifyImage() {
+      assertEquals(ebsImage.getImageType(), ImageType.MACHINE);
+      assertEquals(ebsImage.getRootDeviceType(), RootDeviceType.EBS);
+      assertEquals(ebsImage.getRootDeviceName(), "/dev/sda1");
+      assertEquals(ebsImage.getEbsBlockDevices().entrySet(),
+            ImmutableMap.of("/dev/sda1", new Image.EbsBlockDevice(snapshot.getId(), VOLUME_SIZE, true)).entrySet());
+   }
+
+   private void tryToChangeStuff() {
+      setUserDataForInstanceInRegion();
+      setRamdiskForInstanceInRegion();
+      setKernelForInstanceInRegion();
+      setInstanceTypeForInstanceInRegion();
+      setInstanceInitiatedShutdownBehaviorForInstanceInRegion();
+      setBlockDeviceMappingForInstanceInRegion();
+   }
+
+   private void setUserDataForInstanceInRegion() {
+      client.getInstanceApi().get().setUserDataForInstanceInRegion(null, ebsInstance.getId(), "test".getBytes());
+      assertEquals("test", client.getInstanceApi().get().getUserDataForInstanceInRegion(null, ebsInstance.getId()));
+   }
+
+   private void setRamdiskForInstanceInRegion() {
+      String ramdisk = client.getInstanceApi().get().getRamdiskForInstanceInRegion(null, ebsInstance.getId());
+      client.getInstanceApi().get().setRamdiskForInstanceInRegion(null, ebsInstance.getId(), ramdisk);
+      assertEquals(ramdisk, client.getInstanceApi().get().getRamdiskForInstanceInRegion(null, ebsInstance.getId()));
+   }
+
+   private void setKernelForInstanceInRegion() {
+      String oldKernel = client.getInstanceApi().get().getKernelForInstanceInRegion(null, ebsInstance.getId());
+      client.getInstanceApi().get().setKernelForInstanceInRegion(null, ebsInstance.getId(), oldKernel);
+      assertEquals(oldKernel, client.getInstanceApi().get().getKernelForInstanceInRegion(null, ebsInstance.getId()));
+   }
+
+   private void setInstanceTypeForInstanceInRegion() {
+      client.getInstanceApi().get()
+            .setInstanceTypeForInstanceInRegion(null, ebsInstance.getId(), InstanceType.C1_MEDIUM);
+      assertEquals(InstanceType.C1_MEDIUM,
+            client.getInstanceApi().get().getInstanceTypeForInstanceInRegion(null, ebsInstance.getId()));
+      client.getInstanceApi().get().setInstanceTypeForInstanceInRegion(null, ebsInstance.getId(), InstanceType.M1_SMALL);
+      assertEquals(InstanceType.M1_SMALL,
+            client.getInstanceApi().get().getInstanceTypeForInstanceInRegion(null, ebsInstance.getId()));
+   }
+
+   private void setBlockDeviceMappingForInstanceInRegion() {
+      String volumeId = ebsInstance.getEbsBlockDevices().get("/dev/sda1").getVolumeId();
+
+      Map<String, BlockDevice> mapping = Maps.newLinkedHashMap();
+      mapping.put("/dev/sda1", new BlockDevice(volumeId, false));
+      try {
+         client.getInstanceApi().get().setBlockDeviceMappingForInstanceInRegion(null, ebsInstance.getId(), mapping);
+
+         Map<String, BlockDevice> devices = client.getInstanceApi().get().getBlockDeviceMappingForInstanceInRegion(null,
+               ebsInstance.getId());
+         assertEquals(devices.size(), 1);
+         String deviceName = Iterables.getOnlyElement(devices.keySet());
+         BlockDevice device = Iterables.getOnlyElement(devices.values());
+
+         assertEquals(device.getVolumeId(), volumeId);
+         assertEquals(deviceName, "/dev/sda1");
+         assertEquals(device.isDeleteOnTermination(), false);
+
+         System.out.println("OK: setBlockDeviceMappingForInstanceInRegion");
+      } catch (Exception e) {
+         System.err.println("setBlockDeviceMappingForInstanceInRegion");
+
+         e.printStackTrace();
+      }
+   }
+
+   private void setInstanceInitiatedShutdownBehaviorForInstanceInRegion() {
+      try {
+
+         client.getInstanceApi().get().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
+               ebsInstance.getId(), InstanceInitiatedShutdownBehavior.STOP);
+
+         assertEquals(InstanceInitiatedShutdownBehavior.STOP, client.getInstanceApi().get()
+               .getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, ebsInstance.getId()));
+         client.getInstanceApi().get().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
+               ebsInstance.getId(), InstanceInitiatedShutdownBehavior.TERMINATE);
+
+         assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client.getInstanceApi().get()
+               .getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, 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
+    * 
+    * @throws UnknownHostException
+    */
+   private void sshPing(RunningInstance newDetails) throws UnknownHostException {
+      try {
+         doCheckKey(newDetails);
+      } catch (SshException e) {// try twice in case there is a network timeout
+         try {
+            Thread.sleep(10 * 1000);
+         } catch (InterruptedException e1) {
+         }
+         doCheckKey(newDetails);
+      }
+   }
+
+   private void doCheckKey(RunningInstance newDetails) throws UnknownHostException {
+      doCheckKey(newDetails.getIpAddress());
+   }
+
+   private void doCheckKey(String address) {
+      SshClient ssh = sshFactory.create(HostAndPort.fromParts(address, 22),
+            LoginCredentials.builder().user("ubuntu").privateKey(keyPair.getKeyMaterial()).build());
+      try {
+         ssh.connect();
+         ExecResponse hello = ssh.exec("echo hello");
+         assertEquals(hello.getOutput().trim(), "hello");
+      } finally {
+         if (ssh != null)
+            ssh.disconnect();
+      }
+   }
+
+   private RunningInstance blockUntilWeCanSshIntoInstance(RunningInstance instance) throws UnknownHostException {
+      System.out.printf("%d: %s awaiting instance to run %n", System.currentTimeMillis(), instance.getId());
+      assert runningTester.apply(instance);
+
+      // search my identity for the instance I just created
+      Set<? extends Reservation<? extends RunningInstance>> reservations = client.getInstanceApi().get()
+            .describeInstancesInRegion(instance.getRegion(), instance.getId()); // last
+      // parameter
+      // (ids)
+      // narrows
+      // the
+      // search
+
+      instance = Iterables.getOnlyElement(Iterables.getOnlyElement(reservations));
+
+      System.out.printf("%d: %s awaiting ssh service to start%n", System.currentTimeMillis(), instance.getIpAddress());
+      assert socketTester.apply(HostAndPort.fromParts(instance.getIpAddress(), 22));
+      System.out.printf("%d: %s ssh service started%n", System.currentTimeMillis(), instance.getDnsName());
+      sshPing(instance);
+      System.out.printf("%d: %s ssh connection made%n", System.currentTimeMillis(), instance.getId());
+      return instance;
+   }
+
+   @AfterTest
+   void cleanup() {
+      if (ebsInstance != null) {
+         try {
+            client.getInstanceApi().get().terminateInstancesInRegion(ebsInstance.getRegion(), ebsInstance.getId());
+            terminatedTester.apply(ebsInstance);
+         } catch (Exception e) {
+            e.printStackTrace();
+         }
+      }
+      if (ebsImage != null) {
+         try {
+            client.getAMIApi().get().deregisterImageInRegion(ebsImage.getRegion(), ebsImage.getId());
+         } catch (Exception e) {
+            e.printStackTrace();
+         }
+      }
+
+      if (snapshot != null) {
+         try {
+            client.getElasticBlockStoreApi().get().deleteSnapshotInRegion(snapshot.getRegion(), snapshot.getId());
+         } catch (Exception e) {
+            e.printStackTrace();
+         }
+      }
+      if (attachment != null) {
+         try {
+            client.getElasticBlockStoreApi().get().detachVolumeInRegion(volume.getRegion(), volume.getId(), true);
+            assert volumeTester.apply(volume);
+         } catch (Exception e) {
+            e.printStackTrace();
+         }
+      }
+      if (instance != null) {
+         try {
+            client.getInstanceApi().get().terminateInstancesInRegion(instance.getRegion(), instance.getId());
+            terminatedTester.apply(instance);
+         } catch (Exception e) {
+            e.printStackTrace();
+         }
+      }
+      if (volume != null) {
+         try {
+            client.getElasticBlockStoreApi().get().deleteVolumeInRegion(volume.getRegion(), volume.getId());
+         } catch (Exception e) {
+            e.printStackTrace();
+         }
+      }
+      if (keyPair != null) {
+         try {
+            client.getKeyPairApi().get().deleteKeyPairInRegion(keyPair.getRegion(), keyPair.getKeyName());
+         } catch (Exception e) {
+            e.printStackTrace();
+         }
+      }
+      if (securityGroupName != null) {
+         try {
+            client.getSecurityGroupApi().get().deleteSecurityGroupInRegion(null, securityGroupName);
+         } catch (Exception e) {
+            e.printStackTrace();
+         }
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/EC2ApiMetadataTest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/EC2ApiMetadataTest.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/EC2ApiMetadataTest.java
new file mode 100644
index 0000000..584c1f0
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/EC2ApiMetadataTest.java
@@ -0,0 +1,32 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2;
+
+import org.jclouds.compute.internal.BaseComputeServiceApiMetadataTest;
+import org.testng.annotations.Test;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "EC2ApiMetadataTest")
+public class EC2ApiMetadataTest extends BaseComputeServiceApiMetadataTest {
+
+   public EC2ApiMetadataTest() {
+      super(new EC2ApiMetadata());
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/EC2ContextBuilderText.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/EC2ContextBuilderText.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/EC2ContextBuilderText.java
new file mode 100644
index 0000000..e672fd3
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/EC2ContextBuilderText.java
@@ -0,0 +1,36 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2;
+
+import static org.jclouds.reflect.Reflection2.typeToken;
+
+import org.jclouds.ContextBuilder;
+import org.jclouds.View;
+import org.jclouds.compute.ComputeServiceContext;
+import org.testng.annotations.Test;
+
+/**
+ * @author Andrew Bayer
+ */
+@Test(groups = "unit", testName = "EC2ContextBuilderTest")
+public class EC2ContextBuilderText {
+   public void testAssignability() {
+      View view = ContextBuilder.newBuilder(new EC2ApiMetadata()).credentials("foo", "bar")
+              .buildView(typeToken(ComputeServiceContext.class));
+      view.unwrapApi(EC2Api.class);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindBlockDeviceMappingToIndexedFormParamsTest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindBlockDeviceMappingToIndexedFormParamsTest.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindBlockDeviceMappingToIndexedFormParamsTest.java
new file mode 100644
index 0000000..86973e7
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindBlockDeviceMappingToIndexedFormParamsTest.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.File;
+import java.util.Date;
+import java.util.Map;
+
+import org.jclouds.ec2.domain.Attachment.Status;
+import org.jclouds.ec2.domain.BlockDevice;
+import org.jclouds.http.HttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Maps;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code BindBlockDeviceMappingToIndexedFormParams}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public class BindBlockDeviceMappingToIndexedFormParamsTest {
+   Injector injector = Guice.createInjector();
+   BindBlockDeviceMappingToIndexedFormParams binder = injector
+         .getInstance(BindBlockDeviceMappingToIndexedFormParams.class);
+
+   public void testMappingOrdersLexicographically() {
+      Map<String, BlockDevice> mapping = Maps.newLinkedHashMap();
+      mapping.put("apple", new BlockDevice("appleId", true));
+      Date date = new Date(999999l);
+      mapping.put("cranberry", new BlockDevice("cranberry", Status.ATTACHED, date, false));
+
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost")
+            .addFormParam("InstanceId", "i-foo").build();
+      request = binder.bindToRequest(request, mapping);
+      assertEquals(
+            request.getPayload().getRawContent(),
+            "Action=ModifyInstanceAttribute&BlockDeviceMapping.1.DeviceName=apple&BlockDeviceMapping.1.Ebs.DeleteOnTermination=true&BlockDeviceMapping.1.Ebs.VolumeId=appleId&BlockDeviceMapping.2.DeviceName=cranberry&BlockDeviceMapping.2.Ebs.DeleteOnTermination=false&BlockDeviceMapping.2.Ebs.VolumeId=cranberry&InstanceId=i-foo");
+   }
+
+   @Test(expectedExceptions = IllegalArgumentException.class)
+   public void testMustBeBlockDeviceMapping() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      binder.bindToRequest(request, new File("foo"));
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullIsBad() {
+      HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
+      binder.bindToRequest(request, null);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindBundleIdsToIndexedFormParamsTest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindBundleIdsToIndexedFormParamsTest.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindBundleIdsToIndexedFormParamsTest.java
new file mode 100644
index 0000000..5796373
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindBundleIdsToIndexedFormParamsTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.File;
+
+import org.jclouds.http.HttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code BindBundleIdsToIndexedFormParams}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public class BindBundleIdsToIndexedFormParamsTest {
+   Injector injector = Guice.createInjector();
+   BindBundleIdsToIndexedFormParams binder = injector.getInstance(BindBundleIdsToIndexedFormParams.class);
+
+   public void test() {
+
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      request = binder.bindToRequest(request, new String[] { "alpha", "omega" });
+      assertEquals(request.getPayload().getRawContent(), "BundleId.1=alpha&BundleId.2=omega");
+   }
+
+   @Test(expectedExceptions = IllegalArgumentException.class)
+   public void testMustBeArray() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      binder.bindToRequest(request, new File("foo"));
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullIsBad() {
+      HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
+      binder.bindToRequest(request, null);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindFiltersToIndexedFormParamsTest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindFiltersToIndexedFormParamsTest.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindFiltersToIndexedFormParamsTest.java
new file mode 100644
index 0000000..a4edc1c
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindFiltersToIndexedFormParamsTest.java
@@ -0,0 +1,63 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.File;
+
+import org.jclouds.http.HttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code BindFiltersToIndexedFormParams}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public class BindFiltersToIndexedFormParamsTest {
+   Injector injector = Guice.createInjector();
+   BindFiltersToIndexedFormParams binder = injector.getInstance(BindFiltersToIndexedFormParams.class);
+
+   public void test() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      request = binder.bindToRequest(request, ImmutableMultimap.<String, String> builder()
+                                                               .put("resource-type", "instance")
+                                                               .put("key", "stack")
+                                                               .putAll("value", "Test", "Production")
+                                                               .build());
+      assertEquals(
+            request.getPayload().getRawContent(),
+            "Filter.1.Name=resource-type&Filter.1.Value.1=instance&Filter.2.Name=key&Filter.2.Value.1=stack&Filter.3.Name=value&Filter.3.Value.1=Test&Filter.3.Value.2=Production");
+   }
+
+   @Test(expectedExceptions = IllegalArgumentException.class)
+   public void testMustBeMultimap() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      binder.bindToRequest(request, new File("foo"));
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullIsBad() {
+      HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
+      binder.bindToRequest(request, null);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindGroupNamesToIndexedFormParamsTest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindGroupNamesToIndexedFormParamsTest.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindGroupNamesToIndexedFormParamsTest.java
new file mode 100644
index 0000000..6a63472
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindGroupNamesToIndexedFormParamsTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.File;
+
+import org.jclouds.http.HttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code BindGroupNamesToIndexedFormParams}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public class BindGroupNamesToIndexedFormParamsTest {
+   Injector injector = Guice.createInjector();
+   BindGroupNamesToIndexedFormParams binder = injector.getInstance(BindGroupNamesToIndexedFormParams.class);
+
+   public void test() {
+
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      request = binder.bindToRequest(request, new String[] { "alpha", "omega" });
+      assertEquals(request.getPayload().getRawContent(), "GroupName.1=alpha&GroupName.2=omega");
+   }
+
+   @Test(expectedExceptions = IllegalArgumentException.class)
+   public void testMustBeArray() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      binder.bindToRequest(request, new File("foo"));
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullIsBad() {
+      HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
+      binder.bindToRequest(request, null);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindInstanceIdsToIndexedFormParamsTest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindInstanceIdsToIndexedFormParamsTest.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindInstanceIdsToIndexedFormParamsTest.java
new file mode 100644
index 0000000..b5a932a
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindInstanceIdsToIndexedFormParamsTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.File;
+
+import org.jclouds.http.HttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code BindInstanceIdsToIndexedFormParams}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public class BindInstanceIdsToIndexedFormParamsTest {
+   Injector injector = Guice.createInjector();
+   BindInstanceIdsToIndexedFormParams binder = injector.getInstance(BindInstanceIdsToIndexedFormParams.class);
+
+   public void test() {
+
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      request = binder.bindToRequest(request, new String[] { "alpha", "omega" });
+      assertEquals(request.getPayload().getRawContent(), "InstanceId.1=alpha&InstanceId.2=omega");
+   }
+
+   @Test(expectedExceptions = IllegalArgumentException.class)
+   public void testMustBeArray() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      binder.bindToRequest(request, new File("foo"));
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullIsBad() {
+      HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
+      binder.bindToRequest(request, null);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindKeyNamesToIndexedFormParamsTest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindKeyNamesToIndexedFormParamsTest.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindKeyNamesToIndexedFormParamsTest.java
new file mode 100644
index 0000000..230f678
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindKeyNamesToIndexedFormParamsTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.File;
+
+import org.jclouds.http.HttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code BindKeyNamesToIndexedFormParams}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public class BindKeyNamesToIndexedFormParamsTest {
+   Injector injector = Guice.createInjector();
+   BindKeyNamesToIndexedFormParams binder = injector.getInstance(BindKeyNamesToIndexedFormParams.class);
+
+   public void test() {
+
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      request = binder.bindToRequest(request, new String[] { "alpha", "omega" });
+      assertEquals(request.getPayload().getRawContent(), "KeyName.1=alpha&KeyName.2=omega");
+   }
+
+   @Test(expectedExceptions = IllegalArgumentException.class)
+   public void testMustBeArray() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      binder.bindToRequest(request, new File("foo"));
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullIsBad() {
+      HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
+      binder.bindToRequest(request, null);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindProductCodesToIndexedFormParamsTest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindProductCodesToIndexedFormParamsTest.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindProductCodesToIndexedFormParamsTest.java
new file mode 100644
index 0000000..f452a69
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindProductCodesToIndexedFormParamsTest.java
@@ -0,0 +1,58 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.File;
+
+import org.jclouds.http.HttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code BindProductCodesToIndexedFormParams}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public class BindProductCodesToIndexedFormParamsTest {
+   Injector injector = Guice.createInjector();
+   BindProductCodesToIndexedFormParams binder = injector.getInstance(BindProductCodesToIndexedFormParams.class);
+
+   public void test() {
+
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      request = binder.bindToRequest(request, ImmutableSet.of("alpha", "omega"));
+      assertEquals(request.getPayload().getRawContent(), "ProductCode.1=alpha&ProductCode.2=omega");
+   }
+
+   @Test(expectedExceptions = IllegalArgumentException.class)
+   public void testMustBeIterable() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      binder.bindToRequest(request, new File("foo"));
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullIsBad() {
+      HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
+      binder.bindToRequest(request, null);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindPublicIpsToIndexedFormParamsTest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindPublicIpsToIndexedFormParamsTest.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindPublicIpsToIndexedFormParamsTest.java
new file mode 100644
index 0000000..ae9b79e
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindPublicIpsToIndexedFormParamsTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.File;
+
+import org.jclouds.http.HttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code BindPublicIpsToIndexedFormParams}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public class BindPublicIpsToIndexedFormParamsTest {
+   Injector injector = Guice.createInjector();
+   BindPublicIpsToIndexedFormParams binder = injector.getInstance(BindPublicIpsToIndexedFormParams.class);
+
+   public void test() {
+
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      request = binder.bindToRequest(request, new String[] { "alpha", "omega" });
+      assertEquals(request.getPayload().getRawContent(), "PublicIp.1=alpha&PublicIp.2=omega");
+   }
+
+   @Test(expectedExceptions = IllegalArgumentException.class)
+   public void testMustBeArray() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      binder.bindToRequest(request, new File("foo"));
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullIsBad() {
+      HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
+      binder.bindToRequest(request, null);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindResourceIdsToIndexedFormParamsTest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindResourceIdsToIndexedFormParamsTest.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindResourceIdsToIndexedFormParamsTest.java
new file mode 100644
index 0000000..e90d0e2
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindResourceIdsToIndexedFormParamsTest.java
@@ -0,0 +1,57 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.File;
+
+import org.jclouds.http.HttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.inject.Guice;
+import com.google.inject.Injector;
+
+/**
+ * Tests behavior of {@code BindResourceIdsToIndexedFormParams}
+ * 
+ * @author grkvlt@apache.org
+ */
+@Test(groups = "unit")
+public class BindResourceIdsToIndexedFormParamsTest {
+   Injector injector = Guice.createInjector();
+   BindResourceIdsToIndexedFormParams binder = injector.getInstance(BindResourceIdsToIndexedFormParams.class);
+
+   public void test() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      request = binder.bindToRequest(request, ImmutableList.builder().add("alpha").add("omega").build());
+      assertEquals(request.getPayload().getRawContent(), "ResourceId.1=alpha&ResourceId.2=omega");
+   }
+
+   @Test(expectedExceptions = IllegalArgumentException.class)
+   public void testMustBeArray() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      binder.bindToRequest(request, new File("foo"));
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullIsBad() {
+      HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
+      binder.bindToRequest(request, null);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindS3UploadPolicyAndSignatureTest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindS3UploadPolicyAndSignatureTest.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindS3UploadPolicyAndSignatureTest.java
new file mode 100644
index 0000000..5c92aec
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindS3UploadPolicyAndSignatureTest.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+
+import org.jclouds.ec2.features.BaseEC2ApiTest;
+import org.jclouds.ec2.features.InstanceApi;
+import org.jclouds.http.HttpRequest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code BindS3UploadPolicyAndSignature}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "BindS3UploadPolicyAndSignatureTest")
+public class BindS3UploadPolicyAndSignatureTest extends BaseEC2ApiTest<InstanceApi> {
+   private BindS3UploadPolicyAndSignature binder;
+
+   @BeforeClass
+   @Override
+   protected void setupFactory() throws IOException {
+      super.setupFactory();
+      binder = injector.getInstance(BindS3UploadPolicyAndSignature.class);
+   }
+
+   public void testMapping() {
+      String json = "{\"foo\":true}";
+
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      request = binder.bindToRequest(request, json);
+      assertEquals(
+            request.getPayload().getRawContent(),
+            "Storage.S3.UploadPolicy=eyJmb28iOnRydWV9&Storage.S3.UploadPolicySignature=UbDQLDM5P3aZ840aqJoH%2B6rwDcRo5KrIfsG7vJWHIVY%3D");
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullIsBad() {
+      HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
+      binder.bindToRequest(request, null);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindTagKeysToIndexedFormParamsTest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindTagKeysToIndexedFormParamsTest.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindTagKeysToIndexedFormParamsTest.java
new file mode 100644
index 0000000..05c3c62
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindTagKeysToIndexedFormParamsTest.java
@@ -0,0 +1,54 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.File;
+
+import org.jclouds.http.HttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Tests behavior of {@code BindTagKeysToIndexedFormParams}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public class BindTagKeysToIndexedFormParamsTest {
+   BindTagKeysToIndexedFormParams binder = new BindTagKeysToIndexedFormParams();
+
+   public void test() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      request = binder.bindToRequest(request, ImmutableSet.of("one", "two"));
+      assertEquals(request.getPayload().getRawContent(), "Tag.1.Key=one&Tag.2.Key=two");
+   }
+
+   @Test(expectedExceptions = IllegalArgumentException.class)
+   public void testMustBeIterable() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      binder.bindToRequest(request, new File("foo"));
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullIsBad() {
+      HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
+      binder.bindToRequest(request, null);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-stratos/blob/58fe66df/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindTagsToIndexedFormParamsTest.java
----------------------------------------------------------------------
diff --git a/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindTagsToIndexedFormParamsTest.java b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindTagsToIndexedFormParamsTest.java
new file mode 100644
index 0000000..12614ba
--- /dev/null
+++ b/dependencies/jclouds/apis/ec2/1.7.1-stratos/src/test/java/org/jclouds/ec2/binders/BindTagsToIndexedFormParamsTest.java
@@ -0,0 +1,62 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You 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.ec2.binders;
+
+import static org.testng.Assert.assertEquals;
+
+import java.io.File;
+
+import org.jclouds.http.HttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Tests behavior of {@code BindTagsToIndexedFormParams}
+ * 
+ * @author grkvlt@apache.org
+ */
+@Test(groups = "unit")
+public class BindTagsToIndexedFormParamsTest {
+   BindTagsToIndexedFormParams binder = new BindTagsToIndexedFormParams();
+
+   public void test() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      request = binder.bindToRequest(request, ImmutableMap.of("one", "alpha", "two", "beta"));
+      assertEquals(request.getPayload().getRawContent(),
+            "Tag.1.Key=one&Tag.1.Value=alpha&Tag.2.Key=two&Tag.2.Value=beta");
+   }
+
+   public void testEmpty() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      request = binder.bindToRequest(request, ImmutableSet.of("empty"));
+      assertEquals(request.getPayload().getRawContent(), "Tag.1.Key=empty&Tag.1.Value=");
+   }
+
+   @Test(expectedExceptions = IllegalArgumentException.class)
+   public void testMustBeArray() {
+      HttpRequest request = HttpRequest.builder().method("POST").endpoint("http://localhost").build();
+      binder.bindToRequest(request, new File("foo"));
+   }
+
+   @Test(expectedExceptions = NullPointerException.class)
+   public void testNullIsBad() {
+      HttpRequest request = HttpRequest.builder().method("GET").endpoint("http://momma").build();
+      binder.bindToRequest(request, null);
+   }
+}