You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ab...@apache.org on 2013/07/01 21:13:06 UTC

[01/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Updated Branches:
  refs/heads/master 5f524ee6c -> 5f3b8d3fa


http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupClientLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupClientLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupClientLiveTest.java
deleted file mode 100644
index d7f6663..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupClientLiveTest.java
+++ /dev/null
@@ -1,184 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static com.google.common.collect.Lists.newArrayList;
-import static com.google.common.collect.Sets.newTreeSet;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.jclouds.util.Predicates2.retry;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.fail;
-
-import java.util.ArrayList;
-import java.util.Set;
-import java.util.SortedSet;
-
-import org.jclouds.aws.domain.Region;
-import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
-import org.jclouds.aws.ec2.AWSEC2Client;
-import org.jclouds.aws.ec2.domain.PlacementGroup;
-import org.jclouds.aws.ec2.domain.PlacementGroup.State;
-import org.jclouds.aws.ec2.predicates.PlacementGroupAvailable;
-import org.jclouds.aws.ec2.predicates.PlacementGroupDeleted;
-import org.jclouds.compute.RunNodesException;
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.OsFamily;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.jclouds.compute.predicates.NodePredicates;
-import org.jclouds.ec2.compute.domain.EC2HardwareBuilder;
-import org.jclouds.ec2.domain.InstanceType;
-import org.jclouds.scriptbuilder.domain.Statements;
-import org.jclouds.scriptbuilder.statements.java.InstallJDK;
-import org.jclouds.scriptbuilder.statements.login.AdminAccess;
-import org.jclouds.sshj.config.SshjSshClientModule;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Throwables;
-import com.google.inject.Module;
-
-/**
- * Tests behavior of {@code PlacementGroupClient}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true, testName = "PlacementGroupClientLiveTest")
-public class PlacementGroupClientLiveTest extends BaseComputeServiceContextLiveTest {
-   ArrayList<String> supportedRegions = newArrayList(Region.US_EAST_1, Region.US_WEST_2, Region.EU_WEST_1);
-
-   public PlacementGroupClientLiveTest() {
-      provider = "aws-ec2";
-   }
-
-   private AWSEC2Client client;
-   private Predicate<PlacementGroup> availableTester;
-   private Predicate<PlacementGroup> deletedTester;
-   private PlacementGroup group;
-
-   @Override
-   @BeforeClass(groups = { "integration", "live" })
-   public void setupContext() {
-      super.setupContext();
-      client = view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi();
-      availableTester = retry(new PlacementGroupAvailable(client), 60, 1, SECONDS);
-      deletedTester = retry(new PlacementGroupDeleted(client), 60, 1, SECONDS);
-   }
-
-   @Test
-   void testDescribe() {
-      for (String region : supportedRegions) {
-         SortedSet<PlacementGroup> allResults = newTreeSet(client.getPlacementGroupServices()
-                  .describePlacementGroupsInRegion(region));
-         assertNotNull(allResults);
-         if (allResults.size() >= 1) {
-            PlacementGroup group = allResults.last();
-            SortedSet<PlacementGroup> result = newTreeSet(client.getPlacementGroupServices()
-                     .describePlacementGroupsInRegion(region, group.getName()));
-            assertNotNull(result);
-            PlacementGroup compare = result.last();
-            assertEquals(compare, group);
-         }
-      }
-
-      for (String region : client.getAvailabilityZoneAndRegionServices().describeRegions().keySet()) {
-         if (!supportedRegions.contains(region))
-            try {
-               client.getPlacementGroupServices().describePlacementGroupsInRegion(region);
-               fail("should be unsupported for region: " + region);
-            } catch (UnsupportedOperationException e) {
-            }
-      }
-   }
-
-   @Test
-   void testCreatePlacementGroup() {
-      String groupName = PREFIX + "1";
-      for (String region : supportedRegions) {
-
-         client.getPlacementGroupServices().deletePlacementGroupInRegion(region, groupName);
-         client.getPlacementGroupServices().createPlacementGroupInRegion(region, groupName);
-
-         verifyPlacementGroup(region, groupName);
-      }
-   }
-
-   private void verifyPlacementGroup(String region, String groupName) {
-      assert availableTester.apply(new PlacementGroup(region, groupName, "cluster", State.PENDING)) : group;
-      Set<PlacementGroup> oneResult = client.getPlacementGroupServices().describePlacementGroupsInRegion(region,
-               groupName);
-      assertNotNull(oneResult);
-      assertEquals(oneResult.size(), 1);
-      group = oneResult.iterator().next();
-      assertEquals(group.getName(), groupName);
-      assertEquals(group.getStrategy(), "cluster");
-      assert availableTester.apply(group) : group;
-   }
-
-   public void testStartCCInstance() throws Exception {
-
-      Template template = view.getComputeService().templateBuilder()
-               .fromHardware(EC2HardwareBuilder.cc2_8xlarge().build()).osFamily(OsFamily.AMZN_LINUX).build();
-      assert template != null : "The returned template was null, but it should have a value.";
-      assertEquals(template.getHardware().getProviderId(), InstanceType.CC2_8XLARGE);
-      assertEquals(template.getImage().getUserMetadata().get("rootDeviceType"), "ebs");
-      assertEquals(template.getImage().getUserMetadata().get("virtualizationType"), "hvm");
-      assertEquals(template.getImage().getUserMetadata().get("hypervisor"), "xen");
-
-      template.getOptions().runScript(Statements.newStatementList(AdminAccess.standard(), InstallJDK.fromOpenJDK()));
-
-      String group = PREFIX + "cccluster";
-      view.getComputeService().destroyNodesMatching(NodePredicates.inGroup(group));
-      // TODO make this not lookup an explicit region
-      client.getPlacementGroupServices().deletePlacementGroupInRegion(null, "jclouds#" + group + "#us-east-1");
-
-      try {
-         Set<? extends NodeMetadata> nodes = view.getComputeService().createNodesInGroup(group, 1, template);
-         NodeMetadata node = getOnlyElement(nodes);
-
-         getOnlyElement(getOnlyElement(client.getInstanceServices().describeInstancesInRegion(null,
-                  node.getProviderId())));
-
-      } catch (RunNodesException e) {
-         System.err.println(e.getNodeErrors().keySet());
-         Throwables.propagate(e);
-      } finally {
-         view.getComputeService().destroyNodesMatching(NodePredicates.inGroup(group));
-      }
-   }
-
-   public static final String PREFIX = System.getProperty("user.name") + "ec2";
-
-   @Override
-   @AfterClass(groups = { "integration", "live" })
-   protected void tearDownContext() {
-      if (group != null) {
-         client.getPlacementGroupServices().deletePlacementGroupInRegion(group.getRegion(), group.getName());
-         assert deletedTester.apply(group) : group;
-      }
-      super.tearDownContext();
-   }
-
-   @Override
-   protected Module getSshModule() {
-      return new SshjSshClientModule();
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/SpotInstanceAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/SpotInstanceAsyncClientTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/SpotInstanceAsyncClientTest.java
deleted file mode 100644
index ec7751a..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/SpotInstanceAsyncClientTest.java
+++ /dev/null
@@ -1,100 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-import java.util.Date;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions;
-import org.jclouds.aws.ec2.xml.DescribeSpotPriceHistoryResponseHandler;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.http.functions.ReleasePayloadAndReturn;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.Lists;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code SpotInstanceAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "SpotInstanceAsyncClientTest")
-public class SpotInstanceAsyncClientTest extends BaseAWSEC2AsyncClientTest<SpotInstanceAsyncClient> {
-
-   public void testCancelSpotInstanceRequests() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(SpotInstanceAsyncClient.class, "cancelSpotInstanceRequestsInRegion", String.class,
-            String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "id"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=CancelSpotInstanceRequests&SpotInstanceRequestId.1=id",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, VoidOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeSpotPriceHistory() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(SpotInstanceAsyncClient.class, "describeSpotPriceHistoryInRegion", String.class,
-            DescribeSpotPriceHistoryOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeSpotPriceHistory",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeSpotPriceHistoryResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   Date from = new Date(12345678910l);
-   Date to = new Date(1234567891011l);
-
-   public void testDescribeSpotPriceHistoryArgs() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(SpotInstanceAsyncClient.class, "describeSpotPriceHistoryInRegion", String.class,
-            DescribeSpotPriceHistoryOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, DescribeSpotPriceHistoryOptions.Builder.from(from)
-            .to(to).productDescription("description").instanceType("m1.small")));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(
-            request,
-            "Action=DescribeSpotPriceHistory&StartTime=1970-05-23T21%3A21%3A18.910Z&EndTime=2009-02-13T23%3A31%3A31.011Z&ProductDescription=description&InstanceType.1=m1.small",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeSpotPriceHistoryResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/SpotInstanceClientLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/SpotInstanceClientLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/SpotInstanceClientLiveTest.java
deleted file mode 100644
index 3def6f6..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/SpotInstanceClientLiveTest.java
+++ /dev/null
@@ -1,176 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static com.google.common.base.Predicates.in;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions.Builder.from;
-import static org.jclouds.aws.ec2.options.RequestSpotInstancesOptions.Builder.launchGroup;
-import static org.jclouds.util.Predicates2.retry;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
-import java.util.Date;
-import java.util.Set;
-import java.util.SortedSet;
-import java.util.concurrent.TimeUnit;
-
-import org.jclouds.aws.domain.Region;
-import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
-import org.jclouds.aws.ec2.AWSEC2Client;
-import org.jclouds.aws.ec2.domain.AWSRunningInstance;
-import org.jclouds.aws.ec2.domain.LaunchSpecification;
-import org.jclouds.aws.ec2.domain.Spot;
-import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
-import org.jclouds.aws.ec2.predicates.SpotInstanceRequestActive;
-import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.jclouds.ec2.domain.InstanceType;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.ImmutableSortedSet;
-
-/**
- * Tests behavior of {@code SpotInstanceClient}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true)
-public class SpotInstanceClientLiveTest  extends BaseComputeServiceContextLiveTest {
-   public SpotInstanceClientLiveTest() {
-      provider = "aws-ec2";
-   }
-
-   private static final int SPOT_DELAY_SECONDS = 600;
-   private AWSEC2Client client;
-   private Predicate<SpotInstanceRequest> activeTester;
-   private Set<SpotInstanceRequest> requests;
-   private AWSRunningInstance instance;
-   private long start;
-
-   @Override
-   @BeforeClass(groups = { "integration", "live" })
-   public void setupContext() {
-      super.setupContext();
-      client = view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi();
-      activeTester = retry(new SpotInstanceRequestActive(client), SPOT_DELAY_SECONDS, 1, 1, SECONDS);
-   }
-
-   @Test
-   void testDescribeSpotRequestsInRegion() {
-      for (String region : Region.DEFAULT_REGIONS) {
-         SortedSet<SpotInstanceRequest> allResults = ImmutableSortedSet.copyOf(client.getSpotInstanceServices()
-                  .describeSpotInstanceRequestsInRegion(region));
-         assertNotNull(allResults);
-         if (allResults.size() >= 1) {
-            SpotInstanceRequest request = allResults.last();
-            SortedSet<SpotInstanceRequest> result = ImmutableSortedSet.copyOf(client.getSpotInstanceServices()
-                     .describeSpotInstanceRequestsInRegion(region, request.getId()));
-            assertNotNull(result);
-            SpotInstanceRequest compare = result.last();
-            assertEquals(compare, request);
-         }
-      }
-
-   }
-
-   @Test
-   void testDescribeSpotPriceHistoryInRegion() {
-      for (String region : Region.DEFAULT_REGIONS) {
-         Set<Spot> spots = client.getSpotInstanceServices().describeSpotPriceHistoryInRegion(region, from(new Date()));
-         assertNotNull(spots);
-         assert spots.size() > 0;
-         for (Spot spot : spots) {
-            assert spot.getSpotPrice() > 0 : spots;
-            assertEquals(spot.getRegion(), region);
-            assert in(
-                     ImmutableSet.of("Linux/UNIX", "Linux/UNIX (Amazon VPC)", "SUSE Linux", "SUSE Linux (Amazon VPC)",
-                              "Windows", "Windows (Amazon VPC)")).apply(spot.getProductDescription()) : spot;
-            assert in(
-                     ImmutableSet.of("c1.medium", "c1.xlarge", "cc1.4xlarge", "cg1.4xlarge", "cc2.8xlarge", "m1.large",
-                              "m1.small", "m1.medium", "m1.xlarge", "m2.2xlarge", "m2.4xlarge", "m2.xlarge", "m3.xlarge", 
-                              "m3.2xlarge", "t1.micro")).apply(
-                     spot.getInstanceType()) : spot;
-
-         }
-      }
-
-   }
-
-   @Test(enabled = true)
-   void testCreateSpotInstance() {
-      String launchGroup = PREFIX + "1";
-      for (String region : Region.DEFAULT_REGIONS)
-         for (SpotInstanceRequest request : client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(
-                  region))
-            if (launchGroup.equals(request.getLaunchGroup()))
-               client.getSpotInstanceServices().cancelSpotInstanceRequestsInRegion(region, request.getId());
-
-      start = System.currentTimeMillis();
-
-      requests = client.getSpotInstanceServices().requestSpotInstancesInRegion(
-               "sa-east-1",
-               0.09f,
-               1,
-               LaunchSpecification.builder().imageId("ami-3e3be423").instanceType(InstanceType.M1_SMALL).build(),
-               launchGroup(launchGroup).availabilityZoneGroup(launchGroup).validFrom(
-                        new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(2))).validUntil(
-                        new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(SPOT_DELAY_SECONDS))));
-      assertNotNull(requests);
-
-      for (SpotInstanceRequest request : requests)
-         verifySpotInstance(request);
-   }
-
-   private void verifySpotInstance(SpotInstanceRequest request) {
-      SpotInstanceRequest spot = refresh(request);
-      assertNotNull(spot);
-      assertEquals(spot, request);
-      assert activeTester.apply(request) : refresh(request);
-      System.out.println(System.currentTimeMillis() - start);
-      spot = refresh(request);
-      assert spot.getInstanceId() != null : spot;
-      instance = getOnlyElement(getOnlyElement(client.getInstanceServices().describeInstancesInRegion(spot.getRegion(),
-               spot.getInstanceId())));
-      assertEquals(instance.getSpotInstanceRequestId(), spot.getId());
-   }
-
-   public SpotInstanceRequest refresh(SpotInstanceRequest request) {
-      return getOnlyElement(client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(request.getRegion(),
-               request.getId()));
-   }
-
-   public static final String PREFIX = System.getProperty("user.name") + "ec2";
-
-   @Override
-   @AfterClass(groups = { "integration", "live" })
-   protected void tearDownContext() {
-      if (requests != null) {
-         for (SpotInstanceRequest request : requests)
-            client.getSpotInstanceServices().cancelSpotInstanceRequestsInRegion(request.getRegion(), request.getId());
-         // assert deletedTester.apply(request) : request;
-      }
-      if (instance != null) {
-         client.getInstanceServices().terminateInstancesInRegion(instance.getRegion(), instance.getId());
-      }
-      super.tearDownContext();
-   }
-}


[19/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2RebootNodeStrategy.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2RebootNodeStrategy.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2RebootNodeStrategy.java
index 8ea07e4..c8cafc0 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2RebootNodeStrategy.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2RebootNodeStrategy.java
@@ -23,8 +23,8 @@ import org.jclouds.aws.util.AWSUtils;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
 import org.jclouds.compute.strategy.RebootNodeStrategy;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.services.InstanceClient;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.features.InstanceApi;
 
 /**
  * 
@@ -32,12 +32,12 @@ import org.jclouds.ec2.services.InstanceClient;
  */
 @Singleton
 public class EC2RebootNodeStrategy implements RebootNodeStrategy {
-   private final InstanceClient client;
+   private final InstanceApi client;
    private final GetNodeMetadataStrategy getNode;
 
    @Inject
-   protected EC2RebootNodeStrategy(EC2Client client, GetNodeMetadataStrategy getNode) {
-      this.client = client.getInstanceServices();
+   protected EC2RebootNodeStrategy(EC2Api client, GetNodeMetadataStrategy getNode) {
+      this.client = client.getInstanceApi().get();
       this.getNode = getNode;
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2ResumeNodeStrategy.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2ResumeNodeStrategy.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2ResumeNodeStrategy.java
index ef6e085..5ecccfc 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2ResumeNodeStrategy.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2ResumeNodeStrategy.java
@@ -23,8 +23,8 @@ import org.jclouds.aws.util.AWSUtils;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
 import org.jclouds.compute.strategy.ResumeNodeStrategy;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.services.InstanceClient;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.features.InstanceApi;
 
 /**
  * 
@@ -32,12 +32,12 @@ import org.jclouds.ec2.services.InstanceClient;
  */
 @Singleton
 public class EC2ResumeNodeStrategy implements ResumeNodeStrategy {
-   private final InstanceClient client;
+   private final InstanceApi client;
    private final GetNodeMetadataStrategy getNode;
 
    @Inject
-   protected EC2ResumeNodeStrategy(EC2Client client, GetNodeMetadataStrategy getNode) {
-      this.client = client.getInstanceServices();
+   protected EC2ResumeNodeStrategy(EC2Api client, GetNodeMetadataStrategy getNode) {
+      this.client = client.getInstanceApi().get();
       this.getNode = getNode;
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2SuspendNodeStrategy.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2SuspendNodeStrategy.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2SuspendNodeStrategy.java
index 5a30f97..cf9edd9 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2SuspendNodeStrategy.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2SuspendNodeStrategy.java
@@ -23,8 +23,8 @@ import org.jclouds.aws.util.AWSUtils;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
 import org.jclouds.compute.strategy.SuspendNodeStrategy;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.services.InstanceClient;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.features.InstanceApi;
 
 /**
  * 
@@ -32,12 +32,12 @@ import org.jclouds.ec2.services.InstanceClient;
  */
 @Singleton
 public class EC2SuspendNodeStrategy implements SuspendNodeStrategy {
-   private final InstanceClient client;
+   private final InstanceApi client;
    private final GetNodeMetadataStrategy getNode;
 
    @Inject
-   protected EC2SuspendNodeStrategy(EC2Client client, GetNodeMetadataStrategy getNode) {
-      this.client = client.getInstanceServices();
+   protected EC2SuspendNodeStrategy(EC2Api client, GetNodeMetadataStrategy getNode) {
+      this.client = client.getInstanceApi().get();
       this.getNode = getNode;
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/config/BaseEC2HttpApiModule.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/config/BaseEC2HttpApiModule.java b/apis/ec2/src/main/java/org/jclouds/ec2/config/BaseEC2HttpApiModule.java
new file mode 100644
index 0000000..d976221
--- /dev/null
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/config/BaseEC2HttpApiModule.java
@@ -0,0 +1,78 @@
+/*
+ * 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.config;
+
+import static org.jclouds.reflect.Reflection2.typeToken;
+import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
+
+import java.util.Map;
+
+import javax.inject.Singleton;
+
+import org.jclouds.aws.config.FormSigningHttpApiModule;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.features.SubnetApi;
+import org.jclouds.ec2.features.TagApi;
+import org.jclouds.ec2.features.WindowsApi;
+import org.jclouds.ec2.features.AMIApi;
+import org.jclouds.ec2.features.AvailabilityZoneAndRegionApi;
+import org.jclouds.ec2.features.ElasticBlockStoreApi;
+import org.jclouds.ec2.features.ElasticIPAddressApi;
+import org.jclouds.ec2.features.InstanceApi;
+import org.jclouds.ec2.features.KeyPairApi;
+import org.jclouds.ec2.features.SecurityGroupApi;
+import org.jclouds.ec2.suppliers.DescribeAvailabilityZonesInRegion;
+import org.jclouds.ec2.suppliers.DescribeRegionsForRegionURIs;
+import org.jclouds.location.config.LocationModule;
+import org.jclouds.location.suppliers.RegionIdToURISupplier;
+import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
+import org.jclouds.location.suppliers.RegionIdsSupplier;
+import org.jclouds.location.suppliers.ZoneIdToURISupplier;
+import org.jclouds.location.suppliers.ZoneIdsSupplier;
+import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet;
+import org.jclouds.location.suppliers.derived.ZoneIdToURIFromJoinOnRegionIdToURI;
+import org.jclouds.location.suppliers.derived.ZoneIdsFromRegionIdToZoneIdsValues;
+import org.jclouds.rest.ConfiguresHttpApi;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.reflect.TypeToken;
+import com.google.inject.Provides;
+import com.google.inject.Scopes;
+
+/**
+ * Configures the EC2 connection.
+ * 
+ * @author Adrian Cole (EDIT: Nick Terry nterry@familysearch.org)
+ */
+@ConfiguresHttpApi
+public abstract class BaseEC2HttpApiModule<A extends EC2Api> extends
+         FormSigningHttpApiModule<A> {
+
+   protected BaseEC2HttpApiModule(Class<A> api) {
+      super(api);
+   }
+
+   @Override
+   protected void installLocations() {
+      install(new LocationModule());
+      bind(RegionIdToZoneIdsSupplier.class).to(DescribeAvailabilityZonesInRegion.class).in(Scopes.SINGLETON);
+      bind(RegionIdToURISupplier.class).to(DescribeRegionsForRegionURIs.class).in(Scopes.SINGLETON);
+      bind(ZoneIdsSupplier.class).to(ZoneIdsFromRegionIdToZoneIdsValues.class).in(Scopes.SINGLETON);
+      bind(RegionIdsSupplier.class).to(RegionIdsFromRegionIdToURIKeySet.class).in(Scopes.SINGLETON);
+      bind(ZoneIdToURISupplier.class).to(ZoneIdToURIFromJoinOnRegionIdToURI.class).in(Scopes.SINGLETON);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2HttpApiModule.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2HttpApiModule.java b/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2HttpApiModule.java
new file mode 100644
index 0000000..a7e1d05
--- /dev/null
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2HttpApiModule.java
@@ -0,0 +1,67 @@
+/*
+ * 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.config;
+
+import static org.jclouds.reflect.Reflection2.typeToken;
+import static org.jclouds.rest.config.BinderUtils.bindHttpApi;
+
+import java.util.Map;
+
+import javax.inject.Singleton;
+
+import org.jclouds.aws.config.FormSigningHttpApiModule;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.features.SubnetApi;
+import org.jclouds.ec2.features.TagApi;
+import org.jclouds.ec2.features.WindowsApi;
+import org.jclouds.ec2.features.AMIApi;
+import org.jclouds.ec2.features.AvailabilityZoneAndRegionApi;
+import org.jclouds.ec2.features.ElasticBlockStoreApi;
+import org.jclouds.ec2.features.ElasticIPAddressApi;
+import org.jclouds.ec2.features.InstanceApi;
+import org.jclouds.ec2.features.KeyPairApi;
+import org.jclouds.ec2.features.SecurityGroupApi;
+import org.jclouds.ec2.suppliers.DescribeAvailabilityZonesInRegion;
+import org.jclouds.ec2.suppliers.DescribeRegionsForRegionURIs;
+import org.jclouds.location.config.LocationModule;
+import org.jclouds.location.suppliers.RegionIdToURISupplier;
+import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
+import org.jclouds.location.suppliers.RegionIdsSupplier;
+import org.jclouds.location.suppliers.ZoneIdToURISupplier;
+import org.jclouds.location.suppliers.ZoneIdsSupplier;
+import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet;
+import org.jclouds.location.suppliers.derived.ZoneIdToURIFromJoinOnRegionIdToURI;
+import org.jclouds.location.suppliers.derived.ZoneIdsFromRegionIdToZoneIdsValues;
+import org.jclouds.rest.ConfiguresHttpApi;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.reflect.TypeToken;
+import com.google.inject.Provides;
+import com.google.inject.Scopes;
+
+/**
+ * Configures the EC2 connection.
+ * 
+ * @author Adrian Cole (EDIT: Nick Terry nterry@familysearch.org)
+ */
+@ConfiguresHttpApi
+public class EC2HttpApiModule extends BaseEC2HttpApiModule<EC2Api> {
+
+   public EC2HttpApiModule() {
+      super(EC2Api.class);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2RestClientModule.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2RestClientModule.java b/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2RestClientModule.java
deleted file mode 100644
index 589ce99..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/config/EC2RestClientModule.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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.config;
-
-import static org.jclouds.reflect.Reflection2.typeToken;
-
-import java.util.Map;
-
-import javax.inject.Singleton;
-
-import org.jclouds.aws.config.WithZonesFormSigningRestClientModule;
-import org.jclouds.ec2.EC2Api;
-import org.jclouds.ec2.EC2AsyncApi;
-import org.jclouds.ec2.EC2AsyncClient;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.features.SubnetApi;
-import org.jclouds.ec2.features.SubnetAsyncApi;
-import org.jclouds.ec2.features.TagApi;
-import org.jclouds.ec2.features.TagAsyncApi;
-import org.jclouds.ec2.features.WindowsApi;
-import org.jclouds.ec2.features.WindowsAsyncApi;
-import org.jclouds.ec2.services.AMIAsyncClient;
-import org.jclouds.ec2.services.AMIClient;
-import org.jclouds.ec2.services.AvailabilityZoneAndRegionAsyncClient;
-import org.jclouds.ec2.services.AvailabilityZoneAndRegionClient;
-import org.jclouds.ec2.services.ElasticBlockStoreAsyncClient;
-import org.jclouds.ec2.services.ElasticBlockStoreClient;
-import org.jclouds.ec2.services.ElasticIPAddressAsyncClient;
-import org.jclouds.ec2.services.ElasticIPAddressClient;
-import org.jclouds.ec2.services.InstanceAsyncClient;
-import org.jclouds.ec2.services.InstanceClient;
-import org.jclouds.ec2.services.KeyPairAsyncClient;
-import org.jclouds.ec2.services.KeyPairClient;
-import org.jclouds.ec2.services.SecurityGroupAsyncClient;
-import org.jclouds.ec2.services.SecurityGroupClient;
-import org.jclouds.ec2.services.WindowsAsyncClient;
-import org.jclouds.ec2.services.WindowsClient;
-import org.jclouds.ec2.suppliers.DescribeAvailabilityZonesInRegion;
-import org.jclouds.ec2.suppliers.DescribeRegionsForRegionURIs;
-import org.jclouds.location.config.LocationModule;
-import org.jclouds.location.suppliers.RegionIdToURISupplier;
-import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
-import org.jclouds.location.suppliers.RegionIdsSupplier;
-import org.jclouds.location.suppliers.ZoneIdToURISupplier;
-import org.jclouds.location.suppliers.ZoneIdsSupplier;
-import org.jclouds.location.suppliers.derived.RegionIdsFromRegionIdToURIKeySet;
-import org.jclouds.location.suppliers.derived.ZoneIdToURIFromJoinOnRegionIdToURI;
-import org.jclouds.location.suppliers.derived.ZoneIdsFromRegionIdToZoneIdsValues;
-import org.jclouds.rest.ConfiguresRestClient;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.reflect.TypeToken;
-import com.google.inject.Provides;
-import com.google.inject.Scopes;
-
-/**
- * Configures the EC2 connection.
- * 
- * @author Adrian Cole (EDIT: Nick Terry nterry@familysearch.org)
- */
-@ConfiguresRestClient
-// EC2Api not EC2Client so that this can be used for new apps that only depend on EC2Api
-public class EC2RestClientModule<S extends EC2Api, A extends EC2AsyncApi> extends
-         WithZonesFormSigningRestClientModule<S, A> {
-   public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
-                        .put(AMIClient.class, AMIAsyncClient.class)//
-                        .put(ElasticIPAddressClient.class, ElasticIPAddressAsyncClient.class)//
-                        .put(InstanceClient.class, InstanceAsyncClient.class)//
-                        .put(KeyPairClient.class, KeyPairAsyncClient.class)//
-                        .put(SecurityGroupClient.class, SecurityGroupAsyncClient.class)//
-                        .put(WindowsClient.class, WindowsAsyncClient.class)//
-                        .put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)//
-                        .put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
-                        .put(WindowsApi.class, WindowsAsyncApi.class)//
-                        .put(TagApi.class, TagAsyncApi.class)//
-                        .put(SubnetApi.class, SubnetAsyncApi.class)//
-                        .build();
-   
-   @SuppressWarnings("unchecked")
-   public EC2RestClientModule() {
-      // retaining top-level type of EC2Client vs EC2Api until we migrate all functionality up
-      super(TypeToken.class.cast(typeToken(EC2Client.class)), TypeToken.class.cast(typeToken(EC2AsyncClient.class)), DELEGATE_MAP);
-   }
-
-   protected EC2RestClientModule(TypeToken<S> syncClientType, TypeToken<A> asyncClientType,
-            Map<Class<?>, Class<?>> sync2Async) {
-      super(syncClientType, asyncClientType, sync2Async);
-   }
-   
-
-   /**
-    * so that we can make bindings to {@link EC2Api directly} until we switch
-    * off {@link @EC2Client}
-    */
-   @Singleton
-   @Provides
-   EC2Api provideEC2Api(EC2Client in) {
-      return in;
-   }
-   
-   /**
-    * so that we can make bindings to {@link EC2AsyncApi directly} until we switch
-    * off {@link @EC2AsyncClient}
-    */
-   @Singleton
-   @Provides
-   EC2AsyncApi provideEC2Api(EC2AsyncClient in) {
-      return in;
-   }
-   
-   @Override
-   protected void installLocations() {
-      install(new LocationModule());
-      bind(RegionIdToZoneIdsSupplier.class).to(DescribeAvailabilityZonesInRegion.class).in(Scopes.SINGLETON);
-      bind(RegionIdToURISupplier.class).to(DescribeRegionsForRegionURIs.class).in(Scopes.SINGLETON);
-      bind(ZoneIdsSupplier.class).to(ZoneIdsFromRegionIdToZoneIdsValues.class).in(Scopes.SINGLETON);
-      bind(RegionIdsSupplier.class).to(RegionIdsFromRegionIdToURIKeySet.class).in(Scopes.SINGLETON);
-      bind(ZoneIdToURISupplier.class).to(ZoneIdToURIFromJoinOnRegionIdToURI.class).in(Scopes.SINGLETON);
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/features/AMIApi.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/AMIApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/AMIApi.java
new file mode 100644
index 0000000..40540aa
--- /dev/null
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/AMIApi.java
@@ -0,0 +1,336 @@
+/*
+ * 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.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindUserGroupsToIndexedFormParams;
+import org.jclouds.ec2.binders.BindUserIdsToIndexedFormParams;
+import org.jclouds.ec2.domain.Image;
+import org.jclouds.ec2.domain.Image.EbsBlockDevice;
+import org.jclouds.ec2.domain.Permission;
+import org.jclouds.ec2.options.CreateImageOptions;
+import org.jclouds.ec2.options.DescribeImagesOptions;
+import org.jclouds.ec2.options.RegisterImageBackedByEbsOptions;
+import org.jclouds.ec2.options.RegisterImageOptions;
+import org.jclouds.ec2.xml.BlockDeviceMappingHandler;
+import org.jclouds.ec2.xml.DescribeImagesResponseHandler;
+import org.jclouds.ec2.xml.ImageIdHandler;
+import org.jclouds.ec2.xml.PermissionHandler;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+/**
+ * Provides access to AMI Services.
+ * <p/>
+ * 
+ * @author Adrian Cole
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+public interface AMIApi {
+
+   /**
+    * Returns information about AMIs, AKIs, and ARIs. This includes image type, product codes,
+    * architecture, and kernel and RAM disk IDs. Images available to you include public images,
+    * private images that you own, and private images owned by other users for which you have
+    * explicit launch permissions.
+    * 
+    * @param region
+    *           AMIs are tied to the Region where its files are located within Amazon S3.
+    * @see InstanceApi#describeInstances
+    * @see #describeImageAttribute
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeImages.html"
+    *      />
+    * @see DescribeImagesOptions
+    */
+   @Named("DescribeImages")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeImages")
+   @XMLResponseParser(DescribeImagesResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<? extends Image> describeImagesInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            DescribeImagesOptions... options);
+
+   /**
+    * Creates an AMI that uses an Amazon EBS root device from a "running" or "stopped" instance.
+    * 
+    * @param region
+    *           AMIs are tied to the Region where its files are located within Amazon S3.
+    * @param name
+    *           The name of the AMI that was provided during image creation. 3-128 alphanumeric
+    *           characters, parenthesis (()), commas (,), slashes (/), dashes (-), or underscores(_)
+    * @param instanceId
+    *           The ID of the instance.
+    * @return imageId
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeImages.html"
+    *      />
+    * @see CreateImageOptions
+    * @see InstanceApi#runInstances
+    * @see InstanceApi#describeInstances
+    * @see InstanceApi#terminateInstances
+    * @see <a href=
+    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateImage.html"
+    *      />
+    */
+   @Named("CreateImage")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "CreateImage")
+   @XMLResponseParser(ImageIdHandler.class)
+   String createImageInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("Name") String name, @FormParam("InstanceId") String instanceId, CreateImageOptions... options);
+
+   /**
+    * 
+    * Deregisters the specified AMI. Once deregistered, the AMI cannot be used to launch new
+    * instances.
+    * 
+    * @param region
+    *           AMIs are tied to the Region where its files are located within Amazon S3.
+    * @param imageId
+    *           Unique ID of the AMI which was assigned during registration. To register an AMI, use
+    *           RegisterImage. To view the AMI IDs of AMIs that belong to your identity. use
+    *           DescribeImages.
+    * 
+    * @see #describeImages
+    * @see #registerImage
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeregisterImage.html"
+    *      />
+    */
+   @Named("DeregisterImage")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DeregisterImage")
+   void deregisterImageInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("ImageId") String imageId);
+
+   /**
+    * Registers an AMI with Amazon EC2. Images must be registered before they can be launched. To
+    * launch instances, use the {@link InstanceApi#runInstances} operation.
+    * <p/>
+    * Each AMI is associated with an unique ID which is provided by the Amazon EC2 service through
+    * this operation. If needed, you can deregister an AMI at any time.
+    * <p/>
+    * <h3>Note</h3> Any modifications to an AMI backed by Amazon S3 invalidates this registration.
+    * If you make changes to an image, deregister the previous image and register the new image.
+    * 
+    * @param region
+    *           AMIs are tied to the Region where its files are located within Amazon S3.
+    * @param name
+    *           The name of the AMI that was provided during image creation. 3-128 alphanumeric
+    *           characters, parenthesis (()), commas (,), slashes (/), dashes (-), or underscores(_)
+    * @param pathToManifest
+    *           Full path to your AMI manifest in Amazon S3 storage.
+    * @param options
+    *           Options to specify metadata such as architecture or secondary volumes to be
+    *           associated with this image.
+    * @return imageId
+    * 
+    * @see #describeImages
+    * @see #deregisterImage
+    * @see <a href=
+    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RegisterImage.html"
+    *      />
+    */
+   @Named("RegisterImage")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "RegisterImage")
+   @XMLResponseParser(ImageIdHandler.class)
+   String registerImageFromManifestInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("Name") String imageName, @FormParam("ImageLocation") String pathToManifest,
+            RegisterImageOptions... options);
+
+   /**
+    * Registers an AMI with Amazon EC2. Images must be registered before they can be launched. To
+    * launch instances, use the {@link InstanceApi#runInstances} operation. The root device name
+    * is /dev/sda1
+    * <p/>
+    * Each AMI is associated with an unique ID which is provided by the Amazon EC2 service through
+    * this operation. If needed, you can deregister an AMI at any time.
+    * <p/>
+    * <h3>Note</h3> AMIs backed by Amazon EBS are automatically registered when you create the
+    * image. However, you can use this to register a snapshot of an instance backed by Amazon EBS.
+    * <p/>
+    * Amazon EBS snapshots are not guaranteed to be bootable.
+    * 
+    * @param region
+    *           AMIs are tied to the Region where its files are located within Amazon S3.
+    * @param name
+    *           The name of the AMI that was provided during image creation. 3-128 alphanumeric
+    *           characters, parenthesis (()), commas (,), slashes (/), dashes (-), or underscores(_)
+    * 
+    * @param ebsSnapshotId
+    *           The id of the root snapshot (e.g., snap-6eba6e06).
+    * @param options
+    *           Options to specify metadata such as architecture or secondary volumes to be
+    *           associated with this image.
+    * @return imageId
+    * 
+    * @see #describeImages
+    * @see #deregisterImage
+    * @see <a href=
+    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RegisterImage.html"
+    *      />
+    */
+   @Named("RegisterImage")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "RootDeviceName", "BlockDeviceMapping.0.DeviceName" }, values = { "RegisterImage",
+            "/dev/sda1", "/dev/sda1" })
+   @XMLResponseParser(ImageIdHandler.class)
+   String registerUnixImageBackedByEbsInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("Name") String imageName,
+            @FormParam("BlockDeviceMapping.0.Ebs.SnapshotId") String ebsSnapshotId,
+            RegisterImageBackedByEbsOptions... options);
+
+   /**
+    * Resets the {@code launchPermission}s on an AMI.
+    * 
+    * @param region
+    *           AMIs are tied to the Region where its files are located within Amazon S3.
+    * @param imageId
+    *           ID of the AMI on which the attribute will be reset.
+    * 
+    * @see #addLaunchPermissionsToImage
+    * @see #describeImageAttribute
+    * @see #removeProductCodesFromImage
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ResetImageAttribute.html"
+    *      />
+    */
+   @Named("ResetImageAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "ResetImageAttribute", "launchPermission" })
+   void resetLaunchPermissionsOnImageInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("ImageId") String imageId);
+
+   /**
+    * Adds {@code launchPermission}s to an AMI.
+    * 
+    * @param region
+    *           AMIs are tied to the Region where its files are located within Amazon S3.
+    * @param userIds
+    *           AWS Access Key ID.
+    * @param userGroups
+    *           Name of the groups. Currently supports \"all.\""
+    * @param imageId
+    *           The AMI ID.
+    * 
+    * @see #removeLaunchPermissionsFromImage
+    * @see #describeImageAttribute
+    * @see #resetImageAttribute
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyImageAttribute.html"
+    *      />
+    */
+   @Named("ModifyImageAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "OperationType", "Attribute" }, values = { "ModifyImageAttribute", "add",
+            "launchPermission" })
+   void addLaunchPermissionsToImageInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @BinderParam(BindUserIdsToIndexedFormParams.class) Iterable<String> userIds,
+            @BinderParam(BindUserGroupsToIndexedFormParams.class) Iterable<String> userGroups,
+            @FormParam("ImageId") String imageId);
+
+   /**
+    * @see AMIApi#removeLaunchPermissionsToImageInRegion
+    */
+   @Named("ModifyImageAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "OperationType", "Attribute" }, values = { "ModifyImageAttribute", "remove",
+            "launchPermission" })
+   void removeLaunchPermissionsFromImageInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @BinderParam(BindUserIdsToIndexedFormParams.class) Iterable<String> userIds,
+            @BinderParam(BindUserGroupsToIndexedFormParams.class) Iterable<String> userGroups,
+            @FormParam("ImageId") String imageId);
+
+   /**
+    * Returns the {@link Permission}s of an image.
+    * 
+    * @param region
+    *           AMIs are tied to the Region where its files are located within Amazon S3.
+    * @param imageId
+    *           The ID of the AMI for which an attribute will be described
+    * @see #describeImages
+    * @see #modifyImageAttribute
+    * @see #resetImageAttribute
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeImageAttribute.html"
+    *      />
+    * @see DescribeImagesOptions
+    */
+   @Named("DescribeImageAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeImageAttribute", "launchPermission" })
+   @XMLResponseParser(PermissionHandler.class)
+   Permission getLaunchPermissionForImageInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("ImageId") String imageId);
+
+   /**
+    * Returns a map of device name to block device for the image.
+    * 
+    * @param region
+    *           AMIs are tied to the Region where its files are located within Amazon S3.
+    * @param imageId
+    *           The ID of the AMI for which an attribute will be described
+    * @see #describeImages
+    * @see #modifyImageAttribute
+    * @see #resetImageAttribute
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeImageAttribute.html"
+    *      />
+    * @see DescribeImagesOptions
+    */
+   @Named("DescribeImageAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeImageAttribute", "blockDeviceMapping" })
+   @XMLResponseParser(BlockDeviceMappingHandler.class)
+   Map<String, EbsBlockDevice> getBlockDeviceMappingsForImageInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("ImageId") String imageId);
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApi.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApi.java
new file mode 100644
index 0000000..7de7a48
--- /dev/null
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApi.java
@@ -0,0 +1,90 @@
+/*
+ * 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.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.domain.AvailabilityZoneInfo;
+import org.jclouds.ec2.options.DescribeAvailabilityZonesOptions;
+import org.jclouds.ec2.options.DescribeRegionsOptions;
+import org.jclouds.ec2.xml.DescribeAvailabilityZonesResponseHandler;
+import org.jclouds.ec2.xml.DescribeRegionsResponseHandler;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+/**
+ * Provides access to EC2 Availability Zones and Regions via their REST API.
+ * <p/>
+ * 
+ * @author Adrian Cole
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+public interface AvailabilityZoneAndRegionApi {
+
+   /**
+    * Displays Availability Zones that are currently available to the identity and their states.
+    * 
+    * @see InstanceApi#runInstances
+    * @see #describeRegions
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeAvailabilityZones.html"
+    *      />
+    */
+   @Named("DescribeAvailabilityZones")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeAvailabilityZones")
+   @XMLResponseParser(DescribeAvailabilityZonesResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<AvailabilityZoneInfo> describeAvailabilityZonesInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            DescribeAvailabilityZonesOptions... options);
+
+   /**
+    * Describes Regions that are currently available to the identity.
+    * 
+    * @see InstanceApi#runInstances
+    * @see #describeAvailabilityZones
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeRegions.html"
+    *      />
+    */
+   @Named("DescribeRegions")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeRegions")
+   @XMLResponseParser(DescribeRegionsResponseHandler.class)
+   Map<String, URI> describeRegions(DescribeRegionsOptions... options);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticBlockStoreApi.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticBlockStoreApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticBlockStoreApi.java
new file mode 100644
index 0000000..8e56f77
--- /dev/null
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticBlockStoreApi.java
@@ -0,0 +1,545 @@
+/*
+ * 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.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.EC2Fallbacks.VoidOnVolumeAvailable;
+import org.jclouds.ec2.binders.BindUserGroupsToIndexedFormParams;
+import org.jclouds.ec2.binders.BindUserIdsToIndexedFormParams;
+import org.jclouds.ec2.binders.BindVolumeIdsToIndexedFormParams;
+import org.jclouds.ec2.domain.Attachment;
+import org.jclouds.ec2.domain.Permission;
+import org.jclouds.ec2.domain.Snapshot;
+import org.jclouds.ec2.domain.Volume;
+import org.jclouds.ec2.options.CreateSnapshotOptions;
+import org.jclouds.ec2.options.DescribeSnapshotsOptions;
+import org.jclouds.ec2.options.DetachVolumeOptions;
+import org.jclouds.ec2.xml.AttachmentHandler;
+import org.jclouds.ec2.xml.CreateVolumeResponseHandler;
+import org.jclouds.ec2.xml.DescribeSnapshotsResponseHandler;
+import org.jclouds.ec2.xml.DescribeVolumesResponseHandler;
+import org.jclouds.ec2.xml.PermissionHandler;
+import org.jclouds.ec2.xml.SnapshotHandler;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.location.functions.ZoneToEndpoint;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+/**
+ * Provides access to EC2 Elastic Block Store services via their REST API.
+ * <p/>
+ * 
+ * @author Adrian Cole
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+public interface ElasticBlockStoreApi {
+
+   /**
+    * Creates a new Amazon EBS volume to which any Amazon EC2 instance can attach within the same
+    * Availability Zone. For more information about Amazon EBS, go to the Amazon Elastic Compute
+    * Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
+    * 
+    * @param availabilityZone
+    *           An Amazon EBS volume must be located within the same Availability Zone as the
+    *           instance to which it attaches.
+    * @param snapshotId
+    *           The snapshot from which to create the new volume.
+    * 
+    * @see #describeVolumesInRegion
+    * @see #deleteVolumeInRegion
+    * @see #attachVolumeInRegion
+    * @see #detachVolumeInRegion
+    * @see AvailabilityZoneAndRegionApi#describeAvailabilityZonesInRegion
+    * 
+    * 
+    * @see <a href=
+    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateVolume.html"
+    *      />
+    */
+   @Named("CreateVolume")   
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "CreateVolume")
+   @XMLResponseParser(CreateVolumeResponseHandler.class)
+   Volume createVolumeFromSnapshotInAvailabilityZone(
+            @EndpointParam(parser = ZoneToEndpoint.class) @FormParam("AvailabilityZone") String availabilityZone,
+            @FormParam("SnapshotId") String snapshotId);
+
+   /**
+    * Creates a new Amazon EBS volume to which any Amazon EC2 instance can attach within the same
+    * Availability Zone. This is overloaded {@link #createVolumeFromSnapshotInAvailabilityZone},
+    * which creates a volume with a specific size.
+    * For more information about Amazon EBS, go to the Amazon Elastic Compute
+    * Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
+    *
+    * @param availabilityZone
+    *           An Amazon EBS volume must be located within the same Availability Zone as the
+    *           instance to which it attaches.
+    * @param size
+    *           Size of volume to be created
+    * @param snapshotId
+    *           The snapshot from which to create the new volume.
+    *
+    * @see #createVolumeFromSnapshotInAvailabilityZone
+    * @see #describeVolumesInRegion
+    * @see #deleteVolumeInRegion
+    * @see #attachVolumeInRegion
+    * @see #detachVolumeInRegion
+    * @see AvailabilityZoneAndRegionApi#describeAvailabilityZonesInRegion
+    *
+    *
+    * @see <a href=
+    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateVolume.html"
+    *      />
+    */
+   @Named("CreateVolume")   
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "CreateVolume")
+   @XMLResponseParser(CreateVolumeResponseHandler.class)
+   Volume createVolumeFromSnapshotInAvailabilityZone(
+            @EndpointParam(parser = ZoneToEndpoint.class) @FormParam("AvailabilityZone") String availabilityZone,
+            @FormParam("Size") int size, @FormParam("SnapshotId") String snapshotId);
+
+   /**
+    * Creates a new Amazon EBS volume to which any Amazon EC2 instance can attach within the same
+    * Availability Zone. For more information about Amazon EBS, go to the Amazon Elastic Compute
+    * Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
+    * 
+    * @param availabilityZone
+    *           An Amazon EBS volume must be located within the same Availability Zone as the
+    *           instance to which it attaches.
+    * @param size
+    *           The size of the volume, in GiBs (1-1024). Required if you are not creating a volume
+    *           from a snapshot.
+    * 
+    * 
+    * @see #describeVolumesInRegion
+    * @see #deleteVolumeInRegion
+    * @see #attachVolumeInRegion
+    * @see #detachVolumeInRegion
+    * @see AvailabilityZoneAndRegionApi#describeAvailabilityZonesInRegion
+    * @see <a href=
+    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateVolume.html"
+    *      />
+    */
+   @Named("CreateVolume")   
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "CreateVolume")
+   @XMLResponseParser(CreateVolumeResponseHandler.class)
+   Volume createVolumeInAvailabilityZone(
+            @EndpointParam(parser = ZoneToEndpoint.class) @FormParam("AvailabilityZone") String availabilityZone,
+            @FormParam("Size") int size);
+
+   /**
+    * Describes the specified Amazon EBS volumes that you own. If you do not specify one or more
+    * volume IDs, Amazon EBS describes all volumes that you own. For more information about Amazon
+    * EBS, go to the Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud
+    * User Guide.
+    * 
+    * @param region
+    *           region where the volume is defined
+    * @param volumeIds
+    *           The ID of the volume to list. Defaults to describe all volumes that you own.
+    * 
+    * @see #createSnapshotInRegion
+    * @see #describeSnapshotInRegion
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeVolumes.html"
+    *      />
+    */
+   @POST
+   @Named("DescribeVolumes")   
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeVolumes")
+   @XMLResponseParser(DescribeVolumesResponseHandler.class)
+   Set<Volume> describeVolumesInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @BinderParam(BindVolumeIdsToIndexedFormParams.class) String... volumeIds);
+
+   /**
+    * Deletes an Amazon EBS volume that you own. For more information about Amazon EBS, go to the
+    * Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
+    * 
+    * @param region
+    *           region where the volume is defined
+    * @param volumeId
+    *           The ID of the volume to delete. The volume remains in the deleting state for several
+    *           minutes after entering this command.
+    * 
+    * @see #describeVolumesInRegion
+    * @see #createVolumeInRegion
+    * @see #attachVolumeInRegion
+    * @see #detachVolumeInRegion
+    * 
+    * @see <a href=
+    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteVolume.html"
+    *      />
+    */
+   @Named("DeleteVolume")   
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DeleteVolume")
+   void deleteVolumeInRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("VolumeId") String volumeId);
+
+   /**
+    * Attaches an Amazon EBS volume to a running instance and exposes it as the specified device.
+    * <p/>
+    * 
+    * <h3>Note</h3>
+    * 
+    * Windows instances currently support devices xvda through xvdp. Devices xvda and xvdb are
+    * reserved by the operating system, xvdc is assigned to drive C:\, and, depending on the
+    * instance type, devices xvdd through xvde might be reserved by the instance stores. Any device
+    * that is not reserved can be attached to an Amazon EBS volume. For a list of devices that are
+    * reserved by the instance stores, go to the Amazon Elastic Compute Cloud Developer Guide or
+    * Amazon Elastic Compute Cloud User Guide.
+    * 
+    * @param region
+    *           region where the volume is defined
+    * @param volumeId
+    *           The ID of the volume to delete. The volume remains in the deleting state for several
+    *           minutes after entering this command.
+    * @param force
+    *           Forces detachment if the previous detachment attempt did not occur cleanly (logging
+    *           into an instance, unmounting the volume, and detaching normally). This option can
+    *           lead to data loss or a corrupted file system. Use this option only as a last resort
+    *           to detach a volume from a failed instance. The instance will not have an opportunity
+    *           to flush file system caches nor file system meta data. If you use this option, you
+    *           must perform file system check and repair procedures.
+    * 
+    * @param options
+    *           options like force()
+    * 
+    * @see #describeVolumesInRegion
+    * @see #createVolumeInRegion
+    * @see #attachVolumeInRegion
+    * @see #deleteVolumeInRegion
+    * 
+    * @see <a href=
+    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DetachVolume.html"
+    *      />
+    */
+   @Named("DetachVolume")   
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DetachVolume")
+   @Fallback(VoidOnVolumeAvailable.class)
+   void detachVolumeInRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("VolumeId") String volumeId, @FormParam("Force") boolean force, DetachVolumeOptions... options);
+
+   /**
+    * Attaches an Amazon EBS volume to a running instance and exposes it as the specified device.
+    * 
+    * <h3>Note</h3> Windows instances currently support devices xvda through xvdp. Devices xvda and
+    * xvdb are reserved by the operating system, xvdc is assigned to drive C:\, and, depending on
+    * the instance type, devices xvdd through xvde might be reserved by the instance stores. Any
+    * device that is not reserved can be attached to an Amazon EBS volume. For a list of devices
+    * that are reserved by the instance stores, go to the Amazon Elastic Compute Cloud Developer
+    * Guide or Amazon Elastic Compute Cloud User Guide.
+    * 
+    * @param region
+    *           region where the volume is defined
+    * @param volumeId
+    *           The ID of the Amazon EBS volume. The volume and instance must be within the same
+    *           Availability Zone and the instance must be running.
+    * @param instanceId
+    *           The ID of the instance to which the volume attaches. The volume and instance must be
+    *           within the same Availability Zone and the instance must be running.
+    * @param device
+    *           Specifies how the device is exposed to the instance (e.g., /dev/sdh).
+    * 
+    * @see #describeVolumesInRegion
+    * @see #createVolumeInRegion
+    * @see #detachVolumeInRegion
+    * @see #deleteVolumeInRegion
+    * 
+    * @see <a href=
+    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-AttachVolume.html"
+    *      />
+    */
+   @Named("AttachVolume")   
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "AttachVolume")
+   @XMLResponseParser(AttachmentHandler.class)
+   Attachment attachVolumeInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("VolumeId") String volumeId, @FormParam("InstanceId") String instanceId,
+            @FormParam("Device") String device);
+
+   /**
+    * Creates a snapshot of an Amazon EBS volume and stores it in Amazon S3. You can use snapshots
+    * for backups, to make identical copies of instance devices, and to save data before shutting
+    * down an instance. For more information about Amazon EBS, go to the Amazon Elastic Compute
+    * Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
+    * <p/>
+    * When taking a snapshot of a file system, we recommend unmounting it first. This ensures the
+    * file system metadata is in a consistent state, that the 'mounted indicator' is cleared, and
+    * that all applications using that file system are stopped and in a consistent state. Some file
+    * systems, such as xfs, can freeze and unfreeze activity so a snapshot can be made without
+    * unmounting.
+    * <p/>
+    * For Linux/UNIX, enter the following command from the command line.
+    * 
+    * <pre>
+    * umount - d / dev / sdh
+    * </pre>
+    * <p/>
+    * For Windows, open Disk Management, right-click the volume to unmount, and select Change Drive
+    * Letter and Path. Then, select the mount point to remove and click Remove.
+    * 
+    * @param region
+    *           Snapshots are tied to Regions and can only be used for volumes within the same
+    *           Region.
+    * @param volumeId
+    *           The ID of the Amazon EBS volume of which to take a snapshot.
+    * @param options
+    *           options like passing a description.
+    * @return the Snapshot in progress
+    * 
+    * @see #describeSnapshotsInRegion
+    * @see #deleteSnapshotInRegion
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateSnapshot.html"
+    *      />
+    */
+   @Named("CreateSnapshot")   
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "CreateSnapshot")
+   @XMLResponseParser(SnapshotHandler.class)
+   Snapshot createSnapshotInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("VolumeId") String volumeId, CreateSnapshotOptions... options);
+
+   /**
+    * Returns information about Amazon EBS snapshots available to the user. Information returned
+    * includes volume ID, status, start time, progress, owner ID, volume size, and description.
+    * Snapshots available to the user include public snapshots available for any user to
+    * createVolume, private snapshots owned by the user making the request, and private snapshots
+    * owned by other users for which the user granted explicit create volume permissions.
+    * <p/>
+    * The create volume permissions fall into 3 categories:
+    * <p/>
+    * <table>
+    * <tr>
+    * <td>Permission</td>
+    * <td>Description</td>
+    * </tr>
+    * <tr>
+    * <td>public</td>
+    * <td>The owner of the snapshot granted create volume permissions for the snapshot to the all
+    * group. All users have create volume permissions for these snapshots.</td>
+    * </tr>
+    * <tr>
+    * <td>explicit</td>
+    * <td>The owner of the snapshot granted create volume permissions to a specific user.</td>
+    * </tr>
+    * <tr>
+    * <td>implicit</td>
+    * <td>A user has implicit create volume permissions for all snapshots he or she owns.</td>
+    * </tr>
+    * </table>
+    * <p/>
+    * 
+    * The list of snapshots returned can be modified by specifying snapshot IDs, snapshot owners, or
+    * users with create volume permissions. If no options are specified, Amazon EC2 returns all
+    * snapshots for which the user has create volume permissions.
+    * <p/>
+    * If you specify one or more snapshot IDs, only snapshots that have the specified IDs are
+    * returned. If you specify an invalid snapshot ID, a fault is returned. If you specify a
+    * snapshot ID for which you do not have access, it will not be included in the returned results.
+    * <p/>
+    * If you specify one or more snapshot owners, only snapshots from the specified owners and for
+    * which you have access are returned. The results can include the AWS Account IDs of the
+    * specified owners, amazon for snapshots owned by Amazon or self for snapshots that you own.
+    * <p/>
+    * If you specify a list of restorable users, only users that have create snapshot permissions
+    * for the snapshots are returned. You can specify AWS Account IDs (if you own the snapshot(s)),
+    * self for snapshots for which you own or have explicit permissions, or all for public
+    * snapshots.
+    * 
+    * @param region
+    *           Snapshots are tied to Regions and can only be used for volumes within the same
+    *           Region.
+    * @param options
+    *           specify the snapshot ids or other parameters to clarify the list.
+    * @return matching snapshots.
+    * 
+    * @see #createSnapshotsInRegion
+    * @see #deleteSnapshotInRegion
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSnapshots.html"
+    *      />
+    */
+   @Named("DescribeSnapshots")   
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeSnapshots")
+   @XMLResponseParser(DescribeSnapshotsResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<Snapshot> describeSnapshotsInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            DescribeSnapshotsOptions... options);
+
+   /**
+    * Deletes a snapshot of an Amazon EBS volume that you own. For more information, go to the
+    * Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
+    * 
+    * @param region
+    *           Snapshots are tied to Regions and can only be used for volumes within the same
+    *           Region.
+    * @param snapshotId
+    *           The ID of the Amazon EBS snapshot to delete.
+    * 
+    * @see #createSnapshotInRegion
+    * @see #deleteSnapshotInRegion
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteSnapshot.html"
+    *      />
+    */
+   @Named("DeleteSnapshot")   
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DeleteSnapshot")
+   void deleteSnapshotInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("SnapshotId") String snapshotId);
+
+   /**
+    * Adds {@code createVolumePermission}s to an EBS snapshot.
+    * 
+    * @param region
+    *           Snapshots are tied to Regions and can only be used for volumes within the same
+    *           Region.
+    * @param userIds
+    *           AWS Access Key ID.
+    * @param userGroups
+    *           Name of the groups. Currently supports \"all.\""
+    * @param snapshotId
+    *           The ID of the Amazon EBS snapshot.
+    * 
+    * @see #removeCreateVolumePermissionsFromSnapshot
+    * @see #describeSnapshotAttribute
+    * @see #resetSnapshotAttribute
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifySnapshotAttribute.html"
+    *      />
+    */
+   @Named("ModifySnapshotAttribute")   
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "OperationType", "Attribute" }, values = { "ModifySnapshotAttribute", "add",
+            "createVolumePermission" })
+   void addCreateVolumePermissionsToSnapshotInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @BinderParam(BindUserIdsToIndexedFormParams.class) Iterable<String> userIds,
+            @BinderParam(BindUserGroupsToIndexedFormParams.class) Iterable<String> userGroups,
+            @FormParam("SnapshotId") String snapshotId);
+
+   /**
+    * Removes {@code createVolumePermission}s from an EBS snapshot.
+    * 
+    * @param region
+    *           Snapshots are tied to Regions and can only be used for volumes within the same
+    *           Region.
+    * @param userIds
+    *           AWS Access Key ID.
+    * @param userGroups
+    *           Name of the groups. Currently supports \"all.\""
+    * @param snapshotId
+    *           The ID of the Amazon EBS snapshot.
+    * 
+    * @see #addCreateVolumePermissionsToSnapshot
+    * @see #describeSnapshotAttribute
+    * @see #resetSnapshotAttribute
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifySnapshotAttribute.html"
+    *      />
+    */
+   @Named("ModifySnapshotAttribute")   
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "OperationType", "Attribute" }, values = { "ModifySnapshotAttribute", "remove",
+            "createVolumePermission" })
+   void removeCreateVolumePermissionsFromSnapshotInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @BinderParam(BindUserIdsToIndexedFormParams.class) Iterable<String> userIds,
+            @BinderParam(BindUserGroupsToIndexedFormParams.class) Iterable<String> userGroups,
+            @FormParam("SnapshotId") String snapshotId);
+
+   /**
+    * Returns the {@link Permission}s of an snapshot.
+    * 
+    * @param region
+    *           AMIs are tied to the Region where its files are located within Amazon S3.
+    * @param snapshotId
+    *           The ID of the AMI for which an attribute will be described
+    * @see #describeSnapshots
+    * @see #modifySnapshotAttribute
+    * @see #resetSnapshotAttribute
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSnapshotAttribute.html"
+    *      />
+    * @see DescribeSnapshotsOptions
+    */
+   @Named("DescribeSnapshotAttribute")   
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeSnapshotAttribute", "createVolumePermission" })
+   @XMLResponseParser(PermissionHandler.class)
+   Permission getCreateVolumePermissionForSnapshotInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("SnapshotId") String snapshotId);
+
+   /**
+    * Resets the {@code createVolumePermission}s on an EBS snapshot.
+    * 
+    * @param region
+    *           Snapshots are tied to Regions and can only be used for volumes within the same
+    *           Region.
+    * @param snapshotId
+    *           The ID of the Amazon EBS snapshot.
+    * 
+    * @see #addCreateVolumePermissionsToSnapshot
+    * @see #describeSnapshotAttribute
+    * @see #removeProductCodesFromSnapshot
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ResetSnapshotAttribute.html"
+    *      />
+    */
+   @Named("ResetSnapshotAttribute")   
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "ResetSnapshotAttribute", "createVolumePermission" })
+   void resetCreateVolumePermissionsOnSnapshotInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("SnapshotId") String snapshotId);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticIPAddressApi.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticIPAddressApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticIPAddressApi.java
new file mode 100644
index 0000000..47d93a7
--- /dev/null
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticIPAddressApi.java
@@ -0,0 +1,171 @@
+/*
+ * 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.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindPublicIpsToIndexedFormParams;
+import org.jclouds.ec2.domain.PublicIpInstanceIdPair;
+import org.jclouds.ec2.xml.AllocateAddressResponseHandler;
+import org.jclouds.ec2.xml.DescribeAddressesResponseHandler;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+/**
+ * Provides access to EC2 Elastic IP Addresses via REST API.
+ * <p/>
+ * 
+ * @author Adrian Cole
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+public interface ElasticIPAddressApi {
+
+   /**
+    * Acquires an elastic IP address for use with your identity.
+    * 
+    * @param region
+    *           Elastic IP addresses are tied to a Region and cannot be mapped across Regions.
+    * @see #describeAddresses
+    * @see #releaseAddress
+    * @see #associateAddress
+    * @see #disassociateAddress
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-AllocateAddress.html"
+    */
+   @Named("AllocateAddress")
+   @POST
+   @Path("/")
+   @XMLResponseParser(AllocateAddressResponseHandler.class)
+   @FormParams(keys = ACTION, values = "AllocateAddress")
+   String allocateAddressInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+
+   /**
+    * Associates an elastic IP address with an instance. If the IP address is currently assigned to
+    * another instance, the IP address is assigned to the new instance. This is an idempotent
+    * operation. If you enter it more than once, Amazon EC2 does not return an error.
+    * 
+    * @param region
+    *           Elastic IP addresses are tied to a Region and cannot be mapped across Regions.
+    * @param publicIp
+    *           IP address that you are assigning to the instance.
+    * @param instanceId
+    *           The instance to associate with the IP address.
+    * 
+    * @see #allocateAddress
+    * @see #describeAddresses
+    * @see #releaseAddress
+    * @see #disassociateAddress
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-AssociateAddress.html"
+    */
+   @Named("AssociateAddress")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "AssociateAddress")
+   void associateAddressInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("PublicIp") String publicIp, @FormParam("InstanceId") String instanceId);
+
+   /**
+    * Disassociates the specified elastic IP address from the instance to which it is assigned. This
+    * is an idempotent operation. If you enter it more than once, Amazon EC2 does not return an
+    * error.
+    * 
+    * @param region
+    *           Elastic IP addresses are tied to a Region and cannot be mapped across Regions.
+    * @param publicIp
+    *           IP address that you are assigning to the instance.
+    * 
+    * @see #allocateAddress
+    * @see #describeAddresses
+    * @see #releaseAddress
+    * @see #associateAddress
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DisassociateAddress.html"
+    */
+   @Named("DisassociateAddress")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DisassociateAddress")
+   void disassociateAddressInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("PublicIp") String publicIp);
+
+   /**
+    * Releases an elastic IP address associated with your identity.
+    * 
+    * @param region
+    *           Elastic IP addresses are tied to a Region and cannot be mapped across Regions.
+    * @param publicIp
+    *           The IP address that you are releasing from your identity.
+    * 
+    * @see #allocateAddress
+    * @see #describeAddresses
+    * @see #associateAddress
+    * @see #disassociateAddress
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-ReleaseAddress.html"
+    */
+   @Named("ReleaseAddress")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "ReleaseAddress")
+   void releaseAddressInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("PublicIp") String publicIp);
+
+   /**
+    * Lists elastic IP addresses assigned to your identity or provides information about a specific
+    * address.
+    * 
+    * @param region
+    *           Elastic IP addresses are tied to a Region and cannot be mapped across Regions.
+    * @param publicIps
+    *           Elastic IP address to describe.
+    * 
+    * @throws AWSResponseException
+    *            if the requested publicIp is not found
+    * @see #allocateAddress
+    * @see #releaseAddress
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeAddresses.html"
+    *      />
+    */
+   @Named("DescribeAddresses")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeAddresses")
+   @XMLResponseParser(DescribeAddressesResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<PublicIpInstanceIdPair> describeAddressesInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @BinderParam(BindPublicIpsToIndexedFormParams.class) String... publicIps);
+
+}


[13/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java
new file mode 100644
index 0000000..3eee397
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java
@@ -0,0 +1,202 @@
+/*
+ * 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.features;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.Iterables.concat;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.collect.Sets.newHashSet;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.imageIds;
+import static org.jclouds.ec2.options.RegisterImageBackedByEbsOptions.Builder.addNewBlockDevice;
+import static org.jclouds.util.Predicates2.retry;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Iterator;
+import java.util.Properties;
+import java.util.Set;
+
+import org.jclouds.compute.RunNodesException;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.domain.TemplateBuilderSpec;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.EC2ApiMetadata;
+import org.jclouds.ec2.domain.BlockDevice;
+import org.jclouds.ec2.domain.Image;
+import org.jclouds.ec2.domain.Image.ImageType;
+import org.jclouds.ec2.domain.RootDeviceType;
+import org.jclouds.ec2.domain.RunningInstance;
+import org.jclouds.ec2.domain.Snapshot;
+import org.jclouds.ec2.predicates.InstanceStateRunning;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Tests behavior of {@code AMIApi}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true)
+public class AMIApiLiveTest extends BaseComputeServiceContextLiveTest {
+   private TemplateBuilderSpec ebsTemplate;
+
+   public AMIApiLiveTest() {
+      provider = "ec2";
+   }
+
+   @Override
+   protected Properties setupProperties() {
+      Properties overrides = super.setupProperties();
+      String ebsSpec = checkNotNull(setIfTestSystemPropertyPresent(overrides, provider + ".ebs-template"), provider
+            + ".ebs-template");
+      ebsTemplate = TemplateBuilderSpec.parse(ebsSpec);
+      return overrides;
+   }
+
+   protected EC2Api ec2Api;
+   protected AMIApi client;
+
+   protected Predicate<RunningInstance> runningTester;
+
+   protected Set<String> imagesToDeregister = newHashSet();
+   protected Set<String> snapshotsToDelete = newHashSet();
+   protected String regionId;
+   protected String ebsBackedImageId;
+   protected String ebsBackedImageName = "jcloudstest1";
+   protected String imageId;
+
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      ec2Api = view.unwrapApi(EC2Api.class);
+      runningTester = retry(new InstanceStateRunning(ec2Api), 600, 5, SECONDS);
+
+      client = ec2Api.getAMIApi().get();
+      if (ebsTemplate != null) {
+         Template template = view.getComputeService().templateBuilder().from(ebsTemplate).build();
+         regionId = template.getLocation().getId();
+         imageId = template.getImage().getProviderId();
+         for (Image image : client.describeImagesInRegion(regionId)) {
+            if (ebsBackedImageName.equals(image.getName()))
+               client.deregisterImageInRegion(regionId, image.getId());
+         }
+      }
+   }
+
+   public void testDescribeImageNotExists() {
+      assertEquals(client.describeImagesInRegion(null, imageIds("ami-cdf819a3")).size(), 0);
+   }
+
+   @Test(expectedExceptions = IllegalArgumentException.class)
+   public void testDescribeImageBadId() {
+      client.describeImagesInRegion(null, imageIds("asdaasdsa"));
+   }
+
+   public void testDescribeImages() {
+      for (String region : ec2Api.getConfiguredRegions()) {
+         Set<? extends Image> allResults = client.describeImagesInRegion(region);
+         assertNotNull(allResults);
+         assert allResults.size() >= 2 : allResults.size();
+         Iterator<? extends Image> iterator = allResults.iterator();
+         String id1 = iterator.next().getId();
+         String id2 = iterator.next().getId();
+         Set<? extends Image> twoResults = client.describeImagesInRegion(region, imageIds(id1, id2));
+         assertNotNull(twoResults);
+         assertEquals(twoResults.size(), 2);
+         iterator = twoResults.iterator();
+         assertEquals(iterator.next().getId(), id1);
+         assertEquals(iterator.next().getId(), id2);
+      }
+   }
+
+   @Test
+   public void testCreateAndListEBSBackedImage() throws Exception {
+      Snapshot snapshot = createSnapshot();
+
+      // List of images before...
+      int sizeBefore = client.describeImagesInRegion(regionId).size();
+
+      // Register a new image...
+      ebsBackedImageId = client.registerUnixImageBackedByEbsInRegion(regionId, ebsBackedImageName, snapshot.getId(),
+            addNewBlockDevice("/dev/sda2", "myvirtual", 1).withDescription("adrian"));
+      imagesToDeregister.add(ebsBackedImageId);
+      final Image ebsBackedImage = getOnlyElement(client.describeImagesInRegion(regionId, imageIds(ebsBackedImageId)));
+      assertEquals(ebsBackedImage.getName(), ebsBackedImageName);
+      assertEquals(ebsBackedImage.getImageType(), ImageType.MACHINE);
+      assertEquals(ebsBackedImage.getRootDeviceType(), RootDeviceType.EBS);
+      assertEquals(ebsBackedImage.getRootDeviceName(), "/dev/sda1");
+      assertEquals(ebsBackedImage.getDescription(), "adrian");
+      assertEquals(
+            ebsBackedImage.getEbsBlockDevices().entrySet(),
+            ImmutableMap.of("/dev/sda1", new Image.EbsBlockDevice(snapshot.getId(), snapshot.getVolumeSize(), true),
+                  "/dev/sda2", new Image.EbsBlockDevice(null, 1, false)).entrySet());
+
+      // List of images after - should be one larger than before
+      int after = client.describeImagesInRegion(regionId).size();
+      assertEquals(after, sizeBefore + 1);
+   }
+
+   // Fires up an instance, finds its root volume ID, takes a snapshot, then
+   // terminates the instance.
+   private Snapshot createSnapshot() throws RunNodesException {
+
+      String instanceId = null;
+      try {
+         RunningInstance instance = getOnlyElement(concat(ec2Api.getInstanceApi().get().runInstancesInRegion(
+               regionId, null, imageId, 1, 1)));
+         instanceId = instance.getId();
+         
+         assertTrue(runningTester.apply(instance), instanceId + "didn't achieve the state running!");
+
+         instance = getOnlyElement(concat(ec2Api.getInstanceApi().get().describeInstancesInRegion(regionId,
+               instanceId)));
+         BlockDevice device = instance.getEbsBlockDevices().get("/dev/sda1");
+         assertNotNull(device, "device: /dev/sda1 not present on: " + instance);
+         Snapshot snapshot = ec2Api.getElasticBlockStoreApi().get().createSnapshotInRegion(regionId,
+               device.getVolumeId());
+         snapshotsToDelete.add(snapshot.getId());
+         return snapshot;
+      } finally {
+         if (instanceId != null)
+            ec2Api.getInstanceApi().get().terminateInstancesInRegion(regionId, instanceId);
+      }
+   }
+
+   @Test(dependsOnMethods = "testCreateAndListEBSBackedImage")
+   public void testGetLaunchPermissionForImage() {
+      client.getLaunchPermissionForImageInRegion(regionId, ebsBackedImageId);
+   }
+
+   @Override
+   @AfterClass(groups = { "integration", "live" })
+   protected void tearDownContext() {
+      for (String imageId : imagesToDeregister)
+         client.deregisterImageInRegion(regionId, imageId);
+      for (String snapshotId : snapshotsToDelete)
+         ec2Api.getElasticBlockStoreApi().get().deleteSnapshotInRegion(regionId, snapshotId);
+      super.tearDownContext();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiTest.java
new file mode 100644
index 0000000..c3907ab
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiTest.java
@@ -0,0 +1,521 @@
+/*
+ * 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.features;
+
+import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.executableBy;
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.ec2.options.CreateImageOptions;
+import org.jclouds.ec2.options.DescribeImagesOptions;
+import org.jclouds.ec2.options.RegisterImageBackedByEbsOptions;
+import org.jclouds.ec2.options.RegisterImageOptions;
+import org.jclouds.ec2.xml.BlockDeviceMappingHandler;
+import org.jclouds.ec2.xml.DescribeImagesResponseHandler;
+import org.jclouds.ec2.xml.ImageIdHandler;
+import org.jclouds.ec2.xml.PermissionHandler;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.http.functions.ReleasePayloadAndReturn;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code AMIApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "AMIApiTest")
+public class AMIApiTest extends BaseEC2ApiTest<AMIApi> {
+
+   HttpRequest createImage = HttpRequest.builder().method("POST")
+                                        .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                        .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                        .addFormParam("Action", "CreateImage")
+                                        .addFormParam("InstanceId", "instanceId")
+                                        .addFormParam("Name", "name")
+                                        .addFormParam("Signature", "hBIUf4IUOiCKGQKehaNwwbZUjRN4NC4RSNfJ%2B8kvJdY%3D")
+                                        .addFormParam("SignatureMethod", "HmacSHA256")
+                                        .addFormParam("SignatureVersion", "2")
+                                        .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                        .addFormParam("Version", "2010-06-15")
+                                        .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testCreateImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AMIApi.class, "createImageInRegion", String.class, String.class, String.class,
+               CreateImageOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "instanceId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, createImage.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest createImageOptions = HttpRequest.builder().method("POST")
+                                               .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                               .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                               .addFormParam("Action", "CreateImage")
+                                               .addFormParam("Description", "description")
+                                               .addFormParam("InstanceId", "instanceId")
+                                               .addFormParam("Name", "name")
+                                               .addFormParam("NoReboot", "true")
+                                               .addFormParam("Signature", "fz3KW27JxlSq9ivmVOl4IujcHXXw1cOhdig80I7wR6o%3D")
+                                               .addFormParam("SignatureMethod", "HmacSHA256")
+                                               .addFormParam("SignatureVersion", "2")
+                                               .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                               .addFormParam("Version", "2010-06-15")
+                                               .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testCreateImageOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AMIApi.class, "createImageInRegion", String.class, String.class, String.class,
+               CreateImageOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "instanceId", new CreateImageOptions()
+               .withDescription("description").noReboot()));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, createImageOptions.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest describeImages = HttpRequest.builder().method("POST")
+                                           .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                           .addFormParam("Action", "DescribeImages")
+                                           .addFormParam("Signature", "qE4vexSFJqS0UWK%2BccV3s%2BP9woL3M5HI5bTBoM7s/LY%3D")
+                                           .addFormParam("SignatureMethod", "HmacSHA256")
+                                           .addFormParam("SignatureVersion", "2")
+                                           .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                           .addFormParam("Version", "2010-06-15")
+                                           .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testDescribeImages() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AMIApi.class, "describeImagesInRegion", String.class,
+               DescribeImagesOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, describeImages.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeImagesResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   HttpRequest describeImagesOptions = HttpRequest.builder().method("POST")
+                                                  .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                  .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                  .addFormParam("Action", "DescribeImages")
+                                                  .addFormParam("ExecutableBy", "me")
+                                                  .addFormParam("ImageId.1", "1")
+                                                  .addFormParam("ImageId.2", "2")
+                                                  .addFormParam("Owner.1", "fred")
+                                                  .addFormParam("Owner.2", "nancy")
+                                                  .addFormParam("Signature", "%2BE9wji7oFnNUaGmOBggYNNp6v%2BL8OzSGjuI4nx1l2Jw%3D")
+                                                  .addFormParam("SignatureMethod", "HmacSHA256")
+                                                  .addFormParam("SignatureVersion", "2")
+                                                  .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                  .addFormParam("Version", "2010-06-15")
+                                                  .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testDescribeImagesOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AMIApi.class, "describeImagesInRegion", String.class,
+               DescribeImagesOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, executableBy("me").ownedBy("fred", "nancy").imageIds(
+               "1", "2")));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, describeImagesOptions.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeImagesResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   HttpRequest deregisterImage = HttpRequest.builder().method("POST")
+                                            .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                            .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                            .addFormParam("Action", "DeregisterImage")
+                                            .addFormParam("ImageId", "imageId")
+                                            .addFormParam("Signature", "3sk9LAJAIr2lG04OMuI0qtzCoBtCU1Ac9I6TTmAWjyA%3D")
+                                            .addFormParam("SignatureMethod", "HmacSHA256")
+                                            .addFormParam("SignatureVersion", "2")
+                                            .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                            .addFormParam("Version", "2010-06-15")
+                                            .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testDeregisterImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AMIApi.class, "deregisterImageInRegion", String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, deregisterImage.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest registerImageFromManifest = HttpRequest.builder().method("POST")
+                                                      .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                      .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                      .addFormParam("Action", "RegisterImage")
+                                                      .addFormParam("ImageLocation", "pathToManifest")
+                                                      .addFormParam("Name", "name")
+                                                      .addFormParam("Signature", "alGqfUiV/bpmpCAj/YzG9VxdTeCwOYyoPjNfwYhm7os%3D")
+                                                      .addFormParam("SignatureMethod", "HmacSHA256")
+                                                      .addFormParam("SignatureVersion", "2")
+                                                      .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                      .addFormParam("Version", "2010-06-15")
+                                                      .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testRegisterImageFromManifest() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AMIApi.class, "registerImageFromManifestInRegion", String.class, String.class,
+               String.class, RegisterImageOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "pathToManifest"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, registerImageFromManifest.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest registerImageFromManifestOptions = HttpRequest.builder().method("POST")
+                                                             .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                             .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                             .addFormParam("Action", "RegisterImage")
+                                                             .addFormParam("Description", "description")
+                                                             .addFormParam("ImageLocation", "pathToManifest")
+                                                             .addFormParam("Name", "name")
+                                                             .addFormParam("Signature", "p77vQLVlPoak6cP/8eoM%2Bz6zkSXx9e2iSlGgLvIwP7I%3D")
+                                                             .addFormParam("SignatureMethod", "HmacSHA256")
+                                                             .addFormParam("SignatureVersion", "2")
+                                                             .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                             .addFormParam("Version", "2010-06-15")
+                                                             .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testRegisterImageFromManifestOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AMIApi.class, "registerImageFromManifestInRegion", String.class, String.class,
+               String.class, RegisterImageOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "pathToManifest", new RegisterImageOptions()
+               .withDescription("description")));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, registerImageFromManifestOptions.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest registerImageBackedByEBS = HttpRequest.builder().method("POST")
+                                                     .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                     .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                     .addFormParam("Action", "RegisterImage")
+                                                     .addFormParam("BlockDeviceMapping.0.DeviceName", "/dev/sda1")
+                                                     .addFormParam("BlockDeviceMapping.0.Ebs.SnapshotId", "snapshotId")
+                                                     .addFormParam("Name", "imageName")
+                                                     .addFormParam("RootDeviceName", "/dev/sda1")
+                                                     .addFormParam("Signature", "KGqYXGpJ/UQVTM172Y2TwU4tlG21JXd3Qrx5nSLBVuA%3D")
+                                                     .addFormParam("SignatureMethod", "HmacSHA256")
+                                                     .addFormParam("SignatureVersion", "2")
+                                                     .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                     .addFormParam("Version", "2010-06-15")
+                                                     .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testRegisterImageBackedByEBS() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AMIApi.class, "registerUnixImageBackedByEbsInRegion", String.class,
+               String.class, String.class, RegisterImageBackedByEbsOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageName", "snapshotId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, registerImageBackedByEBS.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest registerImageBackedByEBSOptions = HttpRequest.builder().method("POST")
+                                                            .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                            .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                            .addFormParam("Action", "RegisterImage")
+                                                            .addFormParam("BlockDeviceMapping.0.DeviceName", "/dev/sda1")
+                                                            .addFormParam("BlockDeviceMapping.0.Ebs.SnapshotId", "snapshotId")
+                                                            .addFormParam("BlockDeviceMapping.1.DeviceName", "/dev/device")
+                                                            .addFormParam("BlockDeviceMapping.1.Ebs.DeleteOnTermination", "false")
+                                                            .addFormParam("BlockDeviceMapping.1.Ebs.SnapshotId", "snapshot")
+                                                            .addFormParam("BlockDeviceMapping.2.DeviceName", "/dev/newdevice")
+                                                            .addFormParam("BlockDeviceMapping.2.Ebs.DeleteOnTermination", "false")
+                                                            .addFormParam("BlockDeviceMapping.2.Ebs.VolumeSize", "100")
+                                                            .addFormParam("BlockDeviceMapping.2.VirtualName", "newblock")
+                                                            .addFormParam("Description", "description")
+                                                            .addFormParam("Name", "imageName")
+                                                            .addFormParam("RootDeviceName", "/dev/sda1")
+                                                            .addFormParam("Signature", "xuWi0w8iODQrg4E0azwqNm2lz/Rf4hBa7m%2BunDTZvVI%3D")
+                                                            .addFormParam("SignatureMethod", "HmacSHA256")
+                                                            .addFormParam("SignatureVersion", "2")
+                                                            .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                            .addFormParam("Version", "2010-06-15")
+                                                            .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testRegisterImageBackedByEBSOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AMIApi.class, "registerUnixImageBackedByEbsInRegion", String.class,
+               String.class, String.class, RegisterImageBackedByEbsOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageName", "snapshotId",
+               new RegisterImageBackedByEbsOptions().withDescription("description").addBlockDeviceFromSnapshot(
+                        "/dev/device", null, "snapshot").addNewBlockDevice("/dev/newdevice", "newblock", 100)));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, registerImageBackedByEBSOptions.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest getBlockDeviceMappingsForImage = HttpRequest.builder().method("POST")
+                                                           .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                           .addFormParam("Action", "DescribeImageAttribute")
+                                                           .addFormParam("Attribute", "blockDeviceMapping")
+                                                           .addFormParam("ImageId", "imageId")
+                                                           .addFormParam("Signature", "puwfzm8BlfeKiEZ9CNn5ax86weZ6SQ2xyZhN6etu4gA%3D")
+                                                           .addFormParam("SignatureMethod", "HmacSHA256")
+                                                           .addFormParam("SignatureVersion", "2")
+                                                           .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                           .addFormParam("Version", "2010-06-15")
+                                                           .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testGetBlockDeviceMappingsForImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AMIApi.class, "getBlockDeviceMappingsForImageInRegion", String.class,
+               String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, getBlockDeviceMappingsForImage.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, BlockDeviceMappingHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest getLaunchPermissionForImage = HttpRequest.builder().method("POST")
+                                                        .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                        .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                        .addFormParam("Action", "DescribeImageAttribute")
+                                                        .addFormParam("Attribute", "launchPermission")
+                                                        .addFormParam("ImageId", "imageId")
+                                                        .addFormParam("Signature", "ocCMlLh3Kpg6HwIcPKlrwoPPg9C5rt5nD0dl717mOq8%3D")
+                                                        .addFormParam("SignatureMethod", "HmacSHA256")
+                                                        .addFormParam("SignatureVersion", "2")
+                                                        .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                        .addFormParam("Version", "2010-06-15")
+                                                        .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testGetLaunchPermissionForImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AMIApi.class, "getLaunchPermissionForImageInRegion", String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, getLaunchPermissionForImage.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, PermissionHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest addLaunchPermission = HttpRequest.builder().method("POST")
+                                                          .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                          .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                          .addFormParam("Action", "ModifyImageAttribute")
+                                                          .addFormParam("Attribute", "launchPermission")
+                                                          .addFormParam("ImageId", "imageId")
+                                                          .addFormParam("OperationType", "add")
+                                                          .addFormParam("Signature", "WZzNWOC1KHbuySvXEuLTiBA%2BVUfKpSBN2Lud6MrhlCQ%3D")
+                                                          .addFormParam("SignatureMethod", "HmacSHA256")
+                                                          .addFormParam("SignatureVersion", "2")
+                                                          .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                          .addFormParam("UserGroup.1", "all")
+                                                          .addFormParam("UserId.1", "bob")
+                                                          .addFormParam("UserId.2", "sue")
+                                                          .addFormParam("Version", "2010-06-15")
+                                                          .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testAddLaunchPermissionsToImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AMIApi.class, "addLaunchPermissionsToImageInRegion", String.class,
+               Iterable.class, Iterable.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("bob", "sue"), ImmutableList
+               .of("all"), "imageId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, addLaunchPermission.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest removeLaunchPermission = HttpRequest.builder().method("POST")
+                                                   .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                   .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                   .addFormParam("Action", "ModifyImageAttribute")
+                                                   .addFormParam("Attribute", "launchPermission")
+                                                   .addFormParam("ImageId", "imageId")
+                                                   .addFormParam("OperationType", "remove")
+                                                   .addFormParam("Signature", "z8OYGQBAwu4HwXV6VF/vuOZlBtptxLxtCQiLXY7UvMU%3D")
+                                                   .addFormParam("SignatureMethod", "HmacSHA256")
+                                                   .addFormParam("SignatureVersion", "2")
+                                                   .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                   .addFormParam("UserGroup.1", "all")
+                                                   .addFormParam("UserId.1", "bob")
+                                                   .addFormParam("UserId.2", "sue")
+                                                   .addFormParam("Version", "2010-06-15")
+                                                   .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testRemoveLaunchPermissionsFromImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AMIApi.class, "removeLaunchPermissionsFromImageInRegion", String.class,
+               Iterable.class, Iterable.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("bob", "sue"), ImmutableList
+               .of("all"), "imageId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, removeLaunchPermission.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest resetLaunchPermissionsOnImage = HttpRequest.builder().method("POST")
+                                                          .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                          .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                          .addFormParam("Action", "ResetImageAttribute")
+                                                          .addFormParam("Attribute", "launchPermission")
+                                                          .addFormParam("ImageId", "imageId")
+                                                          .addFormParam("Signature", "mOVwrqAzidhz%2B4E1dqOJAzG9G9ZX7eDpi8BobN4dA%2BE%3D")
+                                                          .addFormParam("SignatureMethod", "HmacSHA256")
+                                                          .addFormParam("SignatureVersion", "2")
+                                                          .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                          .addFormParam("Version", "2010-06-15")
+                                                          .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testResetLaunchPermissionsOnImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AMIApi.class, "resetLaunchPermissionsOnImageInRegion", String.class,
+               String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, resetLaunchPermissionsOnImage.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApiLiveTest.java
new file mode 100644
index 0000000..2867e69
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApiLiveTest.java
@@ -0,0 +1,92 @@
+/*
+ * 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.features;
+
+import static org.jclouds.ec2.options.DescribeAvailabilityZonesOptions.Builder.availabilityZones;
+import static org.jclouds.ec2.options.DescribeRegionsOptions.Builder.regions;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.net.URI;
+import java.util.Iterator;
+import java.util.Map.Entry;
+import java.util.Set;
+import java.util.SortedMap;
+
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.EC2ApiMetadata;
+import org.jclouds.ec2.domain.AvailabilityZoneInfo;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Maps;
+
+/**
+ * Tests behavior of {@code AvailabilityZoneAndRegionApi}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "AvailabilityZoneAndRegionApiLiveTest")
+public class AvailabilityZoneAndRegionApiLiveTest extends BaseComputeServiceContextLiveTest {
+   public AvailabilityZoneAndRegionApiLiveTest() {
+      provider = "ec2";
+   }
+   
+   private EC2Api ec2Api;
+   private AvailabilityZoneAndRegionApi client;
+
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      ec2Api = view.unwrapApi(EC2Api.class);
+      client = ec2Api.getAvailabilityZoneAndRegionApi().get();
+   }
+
+   public void testDescribeAvailabilityZones() {
+      for (String region : ec2Api.getConfiguredRegions()) {
+         Set<AvailabilityZoneInfo> allResults = client.describeAvailabilityZonesInRegion(region);
+         assertNotNull(allResults);
+         assert allResults.size() >= 1 : allResults.size();
+         Iterator<AvailabilityZoneInfo> iterator = allResults.iterator();
+         String id1 = iterator.next().getZone();
+         Set<AvailabilityZoneInfo> oneResult = client.describeAvailabilityZonesInRegion(region,
+               availabilityZones(id1));
+         assertNotNull(oneResult);
+         assertEquals(oneResult.size(), 1);
+         iterator = allResults.iterator();
+         assertEquals(iterator.next().getZone(), id1);
+      }
+   }
+
+   public void testDescribeRegions() {
+      SortedMap<String, URI> allResults = Maps.newTreeMap();
+      allResults.putAll(client.describeRegions());
+      assertNotNull(allResults);
+      assert allResults.size() >= 1 : allResults.size();
+      Iterator<Entry<String, URI>> iterator = allResults.entrySet().iterator();
+      String r1 = iterator.next().getKey();
+      SortedMap<String, URI> oneResult = Maps.newTreeMap();
+      oneResult.putAll(client.describeRegions(regions(r1)));
+      assertNotNull(oneResult);
+      assertEquals(oneResult.size(), 1);
+      iterator = oneResult.entrySet().iterator();
+      assertEquals(iterator.next().getKey(), r1);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApiTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApiTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApiTest.java
new file mode 100644
index 0000000..ae22fe8
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApiTest.java
@@ -0,0 +1,116 @@
+/*
+ * 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.features;
+
+import static org.jclouds.ec2.options.DescribeAvailabilityZonesOptions.Builder.availabilityZones;
+import static org.jclouds.ec2.options.DescribeRegionsOptions.Builder.regions;
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.aws.domain.Region;
+import org.jclouds.ec2.options.DescribeAvailabilityZonesOptions;
+import org.jclouds.ec2.options.DescribeRegionsOptions;
+import org.jclouds.ec2.xml.DescribeAvailabilityZonesResponseHandler;
+import org.jclouds.ec2.xml.DescribeRegionsResponseHandler;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code AvailabilityZoneAndRegionApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "AvailabilityZoneAndRegionApiTest")
+public class AvailabilityZoneAndRegionApiTest extends
+      BaseEC2ApiTest<AvailabilityZoneAndRegionApi> {
+
+   public void testDescribeAvailabilityZones() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AvailabilityZoneAndRegionApi.class, "describeAvailabilityZonesInRegion",
+            String.class, DescribeAvailabilityZonesOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of(Region.US_WEST_1));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-west-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-west-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeAvailabilityZones",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeAvailabilityZonesResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeAvailabilityZonesOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AvailabilityZoneAndRegionApi.class, "describeAvailabilityZonesInRegion",
+            String.class, DescribeAvailabilityZonesOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("us-east-1", availabilityZones("us-east-1a", "us-east-1b")));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+            "Action=DescribeAvailabilityZones&ZoneName.1=us-east-1a&ZoneName.2=us-east-1b",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeAvailabilityZonesResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeRegions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AvailabilityZoneAndRegionApi.class, "describeRegions",
+            DescribeRegionsOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.of());
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeRegions", "application/x-www-form-urlencoded",
+            false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeRegionsResponseHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeRegionsOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AvailabilityZoneAndRegionApi.class, "describeRegions",
+            DescribeRegionsOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of(regions(Region.US_EAST_1, Region.US_WEST_1)));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+            "Action=DescribeRegions&RegionName.1=us-east-1&RegionName.2=us-west-1",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeRegionsResponseHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/BaseEC2ApiTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/BaseEC2ApiTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/BaseEC2ApiTest.java
new file mode 100644
index 0000000..190806c
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/BaseEC2ApiTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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.features;
+
+import static com.google.common.collect.Maps.transformValues;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Singleton;
+
+import org.jclouds.apis.ApiMetadata;
+import org.jclouds.aws.domain.Region;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.date.DateService;
+import org.jclouds.ec2.EC2ApiMetadata;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.compute.domain.RegionAndName;
+import org.jclouds.ec2.config.BaseEC2HttpApiModule;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.location.config.LocationModule;
+import org.jclouds.location.suppliers.RegionIdToURISupplier;
+import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.internal.BaseAsyncApiTest;
+import org.jclouds.util.Suppliers2;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Supplier;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+import com.google.inject.Provides;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public abstract class BaseEC2ApiTest<T> extends BaseAsyncApiTest<T> {
+   @ConfiguresHttpApi
+   protected static class StubEC2HttpApiModule extends BaseEC2HttpApiModule<EC2Api> {
+
+      protected StubEC2HttpApiModule() {
+         super(EC2Api.class);
+      }
+
+      @Provides
+      @Singleton
+      LoadingCache<RegionAndName, Image> provide(){
+         return CacheBuilder.newBuilder().build(new CacheLoader<RegionAndName, Image>() {
+
+            @Override
+            public Image load(RegionAndName key) throws Exception {
+               return null;
+            }
+
+         });
+      }
+      
+      @Override
+      protected String provideTimeStamp(DateService dateService) {
+         return "2009-11-08T15:54:08.897Z";
+      }
+
+      static class Zones implements javax.inject.Provider<Map<String, String>> {
+         @Override
+         public Map<String, String> get() {
+            return ImmutableMap.<String, String> of("us-east-1a", "us-east-1");
+         }
+      }
+
+      @Override
+      protected void installLocations() {
+         install(new LocationModule());
+         bind(RegionIdToURISupplier.class).toInstance(new RegionIdToURISupplier() {
+
+            @Override
+            public Map<String, Supplier<URI>> get() {
+               return transformValues(ImmutableMap.<String, URI> of(Region.EU_WEST_1, URI
+                        .create("https://ec2.eu-west-1.amazonaws.com"), Region.US_EAST_1, URI
+                        .create("https://ec2.us-east-1.amazonaws.com"), Region.US_WEST_1, URI
+                        .create("https://ec2.us-west-1.amazonaws.com")), Suppliers2.<URI> ofInstanceFunction());
+            }
+
+         });
+         bind(RegionIdToZoneIdsSupplier.class).toInstance(new RegionIdToZoneIdsSupplier() {
+
+            @Override
+            public Map<String, Supplier<Set<String>>> get() {
+               return transformValues(ImmutableMap.<String, Set<String>> of("us-east-1", ImmutableSet.of(
+                        "us-east-1a", "us-east-1b", "us-east-1c", "us-east-1b")), Suppliers2
+                        .<Set<String>> ofInstanceFunction());
+            }
+
+         });
+      }
+   }
+
+   protected FormSigner filter;
+
+   @Override
+   protected void checkFilters(HttpRequest request) {
+      assertEquals(request.getFilters().size(), 1);
+      assertEquals(request.getFilters().get(0).getClass(), FormSigner.class);
+   }
+
+   @Override
+   @BeforeTest
+   protected void setupFactory() throws IOException {
+      super.setupFactory();
+      this.filter = injector.getInstance(FormSigner.class);
+   }
+
+   @Override
+   protected Module createModule() {
+      return new StubEC2HttpApiModule();
+   }
+   
+   @Override
+   protected ApiMetadata createApiMetadata() {
+      return new EC2ApiMetadata();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/EC2ElasticBlockStoreApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/EC2ElasticBlockStoreApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/EC2ElasticBlockStoreApiExpectTest.java
new file mode 100644
index 0000000..a72486f
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/EC2ElasticBlockStoreApiExpectTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.features;
+
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.domain.Volume;
+import org.jclouds.ec2.internal.BaseEC2ApiExpectTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "EC2ElasticBlockStoreApiExpectTest")
+public class EC2ElasticBlockStoreApiExpectTest extends BaseEC2ApiExpectTest<EC2Api> {
+   Volume creating = Volume.builder()
+                           .id("vol-2a21e543")
+                           .status(Volume.Status.CREATING)
+                           .availabilityZone("us-east-1a")
+                           .region("us-east-1")
+                           .id("vol-2a21e543")
+                           .size(1)
+                           .createTime(dateService.iso8601DateParse("2009-12-28T05:42:53.000Z"))
+                           .build();
+   
+   public void testCreateVolumeInAvailabilityZone() {
+      Builder<HttpRequest, HttpResponse> builder = ImmutableMap.<HttpRequest, HttpResponse>builder();
+      builder.put(describeRegionsRequest, describeRegionsResponse);
+      builder.putAll(describeAvailabilityZonesRequestResponse);
+      builder.put(
+            HttpRequest.builder()
+                       .method("POST")
+                       .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                       .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                       .payload(payloadFromStringWithContentType("Action=CreateVolume&AvailabilityZone=us-east-1a&Signature=FB5hTZHKSAuiygoafIdJh1EnfTu0ogC2VfRQOar85mg%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Size=4&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
+            HttpResponse.builder()
+                        .statusCode(200)
+                        .payload(payloadFromResource("/created_volume.xml")).build());
+      
+      ElasticBlockStoreApi client = requestsSendResponses(builder.build()).getElasticBlockStoreApi().get();
+
+      assertEquals(client.createVolumeInAvailabilityZone("us-east-1a", 4), creating);
+   }
+   
+   public void testCreateVolumeFromSnapshotInAvailabilityZoneEuSetsCorrectEndpoint() {
+      String region = "eu-west-1";
+      
+      Builder<HttpRequest, HttpResponse> builder = ImmutableMap.<HttpRequest, HttpResponse>builder();
+      builder.put(describeRegionsRequest, describeRegionsResponse);
+      builder.putAll(describeAvailabilityZonesRequestResponse);
+      builder.put(
+            formSigner.filter(HttpRequest.builder()
+                                         .method("POST")
+                                         .endpoint("https://ec2." + region + ".amazonaws.com/")
+                                         .addHeader("Host", "ec2." + region + ".amazonaws.com")
+                                         .addFormParam("Action", "CreateVolume")
+                                         .addFormParam("AvailabilityZone", "eu-west-1a")
+                                         .addFormParam("Size", "1")
+                                         .addFormParam("SnapshotId", "snap-8b7ffbdd").build()),
+            HttpResponse.builder()
+                        .statusCode(200)
+                        .payload(payloadFromResource("/created_volume.xml")).build());
+      
+      ElasticBlockStoreApi client = requestsSendResponses(builder.build()).getElasticBlockStoreApi().get();
+
+      assertEquals(client.createVolumeFromSnapshotInAvailabilityZone(region + "a", 1, "snap-8b7ffbdd"), creating.toBuilder().region(region).build());
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiLiveTest.java
new file mode 100644
index 0000000..380e35e
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiLiveTest.java
@@ -0,0 +1,223 @@
+/*
+ * 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.features;
+import static com.google.common.base.Preconditions.checkNotNull;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.ec2.options.DescribeSnapshotsOptions.Builder.snapshotIds;
+import static org.jclouds.util.Predicates2.retry;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.Set;
+import java.util.SortedSet;
+
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.EC2ApiMetadata;
+import org.jclouds.ec2.domain.AvailabilityZoneInfo;
+import org.jclouds.ec2.domain.Snapshot;
+import org.jclouds.ec2.domain.Volume;
+import org.jclouds.ec2.predicates.SnapshotCompleted;
+import org.jclouds.ec2.predicates.VolumeAvailable;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Strings;
+import com.google.common.collect.Iterables;
+import com.google.common.collect.Sets;
+
+/**
+ * Tests behavior of {@code ElasticBlockStoreApi}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "ElasticBlockStoreApiLiveTest")
+public class ElasticBlockStoreApiLiveTest extends BaseComputeServiceContextLiveTest {
+   public ElasticBlockStoreApiLiveTest() {
+      provider = "ec2";
+   }
+
+   private EC2Api ec2Api;
+   private ElasticBlockStoreApi client;
+
+   private String defaultRegion;
+   private String defaultZone;
+
+   private String volumeId;
+   private Snapshot snapshot;
+
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      ec2Api = view.unwrapApi(EC2Api.class);
+      client = ec2Api.getElasticBlockStoreApi().get();
+      AvailabilityZoneInfo info = Iterables.get(ec2Api.getAvailabilityZoneAndRegionApi().get()
+            .describeAvailabilityZonesInRegion(defaultRegion), 0);
+      defaultRegion = checkNotNull(Strings.emptyToNull(info.getRegion()), "region of " + info);
+      defaultZone = checkNotNull(Strings.emptyToNull(info.getZone()), "zone of " + info);
+   }
+
+   @Test
+   void testDescribeVolumes() {
+      for (String region : ec2Api.getConfiguredRegions()) {
+         SortedSet<Volume> allResults = Sets.newTreeSet(client.describeVolumesInRegion(region));
+         assertNotNull(allResults);
+         if (allResults.size() >= 1) {
+            Volume volume = allResults.last();
+            SortedSet<Volume> result = Sets.newTreeSet(client.describeVolumesInRegion(region, volume.getId()));
+            assertNotNull(result);
+            Volume compare = result.last();
+            assertEquals(compare, volume);
+         }
+      }
+   }
+
+   @Test
+   void testCreateVolumeInAvailabilityZone() {
+      Volume expected = client.createVolumeInAvailabilityZone(defaultZone, 1);
+      assertNotNull(expected);
+      assertEquals(expected.getAvailabilityZone(), defaultZone);
+
+      this.volumeId = expected.getId();
+
+      Set<Volume> result = Sets.newLinkedHashSet(client.describeVolumesInRegion(defaultRegion, expected.getId()));
+      assertNotNull(result);
+      assertEquals(result.size(), 1);
+      Volume volume = result.iterator().next();
+      assertEquals(volume.getId(), expected.getId());
+   }
+
+   @Test(dependsOnMethods = "testCreateVolumeInAvailabilityZone")
+   void testCreateSnapshotInRegion() {
+      Snapshot snapshot = client.createSnapshotInRegion(defaultRegion, volumeId);
+      Predicate<Snapshot> snapshotted = retry(new SnapshotCompleted(client), 600, 10, SECONDS);
+      assert snapshotted.apply(snapshot);
+
+      Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegion(snapshot.getRegion(),
+            snapshotIds(snapshot.getId())));
+
+      assertEquals(result.getProgress(), 100);
+      this.snapshot = result;
+   }
+
+   @Test(dependsOnMethods = "testCreateSnapshotInRegion")
+   void testCreateVolumeFromSnapshotInAvailabilityZone() {
+      Volume volume = client.createVolumeFromSnapshotInAvailabilityZone(defaultZone, snapshot.getId());
+      assertNotNull(volume);
+
+      Predicate<Volume> availabile = retry(new VolumeAvailable(client), 600, 10, SECONDS);
+      assert availabile.apply(volume);
+
+      Volume result = Iterables.getOnlyElement(client.describeVolumesInRegion(snapshot.getRegion(), volume.getId()));
+      assertEquals(volume.getId(), result.getId());
+      assertEquals(volume.getSnapshotId(), snapshot.getId());
+      assertEquals(volume.getAvailabilityZone(), defaultZone);
+      assertEquals(result.getStatus(), Volume.Status.AVAILABLE);
+
+      client.deleteVolumeInRegion(snapshot.getRegion(), volume.getId());
+   }
+
+   @Test(dependsOnMethods = "testCreateSnapshotInRegion")
+   void testCreateVolumeFromSnapshotInAvailabilityZoneWithSize() {
+      Volume volume = client.createVolumeFromSnapshotInAvailabilityZone(defaultZone, 2, snapshot.getId());
+      assertNotNull(volume);
+
+      Predicate<Volume> availabile = retry(new VolumeAvailable(client), 600, 10, SECONDS);
+      assert availabile.apply(volume);
+
+      Volume result = Iterables.getOnlyElement(client.describeVolumesInRegion(snapshot.getRegion(), volume.getId()));
+      assertEquals(volume.getId(), result.getId());
+      assertEquals(volume.getSnapshotId(), snapshot.getId());
+      assertEquals(volume.getAvailabilityZone(), defaultZone);
+      assertEquals(volume.getSize(), 2);
+      assertEquals(result.getStatus(), Volume.Status.AVAILABLE);
+
+      client.deleteVolumeInRegion(snapshot.getRegion(), volume.getId());
+   }
+
+   @Test
+   void testAttachVolumeInRegion() {
+      // TODO: need an instance
+   }
+
+   @Test
+   void testDetachVolumeInRegion() {
+      // TODO: need an instance
+   }
+
+   @Test
+   void testDescribeSnapshots() {
+      for (String region : ec2Api.getConfiguredRegions()) {
+         SortedSet<Snapshot> allResults = Sets.newTreeSet(client.describeSnapshotsInRegion(region));
+         assertNotNull(allResults);
+         if (allResults.size() >= 1) {
+            Snapshot snapshot = allResults.last();
+            Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegion(region,
+                  snapshotIds(snapshot.getId())));
+            assertNotNull(result);
+            assertEquals(result, snapshot);
+         }
+      }
+   }
+
+   @Test(enabled = false)
+   public void testAddCreateVolumePermissionsToSnapshot() {
+      // TODO client.addCreateVolumePermissionsToSnapshotInRegion(defaultRegion,
+      // userIds,
+      // userGroups,
+      // snapshotId);
+   }
+
+   @Test(enabled = false)
+   public void testRemoveCreateVolumePermissionsFromSnapshot() {
+      // TODO
+      // client.removeCreateVolumePermissionsFromSnapshotInRegion(defaultRegion,
+      // userIds,
+      // userGroups,
+      // snapshotId);
+   }
+
+   @Test(enabled = false)
+   public void testResetCreateVolumePermissionsOnSnapshot() {
+      // TODO
+      // client.resetCreateVolumePermissionsOnSnapshotInRegion(defaultRegion,
+      // snapshotId);
+   }
+
+   @Test(dependsOnMethods = "testCreateSnapshotInRegion")
+   public void testGetCreateVolumePermissionForSnapshot() {
+      client.getCreateVolumePermissionForSnapshotInRegion(snapshot.getRegion(), snapshot.getId());
+   }
+
+   @Test(dependsOnMethods = "testCreateSnapshotInRegion")
+   void testDeleteVolumeInRegion() {
+      client.deleteVolumeInRegion(defaultRegion, volumeId);
+      Set<Volume> result = Sets.newLinkedHashSet(client.describeVolumesInRegion(defaultRegion, volumeId));
+      assertEquals(result.size(), 1);
+      Volume volume = result.iterator().next();
+      assertEquals(volume.getStatus(), Volume.Status.DELETING);
+   }
+
+   @Test(dependsOnMethods = "testGetCreateVolumePermissionForSnapshot")
+   void testDeleteSnapshotInRegion() {
+      client.deleteSnapshotInRegion(snapshot.getRegion(), snapshot.getId());
+      assert client.describeSnapshotsInRegion(snapshot.getRegion(), snapshotIds(snapshot.getId())).size() == 0;
+   }
+
+}


[12/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiTest.java
new file mode 100644
index 0000000..b0b4fba
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiTest.java
@@ -0,0 +1,401 @@
+/*
+ * 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.features;
+
+import static org.jclouds.ec2.options.DescribeSnapshotsOptions.Builder.ownedBy;
+import static org.jclouds.ec2.options.DetachVolumeOptions.Builder.fromInstance;
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.ec2.EC2Fallbacks.VoidOnVolumeAvailable;
+import org.jclouds.ec2.options.CreateSnapshotOptions;
+import org.jclouds.ec2.options.DescribeSnapshotsOptions;
+import org.jclouds.ec2.options.DetachVolumeOptions;
+import org.jclouds.ec2.xml.AttachmentHandler;
+import org.jclouds.ec2.xml.DescribeSnapshotsResponseHandler;
+import org.jclouds.ec2.xml.DescribeVolumesResponseHandler;
+import org.jclouds.ec2.xml.PermissionHandler;
+import org.jclouds.ec2.xml.SnapshotHandler;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.http.functions.ReleasePayloadAndReturn;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code ElasticBlockStoreApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "ElasticBlockStoreApiTest")
+public class ElasticBlockStoreApiTest extends BaseEC2ApiTest<ElasticBlockStoreApi> {
+
+   public void testDeleteVolume() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticBlockStoreApi.class, "deleteVolumeInRegion", String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "id"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DeleteVolume&VolumeId=id",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest describeVolumes = HttpRequest.builder().method("POST")
+                                            .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                            .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                            .addFormParam("Action", "DescribeVolumes")
+                                            .addFormParam("Signature", "hNuorhZQS%2BThX5dWXOvBkvnmTpgp6SvwHmgzjjfKyG8%3D")
+                                            .addFormParam("SignatureMethod", "HmacSHA256")
+                                            .addFormParam("SignatureVersion", "2")
+                                            .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                            .addFormParam("Version", "2010-06-15")
+                                            .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testDescribeVolumes() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticBlockStoreApi.class, "describeVolumesInRegion", String.class,
+            String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, describeVolumes.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+      
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeVolumesResponseHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeVolumesArgs() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticBlockStoreApi.class, "describeVolumesInRegion", String.class,
+               String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeVolumes&VolumeId.1=1&VolumeId.2=2",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeVolumesResponseHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest attachVolume = HttpRequest.builder().method("POST")
+                                         .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                         .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                         .addFormParam("Action", "AttachVolume")
+                                         .addFormParam("Device", "/device")
+                                         .addFormParam("InstanceId", "instanceId")
+                                         .addFormParam("Signature", "LaOppR61eWpdNgMYJ3ccfo9vzbmUyJf9Ars%2Bbcu4OGI%3D")
+                                         .addFormParam("SignatureMethod", "HmacSHA256")
+                                         .addFormParam("SignatureVersion", "2")
+                                         .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                         .addFormParam("Version", "2010-06-15")
+                                         .addFormParam("VolumeId", "id")
+                                         .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testAttachVolume() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticBlockStoreApi.class, "attachVolumeInRegion", String.class, String.class,
+               String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "id", "instanceId", "/device"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, attachVolume.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, AttachmentHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest detachVolume = HttpRequest.builder().method("POST")
+                                         .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                         .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                         .addFormParam("Action", "DetachVolume")
+                                         .addFormParam("Force", "false")
+                                         .addFormParam("Signature", "4c6EmHwCYbe%2BifuUV0PNXpKfReoZvJXyme37mKtnLk8%3D")
+                                         .addFormParam("SignatureMethod", "HmacSHA256")
+                                         .addFormParam("SignatureVersion", "2")
+                                         .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                         .addFormParam("Version", "2010-06-15")
+                                         .addFormParam("VolumeId", "id")
+                                         .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testDetachVolume() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticBlockStoreApi.class, "detachVolumeInRegion", String.class, String.class,
+               boolean.class, DetachVolumeOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "id", false));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, detachVolume.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+      
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, VoidOnVolumeAvailable.class);
+
+      checkFilters(request);
+   }
+
+   HttpRequest detachVolumeOptions = HttpRequest.builder().method("POST")
+                                                .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                .addFormParam("Action", "DetachVolume")
+                                                .addFormParam("Device", "/device")
+                                                .addFormParam("Force", "true")
+                                                .addFormParam("InstanceId", "instanceId")
+                                                .addFormParam("Signature", "GrUGXc6H5W%2BNF8zcXU8gSRbt1ELt%2BTcCDEvbY1a88NE%3D")
+                                                .addFormParam("SignatureMethod", "HmacSHA256")
+                                                .addFormParam("SignatureVersion", "2")
+                                                .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                .addFormParam("Version", "2010-06-15")
+                                                .addFormParam("VolumeId", "id")
+                                                .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testDetachVolumeOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticBlockStoreApi.class, "detachVolumeInRegion", String.class, String.class,
+               boolean.class, DetachVolumeOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "id", true, fromInstance("instanceId").fromDevice(
+               "/device")));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, detachVolumeOptions.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+      
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, VoidOnVolumeAvailable.class);
+
+      checkFilters(request);
+   }
+
+   public void testCreateSnapshot() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticBlockStoreApi.class, "createSnapshotInRegion", String.class,
+               String.class, CreateSnapshotOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "volumeId"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=CreateSnapshot&VolumeId=volumeId",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, SnapshotHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testCreateSnapshotOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticBlockStoreApi.class, "createSnapshotInRegion", String.class,
+               String.class, CreateSnapshotOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "volumeId", CreateSnapshotOptions.Builder
+               .withDescription("description")));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+               "Action=CreateSnapshot&VolumeId=volumeId&Description=description",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, SnapshotHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeSnapshots() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticBlockStoreApi.class, "describeSnapshotsInRegion", String.class,
+               DescribeSnapshotsOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeSnapshots", "application/x-www-form-urlencoded",
+               false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeSnapshotsResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeSnapshotsArgs() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticBlockStoreApi.class, "describeSnapshotsInRegion", String.class,
+               DescribeSnapshotsOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ownedBy("o1", "o2").restorableBy("r1", "r2")
+               .snapshotIds("s1", "s2")));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(
+               request,
+               "Action=DescribeSnapshots&Owner.1=o1&Owner.2=o2&RestorableBy.1=r1&RestorableBy.2=r2&SnapshotId.1=s1&SnapshotId.2=s2",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeSnapshotsResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testGetCreateVolumePermissionForSnapshot() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticBlockStoreApi.class, "getCreateVolumePermissionForSnapshotInRegion",
+               String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "snapshotId"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(
+               request,
+               "Action=DescribeSnapshotAttribute&Attribute=createVolumePermission&SnapshotId=snapshotId",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, PermissionHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest addCreateVolumePermissionsToSnapshot = HttpRequest.builder().method("POST")
+                                                                 .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                                 .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                                 .addFormParam("Action", "ModifySnapshotAttribute")
+                                                                 .addFormParam("Attribute", "createVolumePermission")
+                                                                 .addFormParam("OperationType", "add")
+                                                                 .addFormParam("Signature", "AizV1N1rCCXi%2BbzXX/Vz7shFq9yAJAwcmAGyRQMH%2Bjs%3D")
+                                                                 .addFormParam("SignatureMethod", "HmacSHA256")
+                                                                 .addFormParam("SignatureVersion", "2")
+                                                                 .addFormParam("SnapshotId", "snapshotId")
+                                                                 .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                                 .addFormParam("UserGroup.1", "all")
+                                                                 .addFormParam("UserId.1", "bob")
+                                                                 .addFormParam("UserId.2", "sue")
+                                                                 .addFormParam("Version", "2010-06-15")
+                                                                 .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testAddCreateVolumePermissionsToSnapshot() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticBlockStoreApi.class, "addCreateVolumePermissionsToSnapshotInRegion",
+               String.class, Iterable.class, Iterable.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("bob", "sue"), ImmutableList
+               .of("all"), "snapshotId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, addCreateVolumePermissionsToSnapshot.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest removeCreateVolumePermissionsFromSnapshot = HttpRequest.builder().method("POST")
+                                                                      .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                                      .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                                      .addFormParam("Action", "ModifySnapshotAttribute")
+                                                                      .addFormParam("Attribute", "createVolumePermission")
+                                                                      .addFormParam("OperationType", "remove")
+                                                                      .addFormParam("Signature", "Lmlt2daM%2BJ4kIoU9HmCempwVGZP1fC6V%2Br9o8MQjYy8%3D")
+                                                                      .addFormParam("SignatureMethod", "HmacSHA256")
+                                                                      .addFormParam("SignatureVersion", "2")
+                                                                      .addFormParam("SnapshotId", "snapshotId")
+                                                                      .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                                      .addFormParam("UserGroup.1", "all")
+                                                                      .addFormParam("UserId.1", "bob")
+                                                                      .addFormParam("UserId.2", "sue")
+                                                                      .addFormParam("Version", "2010-06-15")
+                                                                      .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testRemoveCreateVolumePermissionsFromSnapshot() throws SecurityException, NoSuchMethodException,
+            IOException {
+      Invokable<?, ?> method = method(ElasticBlockStoreApi.class, "removeCreateVolumePermissionsFromSnapshotInRegion",
+               String.class, Iterable.class, Iterable.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("bob", "sue"), ImmutableList
+               .of("all"), "snapshotId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, removeCreateVolumePermissionsFromSnapshot.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testResetCreateVolumePermissionsOnSnapshot() throws SecurityException, NoSuchMethodException,
+            IOException {
+      Invokable<?, ?> method = method(ElasticBlockStoreApi.class, "resetCreateVolumePermissionsOnSnapshotInRegion",
+               String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "snapshotId"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(
+               request,
+               "Action=ResetSnapshotAttribute&Attribute=createVolumePermission&SnapshotId=snapshotId",
+               "application/x-www-form-urlencoded", false);
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiLiveTest.java
new file mode 100644
index 0000000..119c2de
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiLiveTest.java
@@ -0,0 +1,72 @@
+/*
+ * 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.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.SortedSet;
+
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.EC2ApiMetadata;
+import org.jclouds.ec2.compute.EC2ComputeServiceContext;
+import org.jclouds.ec2.domain.PublicIpInstanceIdPair;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Tests behavior of {@code ElasticIPAddressApi}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "ElasticIPAddressApiLiveTest")
+public class ElasticIPAddressApiLiveTest extends BaseComputeServiceContextLiveTest {
+   public ElasticIPAddressApiLiveTest() {
+      provider = "ec2";
+   }
+
+   private EC2Api ec2Api;
+   private ElasticIPAddressApi client;
+
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      ec2Api = view.unwrapApi(EC2Api.class);
+      client = ec2Api.getElasticIPAddressApi().get();
+   }
+
+   @Test
+   void testDescribeAddresses() {
+      for (String region : ec2Api.getConfiguredRegions()) {
+         SortedSet<PublicIpInstanceIdPair> allResults = Sets.newTreeSet(client.describeAddressesInRegion(region));
+         assertNotNull(allResults);
+         if (allResults.size() >= 1) {
+            PublicIpInstanceIdPair pair = allResults.last();
+            SortedSet<PublicIpInstanceIdPair> result = Sets.newTreeSet(client.describeAddressesInRegion(region, pair
+                     .getPublicIp()));
+            assertNotNull(result);
+            PublicIpInstanceIdPair compare = result.last();
+            assertEquals(compare, pair);
+         }
+      }
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiTest.java
new file mode 100644
index 0000000..d230ca4
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiTest.java
@@ -0,0 +1,140 @@
+/*
+ * 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.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.ec2.xml.AllocateAddressResponseHandler;
+import org.jclouds.ec2.xml.DescribeAddressesResponseHandler;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.http.functions.ReleasePayloadAndReturn;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Lists;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code ElasticIPAddressApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "ElasticIPAddressApiTest")
+public class ElasticIPAddressApiTest extends BaseEC2ApiTest<ElasticIPAddressApi> {
+
+   public void testDisassociateAddress() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticIPAddressApi.class, "disassociateAddressInRegion", String.class,
+            String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "127.0.0.1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DisassociateAddress&PublicIp=127.0.0.1",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest associateAddress = HttpRequest.builder().method("POST")
+                                             .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                             .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                             .addFormParam("Action", "AssociateAddress")
+                                             .addFormParam("InstanceId", "me")
+                                             .addFormParam("PublicIp", "127.0.0.1")
+                                             .addFormParam("Signature", "YmPyvEljuFw0INSUbQx5xAhC/1GQ4a1Ht6TdoXeMc9Y%3D")
+                                             .addFormParam("SignatureMethod", "HmacSHA256")
+                                             .addFormParam("SignatureVersion", "2")
+                                             .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                             .addFormParam("Version", "2010-06-15")
+                                             .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testAssociateAddress() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticIPAddressApi.class, "associateAddressInRegion", String.class,
+            String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "127.0.0.1", "me"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, associateAddress.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testReleaseAddress() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticIPAddressApi.class, "releaseAddressInRegion", String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "127.0.0.1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=ReleaseAddress&PublicIp=127.0.0.1",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeAddresses() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticIPAddressApi.class, "describeAddressesInRegion", String.class,
+            String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "127.0.0.1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeAddresses&PublicIp.1=127.0.0.1",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeAddressesResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testAllocateAddress() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(ElasticIPAddressApi.class, "allocateAddressInRegion", String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=AllocateAddress", "application/x-www-form-urlencoded",
+            false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, AllocateAddressResponseHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiLiveTest.java
new file mode 100644
index 0000000..57f9441
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiLiveTest.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.features;
+
+import static org.testng.Assert.assertNotNull;
+
+import java.util.Set;
+
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.EC2ApiMetadata;
+import org.jclouds.ec2.domain.Reservation;
+import org.jclouds.ec2.domain.RunningInstance;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code EC2Api}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "InstanceApiLiveTest")
+public class InstanceApiLiveTest extends BaseComputeServiceContextLiveTest {
+   public InstanceApiLiveTest() {
+      provider = "ec2";
+   }
+
+   private EC2Api ec2Api;
+   private InstanceApi client;
+
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      ec2Api = view.unwrapApi(EC2Api.class);
+      client = ec2Api.getInstanceApi().get();
+   }
+
+   @Test
+   void testDescribeInstances() {
+      for (String region : ec2Api.getConfiguredRegions()) {
+         Set<? extends Reservation<? extends RunningInstance>> allResults = client.describeInstancesInRegion(region);
+         assertNotNull(allResults);
+         assert allResults.size() >= 0 : allResults.size();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiTest.java
new file mode 100644
index 0000000..2f17735
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiTest.java
@@ -0,0 +1,593 @@
+/*
+ * 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.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.ec2.domain.BlockDevice;
+import org.jclouds.ec2.domain.InstanceType;
+import org.jclouds.ec2.domain.Volume.InstanceInitiatedShutdownBehavior;
+import org.jclouds.ec2.options.RunInstancesOptions;
+import org.jclouds.ec2.xml.BlockDeviceMappingHandler;
+import org.jclouds.ec2.xml.BooleanValueHandler;
+import org.jclouds.ec2.xml.DescribeInstancesResponseHandler;
+import org.jclouds.ec2.xml.GetConsoleOutputResponseHandler;
+import org.jclouds.ec2.xml.InstanceInitiatedShutdownBehaviorHandler;
+import org.jclouds.ec2.xml.InstanceStateChangeHandler;
+import org.jclouds.ec2.xml.InstanceTypeHandler;
+import org.jclouds.ec2.xml.RunInstancesResponseHandler;
+import org.jclouds.ec2.xml.StringValueHandler;
+import org.jclouds.ec2.xml.UnencodeStringValueHandler;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.http.functions.ReleasePayloadAndReturn;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code InstanceApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "InstanceApiTest")
+public class InstanceApiTest extends BaseEC2ApiTest<InstanceApi> {
+   public void testDescribeInstances() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "describeInstancesInRegion", String.class, String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeInstances", "application/x-www-form-urlencoded",
+               false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeInstancesResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeInstancesArgs() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "describeInstancesInRegion", String.class, String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeInstances&InstanceId.1=1&InstanceId.2=2",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeInstancesResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testTerminateInstances() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "terminateInstancesInRegion", String.class,
+               String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=TerminateInstances&InstanceId.1=1&InstanceId.2=2",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testRunInstances() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "runInstancesInRegion", String.class, String.class,
+               String.class, int.class, int.class, RunInstancesOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, null, "ami-voo", 1, 1));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      try {
+         assertPayloadEquals(request, "Action=RunInstances&ImageId=ami-voo&MinCount=1&MaxCount=1",
+                  "application/x-www-form-urlencoded", false);
+      } catch (AssertionError e) {
+         // mvn 3.0 osx 10.6.5 somehow sorts differently
+         assertPayloadEquals(request, "Action=RunInstances&ImageId=ami-voo&MaxCount=1&MinCount=1",
+                  "application/x-www-form-urlencoded", false);
+      }
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, RunInstancesResponseHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testRunInstancesOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "runInstancesInRegion", String.class, String.class,
+               String.class, int.class, int.class, RunInstancesOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("eu-west-1", "eu-west-1a", "ami-voo",
+               1, 5, new RunInstancesOptions().withKernelId("kernelId").withSecurityGroups("group1", "group2")));
+
+      assertRequestLineEquals(request, "POST https://ec2.eu-west-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.eu-west-1.amazonaws.com\n");
+      try {
+         assertPayloadEquals(
+                  request,
+                  "Action=RunInstances&ImageId=ami-voo&MinCount=1&MaxCount=5&KernelId=kernelId&SecurityGroup.1=group1&SecurityGroup.2=group2&Placement.AvailabilityZone=eu-west-1a",
+                  "application/x-www-form-urlencoded", false);
+      } catch (AssertionError e) {
+         // mvn 3.0 osx 10.6.5 somehow sorts differently
+         assertPayloadEquals(
+                  request,
+                  "Action=RunInstances&ImageId=ami-voo&MaxCount=5&MinCount=1&KernelId=kernelId&SecurityGroup.1=group1&SecurityGroup.2=group2&Placement.AvailabilityZone=eu-west-1a",
+                  "application/x-www-form-urlencoded", false);
+      }
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, RunInstancesResponseHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testStopInstances() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "stopInstancesInRegion", String.class, boolean.class,
+               String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, true, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=StopInstances&Force=true&InstanceId.1=1&InstanceId.2=2",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testRebootInstances() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "rebootInstancesInRegion", String.class, String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=RebootInstances&InstanceId.1=1&InstanceId.2=2",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testStartInstances() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "startInstancesInRegion", String.class, String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=StartInstances&InstanceId.1=1&InstanceId.2=2",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetUserDataForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "getUserDataForInstanceInRegion", String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+               "Action=DescribeInstanceAttribute&Attribute=userData&InstanceId=1",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, UnencodeStringValueHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetRootDeviceNameForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "getRootDeviceNameForInstanceInRegion", String.class,
+               String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+               "Action=DescribeInstanceAttribute&Attribute=rootDeviceName&InstanceId=1",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, StringValueHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetRamdiskForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "getRamdiskForInstanceInRegion", String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+               "Action=DescribeInstanceAttribute&Attribute=ramdisk&InstanceId=1",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, StringValueHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetDisableApiTerminationForInstanceInRegion() throws SecurityException, NoSuchMethodException,
+            IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "isApiTerminationDisabledForInstanceInRegion", String.class,
+               String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+               "Action=DescribeInstanceAttribute&Attribute=disableApiTermination&InstanceId=1",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, BooleanValueHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetKernelForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "getKernelForInstanceInRegion", String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeInstanceAttribute&Attribute=kernel&InstanceId=1",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, StringValueHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetInstanceTypeForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "getInstanceTypeForInstanceInRegion", String.class,
+               String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+               "Action=DescribeInstanceAttribute&Attribute=instanceType&InstanceId=1",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, InstanceTypeHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetInstanceInitiatedShutdownBehaviorForInstanceInRegion() throws SecurityException,
+            NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "getInstanceInitiatedShutdownBehaviorForInstanceInRegion",
+               String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(
+               request,
+               "Action=DescribeInstanceAttribute&Attribute=instanceInitiatedShutdownBehavior&InstanceId=1",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, InstanceInitiatedShutdownBehaviorHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetBlockDeviceMappingForInstanceInRegion() throws SecurityException, NoSuchMethodException,
+            IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "getBlockDeviceMappingForInstanceInRegion", String.class,
+               String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+               "Action=DescribeInstanceAttribute&Attribute=blockDeviceMapping&InstanceId=1",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, BlockDeviceMappingHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest setUserDataForInstance = HttpRequest.builder().method("POST")
+                                                   .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                   .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                   .addFormParam("Action", "ModifyInstanceAttribute")
+                                                   .addFormParam("Attribute", "userData")
+                                                   .addFormParam("InstanceId", "1")
+                                                   .addFormParam("Signature", "LfUmzLM5DsACR5nQcEfGF5FPdznOwwhJ7tjhBWfHtGs%3D")
+                                                   .addFormParam("SignatureMethod", "HmacSHA256")
+                                                   .addFormParam("SignatureVersion", "2")
+                                                   .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                   .addFormParam("Value", "dGVzdA%3D%3D")
+                                                   .addFormParam("Version", "2010-06-15")
+                                                   .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testSetUserDataForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "setUserDataForInstanceInRegion", String.class, String.class,
+               byte[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "test".getBytes()));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, setUserDataForInstance.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest setRamdiskForInstance = HttpRequest.builder().method("POST")
+                                                  .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                  .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                  .addFormParam("Action", "ModifyInstanceAttribute")
+                                                  .addFormParam("Attribute", "ramdisk")
+                                                  .addFormParam("InstanceId", "1")
+                                                  .addFormParam("Signature", "qx6NeVbihiYrKvi5Oe5LzMsGHTjS7%2BqoNhh2abt275g%3D")
+                                                  .addFormParam("SignatureMethod", "HmacSHA256")
+                                                  .addFormParam("SignatureVersion", "2")
+                                                  .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                  .addFormParam("Value", "test")
+                                                  .addFormParam("Version", "2010-06-15")
+                                                  .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testSetRamdiskForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "setRamdiskForInstanceInRegion", String.class, String.class,
+               String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "test"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, setRamdiskForInstance.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest setKernelForInstance = HttpRequest.builder().method("POST")
+                                                 .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                 .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                 .addFormParam("Action", "ModifyInstanceAttribute")
+                                                 .addFormParam("Attribute", "kernel")
+                                                 .addFormParam("InstanceId", "1")
+                                                 .addFormParam("Signature", "juSiuoiXJzTxj3q0LUW2528HzDyP4JAcKin%2BI4AuIT0%3D")
+                                                 .addFormParam("SignatureMethod", "HmacSHA256")
+                                                 .addFormParam("SignatureVersion", "2")
+                                                 .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                 .addFormParam("Value", "test")
+                                                 .addFormParam("Version", "2010-06-15")
+                                                 .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testSetKernelForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "setKernelForInstanceInRegion", String.class, String.class,
+               String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "test"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, setKernelForInstance.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest setApiTerminationDisabled = HttpRequest.builder().method("POST")
+                                                      .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                      .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                      .addFormParam("Action", "ModifyInstanceAttribute")
+                                                      .addFormParam("Attribute", "disableApiTermination")
+                                                      .addFormParam("InstanceId", "1")
+                                                      .addFormParam("Signature", "tiBMWWTi22BWeAjsRfuzVom0tQgsOBeYTkatMuWRrbg%3D")
+                                                      .addFormParam("SignatureMethod", "HmacSHA256")
+                                                      .addFormParam("SignatureVersion", "2")
+                                                      .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                      .addFormParam("Value", "true")
+                                                      .addFormParam("Version", "2010-06-15")
+                                                      .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testSetApiTerminationDisabledForInstanceInRegion() throws SecurityException, NoSuchMethodException,
+            IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "setApiTerminationDisabledForInstanceInRegion", String.class,
+               String.class, boolean.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", true));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, setApiTerminationDisabled.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest instanceTypeForInstance = HttpRequest.builder().method("POST")
+                                                    .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                    .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                    .addFormParam("Action", "ModifyInstanceAttribute")
+                                                    .addFormParam("Attribute", "instanceType")
+                                                    .addFormParam("InstanceId", "1")
+                                                    .addFormParam("Signature", "XK%2BzQmQ0S57gXIgVRMqUkKunURN9TaCJD1YWiYMAOHo%3D")
+                                                    .addFormParam("SignatureMethod", "HmacSHA256")
+                                                    .addFormParam("SignatureVersion", "2")
+                                                    .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                    .addFormParam("Value", "c1.medium")
+                                                    .addFormParam("Version", "2010-06-15")
+                                                    .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testSetInstanceTypeForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "setInstanceTypeForInstanceInRegion", String.class,
+               String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", InstanceType.C1_MEDIUM));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, instanceTypeForInstance.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest setInstanceInitiatedShutdownBehavior = HttpRequest.builder().method("POST")
+                                                                 .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                                 .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                                 .addFormParam("Action", "ModifyInstanceAttribute")
+                                                                 .addFormParam("Attribute", "instanceInitiatedShutdownBehavior")
+                                                                 .addFormParam("InstanceId", "1")
+                                                                 .addFormParam("Signature", "s5xBMLd%2BXNVp44x7C6qVE58qBov//f6yvxoM757KcZU%3D")
+                                                                 .addFormParam("SignatureMethod", "HmacSHA256")
+                                                                 .addFormParam("SignatureVersion", "2")
+                                                                 .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                                 .addFormParam("Value", "terminate")
+                                                                 .addFormParam("Version", "2010-06-15")
+                                                                 .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testSetInstanceInitiatedShutdownBehaviorForInstanceInRegion() throws SecurityException,
+            NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "setInstanceInitiatedShutdownBehaviorForInstanceInRegion",
+               String.class, String.class, InstanceInitiatedShutdownBehavior.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", InstanceInitiatedShutdownBehavior.TERMINATE));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, setInstanceInitiatedShutdownBehavior.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest setBlockDeviceMapping = HttpRequest.builder().method("POST")
+                                                           .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                           .addFormParam("Action", "ModifyInstanceAttribute")
+                                                           .addFormParam("BlockDeviceMapping.1.DeviceName", "/dev/sda1")
+                                                           .addFormParam("BlockDeviceMapping.1.Ebs.DeleteOnTermination", "true")
+                                                           .addFormParam("BlockDeviceMapping.1.Ebs.VolumeId", "vol-test1")
+                                                           .addFormParam("InstanceId", "1").build();
+
+   public void testSetBlockDeviceMappingForInstanceInRegion() throws SecurityException, NoSuchMethodException,
+            IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "setBlockDeviceMappingForInstanceInRegion", String.class,
+               String.class, Map.class);
+
+      Map<String, BlockDevice> mapping = Maps.newLinkedHashMap();
+      mapping.put("/dev/sda1", new BlockDevice("vol-test1", true));
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", mapping));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(setBlockDeviceMapping).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+
+      checkFilters(request);
+   }
+
+   public void testGetConsoleOutputForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(InstanceApi.class, "getConsoleOutputForInstanceInRegion", String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+               "Action=GetConsoleOutput&InstanceId=1",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, GetConsoleOutputResponseHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiLiveTest.java
new file mode 100644
index 0000000..c8bbff0
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiLiveTest.java
@@ -0,0 +1,97 @@
+/*
+ * 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.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.Set;
+import java.util.SortedSet;
+
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.EC2ApiMetadata;
+import org.jclouds.ec2.domain.KeyPair;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Sets;
+
+/**
+ * Tests behavior of {@code KeyPairApi}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "KeyPairApiLiveTest")
+public class KeyPairApiLiveTest extends BaseComputeServiceContextLiveTest {
+   public KeyPairApiLiveTest() {
+      provider = "ec2";
+   }
+
+   private EC2Api ec2Api;
+   private KeyPairApi client;
+   
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      ec2Api = view.unwrapApi(EC2Api.class);
+      client = ec2Api.getKeyPairApi().get();
+   }
+
+   @Test
+   void testDescribeKeyPairs() {
+      for (String region : ec2Api.getConfiguredRegions()) {
+         SortedSet<KeyPair> allResults = Sets.newTreeSet(client.describeKeyPairsInRegion(region));
+         assertNotNull(allResults);
+         if (allResults.size() >= 1) {
+            KeyPair pair = allResults.last();
+            SortedSet<KeyPair> result = Sets.newTreeSet(client.describeKeyPairsInRegion(region, pair.getKeyName()));
+            assertNotNull(result);
+            KeyPair compare = result.last();
+            assertEquals(compare, pair);
+         }
+      }
+   }
+
+   public static final String PREFIX = System.getProperty("user.name") + "-ec2";
+
+   @Test
+   void testCreateKeyPair() {
+      String keyName = PREFIX + "1";
+      try {
+         client.deleteKeyPairInRegion(null, keyName);
+      } catch (Exception e) {
+
+      }
+      client.deleteKeyPairInRegion(null, keyName);
+
+      KeyPair result = client.createKeyPairInRegion(null, keyName);
+      assertNotNull(result);
+      assertNotNull(result.getKeyMaterial());
+      assertNotNull(result.getSha1OfPrivateKey());
+      assertEquals(result.getKeyName(), keyName);
+
+      Set<KeyPair> twoResults = Sets.newLinkedHashSet(client.describeKeyPairsInRegion(null, keyName));
+      assertNotNull(twoResults);
+      assertEquals(twoResults.size(), 1);
+      KeyPair listPair = twoResults.iterator().next();
+      assertEquals(listPair.getKeyName(), result.getKeyName());
+      assertEquals(listPair.getSha1OfPrivateKey(), result.getSha1OfPrivateKey());
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiTest.java
new file mode 100644
index 0000000..1d42076
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiTest.java
@@ -0,0 +1,88 @@
+/*
+ * 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.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.ec2.xml.DescribeKeyPairsResponseHandler;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.http.functions.ReleasePayloadAndReturn;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Lists;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code KeyPairApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "KeyPairApiTest")
+public class KeyPairApiTest extends BaseEC2ApiTest<KeyPairApi> {
+
+   public void testDeleteKeyPair() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(KeyPairApi.class, "deleteKeyPairInRegion", String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "mykey"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DeleteKeyPair&KeyName=mykey",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeKeyPairs() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(KeyPairApi.class, "describeKeyPairsInRegion", String.class, String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeKeyPairs", "application/x-www-form-urlencoded",
+            false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeKeyPairsResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeKeyPairsArgs() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(KeyPairApi.class, "describeKeyPairsInRegion", String.class, String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeKeyPairs&KeyName.1=1&KeyName.2=2",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeKeyPairsResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+}


[17/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeAvailabilityZonesOptions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeAvailabilityZonesOptions.java b/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeAvailabilityZonesOptions.java
index c18e5e4..5b3f693 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeAvailabilityZonesOptions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeAvailabilityZonesOptions.java
@@ -30,8 +30,8 @@ import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
  * <code>
  * import static org.jclouds.ec2.options.DescribeAvailabilityZonesOptions.Builder.*
  * <p/>
- * EC2Client connection = // get connection
- * Future<Set<ImageMetadata>> images = connection.getAvailabilityZoneAndRegionServices().describeAvailabilityZones(zones("us-east-1a", "us-east-1b"));
+ * EC2Api connection = // get connection
+ * Future<Set<ImageMetadata>> images = connection.getAvailabilityZoneAndRegionApi().get().describeAvailabilityZones(zones("us-east-1a", "us-east-1b"));
  * <code>
  * 
  * @author Adrian Cole

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeImagesOptions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeImagesOptions.java b/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeImagesOptions.java
index ffcf3e6..d81ba88 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeImagesOptions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeImagesOptions.java
@@ -31,8 +31,8 @@ import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
  * <code>
  * import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.*
  * <p/>
- * EC2Client connection = // get connection
- * Future<Set<ImageMetadata>> images = connection.getAMIServices().describeImages(executableBy("123125").imageIds(1000, 1004));
+ * EC2Api connection = // get connection
+ * Future<Set<ImageMetadata>> images = connection.getAMIApi().get().describeImages(executableBy("123125").imageIds(1000, 1004));
  * <code>
  * 
  * @author Adrian Cole

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeRegionsOptions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeRegionsOptions.java b/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeRegionsOptions.java
index d589e9d..594194d 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeRegionsOptions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeRegionsOptions.java
@@ -30,7 +30,7 @@ import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
  * <code>
  * import static org.jclouds.ec2.options.DescribeRegionsOptions.Builder.*
  * <p/>
- * EC2Client connection = // get connection
+ * EC2Api connection = // get connection
  * Future<Set<ImageMetadata>> images = connection.getRegionsAndRegionsServices().describeRegions(regions("us-east-1a", "us-east-1b"));
  * <code>
  * 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeSnapshotsOptions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeSnapshotsOptions.java b/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeSnapshotsOptions.java
index d64e01e..8dfe3cb 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeSnapshotsOptions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/options/DescribeSnapshotsOptions.java
@@ -29,8 +29,8 @@ import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
  * <code>
  * import static org.jclouds.ec2.options.DescribeSnapshotsOptions.Builder.*
  * <p/>
- * EC2Client connection = // get connection
- * Set<Snapshot> snapshots = connection.getElasticBlockStoreServices().describeSnapshots(restorableBy("123125").snapshotIds(1000, 1004));
+ * EC2Api connection = // get connection
+ * Set<Snapshot> snapshots = connection.getElasticBlockStoreApi().get().describeSnapshots(restorableBy("123125").snapshotIds(1000, 1004));
  * <code>
  * 
  * @author Adrian Cole

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/options/DetachVolumeOptions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/options/DetachVolumeOptions.java b/apis/ec2/src/main/java/org/jclouds/ec2/options/DetachVolumeOptions.java
index 8d95792..0b9fc89 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/options/DetachVolumeOptions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/options/DetachVolumeOptions.java
@@ -29,8 +29,8 @@ import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
  * <code>
  * import static org.jclouds.ec2.options.DetachVolumeOptions.Builder.*
  * <p/>
- * EC2Client client = // get connection
- * client.getElasticBlockStoreServices().detachVolumeInRegion(null, id, fromDevice("123125").force());
+ * EC2Api client = // get connection
+ * client.getElasticBlockStoreApi().get().detachVolumeInRegion(null, id, fromDevice("123125").force());
  * <code>
  * 
  * @author Adrian Cole

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/options/RegisterImageBackedByEbsOptions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/options/RegisterImageBackedByEbsOptions.java b/apis/ec2/src/main/java/org/jclouds/ec2/options/RegisterImageBackedByEbsOptions.java
index 51e3024..1da21c0 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/options/RegisterImageBackedByEbsOptions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/options/RegisterImageBackedByEbsOptions.java
@@ -31,7 +31,7 @@ import org.jclouds.javax.annotation.Nullable;
  * <code>
  * import static org.jclouds.ec2.options.RegisterImageBackedByEbsOptions.Builder.*
  * <p/>
- * EC2Client connection = // get connection
+ * EC2Api connection = // get connection
  * String imageId = connection.getImageServices().registerImageBackedByEbs(...addEphemeralBlockDeviceFromSnapshot("/dev/sda2","virtual-1","snapshot-id"));
  * <code>
  * 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/options/RegisterImageOptions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/options/RegisterImageOptions.java b/apis/ec2/src/main/java/org/jclouds/ec2/options/RegisterImageOptions.java
index da4c0eb..76c2a01 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/options/RegisterImageOptions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/options/RegisterImageOptions.java
@@ -30,7 +30,7 @@ import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
  * <code>
  * import static org.jclouds.ec2.options.RegisterImageOptions.Builder.*
  * <p/>
- * EC2Client connection = // get connection
+ * EC2Api connection = // get connection
  * String imageId = connection.getImageServices().registerImageFromManifest(...withArchitecture(Architecture.I386).withDescription("description"));
  * <code>
  * 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/options/RunInstancesOptions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/options/RunInstancesOptions.java b/apis/ec2/src/main/java/org/jclouds/ec2/options/RunInstancesOptions.java
index 87d2686..25d4e7b 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/options/RunInstancesOptions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/options/RunInstancesOptions.java
@@ -35,7 +35,7 @@ import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
  * <code>
  * import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.*
  * <p/>
- * EC2Client connection = // get connection
+ * EC2Api connection = // get connection
  * Future<ReservationInfo> instances = connection.runInstances(executableBy("123125").imageIds(1000, 1004));
  * <code>
  * 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceHasIpAddress.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceHasIpAddress.java b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceHasIpAddress.java
index 4908b3c..57d576d 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceHasIpAddress.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceHasIpAddress.java
@@ -20,7 +20,7 @@ import javax.annotation.Resource;
 import javax.inject.Singleton;
 
 import org.jclouds.aws.AWSResponseException;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.domain.RunningInstance;
 import org.jclouds.logging.Logger;
 
@@ -37,13 +37,13 @@ import com.google.inject.Inject;
 @Singleton
 public class InstanceHasIpAddress implements Predicate<RunningInstance> {
 
-   private final EC2Client client;
+   private final EC2Api client;
 
    @Resource
    protected Logger logger = Logger.NULL;
 
    @Inject
-   public InstanceHasIpAddress(EC2Client client) {
+   public InstanceHasIpAddress(EC2Api client) {
       this.client = client;
    }
 
@@ -60,7 +60,7 @@ public class InstanceHasIpAddress implements Predicate<RunningInstance> {
    }
 
    private RunningInstance refresh(RunningInstance instance) {
-      return Iterables.getOnlyElement(Iterables.getOnlyElement(client.getInstanceServices()
+      return Iterables.getOnlyElement(Iterables.getOnlyElement(client.getInstanceApi().get()
                .describeInstancesInRegion(instance.getRegion(), instance.getId())));
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceStateRunning.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceStateRunning.java b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceStateRunning.java
index 7239a39..893e689 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceStateRunning.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceStateRunning.java
@@ -19,7 +19,7 @@ package org.jclouds.ec2.predicates;
 import javax.annotation.Resource;
 import javax.inject.Singleton;
 
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.domain.InstanceState;
 import org.jclouds.ec2.domain.RunningInstance;
 import org.jclouds.logging.Logger;
@@ -38,13 +38,13 @@ import com.google.inject.Inject;
 @Singleton
 public class InstanceStateRunning implements Predicate<RunningInstance> {
 
-   private final EC2Client client;
+   private final EC2Api client;
 
    @Resource
    protected Logger logger = Logger.NULL;
 
    @Inject
-   public InstanceStateRunning(EC2Client client) {
+   public InstanceStateRunning(EC2Api client) {
       this.client = client;
    }
 
@@ -63,7 +63,7 @@ public class InstanceStateRunning implements Predicate<RunningInstance> {
 
    private RunningInstance refresh(RunningInstance instance) {
       return Iterables.getOnlyElement(Iterables.getOnlyElement(client
-            .getInstanceServices().describeInstancesInRegion(
+            .getInstanceApi().get().describeInstancesInRegion(
                   instance.getRegion(), instance.getId())));
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceStateStopped.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceStateStopped.java b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceStateStopped.java
index 9619c78..644d858 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceStateStopped.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceStateStopped.java
@@ -21,7 +21,7 @@ import javax.inject.Singleton;
 
 import org.jclouds.ec2.domain.InstanceState;
 import org.jclouds.ec2.domain.RunningInstance;
-import org.jclouds.ec2.services.InstanceClient;
+import org.jclouds.ec2.features.InstanceApi;
 import org.jclouds.logging.Logger;
 
 import com.google.common.base.Predicate;
@@ -37,13 +37,13 @@ import com.google.inject.Inject;
 @Singleton
 public class InstanceStateStopped implements Predicate<RunningInstance> {
 
-   private final InstanceClient client;
+   private final InstanceApi client;
 
    @Resource
    protected Logger logger = Logger.NULL;
 
    @Inject
-   public InstanceStateStopped(InstanceClient client) {
+   public InstanceStateStopped(InstanceApi client) {
       this.client = client;
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceStateTerminated.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceStateTerminated.java b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceStateTerminated.java
index 7796e24..8c9a3fd 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceStateTerminated.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/InstanceStateTerminated.java
@@ -21,7 +21,7 @@ import java.util.NoSuchElementException;
 import javax.annotation.Resource;
 import javax.inject.Singleton;
 
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.domain.InstanceState;
 import org.jclouds.ec2.domain.RunningInstance;
 import org.jclouds.logging.Logger;
@@ -39,13 +39,13 @@ import com.google.inject.Inject;
 @Singleton
 public class InstanceStateTerminated implements Predicate<RunningInstance> {
 
-   private final EC2Client client;
+   private final EC2Api client;
 
    @Resource
    protected Logger logger = Logger.NULL;
 
    @Inject
-   public InstanceStateTerminated(EC2Client client) {
+   public InstanceStateTerminated(EC2Api client) {
       this.client = client;
    }
 
@@ -62,7 +62,7 @@ public class InstanceStateTerminated implements Predicate<RunningInstance> {
    }
 
    private RunningInstance refresh(RunningInstance instance) {
-      return Iterables.getOnlyElement(Iterables.getOnlyElement(client.getInstanceServices()
+      return Iterables.getOnlyElement(Iterables.getOnlyElement(client.getInstanceApi().get()
                .describeInstancesInRegion(instance.getRegion(), instance.getId())));
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/predicates/SnapshotCompleted.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/SnapshotCompleted.java b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/SnapshotCompleted.java
index 658b144..ef5281a 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/SnapshotCompleted.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/SnapshotCompleted.java
@@ -22,7 +22,7 @@ import javax.annotation.Resource;
 import javax.inject.Singleton;
 
 import org.jclouds.ec2.domain.Snapshot;
-import org.jclouds.ec2.services.ElasticBlockStoreClient;
+import org.jclouds.ec2.features.ElasticBlockStoreApi;
 import org.jclouds.logging.Logger;
 
 import com.google.common.base.Predicate;
@@ -38,12 +38,12 @@ import com.google.inject.Inject;
 @Singleton
 public class SnapshotCompleted implements Predicate<Snapshot> {
 
-   private final ElasticBlockStoreClient client;
+   private final ElasticBlockStoreApi client;
    @Resource
    protected Logger logger = Logger.NULL;
 
    @Inject
-   public SnapshotCompleted(ElasticBlockStoreClient client) {
+   public SnapshotCompleted(ElasticBlockStoreApi client) {
       this.client = client;
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/predicates/VolumeAttached.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/VolumeAttached.java b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/VolumeAttached.java
index 2ce17e6..f3ebfaf 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/VolumeAttached.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/VolumeAttached.java
@@ -21,7 +21,7 @@ import javax.inject.Singleton;
 
 import org.jclouds.ec2.domain.Attachment;
 import org.jclouds.ec2.domain.Volume;
-import org.jclouds.ec2.services.ElasticBlockStoreClient;
+import org.jclouds.ec2.features.ElasticBlockStoreApi;
 import org.jclouds.logging.Logger;
 
 import com.google.common.base.Predicate;
@@ -38,12 +38,12 @@ import com.google.inject.Inject;
 @Singleton
 public class VolumeAttached implements Predicate<Attachment> {
 
-   private final ElasticBlockStoreClient client;
+   private final ElasticBlockStoreApi client;
    @Resource
    protected Logger logger = Logger.NULL;
 
    @Inject
-   public VolumeAttached(ElasticBlockStoreClient client) {
+   public VolumeAttached(ElasticBlockStoreApi client) {
       this.client = client;
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/predicates/VolumeAvailable.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/VolumeAvailable.java b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/VolumeAvailable.java
index ae394dc..9688add 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/VolumeAvailable.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/VolumeAvailable.java
@@ -20,7 +20,7 @@ import javax.annotation.Resource;
 import javax.inject.Singleton;
 
 import org.jclouds.ec2.domain.Volume;
-import org.jclouds.ec2.services.ElasticBlockStoreClient;
+import org.jclouds.ec2.features.ElasticBlockStoreApi;
 import org.jclouds.logging.Logger;
 
 import com.google.common.base.Predicate;
@@ -36,12 +36,12 @@ import com.google.inject.Inject;
 @Singleton
 public class VolumeAvailable implements Predicate<Volume> {
 
-   private final ElasticBlockStoreClient client;
+   private final ElasticBlockStoreApi client;
    @Resource
    protected Logger logger = Logger.NULL;
 
    @Inject
-   public VolumeAvailable(ElasticBlockStoreClient client) {
+   public VolumeAvailable(ElasticBlockStoreApi client) {
       this.client = client;
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/predicates/VolumeDetached.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/VolumeDetached.java b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/VolumeDetached.java
index 6415eb0..accabe8 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/predicates/VolumeDetached.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/predicates/VolumeDetached.java
@@ -22,7 +22,7 @@ import javax.annotation.Resource;
 
 import org.jclouds.ec2.domain.Attachment;
 import org.jclouds.ec2.domain.Volume;
-import org.jclouds.ec2.services.ElasticBlockStoreClient;
+import org.jclouds.ec2.features.ElasticBlockStoreApi;
 import org.jclouds.logging.Logger;
 
 import com.google.common.base.Predicate;
@@ -38,12 +38,12 @@ import com.google.inject.Singleton;
 @Singleton
 public class VolumeDetached implements Predicate<Attachment> {
 
-   private final ElasticBlockStoreClient client;
+   private final ElasticBlockStoreApi client;
    @Resource
    protected Logger logger = Logger.NULL;
 
    @Inject
-   public VolumeDetached(ElasticBlockStoreClient client) {
+   public VolumeDetached(ElasticBlockStoreApi client) {
       this.client = client;
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/AMIAsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/AMIAsyncClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/AMIAsyncClient.java
deleted file mode 100644
index cf079f0..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/AMIAsyncClient.java
+++ /dev/null
@@ -1,192 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import java.util.Map;
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.binders.BindUserGroupsToIndexedFormParams;
-import org.jclouds.ec2.binders.BindUserIdsToIndexedFormParams;
-import org.jclouds.ec2.domain.Image;
-import org.jclouds.ec2.domain.Image.EbsBlockDevice;
-import org.jclouds.ec2.domain.Permission;
-import org.jclouds.ec2.options.CreateImageOptions;
-import org.jclouds.ec2.options.DescribeImagesOptions;
-import org.jclouds.ec2.options.RegisterImageBackedByEbsOptions;
-import org.jclouds.ec2.options.RegisterImageOptions;
-import org.jclouds.ec2.xml.BlockDeviceMappingHandler;
-import org.jclouds.ec2.xml.DescribeImagesResponseHandler;
-import org.jclouds.ec2.xml.ImageIdHandler;
-import org.jclouds.ec2.xml.PermissionHandler;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to AMI Services.
- * <p/>
- * 
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface AMIAsyncClient {
-
-   /**
-    * @see AMIClient#describeImagesInRegion
-    */
-   @Named("DescribeImages")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeImages")
-   @XMLResponseParser(DescribeImagesResponseHandler.class)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<? extends Image>> describeImagesInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            DescribeImagesOptions... options);
-
-   /**
-    * @see AMIClient#createImageInRegion
-    */
-   @Named("CreateImage")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "CreateImage")
-   @XMLResponseParser(ImageIdHandler.class)
-   ListenableFuture<String> createImageInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("Name") String name, @FormParam("InstanceId") String instanceId, CreateImageOptions... options);
-
-   /**
-    * @see AMIClient#deregisterImageInRegion
-    */
-   @Named("DeregisterImage")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DeregisterImage")
-   ListenableFuture<Void> deregisterImageInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("ImageId") String imageId);
-
-   /**
-    * @see AMIClient#registerImageFromManifestInRegion
-    */
-   @Named("RegisterImage")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "RegisterImage")
-   @XMLResponseParser(ImageIdHandler.class)
-   ListenableFuture<String> registerImageFromManifestInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("Name") String imageName, @FormParam("ImageLocation") String pathToManifest,
-            RegisterImageOptions... options);
-
-   /**
-    * @see AMIClient#registerUnixImageBackedByEbsInRegion
-    */
-   @Named("RegisterImage")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "RootDeviceName", "BlockDeviceMapping.0.DeviceName" }, values = { "RegisterImage",
-            "/dev/sda1", "/dev/sda1" })
-   @XMLResponseParser(ImageIdHandler.class)
-   ListenableFuture<String> registerUnixImageBackedByEbsInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("Name") String imageName,
-            @FormParam("BlockDeviceMapping.0.Ebs.SnapshotId") String ebsSnapshotId,
-            RegisterImageBackedByEbsOptions... options);
-
-   /**
-    * @see AMIClient#resetLaunchPermissionsOnImageInRegion
-    */
-   @Named("ResetImageAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "ResetImageAttribute", "launchPermission" })
-   ListenableFuture<Void> resetLaunchPermissionsOnImageInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("ImageId") String imageId);
-
-   /**
-    * @see AMIClient#addLaunchPermissionsToImageInRegion
-    */
-   @Named("ModifyImageAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "OperationType", "Attribute" }, values = { "ModifyImageAttribute", "add",
-            "launchPermission" })
-   ListenableFuture<Void> addLaunchPermissionsToImageInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindUserIdsToIndexedFormParams.class) Iterable<String> userIds,
-            @BinderParam(BindUserGroupsToIndexedFormParams.class) Iterable<String> userGroups,
-            @FormParam("ImageId") String imageId);
-
-   /**
-    * @see AMIClient#removeLaunchPermissionsToImageInRegion
-    */
-   @Named("ModifyImageAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "OperationType", "Attribute" }, values = { "ModifyImageAttribute", "remove",
-            "launchPermission" })
-   ListenableFuture<Void> removeLaunchPermissionsFromImageInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindUserIdsToIndexedFormParams.class) Iterable<String> userIds,
-            @BinderParam(BindUserGroupsToIndexedFormParams.class) Iterable<String> userGroups,
-            @FormParam("ImageId") String imageId);
-
-   /**
-    * @see AMIClient#getLaunchPermissionForImageInRegion
-    */
-   @Named("DescribeImageAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeImageAttribute", "launchPermission" })
-   @XMLResponseParser(PermissionHandler.class)
-   ListenableFuture<Permission> getLaunchPermissionForImageInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("ImageId") String imageId);
-
-   /**
-    * @see AMIClient#getBlockDeviceMappingsForImageInRegion
-    */
-   @Named("DescribeImageAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeImageAttribute", "blockDeviceMapping" })
-   @XMLResponseParser(BlockDeviceMappingHandler.class)
-   ListenableFuture<Map<String, EbsBlockDevice>> getBlockDeviceMappingsForImageInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("ImageId") String imageId);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/AMIClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/AMIClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/AMIClient.java
deleted file mode 100644
index ebaec35..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/AMIClient.java
+++ /dev/null
@@ -1,253 +0,0 @@
-/*
- * 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.services;
-
-import java.util.Map;
-import java.util.Set;
-import org.jclouds.ec2.domain.Image;
-import org.jclouds.ec2.domain.Image.EbsBlockDevice;
-import org.jclouds.ec2.domain.Permission;
-import org.jclouds.ec2.options.CreateImageOptions;
-import org.jclouds.ec2.options.DescribeImagesOptions;
-import org.jclouds.ec2.options.RegisterImageBackedByEbsOptions;
-import org.jclouds.ec2.options.RegisterImageOptions;
-import org.jclouds.javax.annotation.Nullable;
-
-/**
- * Provides access to EC2 via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-public interface AMIClient {
-
-   /**
-    * Returns information about AMIs, AKIs, and ARIs. This includes image type, product codes,
-    * architecture, and kernel and RAM disk IDs. Images available to you include public images,
-    * private images that you own, and private images owned by other users for which you have
-    * explicit launch permissions.
-    * 
-    * @param region
-    *           AMIs are tied to the Region where its files are located within Amazon S3.
-    * @see InstanceClient#describeInstances
-    * @see #describeImageAttribute
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeImages.html"
-    *      />
-    * @see DescribeImagesOptions
-    */
-   Set<? extends Image> describeImagesInRegion(@Nullable String region, DescribeImagesOptions... options);
-
-   /**
-    * Returns a map of device name to block device for the image.
-    * 
-    * @param region
-    *           AMIs are tied to the Region where its files are located within Amazon S3.
-    * @param imageId
-    *           The ID of the AMI for which an attribute will be described
-    * @see #describeImages
-    * @see #modifyImageAttribute
-    * @see #resetImageAttribute
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeImageAttribute.html"
-    *      />
-    * @see DescribeImagesOptions
-    */
-   Map<String, EbsBlockDevice> getBlockDeviceMappingsForImageInRegion(@Nullable String region, String imageId);
-
-   /**
-    * Creates an AMI that uses an Amazon EBS root device from a "running" or "stopped" instance.
-    * 
-    * @param region
-    *           AMIs are tied to the Region where its files are located within Amazon S3.
-    * @param name
-    *           The name of the AMI that was provided during image creation. 3-128 alphanumeric
-    *           characters, parenthesis (()), commas (,), slashes (/), dashes (-), or underscores(_)
-    * @param instanceId
-    *           The ID of the instance.
-    * @return imageId
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeImages.html"
-    *      />
-    * @see CreateImageOptions
-    * @see InstanceClient#runInstances
-    * @see InstanceClient#describeInstances
-    * @see InstanceClient#terminateInstances
-    * @see <a href=
-    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateImage.html"
-    *      />
-    */
-   String createImageInRegion(@Nullable String region, String name, String instanceId, CreateImageOptions... options);
-
-   /**
-    * 
-    * Deregisters the specified AMI. Once deregistered, the AMI cannot be used to launch new
-    * instances.
-    * 
-    * @param region
-    *           AMIs are tied to the Region where its files are located within Amazon S3.
-    * @param imageId
-    *           Unique ID of the AMI which was assigned during registration. To register an AMI, use
-    *           RegisterImage. To view the AMI IDs of AMIs that belong to your identity. use
-    *           DescribeImages.
-    * 
-    * @see #describeImages
-    * @see #registerImage
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeregisterImage.html"
-    *      />
-    */
-   void deregisterImageInRegion(@Nullable String region, String imageId);
-
-   /**
-    * Registers an AMI with Amazon EC2. Images must be registered before they can be launched. To
-    * launch instances, use the {@link InstanceClient#runInstances} operation.
-    * <p/>
-    * Each AMI is associated with an unique ID which is provided by the Amazon EC2 service through
-    * this operation. If needed, you can deregister an AMI at any time.
-    * <p/>
-    * <h3>Note</h3> Any modifications to an AMI backed by Amazon S3 invalidates this registration.
-    * If you make changes to an image, deregister the previous image and register the new image.
-    * 
-    * @param region
-    *           AMIs are tied to the Region where its files are located within Amazon S3.
-    * @param name
-    *           The name of the AMI that was provided during image creation. 3-128 alphanumeric
-    *           characters, parenthesis (()), commas (,), slashes (/), dashes (-), or underscores(_)
-    * @param pathToManifest
-    *           Full path to your AMI manifest in Amazon S3 storage.
-    * @param options
-    *           Options to specify metadata such as architecture or secondary volumes to be
-    *           associated with this image.
-    * @return imageId
-    * 
-    * @see #describeImages
-    * @see #deregisterImage
-    * @see <a href=
-    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RegisterImage.html"
-    *      />
-    */
-   String registerImageFromManifestInRegion(@Nullable String region, String name, String pathToManifest,
-            RegisterImageOptions... options);
-
-   /**
-    * Registers an AMI with Amazon EC2. Images must be registered before they can be launched. To
-    * launch instances, use the {@link InstanceClient#runInstances} operation. The root device name
-    * is /dev/sda1
-    * <p/>
-    * Each AMI is associated with an unique ID which is provided by the Amazon EC2 service through
-    * this operation. If needed, you can deregister an AMI at any time.
-    * <p/>
-    * <h3>Note</h3> AMIs backed by Amazon EBS are automatically registered when you create the
-    * image. However, you can use this to register a snapshot of an instance backed by Amazon EBS.
-    * <p/>
-    * Amazon EBS snapshots are not guaranteed to be bootable.
-    * 
-    * @param region
-    *           AMIs are tied to the Region where its files are located within Amazon S3.
-    * @param name
-    *           The name of the AMI that was provided during image creation. 3-128 alphanumeric
-    *           characters, parenthesis (()), commas (,), slashes (/), dashes (-), or underscores(_)
-    * 
-    * @param ebsSnapshotId
-    *           The id of the root snapshot (e.g., snap-6eba6e06).
-    * @param options
-    *           Options to specify metadata such as architecture or secondary volumes to be
-    *           associated with this image.
-    * @return imageId
-    * 
-    * @see #describeImages
-    * @see #deregisterImage
-    * @see <a href=
-    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RegisterImage.html"
-    *      />
-    */
-   String registerUnixImageBackedByEbsInRegion(@Nullable String region, String name, String ebsSnapshotId,
-            RegisterImageBackedByEbsOptions... options);
-
-   /**
-    * Returns the {@link Permission}s of an image.
-    * 
-    * @param region
-    *           AMIs are tied to the Region where its files are located within Amazon S3.
-    * @param imageId
-    *           The ID of the AMI for which an attribute will be described
-    * @see #describeImages
-    * @see #modifyImageAttribute
-    * @see #resetImageAttribute
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeImageAttribute.html"
-    *      />
-    * @see DescribeImagesOptions
-    */
-   Permission getLaunchPermissionForImageInRegion(@Nullable String region, String imageId);
-
-   /**
-    * Adds {@code launchPermission}s to an AMI.
-    * 
-    * @param region
-    *           AMIs are tied to the Region where its files are located within Amazon S3.
-    * @param userIds
-    *           AWS Access Key ID.
-    * @param userGroups
-    *           Name of the groups. Currently supports \"all.\""
-    * @param imageId
-    *           The AMI ID.
-    * 
-    * @see #removeLaunchPermissionsFromImage
-    * @see #describeImageAttribute
-    * @see #resetImageAttribute
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyImageAttribute.html"
-    *      />
-    */
-   void addLaunchPermissionsToImageInRegion(@Nullable String region, Iterable<String> userIds,
-            Iterable<String> userGroups, String imageId);
-
-   /**
-    * Resets the {@code launchPermission}s on an AMI.
-    * 
-    * @param region
-    *           AMIs are tied to the Region where its files are located within Amazon S3.
-    * @param imageId
-    *           ID of the AMI on which the attribute will be reset.
-    * 
-    * @see #addLaunchPermissionsToImage
-    * @see #describeImageAttribute
-    * @see #removeProductCodesFromImage
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ResetImageAttribute.html"
-    *      />
-    */
-   void resetLaunchPermissionsOnImageInRegion(@Nullable String region, String imageId);
-
-   /**
-    * Removes {@code launchPermission}s from an AMI.
-    * 
-    * @param region
-    *           AMIs are tied to the Region where its files are located within Amazon S3.
-    * @param userIds
-    *           AWS Access Key ID.
-    * @param userGroups
-    *           Name of the groups. Currently supports \"all.\""
-    * @param imageId
-    *           The AMI ID.
-    * 
-    * @see #addLaunchPermissionsToImage
-    * @see #describeImageAttribute
-    * @see #resetImageAttribute
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyImageAttribute.html"
-    *      />
-    */
-   void removeLaunchPermissionsFromImageInRegion(@Nullable String region, Iterable<String> userIds,
-            Iterable<String> userGroups, String imageId);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionAsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionAsyncClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionAsyncClient.java
deleted file mode 100644
index 3c5b379..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionAsyncClient.java
+++ /dev/null
@@ -1,80 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import java.net.URI;
-import java.util.Map;
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.domain.AvailabilityZoneInfo;
-import org.jclouds.ec2.options.DescribeAvailabilityZonesOptions;
-import org.jclouds.ec2.options.DescribeRegionsOptions;
-import org.jclouds.ec2.xml.DescribeAvailabilityZonesResponseHandler;
-import org.jclouds.ec2.xml.DescribeRegionsResponseHandler;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to EC2 Availability Zones and Regions via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface AvailabilityZoneAndRegionAsyncClient {
-
-   /**
-    * @see AvailabilityZoneAndRegionClient#describeAvailabilityZonesInRegion
-    */
-   @Named("DescribeAvailabilityZones")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeAvailabilityZones")
-   @XMLResponseParser(DescribeAvailabilityZonesResponseHandler.class)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<? extends Set<AvailabilityZoneInfo>> describeAvailabilityZonesInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            DescribeAvailabilityZonesOptions... options);
-
-   /**
-    * @see AvailabilityZoneAndRegionClient#describeRegions
-    */
-   @Named("DescribeRegions")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeRegions")
-   @XMLResponseParser(DescribeRegionsResponseHandler.class)
-   ListenableFuture<? extends Map<String, URI>> describeRegions(DescribeRegionsOptions... options);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionClient.java
deleted file mode 100644
index 0eef970..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionClient.java
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * 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.services;
-
-import java.net.URI;
-import java.util.Map;
-import java.util.Set;
-import org.jclouds.ec2.domain.AvailabilityZoneInfo;
-import org.jclouds.ec2.options.DescribeAvailabilityZonesOptions;
-import org.jclouds.ec2.options.DescribeRegionsOptions;
-import org.jclouds.javax.annotation.Nullable;
-
-/**
- * Provides EC2 Availability Zones and Regions services for EC2.
- * <p/>
- * 
- * @author Adrian Cole
- */
-public interface AvailabilityZoneAndRegionClient {
-
-   /**
-    * Displays Availability Zones that are currently available to the identity and their states.
-    * 
-    * @see InstanceClient#runInstances
-    * @see #describeRegions
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeAvailabilityZones.html"
-    *      />
-    */
-   Set<AvailabilityZoneInfo> describeAvailabilityZonesInRegion(@Nullable String region,
-            DescribeAvailabilityZonesOptions... options);
-
-   /**
-    * Describes Regions that are currently available to the identity.
-    * 
-    * @see InstanceClient#runInstances
-    * @see #describeAvailabilityZones
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeRegions.html"
-    *      />
-    */
-   Map<String, URI> describeRegions(DescribeRegionsOptions... options);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticBlockStoreAsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticBlockStoreAsyncClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticBlockStoreAsyncClient.java
deleted file mode 100644
index 3b0ccd2..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticBlockStoreAsyncClient.java
+++ /dev/null
@@ -1,239 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.EC2Fallbacks.VoidOnVolumeAvailable;
-import org.jclouds.ec2.binders.BindUserGroupsToIndexedFormParams;
-import org.jclouds.ec2.binders.BindUserIdsToIndexedFormParams;
-import org.jclouds.ec2.binders.BindVolumeIdsToIndexedFormParams;
-import org.jclouds.ec2.domain.Attachment;
-import org.jclouds.ec2.domain.Permission;
-import org.jclouds.ec2.domain.Snapshot;
-import org.jclouds.ec2.domain.Volume;
-import org.jclouds.ec2.options.CreateSnapshotOptions;
-import org.jclouds.ec2.options.DescribeSnapshotsOptions;
-import org.jclouds.ec2.options.DetachVolumeOptions;
-import org.jclouds.ec2.xml.AttachmentHandler;
-import org.jclouds.ec2.xml.CreateVolumeResponseHandler;
-import org.jclouds.ec2.xml.DescribeSnapshotsResponseHandler;
-import org.jclouds.ec2.xml.DescribeVolumesResponseHandler;
-import org.jclouds.ec2.xml.PermissionHandler;
-import org.jclouds.ec2.xml.SnapshotHandler;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.location.functions.ZoneToEndpoint;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to EC2 Elastic Block Store services via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface ElasticBlockStoreAsyncClient {
-
-   /**
-    * @see ElasticBlockStoreClient#createVolumeFromSnapshotInAvailabilityZone
-    */
-   @Named("CreateVolume")   
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "CreateVolume")
-   @XMLResponseParser(CreateVolumeResponseHandler.class)
-   ListenableFuture<Volume> createVolumeFromSnapshotInAvailabilityZone(
-            @EndpointParam(parser = ZoneToEndpoint.class) @FormParam("AvailabilityZone") String availabilityZone,
-            @FormParam("SnapshotId") String snapshotId);
-
-   /**
-    * @see ElasticBlockStoreClient#createVolumeFromSnapshotInAvailabilityZone
-    */
-   @Named("CreateVolume")   
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "CreateVolume")
-   @XMLResponseParser(CreateVolumeResponseHandler.class)
-   ListenableFuture<Volume> createVolumeFromSnapshotInAvailabilityZone(
-            @EndpointParam(parser = ZoneToEndpoint.class) @FormParam("AvailabilityZone") String availabilityZone,
-            @FormParam("Size") int size, @FormParam("SnapshotId") String snapshotId);
-
-   /**
-    * @see ElasticBlockStoreClient#createVolumeInAvailabilityZone
-    */
-   @Named("CreateVolume")   
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "CreateVolume")
-   @XMLResponseParser(CreateVolumeResponseHandler.class)
-   ListenableFuture<Volume> createVolumeInAvailabilityZone(
-            @EndpointParam(parser = ZoneToEndpoint.class) @FormParam("AvailabilityZone") String availabilityZone,
-            @FormParam("Size") int size);
-
-   /**
-    * @see ElasticBlockStoreClient#describeVolumesInRegion
-    */
-   @POST
-   @Named("DescribeVolumes")   
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeVolumes")
-   @XMLResponseParser(DescribeVolumesResponseHandler.class)
-   ListenableFuture<? extends Set<Volume>> describeVolumesInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindVolumeIdsToIndexedFormParams.class) String... volumeIds);
-
-   /**
-    * @see ElasticBlockStoreClient#deleteVolumeInRegion
-    */
-   @Named("DeleteVolume")   
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DeleteVolume")
-   ListenableFuture<Void> deleteVolumeInRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("VolumeId") String volumeId);
-
-   /**
-    * @see ElasticBlockStoreClient#detachVolumeInRegion
-    */
-   @Named("DetachVolume")   
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DetachVolume")
-   @Fallback(VoidOnVolumeAvailable.class)
-   ListenableFuture<Void> detachVolumeInRegion(@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("VolumeId") String volumeId, @FormParam("Force") boolean force, DetachVolumeOptions... options);
-
-   /**
-    * @see ElasticBlockStoreClient#attachVolumeInRegion
-    */
-   @Named("AttachVolume")   
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "AttachVolume")
-   @XMLResponseParser(AttachmentHandler.class)
-   ListenableFuture<Attachment> attachVolumeInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("VolumeId") String volumeId, @FormParam("InstanceId") String instanceId,
-            @FormParam("Device") String device);
-
-   /**
-    * @see ElasticBlockStoreClient#createSnapshotInRegion
-    */
-   @Named("CreateSnapshot")   
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "CreateSnapshot")
-   @XMLResponseParser(SnapshotHandler.class)
-   ListenableFuture<Snapshot> createSnapshotInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("VolumeId") String volumeId, CreateSnapshotOptions... options);
-
-   /**
-    * @see ElasticBlockStoreClient#describeSnapshotsInRegion
-    */
-   @Named("DescribeSnapshots")   
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeSnapshots")
-   @XMLResponseParser(DescribeSnapshotsResponseHandler.class)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<? extends Set<Snapshot>> describeSnapshotsInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            DescribeSnapshotsOptions... options);
-
-   /**
-    * @see ElasticBlockStoreClient#deleteSnapshotInRegion
-    */
-   @Named("DeleteSnapshot")   
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DeleteSnapshot")
-   ListenableFuture<Void> deleteSnapshotInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("SnapshotId") String snapshotId);
-
-   /**
-    * @see ElasticBlockStoreClient#addCreateVolumePermissionsToSnapshotInRegion
-    */
-   @Named("ModifySnapshotAttribute")   
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "OperationType", "Attribute" }, values = { "ModifySnapshotAttribute", "add",
-            "createVolumePermission" })
-   ListenableFuture<Void> addCreateVolumePermissionsToSnapshotInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindUserIdsToIndexedFormParams.class) Iterable<String> userIds,
-            @BinderParam(BindUserGroupsToIndexedFormParams.class) Iterable<String> userGroups,
-            @FormParam("SnapshotId") String snapshotId);
-
-   /**
-    * @see ElasticBlockStoreClient#removeCreateVolumePermissionsFromSnapshotInRegion
-    */
-   @Named("ModifySnapshotAttribute")   
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "OperationType", "Attribute" }, values = { "ModifySnapshotAttribute", "remove",
-            "createVolumePermission" })
-   ListenableFuture<Void> removeCreateVolumePermissionsFromSnapshotInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindUserIdsToIndexedFormParams.class) Iterable<String> userIds,
-            @BinderParam(BindUserGroupsToIndexedFormParams.class) Iterable<String> userGroups,
-            @FormParam("SnapshotId") String snapshotId);
-
-   /**
-    * @see ElasticBlockStoreClient#getCreateVolumePermissionForSnapshotInRegion
-    */
-   @Named("DescribeSnapshotAttribute")   
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeSnapshotAttribute", "createVolumePermission" })
-   @XMLResponseParser(PermissionHandler.class)
-   ListenableFuture<Permission> getCreateVolumePermissionForSnapshotInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("SnapshotId") String snapshotId);
-
-   /**
-    * @see ElasticBlockStoreClient#resetCreateVolumePermissionsOnSnapshotInRegion
-    */
-   @Named("ResetSnapshotAttribute")   
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "ResetSnapshotAttribute", "createVolumePermission" })
-   ListenableFuture<Void> resetCreateVolumePermissionsOnSnapshotInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("SnapshotId") String snapshotId);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticBlockStoreClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticBlockStoreClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticBlockStoreClient.java
deleted file mode 100644
index b12df61..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticBlockStoreClient.java
+++ /dev/null
@@ -1,419 +0,0 @@
-/*
- * 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.services;
-
-import java.util.Set;
-import org.jclouds.ec2.domain.Attachment;
-import org.jclouds.ec2.domain.Permission;
-import org.jclouds.ec2.domain.Snapshot;
-import org.jclouds.ec2.domain.Volume;
-import org.jclouds.ec2.options.CreateSnapshotOptions;
-import org.jclouds.ec2.options.DescribeSnapshotsOptions;
-import org.jclouds.ec2.options.DetachVolumeOptions;
-import org.jclouds.javax.annotation.Nullable;
-
-/**
- * Provides access to EC2 Elastic Block Store services.
- * <p/>
- * 
- * @author Adrian Cole
- */
-public interface ElasticBlockStoreClient {
-
-   /**
-    * Creates a new Amazon EBS volume to which any Amazon EC2 instance can attach within the same
-    * Availability Zone. For more information about Amazon EBS, go to the Amazon Elastic Compute
-    * Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
-    * 
-    * @param availabilityZone
-    *           An Amazon EBS volume must be located within the same Availability Zone as the
-    *           instance to which it attaches.
-    * @param snapshotId
-    *           The snapshot from which to create the new volume.
-    * 
-    * @see #describeVolumesInRegion
-    * @see #deleteVolumeInRegion
-    * @see #attachVolumeInRegion
-    * @see #detachVolumeInRegion
-    * @see AvailabilityZoneAndRegionClient#describeAvailabilityZonesInRegion
-    * 
-    * 
-    * @see <a href=
-    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateVolume.html"
-    *      />
-    */
-   Volume createVolumeFromSnapshotInAvailabilityZone(String availabilityZone,
-            String snapshotId);
-
-   /**
-    * Creates a new Amazon EBS volume to which any Amazon EC2 instance can attach within the same
-    * Availability Zone. This is overloaded {@link #createVolumeFromSnapshotInAvailabilityZone},
-    * which creates a volume with a specific size.
-    * For more information about Amazon EBS, go to the Amazon Elastic Compute
-    * Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
-    *
-    * @param availabilityZone
-    *           An Amazon EBS volume must be located within the same Availability Zone as the
-    *           instance to which it attaches.
-    * @param size
-    *           Size of volume to be created
-    * @param snapshotId
-    *           The snapshot from which to create the new volume.
-    *
-    * @see #createVolumeFromSnapshotInAvailabilityZone
-    * @see #describeVolumesInRegion
-    * @see #deleteVolumeInRegion
-    * @see #attachVolumeInRegion
-    * @see #detachVolumeInRegion
-    * @see AvailabilityZoneAndRegionClient#describeAvailabilityZonesInRegion
-    *
-    *
-    * @see <a href=
-    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateVolume.html"
-    *      />
-    */
-   Volume createVolumeFromSnapshotInAvailabilityZone(String availabilityZone,
-            int size, String snapshotId);
-
-   /**
-    * Creates a new Amazon EBS volume to which any Amazon EC2 instance can attach within the same
-    * Availability Zone. For more information about Amazon EBS, go to the Amazon Elastic Compute
-    * Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
-    * 
-    * @param availabilityZone
-    *           An Amazon EBS volume must be located within the same Availability Zone as the
-    *           instance to which it attaches.
-    * @param size
-    *           The size of the volume, in GiBs (1-1024). Required if you are not creating a volume
-    *           from a snapshot.
-    * 
-    * 
-    * @see #describeVolumesInRegion
-    * @see #deleteVolumeInRegion
-    * @see #attachVolumeInRegion
-    * @see #detachVolumeInRegion
-    * @see AvailabilityZoneAndRegionClient#describeAvailabilityZonesInRegion
-    * @see <a href=
-    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateVolume.html"
-    *      />
-    */
-   Volume createVolumeInAvailabilityZone(String availabilityZone, int size);
-
-   /**
-    * Describes the specified Amazon EBS volumes that you own. If you do not specify one or more
-    * volume IDs, Amazon EBS describes all volumes that you own. For more information about Amazon
-    * EBS, go to the Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud
-    * User Guide.
-    * 
-    * @param region
-    *           region where the volume is defined
-    * @param volumeIds
-    *           The ID of the volume to list. Defaults to describe all volumes that you own.
-    * 
-    * @see #createSnapshotInRegion
-    * @see #describeSnapshotInRegion
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeVolumes.html"
-    *      />
-    */
-   Set<Volume> describeVolumesInRegion(@Nullable String region, String... volumeIds);
-
-   /**
-    * Deletes an Amazon EBS volume that you own. For more information about Amazon EBS, go to the
-    * Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
-    * 
-    * @param region
-    *           region where the volume is defined
-    * @param volumeId
-    *           The ID of the volume to delete. The volume remains in the deleting state for several
-    *           minutes after entering this command.
-    * 
-    * @see #describeVolumesInRegion
-    * @see #createVolumeInRegion
-    * @see #attachVolumeInRegion
-    * @see #detachVolumeInRegion
-    * 
-    * @see <a href=
-    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteVolume.html"
-    *      />
-    */
-   void deleteVolumeInRegion(@Nullable String region, String volumeId);
-
-   /**
-    * Attaches an Amazon EBS volume to a running instance and exposes it as the specified device.
-    * <p/>
-    * 
-    * <h3>Note</h3>
-    * 
-    * Windows instances currently support devices xvda through xvdp. Devices xvda and xvdb are
-    * reserved by the operating system, xvdc is assigned to drive C:\, and, depending on the
-    * instance type, devices xvdd through xvde might be reserved by the instance stores. Any device
-    * that is not reserved can be attached to an Amazon EBS volume. For a list of devices that are
-    * reserved by the instance stores, go to the Amazon Elastic Compute Cloud Developer Guide or
-    * Amazon Elastic Compute Cloud User Guide.
-    * 
-    * @param region
-    *           region where the volume is defined
-    * @param volumeId
-    *           The ID of the volume to delete. The volume remains in the deleting state for several
-    *           minutes after entering this command.
-    * @param force
-    *           Forces detachment if the previous detachment attempt did not occur cleanly (logging
-    *           into an instance, unmounting the volume, and detaching normally). This option can
-    *           lead to data loss or a corrupted file system. Use this option only as a last resort
-    *           to detach a volume from a failed instance. The instance will not have an opportunity
-    *           to flush file system caches nor file system meta data. If you use this option, you
-    *           must perform file system check and repair procedures.
-    * 
-    * @param options
-    *           options like force()
-    * 
-    * @see #describeVolumesInRegion
-    * @see #createVolumeInRegion
-    * @see #attachVolumeInRegion
-    * @see #deleteVolumeInRegion
-    * 
-    * @see <a href=
-    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DetachVolume.html"
-    *      />
-    */
-   void detachVolumeInRegion(@Nullable String region, String volumeId, boolean force,
-            DetachVolumeOptions... options);
-
-   /**
-    * Attaches an Amazon EBS volume to a running instance and exposes it as the specified device.
-    * 
-    * <h3>Note</h3> Windows instances currently support devices xvda through xvdp. Devices xvda and
-    * xvdb are reserved by the operating system, xvdc is assigned to drive C:\, and, depending on
-    * the instance type, devices xvdd through xvde might be reserved by the instance stores. Any
-    * device that is not reserved can be attached to an Amazon EBS volume. For a list of devices
-    * that are reserved by the instance stores, go to the Amazon Elastic Compute Cloud Developer
-    * Guide or Amazon Elastic Compute Cloud User Guide.
-    * 
-    * @param region
-    *           region where the volume is defined
-    * @param volumeId
-    *           The ID of the Amazon EBS volume. The volume and instance must be within the same
-    *           Availability Zone and the instance must be running.
-    * @param instanceId
-    *           The ID of the instance to which the volume attaches. The volume and instance must be
-    *           within the same Availability Zone and the instance must be running.
-    * @param device
-    *           Specifies how the device is exposed to the instance (e.g., /dev/sdh).
-    * 
-    * @see #describeVolumesInRegion
-    * @see #createVolumeInRegion
-    * @see #detachVolumeInRegion
-    * @see #deleteVolumeInRegion
-    * 
-    * @see <a href=
-    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-AttachVolume.html"
-    *      />
-    */
-   Attachment attachVolumeInRegion(@Nullable String region, String volumeId, String instanceId, String device);
-
-   /**
-    * Creates a snapshot of an Amazon EBS volume and stores it in Amazon S3. You can use snapshots
-    * for backups, to make identical copies of instance devices, and to save data before shutting
-    * down an instance. For more information about Amazon EBS, go to the Amazon Elastic Compute
-    * Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
-    * <p/>
-    * When taking a snapshot of a file system, we recommend unmounting it first. This ensures the
-    * file system metadata is in a consistent state, that the 'mounted indicator' is cleared, and
-    * that all applications using that file system are stopped and in a consistent state. Some file
-    * systems, such as xfs, can freeze and unfreeze activity so a snapshot can be made without
-    * unmounting.
-    * <p/>
-    * For Linux/UNIX, enter the following command from the command line.
-    * 
-    * <pre>
-    * umount - d / dev / sdh
-    * </pre>
-    * <p/>
-    * For Windows, open Disk Management, right-click the volume to unmount, and select Change Drive
-    * Letter and Path. Then, select the mount point to remove and click Remove.
-    * 
-    * @param region
-    *           Snapshots are tied to Regions and can only be used for volumes within the same
-    *           Region.
-    * @param volumeId
-    *           The ID of the Amazon EBS volume of which to take a snapshot.
-    * @param options
-    *           options like passing a description.
-    * @return the Snapshot in progress
-    * 
-    * @see #describeSnapshotsInRegion
-    * @see #deleteSnapshotInRegion
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateSnapshot.html"
-    *      />
-    */
-   Snapshot createSnapshotInRegion(@Nullable String region, String volumeId, CreateSnapshotOptions... options);
-
-   /**
-    * Returns information about Amazon EBS snapshots available to the user. Information returned
-    * includes volume ID, status, start time, progress, owner ID, volume size, and description.
-    * Snapshots available to the user include public snapshots available for any user to
-    * createVolume, private snapshots owned by the user making the request, and private snapshots
-    * owned by other users for which the user granted explicit create volume permissions.
-    * <p/>
-    * The create volume permissions fall into 3 categories:
-    * <p/>
-    * <table>
-    * <tr>
-    * <td>Permission</td>
-    * <td>Description</td>
-    * </tr>
-    * <tr>
-    * <td>public</td>
-    * <td>The owner of the snapshot granted create volume permissions for the snapshot to the all
-    * group. All users have create volume permissions for these snapshots.</td>
-    * </tr>
-    * <tr>
-    * <td>explicit</td>
-    * <td>The owner of the snapshot granted create volume permissions to a specific user.</td>
-    * </tr>
-    * <tr>
-    * <td>implicit</td>
-    * <td>A user has implicit create volume permissions for all snapshots he or she owns.</td>
-    * </tr>
-    * </table>
-    * <p/>
-    * 
-    * The list of snapshots returned can be modified by specifying snapshot IDs, snapshot owners, or
-    * users with create volume permissions. If no options are specified, Amazon EC2 returns all
-    * snapshots for which the user has create volume permissions.
-    * <p/>
-    * If you specify one or more snapshot IDs, only snapshots that have the specified IDs are
-    * returned. If you specify an invalid snapshot ID, a fault is returned. If you specify a
-    * snapshot ID for which you do not have access, it will not be included in the returned results.
-    * <p/>
-    * If you specify one or more snapshot owners, only snapshots from the specified owners and for
-    * which you have access are returned. The results can include the AWS Account IDs of the
-    * specified owners, amazon for snapshots owned by Amazon or self for snapshots that you own.
-    * <p/>
-    * If you specify a list of restorable users, only users that have create snapshot permissions
-    * for the snapshots are returned. You can specify AWS Account IDs (if you own the snapshot(s)),
-    * self for snapshots for which you own or have explicit permissions, or all for public
-    * snapshots.
-    * 
-    * @param region
-    *           Snapshots are tied to Regions and can only be used for volumes within the same
-    *           Region.
-    * @param options
-    *           specify the snapshot ids or other parameters to clarify the list.
-    * @return matching snapshots.
-    * 
-    * @see #createSnapshotsInRegion
-    * @see #deleteSnapshotInRegion
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSnapshots.html"
-    *      />
-    */
-   Set<Snapshot> describeSnapshotsInRegion(@Nullable String region, DescribeSnapshotsOptions... options);
-
-   /**
-    * Deletes a snapshot of an Amazon EBS volume that you own. For more information, go to the
-    * Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
-    * 
-    * @param region
-    *           Snapshots are tied to Regions and can only be used for volumes within the same
-    *           Region.
-    * @param snapshotId
-    *           The ID of the Amazon EBS snapshot to delete.
-    * 
-    * @see #createSnapshotInRegion
-    * @see #deleteSnapshotInRegion
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteSnapshot.html"
-    *      />
-    */
-   void deleteSnapshotInRegion(@Nullable String region, String snapshotId);
-
-   /**
-    * Returns the {@link Permission}s of an snapshot.
-    * 
-    * @param region
-    *           AMIs are tied to the Region where its files are located within Amazon S3.
-    * @param snapshotId
-    *           The ID of the AMI for which an attribute will be described
-    * @see #describeSnapshots
-    * @see #modifySnapshotAttribute
-    * @see #resetSnapshotAttribute
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSnapshotAttribute.html"
-    *      />
-    * @see DescribeSnapshotsOptions
-    */
-   Permission getCreateVolumePermissionForSnapshotInRegion(@Nullable String region, String snapshotId);
-
-   /**
-    * Adds {@code createVolumePermission}s to an EBS snapshot.
-    * 
-    * @param region
-    *           Snapshots are tied to Regions and can only be used for volumes within the same
-    *           Region.
-    * @param userIds
-    *           AWS Access Key ID.
-    * @param userGroups
-    *           Name of the groups. Currently supports \"all.\""
-    * @param snapshotId
-    *           The ID of the Amazon EBS snapshot.
-    * 
-    * @see #removeCreateVolumePermissionsFromSnapshot
-    * @see #describeSnapshotAttribute
-    * @see #resetSnapshotAttribute
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifySnapshotAttribute.html"
-    *      />
-    */
-   void addCreateVolumePermissionsToSnapshotInRegion(@Nullable String region, Iterable<String> userIds,
-            Iterable<String> userGroups, String snapshotId);
-
-   /**
-    * Resets the {@code createVolumePermission}s on an EBS snapshot.
-    * 
-    * @param region
-    *           Snapshots are tied to Regions and can only be used for volumes within the same
-    *           Region.
-    * @param snapshotId
-    *           The ID of the Amazon EBS snapshot.
-    * 
-    * @see #addCreateVolumePermissionsToSnapshot
-    * @see #describeSnapshotAttribute
-    * @see #removeProductCodesFromSnapshot
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ResetSnapshotAttribute.html"
-    *      />
-    */
-   void resetCreateVolumePermissionsOnSnapshotInRegion(@Nullable String region, String snapshotId);
-
-   /**
-    * Removes {@code createVolumePermission}s from an EBS snapshot.
-    * 
-    * @param region
-    *           Snapshots are tied to Regions and can only be used for volumes within the same
-    *           Region.
-    * @param userIds
-    *           AWS Access Key ID.
-    * @param userGroups
-    *           Name of the groups. Currently supports \"all.\""
-    * @param snapshotId
-    *           The ID of the Amazon EBS snapshot.
-    * 
-    * @see #addCreateVolumePermissionsToSnapshot
-    * @see #describeSnapshotAttribute
-    * @see #resetSnapshotAttribute
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifySnapshotAttribute.html"
-    *      />
-    */
-   void removeCreateVolumePermissionsFromSnapshotInRegion(@Nullable String region, Iterable<String> userIds,
-            Iterable<String> userGroups, String snapshotId);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticIPAddressAsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticIPAddressAsyncClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticIPAddressAsyncClient.java
deleted file mode 100644
index 8369fa4..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticIPAddressAsyncClient.java
+++ /dev/null
@@ -1,113 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.binders.BindPublicIpsToIndexedFormParams;
-import org.jclouds.ec2.domain.PublicIpInstanceIdPair;
-import org.jclouds.ec2.xml.AllocateAddressResponseHandler;
-import org.jclouds.ec2.xml.DescribeAddressesResponseHandler;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to EC2 Elastic IP Addresses via REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface ElasticIPAddressAsyncClient {
-
-   /**
-    * @see BaseEC2Client#allocateAddressInRegion
-    */
-   @Named("AllocateAddress")
-   @POST
-   @Path("/")
-   @XMLResponseParser(AllocateAddressResponseHandler.class)
-   @FormParams(keys = ACTION, values = "AllocateAddress")
-   ListenableFuture<String> allocateAddressInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
-
-   /**
-    * @see BaseEC2Client#associateAddressInRegion
-    */
-   @Named("AssociateAddress")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "AssociateAddress")
-   ListenableFuture<Void> associateAddressInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("PublicIp") String publicIp, @FormParam("InstanceId") String instanceId);
-
-   /**
-    * @see BaseEC2Client#disassociateAddressInRegion
-    */
-   @Named("DisassociateAddress")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DisassociateAddress")
-   ListenableFuture<Void> disassociateAddressInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("PublicIp") String publicIp);
-
-   /**
-    * @see BaseEC2Client#releaseAddressInRegion
-    */
-   @Named("ReleaseAddress")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "ReleaseAddress")
-   ListenableFuture<Void> releaseAddressInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("PublicIp") String publicIp);
-
-   /**
-    * @see BaseEC2Client#describeAddressesInRegion
-    */
-   @Named("DescribeAddresses")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeAddresses")
-   @XMLResponseParser(DescribeAddressesResponseHandler.class)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<? extends Set<PublicIpInstanceIdPair>> describeAddressesInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindPublicIpsToIndexedFormParams.class) String... publicIps);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticIPAddressClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticIPAddressClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticIPAddressClient.java
deleted file mode 100644
index 2eaec4d..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/ElasticIPAddressClient.java
+++ /dev/null
@@ -1,117 +0,0 @@
-/*
- * 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.services;
-
-import java.util.Set;
-import org.jclouds.ec2.domain.PublicIpInstanceIdPair;
-import org.jclouds.javax.annotation.Nullable;
-
-/**
- * Provides access to EC2 via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-public interface ElasticIPAddressClient {
-
-   /**
-    * Acquires an elastic IP address for use with your identity.
-    * 
-    * @param region
-    *           Elastic IP addresses are tied to a Region and cannot be mapped across Regions.
-    * @see #describeAddresses
-    * @see #releaseAddress
-    * @see #associateAddress
-    * @see #disassociateAddress
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-AllocateAddress.html"
-    */
-   String allocateAddressInRegion(@Nullable String region);
-
-   /**
-    * Associates an elastic IP address with an instance. If the IP address is currently assigned to
-    * another instance, the IP address is assigned to the new instance. This is an idempotent
-    * operation. If you enter it more than once, Amazon EC2 does not return an error.
-    * 
-    * @param region
-    *           Elastic IP addresses are tied to a Region and cannot be mapped across Regions.
-    * @param publicIp
-    *           IP address that you are assigning to the instance.
-    * @param instanceId
-    *           The instance to associate with the IP address.
-    * 
-    * @see #allocateAddress
-    * @see #describeAddresses
-    * @see #releaseAddress
-    * @see #disassociateAddress
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-AssociateAddress.html"
-    */
-   void associateAddressInRegion(@Nullable String region, String publicIp, String instanceId);
-
-   /**
-    * Disassociates the specified elastic IP address from the instance to which it is assigned. This
-    * is an idempotent operation. If you enter it more than once, Amazon EC2 does not return an
-    * error.
-    * 
-    * @param region
-    *           Elastic IP addresses are tied to a Region and cannot be mapped across Regions.
-    * @param publicIp
-    *           IP address that you are assigning to the instance.
-    * 
-    * @see #allocateAddress
-    * @see #describeAddresses
-    * @see #releaseAddress
-    * @see #associateAddress
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DisassociateAddress.html"
-    */
-   void disassociateAddressInRegion(@Nullable String region, String publicIp);
-
-   /**
-    * Releases an elastic IP address associated with your identity.
-    * 
-    * @param region
-    *           Elastic IP addresses are tied to a Region and cannot be mapped across Regions.
-    * @param publicIp
-    *           The IP address that you are releasing from your identity.
-    * 
-    * @see #allocateAddress
-    * @see #describeAddresses
-    * @see #associateAddress
-    * @see #disassociateAddress
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-ReleaseAddress.html"
-    */
-   void releaseAddressInRegion(@Nullable String region, String publicIp);
-
-   /**
-    * Lists elastic IP addresses assigned to your identity or provides information about a specific
-    * address.
-    * 
-    * @param region
-    *           Elastic IP addresses are tied to a Region and cannot be mapped across Regions.
-    * @param publicIps
-    *           Elastic IP address to describe.
-    * 
-    * @throws AWSResponseException
-    *            if the requested publicIp is not found
-    * @see #allocateAddress
-    * @see #releaseAddress
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeAddresses.html"
-    *      />
-    */
-   Set<PublicIpInstanceIdPair> describeAddressesInRegion(@Nullable String region,
-            String... publicIps);
-
-}


[03/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiTest.java
new file mode 100644
index 0000000..69eb068
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiTest.java
@@ -0,0 +1,136 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.aws.ec2.xml.DescribePlacementGroupsResponseHandler;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.http.functions.ReleasePayloadAndReturn;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Lists;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code PlacementGroupApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "PlacementGroupApiTest")
+public class PlacementGroupApiTest extends BaseAWSEC2ApiTest<PlacementGroupApi> {
+
+   public void testDeletePlacementGroup() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(PlacementGroupApi.class, "deletePlacementGroupInRegion", String.class,
+               String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DeletePlacementGroup&GroupName=name",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, VoidOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   HttpRequest createPlacementGroup = HttpRequest.builder().method("POST")
+                                                 .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                 .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                 .addFormParam("Action", "CreatePlacementGroup")
+                                                 .addFormParam("GroupName", "name")
+                                                 .addFormParam("Strategy", "cluster").build();
+
+   public void testCreatePlacementGroup() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(PlacementGroupApi.class, "createPlacementGroupInRegion", String.class,
+               String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "cluster"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(createPlacementGroup).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testCreatePlacementGroupDefault() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(PlacementGroupApi.class, "createPlacementGroupInRegion", String.class,
+               String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=CreatePlacementGroup&Strategy=cluster&GroupName=name",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testDescribePlacementGroups() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(PlacementGroupApi.class, "describePlacementGroupsInRegion", String.class,
+               String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribePlacementGroups",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribePlacementGroupsResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testDescribePlacementGroupsArgs() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(PlacementGroupApi.class, "describePlacementGroupsInRegion", String.class,
+               String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribePlacementGroups&GroupName.1=1&GroupName.2=2",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribePlacementGroupsResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiLiveTest.java
new file mode 100644
index 0000000..522b577
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiLiveTest.java
@@ -0,0 +1,176 @@
+/*
+ * 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.aws.ec2.features;
+
+import static com.google.common.base.Predicates.in;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions.Builder.from;
+import static org.jclouds.aws.ec2.options.RequestSpotInstancesOptions.Builder.launchGroup;
+import static org.jclouds.util.Predicates2.retry;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.Date;
+import java.util.Set;
+import java.util.SortedSet;
+import java.util.concurrent.TimeUnit;
+
+import org.jclouds.aws.domain.Region;
+import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
+import org.jclouds.aws.ec2.AWSEC2Api;
+import org.jclouds.aws.ec2.domain.AWSRunningInstance;
+import org.jclouds.aws.ec2.domain.LaunchSpecification;
+import org.jclouds.aws.ec2.domain.Spot;
+import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
+import org.jclouds.aws.ec2.predicates.SpotInstanceRequestActive;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.ec2.domain.InstanceType;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSortedSet;
+
+/**
+ * Tests behavior of {@code SpotInstanceApi}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true)
+public class SpotInstanceApiLiveTest  extends BaseComputeServiceContextLiveTest {
+   public SpotInstanceApiLiveTest() {
+      provider = "aws-ec2";
+   }
+
+   private static final int SPOT_DELAY_SECONDS = 600;
+   private AWSEC2Api client;
+   private Predicate<SpotInstanceRequest> activeTester;
+   private Set<SpotInstanceRequest> requests;
+   private AWSRunningInstance instance;
+   private long start;
+
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      client = view.unwrapApi(AWSEC2Api.class);
+      activeTester = retry(new SpotInstanceRequestActive(client), SPOT_DELAY_SECONDS, 1, 1, SECONDS);
+   }
+
+   @Test
+   void testDescribeSpotRequestsInRegion() {
+      for (String region : Region.DEFAULT_REGIONS) {
+         SortedSet<SpotInstanceRequest> allResults = ImmutableSortedSet.copyOf(client.getSpotInstanceApi().get()
+                  .describeSpotInstanceRequestsInRegion(region));
+         assertNotNull(allResults);
+         if (allResults.size() >= 1) {
+            SpotInstanceRequest request = allResults.last();
+            SortedSet<SpotInstanceRequest> result = ImmutableSortedSet.copyOf(client.getSpotInstanceApi().get()
+                     .describeSpotInstanceRequestsInRegion(region, request.getId()));
+            assertNotNull(result);
+            SpotInstanceRequest compare = result.last();
+            assertEquals(compare, request);
+         }
+      }
+
+   }
+
+   @Test
+   void testDescribeSpotPriceHistoryInRegion() {
+      for (String region : Region.DEFAULT_REGIONS) {
+         Set<Spot> spots = client.getSpotInstanceApi().get().describeSpotPriceHistoryInRegion(region, from(new Date()));
+         assertNotNull(spots);
+         assert spots.size() > 0;
+         for (Spot spot : spots) {
+            assert spot.getSpotPrice() > 0 : spots;
+            assertEquals(spot.getRegion(), region);
+            assert in(
+                     ImmutableSet.of("Linux/UNIX", "Linux/UNIX (Amazon VPC)", "SUSE Linux", "SUSE Linux (Amazon VPC)",
+                              "Windows", "Windows (Amazon VPC)")).apply(spot.getProductDescription()) : spot;
+            assert in(
+                     ImmutableSet.of("c1.medium", "c1.xlarge", "cc1.4xlarge", "cg1.4xlarge", "cc2.8xlarge", "m1.large",
+                              "m1.small", "m1.medium", "m1.xlarge", "m2.2xlarge", "m2.4xlarge", "m2.xlarge", "m3.xlarge", 
+                              "m3.2xlarge", "t1.micro")).apply(
+                     spot.getInstanceType()) : spot;
+
+         }
+      }
+
+   }
+
+   @Test(enabled = true)
+   void testCreateSpotInstance() {
+      String launchGroup = PREFIX + "1";
+      for (String region : Region.DEFAULT_REGIONS)
+         for (SpotInstanceRequest request : client.getSpotInstanceApi().get().describeSpotInstanceRequestsInRegion(
+                  region))
+            if (launchGroup.equals(request.getLaunchGroup()))
+               client.getSpotInstanceApi().get().cancelSpotInstanceRequestsInRegion(region, request.getId());
+
+      start = System.currentTimeMillis();
+
+      requests = client.getSpotInstanceApi().get().requestSpotInstancesInRegion(
+               "sa-east-1",
+               0.09f,
+               1,
+               LaunchSpecification.builder().imageId("ami-3e3be423").instanceType(InstanceType.M1_SMALL).build(),
+               launchGroup(launchGroup).availabilityZoneGroup(launchGroup).validFrom(
+                        new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(2))).validUntil(
+                        new Date(System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(SPOT_DELAY_SECONDS))));
+      assertNotNull(requests);
+
+      for (SpotInstanceRequest request : requests)
+         verifySpotInstance(request);
+   }
+
+   private void verifySpotInstance(SpotInstanceRequest request) {
+      SpotInstanceRequest spot = refresh(request);
+      assertNotNull(spot);
+      assertEquals(spot, request);
+      assert activeTester.apply(request) : refresh(request);
+      System.out.println(System.currentTimeMillis() - start);
+      spot = refresh(request);
+      assert spot.getInstanceId() != null : spot;
+      instance = getOnlyElement(getOnlyElement(client.getInstanceApi().get().describeInstancesInRegion(spot.getRegion(),
+               spot.getInstanceId())));
+      assertEquals(instance.getSpotInstanceRequestId(), spot.getId());
+   }
+
+   public SpotInstanceRequest refresh(SpotInstanceRequest request) {
+      return getOnlyElement(client.getSpotInstanceApi().get().describeSpotInstanceRequestsInRegion(request.getRegion(),
+               request.getId()));
+   }
+
+   public static final String PREFIX = System.getProperty("user.name") + "ec2";
+
+   @Override
+   @AfterClass(groups = { "integration", "live" })
+   protected void tearDownContext() {
+      if (requests != null) {
+         for (SpotInstanceRequest request : requests)
+            client.getSpotInstanceApi().get().cancelSpotInstanceRequestsInRegion(request.getRegion(), request.getId());
+         // assert deletedTester.apply(request) : request;
+      }
+      if (instance != null) {
+         client.getInstanceApi().get().terminateInstancesInRegion(instance.getRegion(), instance.getId());
+      }
+      super.tearDownContext();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiTest.java
new file mode 100644
index 0000000..f8276e3
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiTest.java
@@ -0,0 +1,100 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+import java.util.Date;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions;
+import org.jclouds.aws.ec2.xml.DescribeSpotPriceHistoryResponseHandler;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.http.functions.ReleasePayloadAndReturn;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Lists;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code SpotInstanceApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "SpotInstanceApiTest")
+public class SpotInstanceApiTest extends BaseAWSEC2ApiTest<SpotInstanceApi> {
+
+   public void testCancelSpotInstanceRequests() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(SpotInstanceApi.class, "cancelSpotInstanceRequestsInRegion", String.class,
+            String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "id"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=CancelSpotInstanceRequests&SpotInstanceRequestId.1=id",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, VoidOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeSpotPriceHistory() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(SpotInstanceApi.class, "describeSpotPriceHistoryInRegion", String.class,
+            DescribeSpotPriceHistoryOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeSpotPriceHistory",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeSpotPriceHistoryResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   Date from = new Date(12345678910l);
+   Date to = new Date(1234567891011l);
+
+   public void testDescribeSpotPriceHistoryArgs() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(SpotInstanceApi.class, "describeSpotPriceHistoryInRegion", String.class,
+            DescribeSpotPriceHistoryOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, DescribeSpotPriceHistoryOptions.Builder.from(from)
+            .to(to).productDescription("description").instanceType("m1.small")));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(
+            request,
+            "Action=DescribeSpotPriceHistory&StartTime=1970-05-23T21%3A21%3A18.910Z&EndTime=2009-02-13T23%3A31%3A31.011Z&ProductDescription=description&InstanceType.1=m1.small",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeSpotPriceHistoryResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/TagSecurityGroupLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/TagSecurityGroupLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/TagSecurityGroupLiveTest.java
index de202ce..c16d835 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/TagSecurityGroupLiveTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/TagSecurityGroupLiveTest.java
@@ -18,8 +18,8 @@ package org.jclouds.aws.ec2.features;
 
 import static org.jclouds.ec2.domain.Tag.ResourceType.SECURITY_GROUP;
 
-import org.jclouds.aws.ec2.AWSEC2Client;
-import org.jclouds.aws.ec2.services.AWSSecurityGroupClient;
+import org.jclouds.aws.ec2.AWSEC2Api;
+import org.jclouds.aws.ec2.features.AWSSecurityGroupApi;
 import org.jclouds.ec2.features.internal.BaseTagApiLiveTest;
 import org.testng.annotations.Test;
 
@@ -51,7 +51,7 @@ public class TagSecurityGroupLiveTest extends BaseTagApiLiveTest {
       securityGroupApi().deleteSecurityGroupInRegionById(null, resource.id);
    }
 
-   private AWSSecurityGroupClient securityGroupApi() {
-      return AWSEC2Client.class.cast(api).getSecurityGroupServices();
+   private AWSSecurityGroupApi securityGroupApi() {
+      return AWSEC2Api.class.cast(api).getSecurityGroupApi().get();
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/functions/ImportOrReturnExistingKeypairTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/functions/ImportOrReturnExistingKeypairTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/functions/ImportOrReturnExistingKeypairTest.java
index a1204e6..cd6b3b7 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/functions/ImportOrReturnExistingKeypairTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/functions/ImportOrReturnExistingKeypairTest.java
@@ -23,11 +23,12 @@ import static org.easymock.EasyMock.verify;
 import static org.jclouds.ssh.SshKeys.fingerprintPublicKey;
 import static org.testng.Assert.assertEquals;
 
-import org.jclouds.aws.ec2.AWSEC2Client;
-import org.jclouds.aws.ec2.services.AWSKeyPairClient;
+import org.jclouds.aws.ec2.AWSEC2Api;
+import org.jclouds.aws.ec2.features.AWSKeyPairApi;
 import org.jclouds.ec2.domain.KeyPair;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableSet;
 
 /**
@@ -44,37 +45,37 @@ public class ImportOrReturnExistingKeypairTest {
 
    @Test
    public void testApply() {
-      AWSEC2Client client = createMock(AWSEC2Client.class);
-      AWSKeyPairClient keyClient = createMock(AWSKeyPairClient.class);
+      AWSEC2Api client = createMock(AWSEC2Api.class);
+      AWSKeyPairApi keyApi = createMock(AWSKeyPairApi.class);
 
-      expect(client.getKeyPairServices()).andReturn(keyClient).atLeastOnce();
+      expect(client.getKeyPairApi()).andReturn((Optional) Optional.of(keyApi)).atLeastOnce();
 
-      expect(keyClient.importKeyPairInRegion("region", "jclouds#group", PUBLIC_KEY)).andReturn(pair);
+      expect(keyApi.importKeyPairInRegion("region", "jclouds#group", PUBLIC_KEY)).andReturn(pair);
 
       replay(client);
-      replay(keyClient);
+      replay(keyApi);
 
       ImportOrReturnExistingKeypair parser = new ImportOrReturnExistingKeypair(client);
 
       assertEquals(parser.importOrReturnExistingKeypair("region", "group", PUBLIC_KEY), pairWithFingerprint);
 
       verify(client);
-      verify(keyClient);
+      verify(keyApi);
    }
 
    @Test
    public void testApplyWithIllegalStateExceptionReturnsExistingKey() {
-      AWSEC2Client client = createMock(AWSEC2Client.class);
-      AWSKeyPairClient keyClient = createMock(AWSKeyPairClient.class);
+      AWSEC2Api client = createMock(AWSEC2Api.class);
+      AWSKeyPairApi keyApi = createMock(AWSKeyPairApi.class);
 
-      expect(client.getKeyPairServices()).andReturn(keyClient).atLeastOnce();
+      expect(client.getKeyPairApi()).andReturn((Optional) Optional.of(keyApi)).atLeastOnce();
 
-      expect(keyClient.importKeyPairInRegion("region", "jclouds#group", PUBLIC_KEY)).andThrow(
+      expect(keyApi.importKeyPairInRegion("region", "jclouds#group", PUBLIC_KEY)).andThrow(
                new IllegalStateException());
-      expect(keyClient.describeKeyPairsInRegion("region", "jclouds#group")).andReturn(ImmutableSet.of(pair));
+      expect(keyApi.describeKeyPairsInRegion("region", "jclouds#group")).andReturn(ImmutableSet.of(pair));
 
       replay(client);
-      replay(keyClient);
+      replay(keyApi);
 
       ImportOrReturnExistingKeypair parser = new ImportOrReturnExistingKeypair(client);
 
@@ -82,33 +83,33 @@ public class ImportOrReturnExistingKeypairTest {
       assertEquals(parser.importOrReturnExistingKeypair("region", "group", PUBLIC_KEY), pairWithFingerprint);
 
       verify(client);
-      verify(keyClient);
+      verify(keyApi);
 
    }
 
    @Test
    public void testApplyWithIllegalStateExceptionRetriesWhenExistingKeyNotFound() {
-      AWSEC2Client client = createMock(AWSEC2Client.class);
-      AWSKeyPairClient keyClient = createMock(AWSKeyPairClient.class);
+      AWSEC2Api client = createMock(AWSEC2Api.class);
+      AWSKeyPairApi keyApi = createMock(AWSKeyPairApi.class);
 
-      expect(client.getKeyPairServices()).andReturn(keyClient).atLeastOnce();
+      expect(client.getKeyPairApi()).andReturn((Optional) Optional.of(keyApi)).atLeastOnce();
 
-      expect(keyClient.importKeyPairInRegion("region", "jclouds#group", PUBLIC_KEY)).andThrow(
+      expect(keyApi.importKeyPairInRegion("region", "jclouds#group", PUBLIC_KEY)).andThrow(
                new IllegalStateException());
-      expect(keyClient.describeKeyPairsInRegion("region", "jclouds#group")).andReturn(ImmutableSet.<KeyPair> of());
-      expect(keyClient.importKeyPairInRegion("region", "jclouds#group", PUBLIC_KEY)).andThrow(
+      expect(keyApi.describeKeyPairsInRegion("region", "jclouds#group")).andReturn(ImmutableSet.<KeyPair> of());
+      expect(keyApi.importKeyPairInRegion("region", "jclouds#group", PUBLIC_KEY)).andThrow(
                new IllegalStateException());
-      expect(keyClient.describeKeyPairsInRegion("region", "jclouds#group")).andReturn(ImmutableSet.<KeyPair> of(pair));
+      expect(keyApi.describeKeyPairsInRegion("region", "jclouds#group")).andReturn(ImmutableSet.<KeyPair> of(pair));
 
       replay(client);
-      replay(keyClient);
+      replay(keyApi);
 
       ImportOrReturnExistingKeypair parser = new ImportOrReturnExistingKeypair(client);
 
       assertEquals(parser.importOrReturnExistingKeypair("region", "group", PUBLIC_KEY), pairWithFingerprint);
 
       verify(client);
-      verify(keyClient);
+      verify(keyApi);
 
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIAsyncClientTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIAsyncClientTest.java
deleted file mode 100644
index aee9b01..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIAsyncClientTest.java
+++ /dev/null
@@ -1,497 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.executableBy;
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.aws.ec2.xml.ProductCodesHandler;
-import org.jclouds.ec2.options.CreateImageOptions;
-import org.jclouds.ec2.options.DescribeImagesOptions;
-import org.jclouds.ec2.options.RegisterImageBackedByEbsOptions;
-import org.jclouds.ec2.options.RegisterImageOptions;
-import org.jclouds.ec2.xml.BlockDeviceMappingHandler;
-import org.jclouds.ec2.xml.DescribeImagesResponseHandler;
-import org.jclouds.ec2.xml.ImageIdHandler;
-import org.jclouds.ec2.xml.PermissionHandler;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.http.functions.ReleasePayloadAndReturn;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code AWSAMIAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "AWSAMIAsyncClientTest")
-public class AWSAMIAsyncClientTest extends BaseAWSEC2AsyncClientTest<AWSAMIAsyncClient> {
-   public AWSAMIAsyncClientTest() {
-      provider = "aws-ec2";
-   }
-
-   HttpRequest createImage = HttpRequest.builder().method("POST")
-                                        .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                        .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                        .addFormParam("Action", "CreateImage")
-                                        .addFormParam("InstanceId", "instanceId")
-                                        .addFormParam("Name", "name").build();
-
-   public void testCreateImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "createImageInRegion", String.class, String.class, String.class,
-               CreateImageOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "instanceId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(createImage).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest createImageOptions = HttpRequest.builder().method("POST")
-                                               .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                               .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                               .addFormParam("Action", "CreateImage")
-                                               .addFormParam("Description", "description")
-                                               .addFormParam("InstanceId", "instanceId")
-                                               .addFormParam("Name", "name")
-                                               .addFormParam("NoReboot", "true").build();
-
-   public void testCreateImageOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "createImageInRegion", String.class, String.class, String.class,
-               CreateImageOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "instanceId", new CreateImageOptions()
-               .withDescription("description").noReboot()));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(createImageOptions).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest describeImages = HttpRequest.builder().method("POST")
-                                           .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                           .addFormParam("Action", "DescribeImages").build();
-
-   public void testDescribeImages() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "describeImagesInRegion", String.class,
-               DescribeImagesOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(describeImages).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeImagesResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   HttpRequest describeImagesOptions = HttpRequest.builder().method("POST")
-                                                  .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                  .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                  .addFormParam("Action", "DescribeImages")
-                                                  .addFormParam("ExecutableBy", "me")
-                                                  .addFormParam("ImageId.1", "1")
-                                                  .addFormParam("ImageId.2", "2")
-                                                  .addFormParam("Owner.1", "fred")
-                                                  .addFormParam("Owner.2", "nancy").build();
-
-   public void testDescribeImagesOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "describeImagesInRegion", String.class,
-               DescribeImagesOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, executableBy("me").ownedBy("fred", "nancy").imageIds(
-               "1", "2")));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(describeImagesOptions).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeImagesResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   HttpRequest deregisterImage = HttpRequest.builder().method("POST")
-                                            .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                            .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                            .addFormParam("Action", "DeregisterImage")
-                                            .addFormParam("ImageId", "imageId").build();
-
-   public void testDeregisterImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "deregisterImageInRegion", String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(deregisterImage).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest registerImageFromManifest = HttpRequest.builder().method("POST")
-                                                      .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                      .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                      .addFormParam("Action", "RegisterImage")
-                                                      .addFormParam("ImageLocation", "pathToManifest")
-                                                      .addFormParam("Name", "name").build();
-
-   public void testRegisterImageFromManifest() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "registerImageFromManifestInRegion", String.class, String.class,
-               String.class, RegisterImageOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "pathToManifest"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(registerImageFromManifest).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest registerImageFromManifestOptions = HttpRequest.builder().method("POST")
-                                                             .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                             .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                             .addFormParam("Action", "RegisterImage")
-                                                             .addFormParam("Description", "description")
-                                                             .addFormParam("ImageLocation", "pathToManifest")
-                                                             .addFormParam("Name", "name").build();
-
-   public void testRegisterImageFromManifestOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "registerImageFromManifestInRegion", String.class, String.class,
-               String.class, RegisterImageOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "pathToManifest", new RegisterImageOptions()
-               .withDescription("description")));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(registerImageFromManifestOptions).getPayload().getRawContent()
-            .toString(), "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest registerImageBackedByEBS = HttpRequest.builder().method("POST")
-                                                     .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                     .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                     .addFormParam("Action", "RegisterImage")
-                                                     .addFormParam("BlockDeviceMapping.0.DeviceName", "/dev/sda1")
-                                                     .addFormParam("BlockDeviceMapping.0.Ebs.SnapshotId", "snapshotId")
-                                                     .addFormParam("Name", "imageName")
-                                                     .addFormParam("RootDeviceName", "/dev/sda1").build();
-
-   public void testRegisterImageBackedByEBS() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "registerUnixImageBackedByEbsInRegion", String.class,
-               String.class, String.class, RegisterImageBackedByEbsOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageName", "snapshotId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(registerImageBackedByEBS).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest registerImageBackedByEBSOptions = HttpRequest.builder().method("POST")
-                                                            .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                            .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                            .addFormParam("Action", "RegisterImage")
-                                                            .addFormParam("BlockDeviceMapping.0.DeviceName", "/dev/sda1")
-                                                            .addFormParam("BlockDeviceMapping.0.Ebs.SnapshotId", "snapshotId")
-                                                            .addFormParam("BlockDeviceMapping.1.DeviceName", "/dev/device")
-                                                            .addFormParam("BlockDeviceMapping.1.Ebs.DeleteOnTermination", "false")
-                                                            .addFormParam("BlockDeviceMapping.1.Ebs.SnapshotId", "snapshot")
-                                                            .addFormParam("BlockDeviceMapping.2.DeviceName", "/dev/newdevice")
-                                                            .addFormParam("BlockDeviceMapping.2.Ebs.DeleteOnTermination", "false")
-                                                            .addFormParam("BlockDeviceMapping.2.Ebs.VolumeSize", "100")
-                                                            .addFormParam("BlockDeviceMapping.2.VirtualName", "newblock")
-                                                            .addFormParam("Description", "description")
-                                                            .addFormParam("Name", "imageName")
-                                                            .addFormParam("RootDeviceName", "/dev/sda1").build();
-
-   public void testRegisterImageBackedByEBSOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "registerUnixImageBackedByEbsInRegion", String.class,
-               String.class, String.class, RegisterImageBackedByEbsOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageName", "snapshotId",
-               new RegisterImageBackedByEbsOptions().withDescription("description").addBlockDeviceFromSnapshot(
-                        "/dev/device", null, "snapshot").addNewBlockDevice("/dev/newdevice", "newblock", 100)));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(registerImageBackedByEBSOptions).getPayload().getRawContent()
-            .toString(), "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest getBlockDeviceMappingsForImage = HttpRequest.builder().method("POST")
-                                                           .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                           .addFormParam("Action", "DescribeImageAttribute")
-                                                           .addFormParam("Attribute", "blockDeviceMapping")
-                                                           .addFormParam("ImageId", "imageId").build();
-
-   public void testGetBlockDeviceMappingsForImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "getBlockDeviceMappingsForImageInRegion", String.class,
-               String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(getBlockDeviceMappingsForImage).getPayload().getRawContent()
-            .toString(), "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, BlockDeviceMappingHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest getLaunchPermissionForImage = HttpRequest.builder().method("POST")
-                                                        .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                        .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                        .addFormParam("Action", "DescribeImageAttribute")
-                                                        .addFormParam("Attribute", "launchPermission")
-                                                        .addFormParam("ImageId", "imageId").build();
-
-   public void testGetLaunchPermissionForImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "getLaunchPermissionForImageInRegion", String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(getLaunchPermissionForImage).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, PermissionHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest addLaunchPermission = HttpRequest.builder().method("POST")
-                                                          .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                          .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                          .addFormParam("Action", "ModifyImageAttribute")
-                                                          .addFormParam("Attribute", "launchPermission")
-                                                          .addFormParam("ImageId", "imageId")
-                                                          .addFormParam("OperationType", "add")
-                                                          .addFormParam("UserGroup.1", "all")
-                                                          .addFormParam("UserId.1", "bob")
-                                                          .addFormParam("UserId.2", "sue").build();
-
-   public void testAddLaunchPermissionsToImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "addLaunchPermissionsToImageInRegion", String.class,
-               Iterable.class, Iterable.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("bob", "sue"), ImmutableList
-               .of("all"), "imageId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(addLaunchPermission).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest removeLaunchPermission = HttpRequest.builder().method("POST")
-                                                   .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                   .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                   .addFormParam("Action", "ModifyImageAttribute")
-                                                   .addFormParam("Attribute", "launchPermission")
-                                                   .addFormParam("ImageId", "imageId")
-                                                   .addFormParam("OperationType", "remove")
-                                                   .addFormParam("UserGroup.1", "all")
-                                                   .addFormParam("UserId.1", "bob")
-                                                   .addFormParam("UserId.2", "sue").build();
-
-   public void testRemoveLaunchPermissionsFromImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "removeLaunchPermissionsFromImageInRegion", String.class,
-               Iterable.class, Iterable.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("bob", "sue"), ImmutableList
-               .of("all"), "imageId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(removeLaunchPermission).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest resetLaunchPermissionsOnImage = HttpRequest.builder().method("POST")
-                                                          .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                          .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                          .addFormParam("Action", "ResetImageAttribute")
-                                                          .addFormParam("Attribute", "launchPermission")
-                                                          .addFormParam("ImageId", "imageId").build();
-
-   public void testResetLaunchPermissionsOnImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "resetLaunchPermissionsOnImageInRegion", String.class,
-               String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-            filter.filter(resetLaunchPermissionsOnImage).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetProductCodesForImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "getProductCodesForImageInRegion", String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-            "Action=DescribeImageAttribute&Attribute=productCodes&ImageId=imageId",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, ProductCodesHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testAddProductCodesToImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "addProductCodesToImageInRegion", String.class, Iterable.class,
-            String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("code1", "code2"), "imageId"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(
-            request,
-            "Action=ModifyImageAttribute&OperationType=add&Attribute=productCodes&ImageId=imageId&ProductCode.1=code1&ProductCode.2=code2",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testRemoveProductCodesFromImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSAMIAsyncClient.class, "removeProductCodesFromImageInRegion", String.class,
-            Iterable.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("code1", "code2"), "imageId"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(
-            request,
-            "Action=ModifyImageAttribute&OperationType=remove&Attribute=productCodes&ImageId=imageId&ProductCode.1=code1&ProductCode.2=code2",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIClientLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIClientLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIClientLiveTest.java
deleted file mode 100644
index 0c8f36f..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSAMIClientLiveTest.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.jclouds.aws.ec2.options.AWSDescribeImagesOptions.Builder.filters;
-import static org.testng.Assert.assertNotNull;
-
-import java.util.Set;
-
-import org.jclouds.aws.domain.Region;
-import org.jclouds.ec2.domain.Image;
-import org.jclouds.ec2.services.AMIClientLiveTest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableMultimap;
-import com.google.common.collect.ImmutableSet;
-
-/**
- * Tests behavior of {@code AMIClient}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true)
-public class AWSAMIClientLiveTest extends AMIClientLiveTest {
-
-   public AWSAMIClientLiveTest() {
-      provider = "aws-ec2";
-   }
-
-   public void testDescribeImagesCC() {
-      Set<? extends Image> ccResults = client.describeImagesInRegion(Region.US_EAST_1,
-            filters(ImmutableMultimap.<String, String> builder()//
-                  .put("virtualization-type", "hvm")//
-                  .put("architecture", "x86_64")//
-                  .putAll("owner-id", ImmutableSet.<String> of("137112412989", "099720109477"))//
-                  .put("hypervisor", "xen")//
-                  .put("state", "available")//
-                  .put("image-type", "machine")//
-                  .put("root-device-type", "ebs")//
-                  .build()).ownedBy("137112412989", "099720109477"));
-      assertNotNull(ccResults);
-      assert (ccResults.size() >= 34) : ccResults;
-   }
-}


[16/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceAsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceAsyncClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceAsyncClient.java
deleted file mode 100644
index 0a1968d..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceAsyncClient.java
+++ /dev/null
@@ -1,361 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import java.util.Map;
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.binders.BindBlockDeviceMappingToIndexedFormParams;
-import org.jclouds.ec2.binders.BindInstanceIdsToIndexedFormParams;
-import org.jclouds.ec2.binders.IfNotNullBindAvailabilityZoneToFormParam;
-import org.jclouds.ec2.domain.BlockDevice;
-import org.jclouds.ec2.domain.InstanceStateChange;
-import org.jclouds.ec2.domain.Reservation;
-import org.jclouds.ec2.domain.RunningInstance;
-import org.jclouds.ec2.domain.Volume.InstanceInitiatedShutdownBehavior;
-import org.jclouds.ec2.functions.ConvertUnencodedBytesToBase64EncodedString;
-import org.jclouds.ec2.options.RunInstancesOptions;
-import org.jclouds.ec2.xml.BlockDeviceMappingHandler;
-import org.jclouds.ec2.xml.BooleanValueHandler;
-import org.jclouds.ec2.xml.DescribeInstancesResponseHandler;
-import org.jclouds.ec2.xml.GetConsoleOutputResponseHandler;
-import org.jclouds.ec2.xml.InstanceInitiatedShutdownBehaviorHandler;
-import org.jclouds.ec2.xml.InstanceStateChangeHandler;
-import org.jclouds.ec2.xml.InstanceTypeHandler;
-import org.jclouds.ec2.xml.RunInstancesResponseHandler;
-import org.jclouds.ec2.xml.StringValueHandler;
-import org.jclouds.ec2.xml.UnencodeStringValueHandler;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.ParamParser;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to EC2 Instance Services via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface InstanceAsyncClient {
-
-   /**
-    * @see InstanceClient#describeInstancesInRegion
-    */
-   @Named("DescribeInstances")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeInstances")
-   @XMLResponseParser(DescribeInstancesResponseHandler.class)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<? extends Set<? extends Reservation<? extends RunningInstance>>> describeInstancesInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
-
-   /**
-    * @see InstanceClient#runInstancesInRegion
-    */
-   @Named("RunInstances")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "RunInstances")
-   @XMLResponseParser(RunInstancesResponseHandler.class)
-   ListenableFuture<? extends Reservation<? extends RunningInstance>> runInstancesInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @Nullable @BinderParam(IfNotNullBindAvailabilityZoneToFormParam.class) String nullableAvailabilityZone,
-         @FormParam("ImageId") String imageId, @FormParam("MinCount") int minCount,
-         @FormParam("MaxCount") int maxCount, RunInstancesOptions... options);
-
-   /**
-    * @see InstanceClient#rebootInstancesInRegion
-    */
-   @Named("RebootInstances")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "RebootInstances")
-   ListenableFuture<Void> rebootInstancesInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
-
-   /**
-    * @see InstanceClient#terminateInstancesInRegion
-    */
-   @Named("TerminateInstances")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "TerminateInstances")
-   @XMLResponseParser(InstanceStateChangeHandler.class)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<? extends InstanceStateChange>> terminateInstancesInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
-
-   /**
-    * @see InstanceClient#stopInstancesInRegion
-    */
-   @Named("StopInstances")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "StopInstances")
-   @XMLResponseParser(InstanceStateChangeHandler.class)
-   ListenableFuture<Set<? extends InstanceStateChange>> stopInstancesInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("Force") boolean force,
-         @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
-
-   /**
-    * @see InstanceClient#startInstancesInRegion
-    */
-   @Named("StartInstances")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "StartInstances")
-   @XMLResponseParser(InstanceStateChangeHandler.class)
-   ListenableFuture<Set<? extends InstanceStateChange>> startInstancesInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
-
-   /**
-    * @see AMIClient#getUserDataForInstanceInRegion
-    */
-   @Named("DescribeInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "userData" })
-   @XMLResponseParser(UnencodeStringValueHandler.class)
-   ListenableFuture<String> getUserDataForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId);
-
-   /**
-    * @see AMIClient#getRootDeviceNameForInstanceInRegion
-    */
-   @Named("DescribeInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "rootDeviceName" })
-   @XMLResponseParser(StringValueHandler.class)
-   ListenableFuture<String> getRootDeviceNameForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId);
-
-   /**
-    * @see AMIClient#getRamdiskForInstanceInRegion
-    */
-   @Named("DescribeInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "ramdisk" })
-   @XMLResponseParser(StringValueHandler.class)
-   ListenableFuture<String> getRamdiskForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId);
-
-   /**
-    * @see AMIClient#getKernelForInstanceInRegion
-    */
-   @Named("DescribeInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "kernel" })
-   @XMLResponseParser(StringValueHandler.class)
-   ListenableFuture<String> getKernelForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId);
-
-   /**
-    * @see AMIClient#isApiTerminationDisabledForInstanceInRegion
-    */
-   @Named("DescribeInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "disableApiTermination" })
-   @XMLResponseParser(BooleanValueHandler.class)
-   ListenableFuture<Boolean> isApiTerminationDisabledForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId);
-
-   /**
-    * @see AMIClient#getInstanceTypeForInstanceInRegion
-    */
-   @Named("DescribeInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "instanceType" })
-   @XMLResponseParser(InstanceTypeHandler.class)
-   ListenableFuture<String> getInstanceTypeForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId);
-
-   /**
-    * @see AMIClient#getInstanceInitiatedShutdownBehaviorForInstanceInRegion
-    */
-   @Named("DescribeInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute",
-         "instanceInitiatedShutdownBehavior" })
-   @XMLResponseParser(InstanceInitiatedShutdownBehaviorHandler.class)
-   ListenableFuture<InstanceInitiatedShutdownBehavior> getInstanceInitiatedShutdownBehaviorForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId);
-
-   /**
-    * @see InstanceClient#getBlockDeviceMappingForInstanceInRegion
-    */
-   @Named("DescribeInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "blockDeviceMapping" })
-   @XMLResponseParser(BlockDeviceMappingHandler.class)
-   ListenableFuture<? extends Map<String, BlockDevice>> getBlockDeviceMappingForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId);
-
-   /**
-    * @see AMIClient#resetRamdiskForInstanceInRegion
-    */
-   @Named("ResetInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "ResetInstanceAttribute", "ramdisk" })
-   ListenableFuture<Void> resetRamdiskForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId);
-
-   /**
-    * @see AMIClient#resetKernelForInstanceInRegion
-    */
-   @Named("ResetInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "ResetInstanceAttribute", "kernel" })
-   ListenableFuture<Void> resetKernelForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId);
-
-   /**
-    * @see AMIClient#setUserDataForInstanceInRegion
-    */
-   @Named("ModifyInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "userData" })
-   ListenableFuture<Void> setUserDataForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId,
-         @FormParam("Value") @ParamParser(ConvertUnencodedBytesToBase64EncodedString.class) byte[] unencodedData);
-
-   /**
-    * @see AMIClient#setRamdiskForInstanceInRegion
-    */
-   @Named("ModifyInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "ramdisk" })
-   ListenableFuture<Void> setRamdiskForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId, @FormParam("Value") String ramdisk);
-
-   /**
-    * @see AMIClient#setKernelForInstanceInRegion
-    */
-   @Named("ModifyInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "kernel" })
-   ListenableFuture<Void> setKernelForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId, @FormParam("Value") String kernel);
-
-   /**
-    * @see AMIClient#setApiTerminationDisabledForInstanceInRegion
-    */
-   @Named("ModifyInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "disableApiTermination" })
-   ListenableFuture<Void> setApiTerminationDisabledForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId, @FormParam("Value") boolean apiTerminationDisabled);
-
-   /**
-    * @see AMIClient#setInstanceTypeForInstanceInRegion
-    */
-   @Named("ModifyInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "instanceType" })
-   ListenableFuture<Void> setInstanceTypeForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId, @FormParam("Value") String instanceType);
-
-   /**
-    * @see AMIClient#setInstanceInitiatedShutdownBehaviorForInstanceInRegion
-    */
-   @Named("ModifyInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute",
-         "instanceInitiatedShutdownBehavior" })
-   ListenableFuture<Void> setInstanceInitiatedShutdownBehaviorForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId,
-         @FormParam("Value") InstanceInitiatedShutdownBehavior instanceInitiatedShutdownBehavior);
-
-   /**
-    * @see InstanceClient#setBlockDeviceMappingForInstanceInRegion
-    */
-   @Named("ModifyInstanceAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION }, values = { "ModifyInstanceAttribute" })
-   ListenableFuture<Void> setBlockDeviceMappingForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId,
-         @BinderParam(BindBlockDeviceMappingToIndexedFormParams.class) Map<String, BlockDevice> blockDeviceMapping);
-
-   /**
-    * @see InstanceClient#getConsoleOutputForInstanceInRegion(String, String)
-    */
-   @Named("GetConsoleOutput")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION }, values = { "GetConsoleOutput" })
-   @XMLResponseParser(GetConsoleOutputResponseHandler.class)
-   ListenableFuture<String> getConsoleOutputForInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceClient.java
deleted file mode 100644
index 2bd6e26..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/InstanceClient.java
+++ /dev/null
@@ -1,587 +0,0 @@
-/*
- * 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.services;
-
-import java.util.Map;
-import java.util.Set;
-import org.jclouds.ec2.domain.BlockDevice;
-import org.jclouds.ec2.domain.InstanceStateChange;
-import org.jclouds.ec2.domain.Reservation;
-import org.jclouds.ec2.domain.RunningInstance;
-import org.jclouds.ec2.domain.Volume.InstanceInitiatedShutdownBehavior;
-import org.jclouds.ec2.options.RunInstancesOptions;
-import org.jclouds.javax.annotation.Nullable;
-
-/**
- * Provides access to EC2 via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-public interface InstanceClient {
-
-   /**
-    * Returns information about instances that you own.
-    * <p/>
-    * 
-    * If you specify one or more instance IDs, Amazon EC2 returns information
-    * for those instances. If you do not specify instance IDs, Amazon EC2
-    * returns information for all relevant instances. If you specify an invalid
-    * instance ID, a fault is returned. If you specify an instance that you do
-    * not own, it will not be included in the returned results.
-    * <p/>
-    * Recently terminated instances might appear in the returned results.This
-    * interval is usually less than one hour.
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * 
-    * @see #runInstancesInRegion
-    * @see #terminateInstancesInRegion
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html"
-    *      />
-    */
-   Set<? extends Reservation<? extends RunningInstance>> describeInstancesInRegion(@Nullable String region,
-         String... instanceIds);
-
-   /**
-    * Launches a specified number of instances of an AMI for which you have
-    * permissions.
-    * <p/>
-    * 
-    * If Amazon EC2 cannot launch the minimum number AMIs you request, no
-    * instances will be launched. If there is insufficient capacity to launch
-    * the maximum number of AMIs you request, Amazon EC2 launches the minimum
-    * number specified for each AMI and allocate the remaining available
-    * instances using round robin.
-    * <p/>
-    * <h4>Security Groups</h4>
-    * <b>Note:</b> Every instance is launched in a security group (created using
-    * the CreateSecurityGroup operation.
-    * <h4>Key Pair</h4>
-    * You can provide an optional key pair ID for each image in the launch
-    * request (created using the CreateKeyPair operation). All instances that
-    * are created from images that use this key pair will have access to the
-    * associated public key at boot. You can use this key to provide secure
-    * access to an instance of an image on a per-instance basis. Amazon EC2
-    * public images use this feature to provide secure access without passwords.
-    * <p/>
-    * <b>Note:</b> Launching public images without a key pair ID will leave them
-    * inaccessible.
-    * <p/>
-    * The public key material is made available to the instance at boot time by
-    * placing it in the openssh_id.pub file on a logical device that is exposed
-    * to the instance as /dev/sda2 (the instance store). The format of this file
-    * is suitable for use as an entry within ~/.ssh/authorized_keys (the OpenSSH
-    * format). This can be done at boot (e.g., as part of rc.local) allowing for
-    * secure access without passwords.
-    * <h4>User Data</h4>
-    * Optional user data can be provided in the launch request. All instances
-    * that collectively comprise the launch request have access to this data.
-    * For more information, go the Amazon Elastic Compute Cloud Developer Guide.
-    * <h4>Product Codes</h4>
-    * 
-    * <b>Note:</b> If any of the AMIs have a product code attached for which the
-    * user has not subscribed, the RunInstances call will fail.
-    * <h4>Kernel</h4>
-    * 
-    * <b>Important:</b> We strongly recommend using the 2.6.18 Xen stock kernel
-    * with High-CPU and High-Memory instances. Although the default Amazon EC2
-    * kernels will work, the new kernels provide greater stability and
-    * performance for these instance types. For more information about kernels,
-    * go the Amazon Elastic Compute Cloud Developer Guide.
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param nullableAvailabilityZone
-    *           Specifies the placement constraints (Availability Zones) for
-    *           launching the instances. If null, Amazon will determine the best
-    *           availability zone to place the instance.
-    * @param imageId
-    *           Unique ID of a machine image, returned by a call to
-    * @param minCount
-    *           Minimum number of instances to launch. If the value is more than
-    *           Amazon EC2 can launch, no instances a re launched at all.
-    *           Constraints: Between 1 and the maximum number allowed for your
-    *           account (default: 20).
-    * @param maxCount
-    *           Maximum number of instances to launch. If the value is more than
-    *           Amazon EC2 can launch, the largest possible number above
-    *           minCount will be launched instead. Constraints: Between 1 and
-    *           the maximum number allowed for your account (default: 20).
-    * @see #describeInstancesInRegion
-    * @see #terminateInstancesInRegion
-    * @see #authorizeSecurityGroupIngressInRegion
-    * @see #revokeSecurityGroupIngressInRegion
-    * @see #describeSecurityGroupsInRegion
-    * @see #createSecurityGroupInRegion
-    * @see #createKeyPairInRegion
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RunInstances.html"
-    *      />
-    * @see RunInstancesOptions
-    */
-   Reservation<? extends RunningInstance> runInstancesInRegion(@Nullable String region,
-         @Nullable String nullableAvailabilityZone, String imageId,
-         int minCount, int maxCount, RunInstancesOptions... options);
-
-   /**
-    * Shuts down one or more instances. This operation is idempotent; if you
-    * terminate an instance more than once, each call will succeed.
-    * <p/>
-    * Terminated instances will remain visible after termination (approximately
-    * one hour).
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceIds
-    *           Instance ID to terminate.
-    * @see #describeInstancesInRegion
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-TerminateInstances.html"
-    *      />
-    */
-   Set<? extends InstanceStateChange> terminateInstancesInRegion(@Nullable String region,
-         String... instanceIds);
-
-   /**
-    * Stops an instance that uses an Amazon EBS volume as its root device.
-    * <p/>
-    * Instances that use Amazon EBS volumes as their root devices can be quickly
-    * stopped and started. When an instance is stopped, the compute resources
-    * are released and you are not billed for hourly instance usage. However,
-    * your root partition Amazon EBS volume remains, continues to persist your
-    * data, and you are charged for Amazon EBS volume usage. You can restart
-    * your instance at any time.
-    * <h3>Note</h3>
-    * Before stopping an instance, make sure it is in a state from which it can
-    * be restarted. Stopping an instance does not preserve data stored in RAM.
-    * <p/>
-    * Performing this operation on an instance that uses an instance store as
-    * its root device returns an error.
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param force
-    *           Forces the instance to stop. The instance will not have an
-    *           opportunity to flush file system caches nor file system meta
-    *           data. If you use this option, you must perform file system check
-    *           and repair procedures. This option is not recommended for
-    *           Windows instances.
-    * @param instanceIds
-    *           Instance ID to stop.
-    * 
-    * @see #startInstancesInRegion
-    * @see #runInstancesInRegion
-    * @see #describeInstancesInRegion
-    * @see #terminateInstancesInRegion
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StopInstances.html"
-    *      />
-    */
-   Set<? extends InstanceStateChange> stopInstancesInRegion(@Nullable String region,
-         boolean force, String... instanceIds);
-
-   /**
-    * Requests a reboot of one or more instances. This operation is
-    * asynchronous; it only queues a request to reboot the specified
-    * instance(s). The operation will succeed if the instances are valid and
-    * belong to you. Requests to reboot terminated instances are ignored. <h3>
-    * Note</h3> If a Linux/UNIX instance does not cleanly shut down within four
-    * minutes, Amazon EC2 will perform a hard reboot.
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * 
-    * @param instanceIds
-    *           Instance ID to reboot.
-    * 
-    * @see #startInstancesInRegion
-    * @see #runInstancesInRegion
-    * @see #describeInstancesInRegion
-    * @see #terminateInstancesInRegion
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StopInstances.html"
-    *      />
-    */
-   void rebootInstancesInRegion(@Nullable String region, String... instanceIds);
-
-   /**
-    * Starts an instance that uses an Amazon EBS volume as its root device.
-    * <p/>
-    * Instances that use Amazon EBS volumes as their root devices can be quickly
-    * stopped and started. When an instance is stopped, the compute resources
-    * are released and you are not billed for hourly instance usage. However,
-    * your root partition Amazon EBS volume remains, continues to persist your
-    * data, and you are charged for Amazon EBS volume usage. You can restart
-    * your instance at any time.
-    * <h3>Note</h3>
-    * Before stopping an instance, make sure it is in a state from which it can
-    * be restarted. Stopping an instance does not preserve data stored in RAM.
-    * <p/>
-    * Performing this operation on an instance that uses an instance store as
-    * its root device returns an error.
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceIds
-    *           Instance ID to start.
-    * 
-    * @see #stopInstancesInRegion
-    * @see #runInstancesInRegion
-    * @see #describeInstancesInRegion
-    * @see #terminateInstancesInRegion
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StartInstances.html"
-    *      />
-    */
-   Set<? extends InstanceStateChange> startInstancesInRegion(@Nullable String region,
-         String... instanceIds);
-
-   /**
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to describe the attribute of
-    * @return unencoded user data
-    */
-   String getUserDataForInstanceInRegion(@Nullable String region,
-         String instanceId);
-
-   /**
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to describe the attribute of
-    * @return The root device name (e.g., /dev/sda1).
-    */
-   String getRootDeviceNameForInstanceInRegion(@Nullable String region,
-         String instanceId);
-
-   /**
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to describe the attribute of
-    * @return the ID of the RAM disk associated with the AMI.
-    */
-   String getRamdiskForInstanceInRegion(@Nullable String region,
-         String instanceId);
-
-   /**
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to describe the attribute of
-    * @return the ID of the kernel associated with the AMI.
-    */
-   String getKernelForInstanceInRegion(@Nullable String region,
-         String instanceId);
-
-   /**
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to describe the attribute of
-    * @return Specifies whether the instance can be terminated using the APIs.
-    *         You must modify this attribute before you can terminate any
-    *         "locked" instances from the APIs.
-    */
-   boolean isApiTerminationDisabledForInstanceInRegion(@Nullable String region,
-         String instanceId);
-
-   /**
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to describe the attribute of
-    * @return The instance type of the instance.
-    */
-   String getInstanceTypeForInstanceInRegion(@Nullable String region,
-         String instanceId);
-
-   /**
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to describe the attribute of
-    * @return whether the instance's Amazon EBS volumes are stopped or
-    *         terminated when the instance is shut down.
-    */
-   InstanceInitiatedShutdownBehavior getInstanceInitiatedShutdownBehaviorForInstanceInRegion(
-         String region, String instanceId);
-
-   /**
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to describe the attribute of
-    * @return Describes the mapping that defines native device names to use when
-    *         exposing virtual devices.
-    */
-   Map<String, BlockDevice> getBlockDeviceMappingForInstanceInRegion(
-         @Nullable String region, String instanceId);
-
-   /**
-    * Resets an attribute of an instance to its default value.
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to reset the attribute of
-    * @return the ID of the RAM disk associated with the AMI.
-    */
-   String resetRamdiskForInstanceInRegion(@Nullable String region,
-         String instanceId);
-
-   /**
-    * Resets an attribute of an instance to its default value.
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to reset the attribute of
-    * @return the ID of the kernel associated with the AMI.
-    */
-   String resetKernelForInstanceInRegion(@Nullable String region,
-         String instanceId);
-
-   /**
-    * Sets the userData used for starting the instance.
-    * <p/>
-    * The instance needs to be in a {@link InstanceState#STOPPED} state, which
-    * implies two things:
-    * <ol>
-    * <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
-    * <li>You have stopped and waited for the instance to transition from
-    * {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
-    * </ol>
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to change the attribute of
-    * @param unencodedData
-    *           unencoded data to set as userData
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
-    *      />
-    */
-   void setUserDataForInstanceInRegion(@Nullable String region,
-         String instanceId, byte[] unencodedData);
-
-   /**
-    * Sets the ramdisk used for starting the instance.
-    * <p/>
-    * The instance needs to be in a {@link InstanceState#STOPPED} state, which
-    * implies two things:
-    * <ol>
-    * <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
-    * <li>You have stopped and waited for the instance to transition from
-    * {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
-    * </ol>
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to change the attribute of
-    * @param ramdisk
-    *           ramdisk used to start the instance
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
-    *      />
-    */
-   void setRamdiskForInstanceInRegion(@Nullable String region,
-         String instanceId, String ramdisk);
-
-   /**
-    * Sets the kernelId used for starting the instance.
-    * <p/>
-    * The instance needs to be in a {@link InstanceState#STOPPED} state, which
-    * implies two things:
-    * <ol>
-    * <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
-    * <li>You have stopped and waited for the instance to transition from
-    * {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
-    * </ol>
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to change the attribute of
-    * @param kernel
-    *           kernelId used to start the instance
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
-    *      />
-    */
-   void setKernelForInstanceInRegion(@Nullable String region,
-         String instanceId, String kernel);
-
-   /**
-    * This command works while the instance is running and controls whether or
-    * not the api can be used to terminate the instance.
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to reset the attribute of
-    * @param apiTerminationDisabled
-    *           true to disable api termination
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
-    *      />
-    */
-   void setApiTerminationDisabledForInstanceInRegion(@Nullable String region,
-         String instanceId, boolean apiTerminationDisabled);
-
-   /**
-    * Sets the instanceType used for starting the instance.
-    * <p/>
-    * The instance needs to be in a {@link InstanceState#STOPPED} state, which
-    * implies two things:
-    * <ol>
-    * <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
-    * <li>You have stopped and waited for the instance to transition from
-    * {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
-    * </ol>
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to change the attribute of
-    * @param instanceType
-    *           instanceType used to start the instance
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
-    *      />
-    */
-   void setInstanceTypeForInstanceInRegion(@Nullable String region,
-         String instanceId, String instanceType);
-
-   /**
-    * Specifies whether the instance's Amazon EBS volumes are stopped or
-    * terminated when the instance is shut down.
-    * <p/>
-    * The instance needs to be in a {@link InstanceState#STOPPED} state, which
-    * implies two things:
-    * <ol>
-    * <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
-    * <li>You have stopped and waited for the instance to transition from
-    * {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
-    * </ol>
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to change the attribute of
-    * @param instanceInitiatedShutdownBehavior
-    *           whether the instance's Amazon EBS volumes are stopped or
-    *           terminated when the instance is shut down.
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
-    *      />
-    */
-   void setInstanceInitiatedShutdownBehaviorForInstanceInRegion(
-         @Nullable String region, String instanceId,
-         InstanceInitiatedShutdownBehavior instanceInitiatedShutdownBehavior);
-
-   /**
-    * Sets the blockDeviceMapping used for an instance.
-    * <p/>
-    * The instance needs to be in a {@link InstanceState#STOPPED} state, which
-    * implies two things:
-    * <ol>
-    * <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
-    * <li>You have stopped and waited for the instance to transition from
-    * {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
-    * </ol>
-    * 
-    * To create the instances of {@link BlockDevice}, the
-    * constructor can be used with the following parameters:
-    * {@link BlockDevice#EbsBlockDevice(String, String, boolean)}
-    * , that are:
-    * <ol>
-    * <li>Volume id (required), for instance, "vol-blah"</li>
-    * <li>Device name (optional), for instance, "/dev/sda1". To find out more
-    * about device names, read the next paragraph.</li>
-    * <li>Delete on termination flag (optional), which defines whether the
-    * volume will be deleted upon instance's termination.</li>
-    * </ol>
-    * <p/>
-    * Note that the device names between Linux and Windows differ. For Linux,
-    * ensure that your device name is in the form /dev/sd[a-z] . For example,
-    * /dev/sda , /dev/sdb and /dev/sdh are all valid device names.
-    * <p/>
-    * For Windows, the root device is still referred to as /dev/sda1 . For other
-    * devices, ensure that they are in the form /xvd[c-p] . For example, /xvde ,
-    * /xvdf and /xvdp are all valid Windows device names.
-    * <p/>
-    * <b>NOTE</b>: As of now 02/20/2010, this command only works to change the
-    * DeleteOnTermination property of the device. The volume must be
-    * <i>attached</i> to a stopped instance.
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to change the attribute of
-    * @param blockDeviceMapping
-    *           blockDeviceMapping used to start the instance
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
-    *      />
-    */
-   void setBlockDeviceMappingForInstanceInRegion(@Nullable String region,
-         String instanceId, Map<String, BlockDevice> blockDeviceMapping);
-
-   /**
-    * Retrieves console output for the specified instance.
-    *
-    * Instance console output is buffered and posted shortly after instance boot, reboot, and termination. Amazon EC2 preserves
-    * the most recent 64 KB output which will be available for at least one hour after the most recent post.
-    *
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance
-    *           ID is tied to the Region.
-    * @param instanceId
-    *           which instance to retrieve console output for
-    * @return The console output
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-GetConsoleOutput.html">
-    *       ApiReference query GetConsoleOutput</a>
-    */
-   String getConsoleOutputForInstanceInRegion(@Nullable String region,
-         String instanceId);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/KeyPairAsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/KeyPairAsyncClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/KeyPairAsyncClient.java
deleted file mode 100644
index 48e0059..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/KeyPairAsyncClient.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.binders.BindKeyNamesToIndexedFormParams;
-import org.jclouds.ec2.domain.KeyPair;
-import org.jclouds.ec2.xml.DescribeKeyPairsResponseHandler;
-import org.jclouds.ec2.xml.KeyPairResponseHandler;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to EC2 via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface KeyPairAsyncClient {
-
-   /**
-    * @see KeyPairClient#createKeyPairInRegion
-    */
-   @Named("CreateKeyPair")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "CreateKeyPair")
-   @XMLResponseParser(KeyPairResponseHandler.class)
-   ListenableFuture<KeyPair> createKeyPairInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("KeyName") String keyName);
-
-   /**
-    * @see KeyPairClient#describeKeyPairsInRegion
-    */
-   @Named("DescribeKeyPairs")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeKeyPairs")
-   @XMLResponseParser(DescribeKeyPairsResponseHandler.class)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<? extends Set<KeyPair>> describeKeyPairsInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindKeyNamesToIndexedFormParams.class) String... keyPairNames);
-
-   /**
-    * @see KeyPairClient#deleteKeyPairInRegion
-    */
-   @Named("DeleteKeyPair")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DeleteKeyPair")
-   ListenableFuture<Void> deleteKeyPairInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("KeyName") String keyName);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/KeyPairClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/KeyPairClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/KeyPairClient.java
deleted file mode 100644
index 0210f9d..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/KeyPairClient.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.services;
-
-import java.util.Set;
-import org.jclouds.ec2.domain.KeyPair;
-import org.jclouds.javax.annotation.Nullable;
-
-/**
- * Provides access to EC2 via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-public interface KeyPairClient {
-
-   /**
-    * Creates a new 2048-bit RSA key pair with the specified name. The public key is stored by
-    * Amazon EC2 and the private key is displayed on the console. The private key is returned as an
-    * unencrypted PEM encoded PKCS#8 private key. If a key with the specified name already exists,
-    * Amazon EC2 returns an error.
-    * 
-    * @param region
-    *           Key pairs (to connect to instances) are Region-specific.
-    * @param keyName
-    *           A unique name for the key pair.
-    * 
-    * @see #runInstances
-    * @see #describeKeyPairs
-    * @see #deleteKeyPair
-    * 
-    * @see <a href=
-    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateKeyPair.html"
-    *      />
-    */
-   KeyPair createKeyPairInRegion(@Nullable String region, String keyName);
-
-   /**
-    * Returns information about key pairs available to you. If you specify key pairs, information
-    * about those key pairs is returned. Otherwise, information for all registered key pairs is
-    * returned.
-    * 
-    * @param region
-    *           Key pairs (to connect to instances) are Region-specific.
-    * @param keyPairNames
-    *           Key pairs to describe.
-    * 
-    * @see #runInstances
-    * @see #describeAvailabilityZones
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeKeyPairs.html"
-    *      />
-    */
-   Set<KeyPair> describeKeyPairsInRegion(@Nullable String region, String... keyPairNames);
-
-   /**
-    * Deletes the specified key pair, by removing the public key from Amazon EC2. You must own the
-    * key pair
-    * 
-    * @param region
-    *           Key pairs (to connect to instances) are Region-specific.
-    * @param keyName
-    *           Name of the key pair to delete
-    * 
-    * @see #describeKeyPairs
-    * @see #createKeyPair
-    * 
-    * @see <a href=
-    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteKeyPair.html"
-    *      />
-    */
-   void deleteKeyPairInRegion(@Nullable String region, String keyName);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/SecurityGroupAsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/SecurityGroupAsyncClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/SecurityGroupAsyncClient.java
deleted file mode 100644
index 0de10f9..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/SecurityGroupAsyncClient.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.binders.BindGroupNamesToIndexedFormParams;
-import org.jclouds.ec2.binders.BindUserIdGroupPairToSourceSecurityGroupFormParams;
-import org.jclouds.ec2.domain.SecurityGroup;
-import org.jclouds.ec2.domain.UserIdGroupPair;
-import org.jclouds.ec2.xml.DescribeSecurityGroupsResponseHandler;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.net.domain.IpProtocol;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to EC2 via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface SecurityGroupAsyncClient {
-
-   /**
-    * @see SecurityGroupClient#createSecurityGroupInRegion
-    */
-   @Named("CreateSecurityGroup")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "CreateSecurityGroup")
-   ListenableFuture<Void> createSecurityGroupInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("GroupName") String name, @FormParam("GroupDescription") String description);
-
-   /**
-    * @see SecurityGroupClient#deleteSecurityGroupInRegion
-    */
-   @Named("DeleteSecurityGroup")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DeleteSecurityGroup")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> deleteSecurityGroupInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, @FormParam("GroupName") String name);
-
-   /**
-    * @see SecurityGroupClient#describeSecurityGroupsInRegion
-    */
-   @Named("DescribeSecurityGroups")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeSecurityGroups")
-   @XMLResponseParser(DescribeSecurityGroupsResponseHandler.class)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<? extends Set<SecurityGroup>> describeSecurityGroupsInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindGroupNamesToIndexedFormParams.class) String... securityGroupNames);
-
-   /**
-    * @see SecurityGroupClient#authorizeSecurityGroupIngressInRegion(@ org.jclouds.javax.annotation.Nullable Region,
-    *      String,UserIdGroupPair)
-    */
-   @Named("AuthorizeSecurityGroupIngress")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "AuthorizeSecurityGroupIngress")
-   ListenableFuture<Void> authorizeSecurityGroupIngressInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("GroupName") String groupName,
-            @BinderParam(BindUserIdGroupPairToSourceSecurityGroupFormParams.class) UserIdGroupPair sourceSecurityGroup);
-
-   /**
-    * @see SecurityGroupClient#authorizeSecurityGroupIngressInRegion(@ org.jclouds.javax.annotation.Nullable Region,
-    *      String,IpProtocol,int,int,String)
-    */
-   @Named("AuthorizeSecurityGroupIngress")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "AuthorizeSecurityGroupIngress")
-   ListenableFuture<Void> authorizeSecurityGroupIngressInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("GroupName") String groupName, @FormParam("IpProtocol") IpProtocol ipProtocol,
-            @FormParam("FromPort") int fromPort, @FormParam("ToPort") int toPort, @FormParam("CidrIp") String cidrIp);
-
-   /**
-    * @see SecurityGroupClient#revokeSecurityGroupIngressInRegion(@Nullable Region,
-    *      String,UserIdGroupPair)
-    */
-   @Named("RevokeSecurityGroupIngress")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "RevokeSecurityGroupIngress")
-   ListenableFuture<Void> revokeSecurityGroupIngressInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("GroupName") String groupName,
-            @BinderParam(BindUserIdGroupPairToSourceSecurityGroupFormParams.class) UserIdGroupPair sourceSecurityGroup);
-
-   /**
-    * @see SecurityGroupClient#revokeSecurityGroupIngressInRegion(@ org.jclouds.javax.annotation.Nullable Region,
-    *      String,IpProtocol,int,int,String)
-    */
-   @Named("RevokeSecurityGroupIngress")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "RevokeSecurityGroupIngress")
-   ListenableFuture<Void> revokeSecurityGroupIngressInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("GroupName") String groupName, @FormParam("IpProtocol") IpProtocol ipProtocol,
-            @FormParam("FromPort") int fromPort, @FormParam("ToPort") int toPort, @FormParam("CidrIp") String cidrIp);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/SecurityGroupClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/SecurityGroupClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/SecurityGroupClient.java
deleted file mode 100644
index 23c8272..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/SecurityGroupClient.java
+++ /dev/null
@@ -1,226 +0,0 @@
-/*
- * 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.services;
-
-import java.util.Set;
-import org.jclouds.ec2.domain.SecurityGroup;
-import org.jclouds.ec2.domain.UserIdGroupPair;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.net.domain.IpProtocol;
-
-/**
- * Provides access to EC2 via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-public interface SecurityGroupClient {
-
-   /**
-    * Creates a new security group. Group names must be unique per identity.
-    * 
-    * @param region
-    *           Security groups are not copied across Regions. Instances within the Region cannot
-    *           communicate with instances outside the Region using group-based firewall rules.
-    *           Traffic from instances in another Region is seen as WAN bandwidth.
-    * @param name
-    *           Name of the security group. Accepts alphanumeric characters, spaces, dashes, and
-    *           underscores.
-    * @param description
-    *           Description of the group. This is informational only. If the description contains
-    *           spaces, you must enc lose it in single quotes (') or URL-encode it. Accepts
-    *           alphanumeric characters, spaces, dashes, and underscores.
-    * @see #runInstances
-    * @see #describeSecurityGroups
-    * @see #authorizeSecurityGroupIngress
-    * @see #revokeSecurityGroupIngress
-    * @see #deleteSecurityGroup
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateSecurityGroup.html"
-    *      />
-    */
-   void createSecurityGroupInRegion(@Nullable String region, String name, String description);
-
-   /**
-    * Deletes a security group that you own.
-    * 
-    * @param region
-    *           Security groups are not copied across Regions. Instances within the Region cannot
-    *           communicate with instances outside the Region using group-based firewall rules.
-    *           Traffic from instances in another Region is seen as WAN bandwidth.
-    * @param name
-    *           Name of the security group to delete.
-    * 
-    * @see #describeSecurityGroups
-    * @see #authorizeSecurityGroupIngress
-    * @see #revokeSecurityGroupIngress
-    * @see #createSecurityGroup
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteSecurityGroup.html"
-    *      />
-    */
-   void deleteSecurityGroupInRegion(@Nullable String region, String name);
-
-   /**
-    * Returns information about security groups that you own.
-    * 
-    * @param region
-    *           Security groups are not copied across Regions. Instances within the Region cannot
-    *           communicate with instances outside the Region using group-based firewall rules.
-    *           Traffic from instances in another Region is seen as WAN bandwidth.
-    * @param securityGroupNames
-    *           Name of the security groups
-    * 
-    * @see #createSecurityGroup
-    * @see #authorizeSecurityGroupIngress
-    * @see #revokeSecurityGroupIngress
-    * @see #deleteSecurityGroup
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSecurityGroups.html"
-    *      />
-    */
-   Set<SecurityGroup> describeSecurityGroupsInRegion(@Nullable String region,
-            String... securityGroupNames);
-
-   /**
-    * 
-    * Adds permissions to a security group based on another group.
-    * 
-    * @param region
-    *           Security groups are not copied across Regions. Instances within the Region cannot
-    *           communicate with instances outside the Region using group-based firewall rules.
-    *           Traffic from instances in another Region is seen as WAN bandwidth.
-    * @param groupName
-    *           Name of the group to modify. The name must be valid and belong to the identity
-    * @param sourceSecurityGroup
-    *           group to associate with this group.
-    * 
-    * @see #createSecurityGroup
-    * @see #describeSecurityGroups
-    * @see #revokeSecurityGroupIngress
-    * @see #deleteSecurityGroup
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-AuthorizeSecurityGroupIngress.html"
-    * 
-    */
-   void authorizeSecurityGroupIngressInRegion(@Nullable String region, String groupName,
-            UserIdGroupPair sourceSecurityGroup);
-
-   /**
-    * 
-    * Adds permissions to a security group.
-    * <p/>
-    * Permissions are specified by the IP protocol (TCP, UDP or ICMP), the source of the request (by
-    * IP range or an Amazon EC2 user-group pair), the source and destination port ranges (for TCP
-    * and UDP), and the ICMP codes and types (for ICMP). When authorizing ICMP, -1 can be used as a
-    * wildcard in the type and code fields. Permission changes are propagated to instances within
-    * the security group as quickly as possible. However, depending on the number of instances, a
-    * small delay might occur.
-    * 
-    * @param region
-    *           Security groups are not copied across Regions. Instances within the Region cannot
-    *           communicate with instances outside the Region using group-based firewall rules.
-    *           Traffic from instances in another Region is seen as WAN bandwidth.
-    * @param groupName
-    *           Name of the group to modify. The name must be valid and belong to the identity
-    * @param ipProtocol
-    *           IP protocol.
-    * @param fromPort
-    *           Start of port range for the TCP and UDP protocols, or an ICMP type number. An ICMP
-    *           type number of -1 indicates a wildcard (i.e., any ICMP type number).
-    * @param toPort
-    *           End of port range for the TCP and UDP protocols, or an ICMP code. An ICMP code of -1
-    *           indicates a wildcard (i.e., any ICMP code).
-    * @param cidrIp
-    *           CIDR range.
-    * 
-    * @see #createSecurityGroup
-    * @see #describeSecurityGroups
-    * @see #revokeSecurityGroupIngress
-    * @see #deleteSecurityGroup
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-AuthorizeSecurityGroupIngress.html"
-    * 
-    */
-   void authorizeSecurityGroupIngressInRegion(@Nullable String region, String groupName,
-            IpProtocol ipProtocol, int fromPort, int toPort, String cidrIp);
-
-   /**
-    * 
-    * Revokes permissions from a security group. The permissions used to revoke must be specified
-    * using the same values used to grant the permissions.
-    * 
-    * @param region
-    *           Security groups are not copied across Regions. Instances within the Region cannot
-    *           communicate with instances outside the Region using group-based firewall rules.
-    *           Traffic from instances in another Region is seen as WAN bandwidth.
-    * @param groupName
-    *           Name of the group to modify. The name must be valid and belong to the identity
-    * @param sourceSecurityGroup
-    *           group to associate with this group.
-    * 
-    * @see #createSecurityGroup
-    * @see #describeSecurityGroups
-    * @see #authorizeSecurityGroupIngress
-    * @see #deleteSecurityGroup
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RevokeSecurityGroupIngress.html"
-    * 
-    */
-   void revokeSecurityGroupIngressInRegion(@Nullable String region, String groupName,
-            UserIdGroupPair sourceSecurityGroup);
-
-   /**
-    * 
-    * Revokes permissions from a security group. The permissions used to revoke must be specified
-    * using the same values used to grant the permissions.
-    * <p/>
-    * Permissions are specified by IP protocol (TCP, UDP, or ICMP), the source of the request (by IP
-    * range or an Amazon EC2 user-group pair), the source and destination port ranges (for TCP and
-    * UDP), and the ICMP codes and types (for ICMP).
-    * 
-    * Permission changes are quickly propagated to instances within the security group. However,
-    * depending on the number of instances in the group, a small delay is might occur.
-    * 
-    * @param region
-    *           Security groups are not copied across Regions. Instances within the Region cannot
-    *           communicate with instances outside the Region using group-based firewall rules.
-    *           Traffic from instances in another Region is seen as WAN bandwidth.
-    * @param groupName
-    *           Name of the group to modify. The name must be valid and belong to the identity
-    * @param ipProtocol
-    *           IP protocol.
-    * @param fromPort
-    *           Start of port range for the TCP and UDP protocols, or an ICMP type number. An ICMP
-    *           type number of -1 indicates a wildcard (i.e., any ICMP type number).
-    * @param toPort
-    *           End of port range for the TCP and UDP protocols, or an ICMP code. An ICMP code of -1
-    *           indicates a wildcard (i.e., any ICMP code).
-    * @param cidrIp
-    *           CIDR range.
-    * 
-    * @see #createSecurityGroup
-    * @see #describeSecurityGroups
-    * @see #authorizeSecurityGroupIngress
-    * @see #deleteSecurityGroup
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RevokeSecurityGroupIngress.html"
-    * 
-    */
-   void revokeSecurityGroupIngressInRegion(@Nullable String region, String groupName, IpProtocol ipProtocol,
-            int fromPort, int toPort, String cidrIp);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/WindowsAsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/WindowsAsyncClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/WindowsAsyncClient.java
deleted file mode 100644
index 70d2cc8..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/WindowsAsyncClient.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.binders.BindBundleIdsToIndexedFormParams;
-import org.jclouds.ec2.binders.BindS3UploadPolicyAndSignature;
-import org.jclouds.ec2.domain.BundleTask;
-import org.jclouds.ec2.domain.PasswordData;
-import org.jclouds.ec2.options.BundleInstanceS3StorageOptions;
-import org.jclouds.ec2.xml.BundleTaskHandler;
-import org.jclouds.ec2.xml.DescribeBundleTasksResponseHandler;
-import org.jclouds.ec2.xml.GetPasswordDataResponseHandler;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to EC2 Windows via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface WindowsAsyncClient {
-
-   /**
-    * @see WindowsClient#bundleInstanceInRegion
-    */
-   @Named("BundleInstance")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "BundleInstance")
-   @XMLResponseParser(BundleTaskHandler.class)
-   ListenableFuture<BundleTask> bundleInstanceInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("InstanceId") String instanceId, @FormParam("Storage.S3.Prefix") String prefix,
-            @FormParam("Storage.S3.Bucket") String bucket,
-            @BinderParam(BindS3UploadPolicyAndSignature.class) String uploadPolicy,
-            BundleInstanceS3StorageOptions... options);
-
-   /**
-    * @see WindowsClient#cancelBundleTaskInRegion
-    */
-   @Named("CancelBundleTask")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "CancelBundleTask")
-   @XMLResponseParser(BundleTaskHandler.class)
-   ListenableFuture<BundleTask> cancelBundleTaskInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("BundleId") String bundleId);
-
-   /**
-    * @see BundleTaskClient#describeBundleTasksInRegion
-    */
-   @Named("DescribeBundleTasks")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeBundleTasks")
-   @XMLResponseParser(DescribeBundleTasksResponseHandler.class)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<? extends Set<BundleTask>> describeBundleTasksInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindBundleIdsToIndexedFormParams.class) String... bundleTaskIds);
-
-   /**
-    * @see WindowsClient#getPasswordDataInRegion
-    */
-   @Named("GetPasswordData")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "GetPasswordData")
-   @XMLResponseParser(GetPasswordDataResponseHandler.class)
-   ListenableFuture<PasswordData> getPasswordDataInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("InstanceId") String instanceId);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/services/WindowsClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/services/WindowsClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/services/WindowsClient.java
deleted file mode 100644
index e03320a..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/services/WindowsClient.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.services;
-
-import java.util.Set;
-import org.jclouds.ec2.domain.BundleTask;
-import org.jclouds.ec2.domain.PasswordData;
-import org.jclouds.ec2.options.BundleInstanceS3StorageOptions;
-import org.jclouds.javax.annotation.Nullable;
-
-/**
- * Provides windows services for EC2. For more information, refer to the Amazon
- * EC2 Developer Guide.
- * <p/>
- * 
- * @author Adrian Cole
- */
-public interface WindowsClient {
-   /**
-    * Bundles the Windows instance. This procedure is not applicable for Linux
-    * and UNIX instances. For more information, go to the Amazon Elastic Compute
-    * Cloud Developer Guide or Amazon Elastic Compute Cloud Getting Started
-    * Guide.
-    * 
-    * @param region
-    *           Bundles are tied to the Region where its files are located
-    *           within Amazon S3.
-    * 
-    * @param instanceId
-    *           The ID of the instance to bundle.
-    * @param prefix
-    *           Specifies the beginning of the file name of the AMI.
-    * @param bucket
-    *           The bucket in which to store the AMI. You can specify a bucket
-    *           that you already own or a new bucket that Amazon EC2 creates on
-    *           your behalf. If you specify a bucket that belongs to someone
-    *           else, Amazon EC2 returns an error.
-    * @param uploadPolicy
-    *           An Amazon S3 upload policy that gives Amazon EC2 permission to
-    *           upload items into Amazon S3 on the user's behalf.
-    *           <p/>
-    *           ex.
-    * 
-    *           <pre>
-    * {"expiration": "2008-08-30T08:49:09Z","conditions": ["bucket": "my-bucket"},["starts-with", "$key", "my-new-image"]]}
-    * </pre>
-    * 
-    * @param options
-    *           if the bucket isn't owned by you, use this to set the bucket's
-    *           accesskeyid
-    * @return status of the work
-    * 
-    * @see #cancelBundleTaskInRegion
-    * @see #describeBundleTasksInRegion
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-BundleInstance.html"
-    *      />
-    */
-   BundleTask bundleInstanceInRegion(@Nullable String region, String instanceId, String prefix, String bucket,
-         String uploadPolicy, BundleInstanceS3StorageOptions... options);
-
-   /**
-    * Cancels an Amazon EC2 bundling operation.
-    * 
-    * @param region
-    *           The bundleTask ID is tied to the Region.
-    * @param bundleId
-    *           The ID of the bundle task to cancel.
-    * @return task for the cancel.
-    * 
-    * @see #bundleInstanceInRegion
-    * @see #describeBundleTasksInRegion
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CancelBundleTask.html"
-    *      />
-    */
-   BundleTask cancelBundleTaskInRegion(@Nullable String region, String bundleId);
-
-   /**
-    * 
-    * Describes current bundling tasks.
-    * 
-    * @param region
-    *           The bundleTask ID is tied to the Region.
-    * 
-    * @see #cancelBundleTaskInRegion
-    * @see #bundleInstanceInRegion
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeBundleTasks.html"
-    *      />
-    */
-   Set<BundleTask> describeBundleTasksInRegion(@Nullable String region, String... bundleTaskIds);
-
-   /**
-    *
-    * Retrieves the encrypted administrator password for the instances running Windows.
-    *
-    * @param region The region where the instance is based
-    * @param instanceId The ID of the instance to query
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-GetPasswordData.html" />
-    */
-   PasswordData getPasswordDataInRegion(@Nullable String region, String instanceId);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeAvailabilityZonesInRegion.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeAvailabilityZonesInRegion.java b/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeAvailabilityZonesInRegion.java
index cd7767c..f97e962 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeAvailabilityZonesInRegion.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeAvailabilityZonesInRegion.java
@@ -23,9 +23,9 @@ import javax.annotation.Resource;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.domain.AvailabilityZoneInfo;
-import org.jclouds.ec2.services.AvailabilityZoneAndRegionClient;
+import org.jclouds.ec2.features.AvailabilityZoneAndRegionApi;
 import org.jclouds.http.HttpResponseException;
 import org.jclouds.location.Region;
 import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
@@ -45,12 +45,12 @@ public class DescribeAvailabilityZonesInRegion implements RegionIdToZoneIdsSuppl
    @Resource
    protected Logger logger = Logger.NULL;
 
-   private final AvailabilityZoneAndRegionClient client;
+   private final AvailabilityZoneAndRegionApi client;
    private final Supplier<Set<String>> regions;
 
    @Inject
-   public DescribeAvailabilityZonesInRegion(EC2Client client, @Region Supplier<Set<String>> regions) {
-      this.client = client.getAvailabilityZoneAndRegionServices();
+   public DescribeAvailabilityZonesInRegion(EC2Api client, @Region Supplier<Set<String>> regions) {
+      this.client = client.getAvailabilityZoneAndRegionApi().get();
       this.regions = regions;
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForRegionURIs.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForRegionURIs.java b/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForRegionURIs.java
index 0cbaee8..d8d7a51 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForRegionURIs.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/suppliers/DescribeRegionsForRegionURIs.java
@@ -22,8 +22,8 @@ import java.util.Map;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.services.AvailabilityZoneAndRegionClient;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.features.AvailabilityZoneAndRegionApi;
 import org.jclouds.location.Region;
 import org.jclouds.location.suppliers.RegionIdToURISupplier;
 import org.jclouds.util.Suppliers2;
@@ -33,11 +33,11 @@ import com.google.common.collect.Maps;
 
 @Singleton
 public class DescribeRegionsForRegionURIs implements RegionIdToURISupplier {
-   private final AvailabilityZoneAndRegionClient client;
+   private final AvailabilityZoneAndRegionApi client;
 
    @Inject
-   public DescribeRegionsForRegionURIs(EC2Client client) {
-      this.client = client.getAvailabilityZoneAndRegionServices();
+   public DescribeRegionsForRegionURIs(EC2Api client) {
+      this.client = client.getAvailabilityZoneAndRegionApi().get();
    }
 
    @Singleton


[02/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSInstanceAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSInstanceAsyncClientTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSInstanceAsyncClientTest.java
deleted file mode 100644
index 6fa19d7..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSInstanceAsyncClientTest.java
+++ /dev/null
@@ -1,539 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.aws.ec2.options.AWSRunInstancesOptions;
-import org.jclouds.aws.ec2.xml.AWSDescribeInstancesResponseHandler;
-import org.jclouds.aws.ec2.xml.AWSRunInstancesResponseHandler;
-import org.jclouds.ec2.domain.BlockDevice;
-import org.jclouds.ec2.domain.InstanceType;
-import org.jclouds.ec2.domain.Volume.InstanceInitiatedShutdownBehavior;
-import org.jclouds.ec2.options.RunInstancesOptions;
-import org.jclouds.ec2.xml.BlockDeviceMappingHandler;
-import org.jclouds.ec2.xml.BooleanValueHandler;
-import org.jclouds.ec2.xml.InstanceInitiatedShutdownBehaviorHandler;
-import org.jclouds.ec2.xml.InstanceStateChangeHandler;
-import org.jclouds.ec2.xml.InstanceTypeHandler;
-import org.jclouds.ec2.xml.StringValueHandler;
-import org.jclouds.ec2.xml.UnencodeStringValueHandler;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.http.functions.ReleasePayloadAndReturn;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code AWSInstanceAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during
-// surefire
-@Test(groups = "unit", testName = "AWSInstanceAsyncClientTest")
-public class AWSInstanceAsyncClientTest extends BaseAWSEC2AsyncClientTest<AWSInstanceAsyncClient> {
-   public void testDescribeInstances() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "describeInstancesInRegion", String.class, String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeInstances", "application/x-www-form-urlencoded",
-            false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, AWSDescribeInstancesResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeInstancesArgs() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "describeInstancesInRegion", String.class, String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeInstances&InstanceId.1=1&InstanceId.2=2",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, AWSDescribeInstancesResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testTerminateInstances() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "terminateInstancesInRegion", String.class, String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=TerminateInstances&InstanceId.1=1&InstanceId.2=2",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testRunInstances() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "runInstancesInRegion", String.class, String.class,
-            String.class, int.class, int.class, RunInstancesOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, null, "ami-voo", 1, 1));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=RunInstances&ImageId=ami-voo&MinCount=1&MaxCount=1",
-            "application/x-www-form-urlencoded", false);
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, AWSRunInstancesResponseHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testRunInstancesOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "runInstancesInRegion", String.class, String.class,
-            String.class, int.class, int.class, RunInstancesOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(
-            method,
-            Lists.<Object> newArrayList("us-east-1",
-            "us-east-1a",
-            "ami-voo",
-            1,
-            5,
-            new AWSRunInstancesOptions().withKernelId("kernelId").enableMonitoring()
-                  .withSecurityGroups("group1", "group2")));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(
-            request,
-            "Action=RunInstances&ImageId=ami-voo&MinCount=1&MaxCount=5&KernelId=kernelId&Monitoring.Enabled=true&SecurityGroup.1=group1&SecurityGroup.2=group2&Placement.AvailabilityZone=us-east-1a",
-            "application/x-www-form-urlencoded", false);
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, AWSRunInstancesResponseHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testStopInstances() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "stopInstancesInRegion", String.class, boolean.class,
-            String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, true, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=StopInstances&Force=true&InstanceId.1=1&InstanceId.2=2",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testRebootInstances() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "rebootInstancesInRegion", String.class,
-            String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=RebootInstances&InstanceId.1=1&InstanceId.2=2",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testStartInstances() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "startInstancesInRegion", String.class,
-            String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=StartInstances&InstanceId.1=1&InstanceId.2=2",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetUserDataForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "getUserDataForInstanceInRegion", String.class,
-            String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-            "Action=DescribeInstanceAttribute&Attribute=userData&InstanceId=1",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, UnencodeStringValueHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetRootDeviceNameForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "getRootDeviceNameForInstanceInRegion", String.class,
-            String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-            "Action=DescribeInstanceAttribute&Attribute=rootDeviceName&InstanceId=1",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, StringValueHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetRamdiskForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "getRamdiskForInstanceInRegion", String.class,
-            String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-            "Action=DescribeInstanceAttribute&Attribute=ramdisk&InstanceId=1",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, StringValueHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetDisableApiTerminationForInstanceInRegion() throws SecurityException, NoSuchMethodException,
-         IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "isApiTerminationDisabledForInstanceInRegion",
-            String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-            "Action=DescribeInstanceAttribute&Attribute=disableApiTermination&InstanceId=1",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, BooleanValueHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetKernelForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "getKernelForInstanceInRegion", String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeInstanceAttribute&Attribute=kernel&InstanceId=1",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, StringValueHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetInstanceTypeForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "getInstanceTypeForInstanceInRegion", String.class,
-            String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-            "Action=DescribeInstanceAttribute&Attribute=instanceType&InstanceId=1",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, InstanceTypeHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetInstanceInitiatedShutdownBehaviorForInstanceInRegion() throws SecurityException,
-         NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "getInstanceInitiatedShutdownBehaviorForInstanceInRegion",
-            String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(
-            request,
-            "Action=DescribeInstanceAttribute&Attribute=instanceInitiatedShutdownBehavior&InstanceId=1",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, InstanceInitiatedShutdownBehaviorHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetBlockDeviceMappingForInstanceInRegion() throws SecurityException, NoSuchMethodException,
-         IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "getBlockDeviceMappingForInstanceInRegion", String.class,
-            String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-            "Action=DescribeInstanceAttribute&Attribute=blockDeviceMapping&InstanceId=1",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, BlockDeviceMappingHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest setUserDataForInstance = HttpRequest.builder().method("POST")
-                                                   .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                   .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                   .addFormParam("Action", "ModifyInstanceAttribute")
-                                                   .addFormParam("Attribute", "userData")
-                                                   .addFormParam("InstanceId", "1")
-                                                   .addFormParam("Value", "dGVzdA%3D%3D").build();
-
-   public void testSetUserDataForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "setUserDataForInstanceInRegion", String.class, String.class,
-               byte[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "test".getBytes()));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(setUserDataForInstance).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest setRamdiskForInstance = HttpRequest.builder().method("POST")
-                                                  .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                  .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                  .addFormParam("Action", "ModifyInstanceAttribute")
-                                                  .addFormParam("Attribute", "ramdisk")
-                                                  .addFormParam("InstanceId", "1")
-                                                  .addFormParam("Value", "test").build();
-
-   public void testSetRamdiskForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "setRamdiskForInstanceInRegion", String.class, String.class,
-               String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "test"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(setRamdiskForInstance).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest setKernelForInstance = HttpRequest.builder().method("POST")
-                                                 .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                 .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                 .addFormParam("Action", "ModifyInstanceAttribute")
-                                                 .addFormParam("Attribute", "kernel")
-                                                 .addFormParam("InstanceId", "1")
-                                                 .addFormParam("Value", "test").build();
-
-   public void testSetKernelForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "setKernelForInstanceInRegion", String.class, String.class,
-               String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "test"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(setKernelForInstance).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest setApiTerminationDisabled = HttpRequest.builder().method("POST")
-                                                      .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                      .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                      .addFormParam("Action", "ModifyInstanceAttribute")
-                                                      .addFormParam("Attribute", "disableApiTermination")
-                                                      .addFormParam("InstanceId", "1")
-                                                      .addFormParam("Value", "true").build();
-
-   public void testSetApiTerminationDisabledForInstanceInRegion() throws SecurityException, NoSuchMethodException,
-            IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "setApiTerminationDisabledForInstanceInRegion", String.class,
-               String.class, boolean.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", true));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(setApiTerminationDisabled).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest instanceTypeForInstance = HttpRequest.builder().method("POST")
-                                                    .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                    .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                    .addFormParam("Action", "ModifyInstanceAttribute")
-                                                    .addFormParam("Attribute", "instanceType")
-                                                    .addFormParam("InstanceId", "1")
-                                                    .addFormParam("Value", "c1.medium").build();
-
-   public void testSetInstanceTypeForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "setInstanceTypeForInstanceInRegion", String.class,
-               String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", InstanceType.C1_MEDIUM));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(instanceTypeForInstance).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest setInstanceInitiatedShutdownBehavior = HttpRequest.builder().method("POST")
-                                                                 .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                                 .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                                 .addFormParam("Action", "ModifyInstanceAttribute")
-                                                                 .addFormParam("Attribute", "instanceInitiatedShutdownBehavior")
-                                                                 .addFormParam("InstanceId", "1")
-                                                                 .addFormParam("Value", "terminate").build();
-
-   public void testSetInstanceInitiatedShutdownBehaviorForInstanceInRegion() throws SecurityException,
-            NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "setInstanceInitiatedShutdownBehaviorForInstanceInRegion",
-               String.class, String.class, InstanceInitiatedShutdownBehavior.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", InstanceInitiatedShutdownBehavior.TERMINATE));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(setInstanceInitiatedShutdownBehavior).getPayload().getRawContent()
-            .toString(), "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest setBlockDeviceMapping = HttpRequest.builder().method("POST")
-                                                           .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                           .addFormParam("Action", "ModifyInstanceAttribute")
-                                                           .addFormParam("BlockDeviceMapping.1.DeviceName", "/dev/sda1")
-                                                           .addFormParam("BlockDeviceMapping.1.Ebs.DeleteOnTermination", "true")
-                                                           .addFormParam("BlockDeviceMapping.1.Ebs.VolumeId", "vol-test1")
-                                                           .addFormParam("InstanceId", "1").build();
-
-   public void testSetBlockDeviceMappingForInstanceInRegion() throws SecurityException, NoSuchMethodException,
-         IOException {
-      Invokable<?, ?> method = method(AWSInstanceAsyncClient.class, "setBlockDeviceMappingForInstanceInRegion", String.class,
-            String.class, Map.class);
-
-      Map<String, BlockDevice> mapping = Maps.newLinkedHashMap();
-      mapping.put("/dev/sda1", new BlockDevice("vol-test1", true));
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", mapping));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(setBlockDeviceMapping).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSInstanceClientLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSInstanceClientLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSInstanceClientLiveTest.java
deleted file mode 100644
index f2a3600..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSInstanceClientLiveTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.testng.Assert.assertNotNull;
-
-import java.util.Set;
-
-import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
-import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.jclouds.ec2.domain.Reservation;
-import org.jclouds.ec2.domain.RunningInstance;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-/**
- * Tests behavior of {@code EC2Client}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true)
-public class AWSInstanceClientLiveTest extends BaseComputeServiceContextLiveTest {
-   public AWSInstanceClientLiveTest() {
-      provider = "aws-ec2";
-   }
-   
-   public static final String PREFIX = System.getProperty("user.name") + "-ec2";
-
-   private AWSInstanceClient client;
-   
-   @Override
-   @BeforeClass(groups = { "integration", "live" })
-   public void setupContext() {
-      super.setupContext();
-      client = view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi().getInstanceServices();
-   }
-
-   @Test
-   void testDescribeInstances() {
-      for (String region : view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi().getAvailabilityZoneAndRegionServices().describeRegions().keySet()) {
-         Set<? extends Reservation<? extends RunningInstance>> allResults = client.describeInstancesInRegion(region);
-         assertNotNull(allResults);
-         assert allResults.size() >= 0 : allResults.size();
-      }
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSKeyPairAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSKeyPairAsyncClientTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSKeyPairAsyncClientTest.java
deleted file mode 100644
index ef2a9e3..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSKeyPairAsyncClientTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.ec2.xml.DescribeKeyPairsResponseHandler;
-import org.jclouds.ec2.xml.KeyPairResponseHandler;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.http.functions.ReleasePayloadAndReturn;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.Lists;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code AWSKeyPairAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "AWSKeyPairAsyncClientTest")
-public class AWSKeyPairAsyncClientTest extends BaseAWSEC2AsyncClientTest<AWSKeyPairAsyncClient> {
-
-   public void testCreateKeyPair() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSKeyPairAsyncClient.class, "createKeyPairInRegion", String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "mykey"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=CreateKeyPair&KeyName=mykey",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, KeyPairResponseHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest importKeyPair = HttpRequest.builder().method("POST")
-                                          .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                          .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                          .addFormParam("Action", "ImportKeyPair")
-                                          .addFormParam("KeyName", "mykey")
-                                          .addFormParam("PublicKeyMaterial", "c3NoLXJzYSBBQQ%3D%3D").build();
-
-   public void testImportKeyPair() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSKeyPairAsyncClient.class, "importKeyPairInRegion", String.class, String.class,
-            String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "mykey", "ssh-rsa AA"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(importKeyPair).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, KeyPairResponseHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testDeleteKeyPair() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSKeyPairAsyncClient.class, "deleteKeyPairInRegion", String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "mykey"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DeleteKeyPair&KeyName=mykey",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeKeyPairs() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSKeyPairAsyncClient.class, "describeKeyPairsInRegion", String.class,
-            String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeKeyPairs", "application/x-www-form-urlencoded",
-            false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeKeyPairsResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeKeyPairsArgs() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSKeyPairAsyncClient.class, "describeKeyPairsInRegion", String.class,
-            String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeKeyPairs&KeyName.1=1&KeyName.2=2",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeKeyPairsResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSKeyPairClientLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSKeyPairClientLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSKeyPairClientLiveTest.java
deleted file mode 100644
index 62cc313..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSKeyPairClientLiveTest.java
+++ /dev/null
@@ -1,209 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static com.google.common.collect.Iterables.get;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static com.google.common.collect.Sets.newTreeSet;
-import static org.jclouds.compute.options.TemplateOptions.Builder.overrideLoginCredentials;
-import static org.jclouds.compute.predicates.NodePredicates.inGroup;
-import static org.jclouds.compute.predicates.NodePredicates.runningInGroup;
-import static org.jclouds.scriptbuilder.domain.Statements.exec;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.fail;
-
-import java.io.FileNotFoundException;
-import java.io.IOException;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedSet;
-
-import org.jclouds.aws.domain.Region;
-import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
-import org.jclouds.aws.ec2.AWSEC2Client;
-import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
-import org.jclouds.aws.ec2.domain.AWSRunningInstance;
-import org.jclouds.compute.ComputeServiceContext;
-import org.jclouds.compute.ComputeTestUtils;
-import org.jclouds.compute.domain.ExecResponse;
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.jclouds.compute.options.TemplateOptions;
-import org.jclouds.domain.LoginCredentials;
-import org.jclouds.ec2.domain.KeyPair;
-import org.jclouds.logging.log4j.config.Log4JLoggingModule;
-import org.jclouds.sshj.config.SshjSshClientModule;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.inject.Module;
-
-/**
- * Tests behavior of {@code AWSKeyPairClient}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true)
-public class AWSKeyPairClientLiveTest extends BaseComputeServiceContextLiveTest {
-   public AWSKeyPairClientLiveTest() {
-      provider = "aws-ec2";
-   }
-
-   private AWSKeyPairClient client;
-   
-   @Override
-   @BeforeClass(groups = { "integration", "live" })
-   public void setupContext() {
-      super.setupContext();
-      client = view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi().getKeyPairServices();
-   }
-
-   public void testNoSsh() throws Exception {
-
-      Map<String, String> keyPair = ComputeTestUtils.setupKeyPair();
-
-      AWSInstanceClient instanceClient = AWSEC2Client.class.cast(view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi()).getInstanceServices();
-
-      String group = PREFIX + "unssh";
-      view.getComputeService().destroyNodesMatching(inGroup(group));
-
-      TemplateOptions options = view.getComputeService().templateOptions();
-
-      options.authorizePublicKey(keyPair.get("public")).as(AWSEC2TemplateOptions.class);
-
-      ComputeServiceContext noSshContext = null;
-      try {
-         noSshContext = createView(setupProperties(), ImmutableSet.<Module> of(new Log4JLoggingModule()));
-
-         Set<? extends NodeMetadata> nodes = noSshContext.getComputeService().createNodesInGroup(group, 1, options);
-
-         NodeMetadata first = get(nodes, 0);
-         assert first.getCredentials() != null : first;
-         assert first.getCredentials().identity != null : first;
-         // credentials should not be present as the import public key call doesn't have access to
-         // the related private key
-         assert first.getCredentials().credential == null : first;
-
-         AWSRunningInstance instance = getInstance(instanceClient, first.getProviderId());
-
-         assertEquals(instance.getKeyName(), "jclouds#" + group);
-
-         Map<? extends NodeMetadata, ExecResponse> responses = view.getComputeService()
-               .runScriptOnNodesMatching(
-                     runningInGroup(group),
-                     exec("echo hello"),
-                     overrideLoginCredentials(
-                           LoginCredentials.builder().user(first.getCredentials().identity)
-                                 .privateKey(keyPair.get("private")).build()).wrapInInitScript(false).runAsRoot(false));
-
-         ExecResponse hello = getOnlyElement(responses.values());
-         assertEquals(hello.getOutput().trim(), "hello");
-
-      } finally {
-         noSshContext.close();
-         view.getComputeService().destroyNodesMatching(inGroup(group));
-      }
-   }
-
-   @Test
-   void testDescribeAWSKeyPairs() {
-      for (String region : Region.DEFAULT_REGIONS) {
-
-         SortedSet<KeyPair> allResults = newTreeSet(client.describeKeyPairsInRegion(region));
-         assertNotNull(allResults);
-         if (allResults.size() >= 1) {
-            KeyPair pair = allResults.last();
-            SortedSet<KeyPair> result = newTreeSet(client.describeKeyPairsInRegion(region, pair.getKeyName()));
-            assertNotNull(result);
-            KeyPair compare = result.last();
-            assertEquals(compare, pair);
-         }
-      }
-   }
-
-   public static final String PREFIX = System.getProperty("user.name") + "-ec2";
-
-   @Test
-   void testCreateKeyPair() {
-      String keyName = PREFIX + "1";
-      cleanupKeyPair(keyName);
-      try {
-         KeyPair keyPair = client.createKeyPairInRegion(null, keyName);
-         checkKeyPair(keyName, keyPair);
-         assertNotNull(keyPair.getKeyMaterial());
-      } finally {
-         cleanupKeyPair(keyName);
-      }
-   }
-
-   protected void cleanupKeyPair(String keyName) {
-      try {
-         client.deleteKeyPairInRegion(null, keyName);
-      } catch (Exception e) {
-
-      }
-      client.deleteKeyPairInRegion(null, keyName);
-   }
-
-   @Test
-   void testImportKeyPair() throws FileNotFoundException, IOException {
-      String keyName = PREFIX + "2";
-      cleanupKeyPair(keyName);
-      Map<String, String> myKey = ComputeTestUtils.setupKeyPair();
-      try {
-         KeyPair keyPair = client.importKeyPairInRegion(null, keyName, myKey.get("public"));
-         checkKeyPair(keyName, keyPair);
-         // TODO generate correct fingerprint and check
-         // assertEquals(keyPair.getKeyFingerprint(),
-         // CryptoStreams.hex(CryptoStreams.md5(myKey.get("public").getBytes())));
-
-         // try again to see if there's an error
-         try {
-            client.importKeyPairInRegion(null, keyName, myKey.get("public"));
-            fail("Expected IllegalStateException");
-         } catch (IllegalStateException e) {
-
-         }
-      } finally {
-         cleanupKeyPair(keyName);
-      }
-   }
-
-   protected void checkKeyPair(String keyName, KeyPair keyPair) {
-      assertNotNull(keyPair);
-      assertNotNull(keyPair.getSha1OfPrivateKey());
-      assertEquals(keyPair.getKeyName(), keyName);
-
-      Set<KeyPair> twoResults = client.describeKeyPairsInRegion(null, keyName);
-      assertNotNull(twoResults);
-      assertEquals(twoResults.size(), 1);
-      KeyPair listPair = twoResults.iterator().next();
-      assertEquals(listPair.getKeyName(), keyPair.getKeyName());
-      assertEquals(listPair.getSha1OfPrivateKey(), keyPair.getSha1OfPrivateKey());
-   }
-
-   protected AWSRunningInstance getInstance(AWSInstanceClient instanceClient, String id) {
-      return getOnlyElement(getOnlyElement(instanceClient.describeInstancesInRegion(null, id)));
-   }
-   
-   @Override
-   protected Module getSshModule() {
-      return new SshjSshClientModule();
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSSecurityGroupAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSSecurityGroupAsyncClientTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSSecurityGroupAsyncClientTest.java
deleted file mode 100644
index 9ebead5..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSSecurityGroupAsyncClientTest.java
+++ /dev/null
@@ -1,207 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.ec2.util.IpPermissions;
-import org.jclouds.ec2.xml.DescribeSecurityGroupsResponseHandler;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.http.functions.ReleasePayloadAndReturn;
-import org.jclouds.net.domain.IpPermission;
-import org.jclouds.net.domain.IpProtocol;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Lists;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code AWSSecurityGroupAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during
-// surefire
-@Test(groups = "unit", testName = "AWSSecurityGroupAsyncClientTest")
-public class AWSSecurityGroupAsyncClientTest extends BaseAWSEC2AsyncClientTest<AWSSecurityGroupAsyncClient> {
-   public AWSSecurityGroupAsyncClientTest() {
-      provider = "aws-ec2";
-   }
-
-   public void testDeleteSecurityGroup() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSSecurityGroupAsyncClient.class, "deleteSecurityGroupInRegionById", String.class,
-            String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "id"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DeleteSecurityGroup&GroupId=id",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, VoidOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeSecurityGroups() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSSecurityGroupAsyncClient.class, "describeSecurityGroupsInRegionById", String.class,
-            String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeSecurityGroups",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeSecurityGroupsResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeSecurityGroupsArgs() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSSecurityGroupAsyncClient.class, "describeSecurityGroupsInRegionById", String.class,
-            String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeSecurityGroups&GroupId.1=1&GroupId.2=2",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeSecurityGroupsResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   HttpRequest createSecurityGroup = HttpRequest.builder().method("POST")
-                                                .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                .addFormParam("Action", "CreateSecurityGroup")
-                                                .addFormParam("GroupDescription", "description")
-                                                .addFormParam("GroupName", "name").build();
-
-   public void testCreateSecurityGroup() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSSecurityGroupAsyncClient.class, "createSecurityGroupInRegion", String.class,
-            String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "description"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(createSecurityGroup).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testAuthorizeSecurityGroupIpPermission() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSSecurityGroupAsyncClient.class, "authorizeSecurityGroupIngressInRegion",
-            String.class, String.class, IpPermission.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", IpPermissions.permitAnyProtocol()));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(
-            request,
-            "Action=AuthorizeSecurityGroupIngress&GroupId=group&IpPermissions.0.IpProtocol=-1&IpPermissions.0.FromPort=1&IpPermissions.0.ToPort=65535&IpPermissions.0.IpRanges.0.CidrIp=0.0.0.0/0",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testAuthorizeSecurityGroupIpPermissions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSSecurityGroupAsyncClient.class, "authorizeSecurityGroupIngressInRegion",
-            String.class, String.class, Iterable.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", ImmutableSet.<IpPermission> of(IpPermissions
-            .permit(IpProtocol.TCP).originatingFromCidrBlock("1.1.1.1/32"), IpPermissions.permitICMP().type(8).andCode(0)
-            .originatingFromSecurityGroupId("groupId"))));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(
-            request,
-            "Action=AuthorizeSecurityGroupIngress&GroupId=group&IpPermissions.0.IpProtocol=tcp&IpPermissions.0.FromPort=1&IpPermissions.0.ToPort=65535&IpPermissions.0.IpRanges.0.CidrIp=1.1.1.1/32&IpPermissions.1.IpProtocol=icmp&IpPermissions.1.FromPort=8&IpPermissions.1.ToPort=0&IpPermissions.1.Groups.0.GroupId=groupId",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testRevokeSecurityGroupIpPermission() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSSecurityGroupAsyncClient.class, "revokeSecurityGroupIngressInRegion", String.class,
-            String.class, IpPermission.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", IpPermissions.permitAnyProtocol()));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(
-            request,
-            "Action=RevokeSecurityGroupIngress&GroupId=group&IpPermissions.0.IpProtocol=-1&IpPermissions.0.FromPort=1&IpPermissions.0.ToPort=65535&IpPermissions.0.IpRanges.0.CidrIp=0.0.0.0/0",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testRevokeSecurityGroupIpPermissions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AWSSecurityGroupAsyncClient.class, "revokeSecurityGroupIngressInRegion", String.class,
-            String.class, Iterable.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", ImmutableSet.<IpPermission> of(IpPermissions
-            .permit(IpProtocol.TCP).originatingFromCidrBlock("1.1.1.1/32"), IpPermissions.permitICMP().type(8).andCode(0)
-            .originatingFromSecurityGroupId("groupId"))));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(
-            request,
-            "Action=RevokeSecurityGroupIngress&GroupId=group&IpPermissions.0.IpProtocol=tcp&IpPermissions.0.FromPort=1&IpPermissions.0.ToPort=65535&IpPermissions.0.IpRanges.0.CidrIp=1.1.1.1/32&IpPermissions.1.IpProtocol=icmp&IpPermissions.1.FromPort=8&IpPermissions.1.ToPort=0&IpPermissions.1.Groups.0.GroupId=groupId",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSSecurityGroupClientLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSSecurityGroupClientLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSSecurityGroupClientLiveTest.java
deleted file mode 100644
index 76c7e91..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/AWSSecurityGroupClientLiveTest.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
-import java.util.Set;
-
-import org.jclouds.ec2.domain.SecurityGroup;
-import org.jclouds.ec2.services.SecurityGroupClientLiveTest;
-import org.jclouds.ec2.util.IpPermissions;
-import org.jclouds.net.domain.IpPermission;
-import org.jclouds.net.domain.IpProtocol;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableMultimap;
-
-/**
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true)
-public class AWSSecurityGroupClientLiveTest extends SecurityGroupClientLiveTest {
-   public AWSSecurityGroupClientLiveTest() {
-      provider = "aws-ec2";
-   }
-
-   @Test
-   void testAuthorizeSecurityGroupIngressIpPermission() throws InterruptedException {
-      final String group1Name = PREFIX + "ingress11";
-      String group2Name = PREFIX + "ingress12";
-      cleanupAndSleep(group2Name);
-      cleanupAndSleep(group1Name);
-      try {
-         String group1Id = AWSSecurityGroupClient.class.cast(client).createSecurityGroupInRegionAndReturnId(null,
-               group1Name, group1Name);
-         String group2Id = AWSSecurityGroupClient.class.cast(client).createSecurityGroupInRegionAndReturnId(null,
-               group2Name, group2Name);
-         Thread.sleep(100);// eventual consistent
-         ensureGroupsExist(group1Name, group2Name);
-         AWSSecurityGroupClient.class.cast(client).authorizeSecurityGroupIngressInRegion(null, group1Id,
-               IpPermissions.permit(IpProtocol.TCP).port(80));
-         assertEventually(new GroupHasPermission(client, group1Name, new TCPPort80AllIPs()));
-         Set<SecurityGroup> oneResult = client.describeSecurityGroupsInRegion(null, group1Name);
-         assertNotNull(oneResult);
-         assertEquals(oneResult.size(), 1);
-         final SecurityGroup group = oneResult.iterator().next();
-         assertEquals(group.getName(), group1Name);
-         IpPermissions group2CanHttpGroup1 = IpPermissions.permit(IpProtocol.TCP).port(80)
-               .originatingFromSecurityGroupId(group1Id);
-         AWSSecurityGroupClient.class.cast(client).authorizeSecurityGroupIngressInRegion(null, group2Id,
-               group2CanHttpGroup1);
-         assertEventually(new GroupHasPermission(client, group2Name, new Predicate<IpPermission>() {
-            @Override
-            public boolean apply(IpPermission arg0) {
-               return arg0.getTenantIdGroupNamePairs().equals(ImmutableMultimap.of(group.getOwnerId(), group1Name))
-                     && arg0.getFromPort() == 80 && arg0.getToPort() == 80 && arg0.getIpProtocol() == IpProtocol.TCP;
-            }
-         }));
-
-         AWSSecurityGroupClient.class.cast(client).revokeSecurityGroupIngressInRegion(null, group2Id,
-               group2CanHttpGroup1);
-         assertEventually(new GroupHasNoPermissions(client, group2Name));
-      } finally {
-         client.deleteSecurityGroupInRegion(null, group2Name);
-         client.deleteSecurityGroupInRegion(null, group1Name);
-      }
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/BaseAWSEC2AsyncClientTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/BaseAWSEC2AsyncClientTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/BaseAWSEC2AsyncClientTest.java
deleted file mode 100644
index 3c712c1..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/BaseAWSEC2AsyncClientTest.java
+++ /dev/null
@@ -1,135 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static com.google.common.collect.Maps.transformValues;
-import static org.testng.Assert.assertEquals;
-
-import java.io.IOException;
-import java.net.URI;
-import java.util.Map;
-import java.util.Set;
-
-import javax.inject.Singleton;
-
-import org.jclouds.aws.domain.Region;
-import org.jclouds.aws.ec2.AWSEC2ProviderMetadata;
-import org.jclouds.aws.ec2.config.AWSEC2RestClientModule;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.compute.domain.Image;
-import org.jclouds.date.DateService;
-import org.jclouds.ec2.compute.domain.RegionAndName;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.location.config.LocationModule;
-import org.jclouds.location.suppliers.RegionIdToURISupplier;
-import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
-import org.jclouds.rest.ConfiguresRestClient;
-import org.jclouds.rest.internal.BaseAsyncClientTest;
-import org.jclouds.util.Suppliers2;
-import org.testng.annotations.BeforeTest;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Supplier;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.inject.Module;
-import com.google.inject.Provides;
-
-/**
- * @author Adrian Cole
- */
-@Test(groups = "unit")
-public abstract class BaseAWSEC2AsyncClientTest<T> extends BaseAsyncClientTest<T> {
-
-      @ConfiguresRestClient
-   protected static class StubAWSEC2RestClientModule extends AWSEC2RestClientModule {
-
-      @Override
-      protected String provideTimeStamp(DateService dateService) {
-         return "2009-11-08T15:54:08.897Z";
-      }
-
-      @Provides
-      @Singleton
-      LoadingCache<RegionAndName, Image> provide() {
-         return CacheBuilder.newBuilder().build(new CacheLoader<RegionAndName, Image>() {
-
-            @Override
-            public Image load(RegionAndName key) throws Exception {
-               return null;
-            }
-
-         });
-      }
-
-      @Override
-      protected void installLocations() {
-         install(new LocationModule());
-         bind(RegionIdToURISupplier.class).toInstance(new RegionIdToURISupplier() {
-
-            @Override
-            public Map<String, Supplier<URI>> get() {
-               return transformValues(ImmutableMap.<String, URI> of(Region.EU_WEST_1, URI
-                        .create("https://ec2.eu-west-1.amazonaws.com"), Region.US_EAST_1, URI
-                        .create("https://ec2.us-east-1.amazonaws.com"), Region.US_WEST_1, URI
-                        .create("https://ec2.us-west-1.amazonaws.com")), Suppliers2.<URI> ofInstanceFunction());
-            }
-
-         });
-         bind(RegionIdToZoneIdsSupplier.class).toInstance(new RegionIdToZoneIdsSupplier() {
-
-            @Override
-            public Map<String, Supplier<Set<String>>> get() {
-               return transformValues(ImmutableMap.<String, Set<String>> of("us-east-1", ImmutableSet.of("us-east-1a",
-                        "us-east-1b", "us-east-1c", "us-east-1b")), Suppliers2.<Set<String>> ofInstanceFunction());
-            }
-
-         });
-      }
-   }
-
-   protected FormSigner filter;
-
-   @Override
-   protected void checkFilters(HttpRequest request) {
-      assertEquals(request.getFilters().size(), 1);
-      assertEquals(request.getFilters().get(0).getClass(), FormSigner.class);
-   }
-
-   @Override
-   @BeforeTest
-   protected void setupFactory() throws IOException {
-      super.setupFactory();
-      this.filter = injector.getInstance(FormSigner.class);
-   }
-
-   @Override
-   protected Module createModule() {
-      return new StubAWSEC2RestClientModule();
-   }
-
-   protected String provider = "aws-ec2";
-
-   @Override
-   public AWSEC2ProviderMetadata createProviderMetadata(){
-      return new AWSEC2ProviderMetadata();
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/MonitoringAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/MonitoringAsyncClientTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/MonitoringAsyncClientTest.java
deleted file mode 100644
index 837ac70..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/MonitoringAsyncClientTest.java
+++ /dev/null
@@ -1,73 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.aws.ec2.xml.MonitoringStateHandler;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.Lists;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code MonitoringAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "MonitoringAsyncClientTest")
-public class MonitoringAsyncClientTest extends BaseAWSEC2AsyncClientTest<MonitoringAsyncClient> {
-
-   public void testUnmonitorInstances() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(MonitoringAsyncClient.class, "unmonitorInstancesInRegion", String.class, String.class,
-            String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "instance1", "instance2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      String payload = "Action=UnmonitorInstances&InstanceId.0=instance1&InstanceId.1=instance2";
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, payload, "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, MonitoringStateHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testMonitorInstances() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(MonitoringAsyncClient.class, "monitorInstancesInRegion", String.class, String.class,
-            String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "instance1", "instance2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-            "Action=MonitorInstances&InstanceId.0=instance1&InstanceId.1=instance2",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, MonitoringStateHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/MonitoringClientLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/MonitoringClientLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/MonitoringClientLiveTest.java
deleted file mode 100644
index 1df3493..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/MonitoringClientLiveTest.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.testng.Assert.assertEquals;
-
-import java.util.Map;
-
-import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
-import org.jclouds.aws.ec2.domain.MonitoringState;
-import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-/**
- * Tests behavior of {@code MonitoringClient}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true)
-public class MonitoringClientLiveTest extends BaseComputeServiceContextLiveTest {
-   public MonitoringClientLiveTest() {
-      provider = "aws-ec2";
-   }
-
-   private MonitoringClient client;
-   private static final String DEFAULT_INSTANCE = "i-TODO";
-
-   
-   @Override
-   @BeforeClass(groups = { "integration", "live" })
-   public void setupContext() {
-      super.setupContext();
-      client = view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi().getMonitoringServices();
-   }
-
-   @Test(enabled = false)
-   // TODO get instance
-   public void testMonitorInstances() {
-      Map<String, MonitoringState> monitoringState = client.monitorInstancesInRegion(null, DEFAULT_INSTANCE);
-      assertEquals(monitoringState.get(DEFAULT_INSTANCE), MonitoringState.PENDING);
-   }
-
-   @Test(enabled = false)
-   // TODO get instance
-   public void testUnmonitorInstances() {
-      Map<String, MonitoringState> monitoringState = client.unmonitorInstancesInRegion(null, DEFAULT_INSTANCE);
-      assertEquals(monitoringState.get(DEFAULT_INSTANCE), MonitoringState.PENDING);
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupAsyncClientTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupAsyncClientTest.java
deleted file mode 100644
index 4f3eb18..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/services/PlacementGroupAsyncClientTest.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.aws.ec2.xml.DescribePlacementGroupsResponseHandler;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.http.functions.ReleasePayloadAndReturn;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.Lists;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code PlacementGroupAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "PlacementGroupAsyncClientTest")
-public class PlacementGroupAsyncClientTest extends BaseAWSEC2AsyncClientTest<PlacementGroupAsyncClient> {
-
-   public void testDeletePlacementGroup() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(PlacementGroupAsyncClient.class, "deletePlacementGroupInRegion", String.class,
-               String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DeletePlacementGroup&GroupName=name",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, VoidOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   HttpRequest createPlacementGroup = HttpRequest.builder().method("POST")
-                                                 .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                 .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                 .addFormParam("Action", "CreatePlacementGroup")
-                                                 .addFormParam("GroupName", "name")
-                                                 .addFormParam("Strategy", "cluster").build();
-
-   public void testCreatePlacementGroup() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(PlacementGroupAsyncClient.class, "createPlacementGroupInRegion", String.class,
-               String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "cluster"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(createPlacementGroup).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testCreatePlacementGroupDefault() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(PlacementGroupAsyncClient.class, "createPlacementGroupInRegion", String.class,
-               String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=CreatePlacementGroup&Strategy=cluster&GroupName=name",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testDescribePlacementGroups() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(PlacementGroupAsyncClient.class, "describePlacementGroupsInRegion", String.class,
-               String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribePlacementGroups",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribePlacementGroupsResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testDescribePlacementGroupsArgs() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(PlacementGroupAsyncClient.class, "describePlacementGroupsInRegion", String.class,
-               String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribePlacementGroups&GroupName.1=1&GroupName.2=2",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribePlacementGroupsResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-}


[10/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/AMIClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/AMIClientLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/AMIClientLiveTest.java
deleted file mode 100644
index 5babe82..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/AMIClientLiveTest.java
+++ /dev/null
@@ -1,202 +0,0 @@
-/*
- * 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.services;
-
-import static com.google.common.base.Preconditions.checkNotNull;
-import static com.google.common.collect.Iterables.concat;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static com.google.common.collect.Sets.newHashSet;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.imageIds;
-import static org.jclouds.ec2.options.RegisterImageBackedByEbsOptions.Builder.addNewBlockDevice;
-import static org.jclouds.util.Predicates2.retry;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import java.util.Iterator;
-import java.util.Properties;
-import java.util.Set;
-
-import org.jclouds.compute.RunNodesException;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.domain.TemplateBuilderSpec;
-import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.jclouds.ec2.EC2ApiMetadata;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.domain.BlockDevice;
-import org.jclouds.ec2.domain.Image;
-import org.jclouds.ec2.domain.Image.ImageType;
-import org.jclouds.ec2.domain.RootDeviceType;
-import org.jclouds.ec2.domain.RunningInstance;
-import org.jclouds.ec2.domain.Snapshot;
-import org.jclouds.ec2.predicates.InstanceStateRunning;
-import org.testng.annotations.AfterClass;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Predicate;
-import com.google.common.collect.ImmutableMap;
-
-/**
- * Tests behavior of {@code AMIClient}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true)
-public class AMIClientLiveTest extends BaseComputeServiceContextLiveTest {
-   private TemplateBuilderSpec ebsTemplate;
-
-   public AMIClientLiveTest() {
-      provider = "ec2";
-   }
-
-   @Override
-   protected Properties setupProperties() {
-      Properties overrides = super.setupProperties();
-      String ebsSpec = checkNotNull(setIfTestSystemPropertyPresent(overrides, provider + ".ebs-template"), provider
-            + ".ebs-template");
-      ebsTemplate = TemplateBuilderSpec.parse(ebsSpec);
-      return overrides;
-   }
-
-   protected EC2Client ec2Client;
-   protected AMIClient client;
-
-   protected Predicate<RunningInstance> runningTester;
-
-   protected Set<String> imagesToDeregister = newHashSet();
-   protected Set<String> snapshotsToDelete = newHashSet();
-   protected String regionId;
-   protected String ebsBackedImageId;
-   protected String ebsBackedImageName = "jcloudstest1";
-   protected String imageId;
-
-   @Override
-   @BeforeClass(groups = { "integration", "live" })
-   public void setupContext() {
-      super.setupContext();
-      ec2Client = view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi();
-      runningTester = retry(new InstanceStateRunning(ec2Client), 600, 5, SECONDS);
-
-      client = ec2Client.getAMIServices();
-      if (ebsTemplate != null) {
-         Template template = view.getComputeService().templateBuilder().from(ebsTemplate).build();
-         regionId = template.getLocation().getId();
-         imageId = template.getImage().getProviderId();
-         for (Image image : client.describeImagesInRegion(regionId)) {
-            if (ebsBackedImageName.equals(image.getName()))
-               client.deregisterImageInRegion(regionId, image.getId());
-         }
-      }
-   }
-
-   public void testDescribeImageNotExists() {
-      assertEquals(client.describeImagesInRegion(null, imageIds("ami-cdf819a3")).size(), 0);
-   }
-
-   @Test(expectedExceptions = IllegalArgumentException.class)
-   public void testDescribeImageBadId() {
-      client.describeImagesInRegion(null, imageIds("asdaasdsa"));
-   }
-
-   public void testDescribeImages() {
-      for (String region : ec2Client.getConfiguredRegions()) {
-         Set<? extends Image> allResults = client.describeImagesInRegion(region);
-         assertNotNull(allResults);
-         assert allResults.size() >= 2 : allResults.size();
-         Iterator<? extends Image> iterator = allResults.iterator();
-         String id1 = iterator.next().getId();
-         String id2 = iterator.next().getId();
-         Set<? extends Image> twoResults = client.describeImagesInRegion(region, imageIds(id1, id2));
-         assertNotNull(twoResults);
-         assertEquals(twoResults.size(), 2);
-         iterator = twoResults.iterator();
-         assertEquals(iterator.next().getId(), id1);
-         assertEquals(iterator.next().getId(), id2);
-      }
-   }
-
-   @Test
-   public void testCreateAndListEBSBackedImage() throws Exception {
-      Snapshot snapshot = createSnapshot();
-
-      // List of images before...
-      int sizeBefore = client.describeImagesInRegion(regionId).size();
-
-      // Register a new image...
-      ebsBackedImageId = client.registerUnixImageBackedByEbsInRegion(regionId, ebsBackedImageName, snapshot.getId(),
-            addNewBlockDevice("/dev/sda2", "myvirtual", 1).withDescription("adrian"));
-      imagesToDeregister.add(ebsBackedImageId);
-      final Image ebsBackedImage = getOnlyElement(client.describeImagesInRegion(regionId, imageIds(ebsBackedImageId)));
-      assertEquals(ebsBackedImage.getName(), ebsBackedImageName);
-      assertEquals(ebsBackedImage.getImageType(), ImageType.MACHINE);
-      assertEquals(ebsBackedImage.getRootDeviceType(), RootDeviceType.EBS);
-      assertEquals(ebsBackedImage.getRootDeviceName(), "/dev/sda1");
-      assertEquals(ebsBackedImage.getDescription(), "adrian");
-      assertEquals(
-            ebsBackedImage.getEbsBlockDevices().entrySet(),
-            ImmutableMap.of("/dev/sda1", new Image.EbsBlockDevice(snapshot.getId(), snapshot.getVolumeSize(), true),
-                  "/dev/sda2", new Image.EbsBlockDevice(null, 1, false)).entrySet());
-
-      // List of images after - should be one larger than before
-      int after = client.describeImagesInRegion(regionId).size();
-      assertEquals(after, sizeBefore + 1);
-   }
-
-   // Fires up an instance, finds its root volume ID, takes a snapshot, then
-   // terminates the instance.
-   private Snapshot createSnapshot() throws RunNodesException {
-
-      String instanceId = null;
-      try {
-         RunningInstance instance = getOnlyElement(concat(ec2Client.getInstanceServices().runInstancesInRegion(
-               regionId, null, imageId, 1, 1)));
-         instanceId = instance.getId();
-         
-         assertTrue(runningTester.apply(instance), instanceId + "didn't achieve the state running!");
-
-         instance = getOnlyElement(concat(ec2Client.getInstanceServices().describeInstancesInRegion(regionId,
-               instanceId)));
-         BlockDevice device = instance.getEbsBlockDevices().get("/dev/sda1");
-         assertNotNull(device, "device: /dev/sda1 not present on: " + instance);
-         Snapshot snapshot = ec2Client.getElasticBlockStoreServices().createSnapshotInRegion(regionId,
-               device.getVolumeId());
-         snapshotsToDelete.add(snapshot.getId());
-         return snapshot;
-      } finally {
-         if (instanceId != null)
-            ec2Client.getInstanceServices().terminateInstancesInRegion(regionId, instanceId);
-      }
-   }
-
-   @Test(dependsOnMethods = "testCreateAndListEBSBackedImage")
-   public void testGetLaunchPermissionForImage() {
-      client.getLaunchPermissionForImageInRegion(regionId, ebsBackedImageId);
-   }
-
-   @Override
-   @AfterClass(groups = { "integration", "live" })
-   protected void tearDownContext() {
-      for (String imageId : imagesToDeregister)
-         client.deregisterImageInRegion(regionId, imageId);
-      for (String snapshotId : snapshotsToDelete)
-         ec2Client.getElasticBlockStoreServices().deleteSnapshotInRegion(regionId, snapshotId);
-      super.tearDownContext();
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionAsyncClientTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionAsyncClientTest.java
deleted file mode 100644
index 13293fe..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionAsyncClientTest.java
+++ /dev/null
@@ -1,116 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.ec2.options.DescribeAvailabilityZonesOptions.Builder.availabilityZones;
-import static org.jclouds.ec2.options.DescribeRegionsOptions.Builder.regions;
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.aws.domain.Region;
-import org.jclouds.ec2.options.DescribeAvailabilityZonesOptions;
-import org.jclouds.ec2.options.DescribeRegionsOptions;
-import org.jclouds.ec2.xml.DescribeAvailabilityZonesResponseHandler;
-import org.jclouds.ec2.xml.DescribeRegionsResponseHandler;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code AvailabilityZoneAndRegionAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "AvailabilityZoneAndRegionAsyncClientTest")
-public class AvailabilityZoneAndRegionAsyncClientTest extends
-      BaseEC2AsyncClientTest<AvailabilityZoneAndRegionAsyncClient> {
-
-   public void testDescribeAvailabilityZones() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AvailabilityZoneAndRegionAsyncClient.class, "describeAvailabilityZonesInRegion",
-            String.class, DescribeAvailabilityZonesOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of(Region.US_WEST_1));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-west-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-west-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeAvailabilityZones",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeAvailabilityZonesResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeAvailabilityZonesOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AvailabilityZoneAndRegionAsyncClient.class, "describeAvailabilityZonesInRegion",
-            String.class, DescribeAvailabilityZonesOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("us-east-1", availabilityZones("us-east-1a", "us-east-1b")));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-            "Action=DescribeAvailabilityZones&ZoneName.1=us-east-1a&ZoneName.2=us-east-1b",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeAvailabilityZonesResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeRegions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AvailabilityZoneAndRegionAsyncClient.class, "describeRegions",
-            DescribeRegionsOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.of());
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeRegions", "application/x-www-form-urlencoded",
-            false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeRegionsResponseHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeRegionsOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AvailabilityZoneAndRegionAsyncClient.class, "describeRegions",
-            DescribeRegionsOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of(regions(Region.US_EAST_1, Region.US_WEST_1)));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-            "Action=DescribeRegions&RegionName.1=us-east-1&RegionName.2=us-west-1",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeRegionsResponseHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionClientLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionClientLiveTest.java
deleted file mode 100644
index 4caec98..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/AvailabilityZoneAndRegionClientLiveTest.java
+++ /dev/null
@@ -1,92 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.ec2.options.DescribeAvailabilityZonesOptions.Builder.availabilityZones;
-import static org.jclouds.ec2.options.DescribeRegionsOptions.Builder.regions;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
-import java.net.URI;
-import java.util.Iterator;
-import java.util.Map.Entry;
-import java.util.Set;
-import java.util.SortedMap;
-
-import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.jclouds.ec2.EC2ApiMetadata;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.domain.AvailabilityZoneInfo;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.Maps;
-
-/**
- * Tests behavior of {@code AvailabilityZoneAndRegionClient}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true, testName = "AvailabilityZoneAndRegionClientLiveTest")
-public class AvailabilityZoneAndRegionClientLiveTest extends BaseComputeServiceContextLiveTest {
-   public AvailabilityZoneAndRegionClientLiveTest() {
-      provider = "ec2";
-   }
-   
-   private EC2Client ec2Client;
-   private AvailabilityZoneAndRegionClient client;
-
-   @Override
-   @BeforeClass(groups = { "integration", "live" })
-   public void setupContext() {
-      super.setupContext();
-      ec2Client = view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi();
-      client = ec2Client.getAvailabilityZoneAndRegionServices();
-   }
-
-   public void testDescribeAvailabilityZones() {
-      for (String region : ec2Client.getConfiguredRegions()) {
-         Set<AvailabilityZoneInfo> allResults = client.describeAvailabilityZonesInRegion(region);
-         assertNotNull(allResults);
-         assert allResults.size() >= 1 : allResults.size();
-         Iterator<AvailabilityZoneInfo> iterator = allResults.iterator();
-         String id1 = iterator.next().getZone();
-         Set<AvailabilityZoneInfo> oneResult = client.describeAvailabilityZonesInRegion(region,
-               availabilityZones(id1));
-         assertNotNull(oneResult);
-         assertEquals(oneResult.size(), 1);
-         iterator = allResults.iterator();
-         assertEquals(iterator.next().getZone(), id1);
-      }
-   }
-
-   public void testDescribeRegions() {
-      SortedMap<String, URI> allResults = Maps.newTreeMap();
-      allResults.putAll(client.describeRegions());
-      assertNotNull(allResults);
-      assert allResults.size() >= 1 : allResults.size();
-      Iterator<Entry<String, URI>> iterator = allResults.entrySet().iterator();
-      String r1 = iterator.next().getKey();
-      SortedMap<String, URI> oneResult = Maps.newTreeMap();
-      oneResult.putAll(client.describeRegions(regions(r1)));
-      assertNotNull(oneResult);
-      assertEquals(oneResult.size(), 1);
-      iterator = oneResult.entrySet().iterator();
-      assertEquals(iterator.next().getKey(), r1);
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/BaseEC2AsyncClientTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/BaseEC2AsyncClientTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/BaseEC2AsyncClientTest.java
deleted file mode 100644
index af7b3df..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/BaseEC2AsyncClientTest.java
+++ /dev/null
@@ -1,142 +0,0 @@
-/*
- * 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.services;
-
-import static com.google.common.collect.Maps.transformValues;
-import static org.testng.Assert.assertEquals;
-
-import java.io.IOException;
-import java.net.URI;
-import java.util.Map;
-import java.util.Set;
-
-import javax.inject.Singleton;
-
-import org.jclouds.apis.ApiMetadata;
-import org.jclouds.aws.domain.Region;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.compute.domain.Image;
-import org.jclouds.date.DateService;
-import org.jclouds.ec2.EC2ApiMetadata;
-import org.jclouds.ec2.EC2AsyncClient;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.compute.domain.RegionAndName;
-import org.jclouds.ec2.config.EC2RestClientModule;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.location.config.LocationModule;
-import org.jclouds.location.suppliers.RegionIdToURISupplier;
-import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
-import org.jclouds.rest.ConfiguresRestClient;
-import org.jclouds.rest.internal.BaseAsyncClientTest;
-import org.jclouds.util.Suppliers2;
-import org.testng.annotations.BeforeTest;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Supplier;
-import com.google.common.cache.CacheBuilder;
-import com.google.common.cache.CacheLoader;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableSet;
-import com.google.inject.Module;
-import com.google.inject.Provides;
-
-/**
- * @author Adrian Cole
- */
-@Test(groups = "unit")
-public abstract class BaseEC2AsyncClientTest<T> extends BaseAsyncClientTest<T> {
-   @ConfiguresRestClient
-   protected static class StubEC2RestClientModule extends EC2RestClientModule<EC2Client, EC2AsyncClient> {
-
-      @Provides
-      @Singleton
-      LoadingCache<RegionAndName, Image> provide(){
-         return CacheBuilder.newBuilder().build(new CacheLoader<RegionAndName, Image>() {
-
-            @Override
-            public Image load(RegionAndName key) throws Exception {
-               return null;
-            }
-
-         });
-      }
-      
-      @Override
-      protected String provideTimeStamp(DateService dateService) {
-         return "2009-11-08T15:54:08.897Z";
-      }
-
-      static class Zones implements javax.inject.Provider<Map<String, String>> {
-         @Override
-         public Map<String, String> get() {
-            return ImmutableMap.<String, String> of("us-east-1a", "us-east-1");
-         }
-      }
-
-      @Override
-      protected void installLocations() {
-         install(new LocationModule());
-         bind(RegionIdToURISupplier.class).toInstance(new RegionIdToURISupplier() {
-
-            @Override
-            public Map<String, Supplier<URI>> get() {
-               return transformValues(ImmutableMap.<String, URI> of(Region.EU_WEST_1, URI
-                        .create("https://ec2.eu-west-1.amazonaws.com"), Region.US_EAST_1, URI
-                        .create("https://ec2.us-east-1.amazonaws.com"), Region.US_WEST_1, URI
-                        .create("https://ec2.us-west-1.amazonaws.com")), Suppliers2.<URI> ofInstanceFunction());
-            }
-
-         });
-         bind(RegionIdToZoneIdsSupplier.class).toInstance(new RegionIdToZoneIdsSupplier() {
-
-            @Override
-            public Map<String, Supplier<Set<String>>> get() {
-               return transformValues(ImmutableMap.<String, Set<String>> of("us-east-1", ImmutableSet.of(
-                        "us-east-1a", "us-east-1b", "us-east-1c", "us-east-1b")), Suppliers2
-                        .<Set<String>> ofInstanceFunction());
-            }
-
-         });
-      }
-   }
-
-   protected FormSigner filter;
-
-   @Override
-   protected void checkFilters(HttpRequest request) {
-      assertEquals(request.getFilters().size(), 1);
-      assertEquals(request.getFilters().get(0).getClass(), FormSigner.class);
-   }
-
-   @Override
-   @BeforeTest
-   protected void setupFactory() throws IOException {
-      super.setupFactory();
-      this.filter = injector.getInstance(FormSigner.class);
-   }
-
-   @Override
-   protected Module createModule() {
-      return new StubEC2RestClientModule();
-   }
-   
-   @Override
-   protected ApiMetadata createApiMetadata() {
-      return new EC2ApiMetadata();
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/EC2ElasticBlockStoreClientExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/EC2ElasticBlockStoreClientExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/EC2ElasticBlockStoreClientExpectTest.java
deleted file mode 100644
index b0332c3..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/EC2ElasticBlockStoreClientExpectTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.services;
-
-import static org.testng.Assert.assertEquals;
-
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.domain.Volume;
-import org.jclouds.ec2.internal.BaseEC2ClientExpectTest;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMap.Builder;
-
-/**
- * @author Adrian Cole
- */
-@Test(groups = "unit", testName = "EC2ElasticBlockStoreClientExpectTest")
-public class EC2ElasticBlockStoreClientExpectTest extends BaseEC2ClientExpectTest<EC2Client> {
-   Volume creating = Volume.builder()
-                           .id("vol-2a21e543")
-                           .status(Volume.Status.CREATING)
-                           .availabilityZone("us-east-1a")
-                           .region("us-east-1")
-                           .id("vol-2a21e543")
-                           .size(1)
-                           .createTime(dateService.iso8601DateParse("2009-12-28T05:42:53.000Z"))
-                           .build();
-   
-   public void testCreateVolumeInAvailabilityZone() {
-      Builder<HttpRequest, HttpResponse> builder = ImmutableMap.<HttpRequest, HttpResponse>builder();
-      builder.put(describeRegionsRequest, describeRegionsResponse);
-      builder.putAll(describeAvailabilityZonesRequestResponse);
-      builder.put(
-            HttpRequest.builder()
-                       .method("POST")
-                       .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                       .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                       .payload(payloadFromStringWithContentType("Action=CreateVolume&AvailabilityZone=us-east-1a&Signature=FB5hTZHKSAuiygoafIdJh1EnfTu0ogC2VfRQOar85mg%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Size=4&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-06-15&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
-            HttpResponse.builder()
-                        .statusCode(200)
-                        .payload(payloadFromResource("/created_volume.xml")).build());
-      
-      ElasticBlockStoreClient client = requestsSendResponses(builder.build()).getElasticBlockStoreServices();
-
-      assertEquals(client.createVolumeInAvailabilityZone("us-east-1a", 4), creating);
-   }
-   
-   public void testCreateVolumeFromSnapshotInAvailabilityZoneEuSetsCorrectEndpoint() {
-      String region = "eu-west-1";
-      
-      Builder<HttpRequest, HttpResponse> builder = ImmutableMap.<HttpRequest, HttpResponse>builder();
-      builder.put(describeRegionsRequest, describeRegionsResponse);
-      builder.putAll(describeAvailabilityZonesRequestResponse);
-      builder.put(
-            formSigner.filter(HttpRequest.builder()
-                                         .method("POST")
-                                         .endpoint("https://ec2." + region + ".amazonaws.com/")
-                                         .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                                         .addFormParam("Action", "CreateVolume")
-                                         .addFormParam("AvailabilityZone", "eu-west-1a")
-                                         .addFormParam("Size", "1")
-                                         .addFormParam("SnapshotId", "snap-8b7ffbdd").build()),
-            HttpResponse.builder()
-                        .statusCode(200)
-                        .payload(payloadFromResource("/created_volume.xml")).build());
-      
-      ElasticBlockStoreClient client = requestsSendResponses(builder.build()).getElasticBlockStoreServices();
-
-      assertEquals(client.createVolumeFromSnapshotInAvailabilityZone(region + "a", 1, "snap-8b7ffbdd"), creating.toBuilder().region(region).build());
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticBlockStoreAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticBlockStoreAsyncClientTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticBlockStoreAsyncClientTest.java
deleted file mode 100644
index 5858889..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticBlockStoreAsyncClientTest.java
+++ /dev/null
@@ -1,401 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.ec2.options.DescribeSnapshotsOptions.Builder.ownedBy;
-import static org.jclouds.ec2.options.DetachVolumeOptions.Builder.fromInstance;
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.ec2.EC2Fallbacks.VoidOnVolumeAvailable;
-import org.jclouds.ec2.options.CreateSnapshotOptions;
-import org.jclouds.ec2.options.DescribeSnapshotsOptions;
-import org.jclouds.ec2.options.DetachVolumeOptions;
-import org.jclouds.ec2.xml.AttachmentHandler;
-import org.jclouds.ec2.xml.DescribeSnapshotsResponseHandler;
-import org.jclouds.ec2.xml.DescribeVolumesResponseHandler;
-import org.jclouds.ec2.xml.PermissionHandler;
-import org.jclouds.ec2.xml.SnapshotHandler;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.http.functions.ReleasePayloadAndReturn;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code ElasticBlockStoreAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "ElasticBlockStoreAsyncClientTest")
-public class ElasticBlockStoreAsyncClientTest extends BaseEC2AsyncClientTest<ElasticBlockStoreAsyncClient> {
-
-   public void testDeleteVolume() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticBlockStoreAsyncClient.class, "deleteVolumeInRegion", String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "id"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DeleteVolume&VolumeId=id",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest describeVolumes = HttpRequest.builder().method("POST")
-                                            .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                            .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                            .addFormParam("Action", "DescribeVolumes")
-                                            .addFormParam("Signature", "hNuorhZQS%2BThX5dWXOvBkvnmTpgp6SvwHmgzjjfKyG8%3D")
-                                            .addFormParam("SignatureMethod", "HmacSHA256")
-                                            .addFormParam("SignatureVersion", "2")
-                                            .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                            .addFormParam("Version", "2010-06-15")
-                                            .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testDescribeVolumes() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticBlockStoreAsyncClient.class, "describeVolumesInRegion", String.class,
-            String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, describeVolumes.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-      
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeVolumesResponseHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeVolumesArgs() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticBlockStoreAsyncClient.class, "describeVolumesInRegion", String.class,
-               String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeVolumes&VolumeId.1=1&VolumeId.2=2",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeVolumesResponseHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest attachVolume = HttpRequest.builder().method("POST")
-                                         .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                         .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                         .addFormParam("Action", "AttachVolume")
-                                         .addFormParam("Device", "/device")
-                                         .addFormParam("InstanceId", "instanceId")
-                                         .addFormParam("Signature", "LaOppR61eWpdNgMYJ3ccfo9vzbmUyJf9Ars%2Bbcu4OGI%3D")
-                                         .addFormParam("SignatureMethod", "HmacSHA256")
-                                         .addFormParam("SignatureVersion", "2")
-                                         .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                         .addFormParam("Version", "2010-06-15")
-                                         .addFormParam("VolumeId", "id")
-                                         .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testAttachVolume() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticBlockStoreAsyncClient.class, "attachVolumeInRegion", String.class, String.class,
-               String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "id", "instanceId", "/device"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, attachVolume.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, AttachmentHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest detachVolume = HttpRequest.builder().method("POST")
-                                         .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                         .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                         .addFormParam("Action", "DetachVolume")
-                                         .addFormParam("Force", "false")
-                                         .addFormParam("Signature", "4c6EmHwCYbe%2BifuUV0PNXpKfReoZvJXyme37mKtnLk8%3D")
-                                         .addFormParam("SignatureMethod", "HmacSHA256")
-                                         .addFormParam("SignatureVersion", "2")
-                                         .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                         .addFormParam("Version", "2010-06-15")
-                                         .addFormParam("VolumeId", "id")
-                                         .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testDetachVolume() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticBlockStoreAsyncClient.class, "detachVolumeInRegion", String.class, String.class,
-               boolean.class, DetachVolumeOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "id", false));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, detachVolume.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-      
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, VoidOnVolumeAvailable.class);
-
-      checkFilters(request);
-   }
-
-   HttpRequest detachVolumeOptions = HttpRequest.builder().method("POST")
-                                                .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                .addFormParam("Action", "DetachVolume")
-                                                .addFormParam("Device", "/device")
-                                                .addFormParam("Force", "true")
-                                                .addFormParam("InstanceId", "instanceId")
-                                                .addFormParam("Signature", "GrUGXc6H5W%2BNF8zcXU8gSRbt1ELt%2BTcCDEvbY1a88NE%3D")
-                                                .addFormParam("SignatureMethod", "HmacSHA256")
-                                                .addFormParam("SignatureVersion", "2")
-                                                .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                .addFormParam("Version", "2010-06-15")
-                                                .addFormParam("VolumeId", "id")
-                                                .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testDetachVolumeOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticBlockStoreAsyncClient.class, "detachVolumeInRegion", String.class, String.class,
-               boolean.class, DetachVolumeOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "id", true, fromInstance("instanceId").fromDevice(
-               "/device")));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, detachVolumeOptions.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-      
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, VoidOnVolumeAvailable.class);
-
-      checkFilters(request);
-   }
-
-   public void testCreateSnapshot() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticBlockStoreAsyncClient.class, "createSnapshotInRegion", String.class,
-               String.class, CreateSnapshotOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "volumeId"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=CreateSnapshot&VolumeId=volumeId",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, SnapshotHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testCreateSnapshotOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticBlockStoreAsyncClient.class, "createSnapshotInRegion", String.class,
-               String.class, CreateSnapshotOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "volumeId", CreateSnapshotOptions.Builder
-               .withDescription("description")));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-               "Action=CreateSnapshot&VolumeId=volumeId&Description=description",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, SnapshotHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeSnapshots() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticBlockStoreAsyncClient.class, "describeSnapshotsInRegion", String.class,
-               DescribeSnapshotsOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeSnapshots", "application/x-www-form-urlencoded",
-               false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeSnapshotsResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeSnapshotsArgs() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticBlockStoreAsyncClient.class, "describeSnapshotsInRegion", String.class,
-               DescribeSnapshotsOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ownedBy("o1", "o2").restorableBy("r1", "r2")
-               .snapshotIds("s1", "s2")));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(
-               request,
-               "Action=DescribeSnapshots&Owner.1=o1&Owner.2=o2&RestorableBy.1=r1&RestorableBy.2=r2&SnapshotId.1=s1&SnapshotId.2=s2",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeSnapshotsResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testGetCreateVolumePermissionForSnapshot() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticBlockStoreAsyncClient.class, "getCreateVolumePermissionForSnapshotInRegion",
-               String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "snapshotId"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(
-               request,
-               "Action=DescribeSnapshotAttribute&Attribute=createVolumePermission&SnapshotId=snapshotId",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, PermissionHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest addCreateVolumePermissionsToSnapshot = HttpRequest.builder().method("POST")
-                                                                 .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                                 .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                                 .addFormParam("Action", "ModifySnapshotAttribute")
-                                                                 .addFormParam("Attribute", "createVolumePermission")
-                                                                 .addFormParam("OperationType", "add")
-                                                                 .addFormParam("Signature", "AizV1N1rCCXi%2BbzXX/Vz7shFq9yAJAwcmAGyRQMH%2Bjs%3D")
-                                                                 .addFormParam("SignatureMethod", "HmacSHA256")
-                                                                 .addFormParam("SignatureVersion", "2")
-                                                                 .addFormParam("SnapshotId", "snapshotId")
-                                                                 .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                                 .addFormParam("UserGroup.1", "all")
-                                                                 .addFormParam("UserId.1", "bob")
-                                                                 .addFormParam("UserId.2", "sue")
-                                                                 .addFormParam("Version", "2010-06-15")
-                                                                 .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testAddCreateVolumePermissionsToSnapshot() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticBlockStoreAsyncClient.class, "addCreateVolumePermissionsToSnapshotInRegion",
-               String.class, Iterable.class, Iterable.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("bob", "sue"), ImmutableList
-               .of("all"), "snapshotId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, addCreateVolumePermissionsToSnapshot.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest removeCreateVolumePermissionsFromSnapshot = HttpRequest.builder().method("POST")
-                                                                      .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                                      .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                                      .addFormParam("Action", "ModifySnapshotAttribute")
-                                                                      .addFormParam("Attribute", "createVolumePermission")
-                                                                      .addFormParam("OperationType", "remove")
-                                                                      .addFormParam("Signature", "Lmlt2daM%2BJ4kIoU9HmCempwVGZP1fC6V%2Br9o8MQjYy8%3D")
-                                                                      .addFormParam("SignatureMethod", "HmacSHA256")
-                                                                      .addFormParam("SignatureVersion", "2")
-                                                                      .addFormParam("SnapshotId", "snapshotId")
-                                                                      .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                                      .addFormParam("UserGroup.1", "all")
-                                                                      .addFormParam("UserId.1", "bob")
-                                                                      .addFormParam("UserId.2", "sue")
-                                                                      .addFormParam("Version", "2010-06-15")
-                                                                      .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testRemoveCreateVolumePermissionsFromSnapshot() throws SecurityException, NoSuchMethodException,
-            IOException {
-      Invokable<?, ?> method = method(ElasticBlockStoreAsyncClient.class, "removeCreateVolumePermissionsFromSnapshotInRegion",
-               String.class, Iterable.class, Iterable.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("bob", "sue"), ImmutableList
-               .of("all"), "snapshotId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, removeCreateVolumePermissionsFromSnapshot.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testResetCreateVolumePermissionsOnSnapshot() throws SecurityException, NoSuchMethodException,
-            IOException {
-      Invokable<?, ?> method = method(ElasticBlockStoreAsyncClient.class, "resetCreateVolumePermissionsOnSnapshotInRegion",
-               String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "snapshotId"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(
-               request,
-               "Action=ResetSnapshotAttribute&Attribute=createVolumePermission&SnapshotId=snapshotId",
-               "application/x-www-form-urlencoded", false);
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticBlockStoreClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticBlockStoreClientLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticBlockStoreClientLiveTest.java
deleted file mode 100644
index 7faeefb..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticBlockStoreClientLiveTest.java
+++ /dev/null
@@ -1,223 +0,0 @@
-/*
- * 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.services;
-import static com.google.common.base.Preconditions.checkNotNull;
-import static java.util.concurrent.TimeUnit.SECONDS;
-import static org.jclouds.ec2.options.DescribeSnapshotsOptions.Builder.snapshotIds;
-import static org.jclouds.util.Predicates2.retry;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
-import java.util.Set;
-import java.util.SortedSet;
-
-import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.jclouds.ec2.EC2ApiMetadata;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.domain.AvailabilityZoneInfo;
-import org.jclouds.ec2.domain.Snapshot;
-import org.jclouds.ec2.domain.Volume;
-import org.jclouds.ec2.predicates.SnapshotCompleted;
-import org.jclouds.ec2.predicates.VolumeAvailable;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Predicate;
-import com.google.common.base.Strings;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.Sets;
-
-/**
- * Tests behavior of {@code ElasticBlockStoreClient}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true, testName = "ElasticBlockStoreClientLiveTest")
-public class ElasticBlockStoreClientLiveTest extends BaseComputeServiceContextLiveTest {
-   public ElasticBlockStoreClientLiveTest() {
-      provider = "ec2";
-   }
-
-   private EC2Client ec2Client;
-   private ElasticBlockStoreClient client;
-
-   private String defaultRegion;
-   private String defaultZone;
-
-   private String volumeId;
-   private Snapshot snapshot;
-
-   @Override
-   @BeforeClass(groups = { "integration", "live" })
-   public void setupContext() {
-      super.setupContext();
-      ec2Client = view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi();
-      client = ec2Client.getElasticBlockStoreServices();
-      AvailabilityZoneInfo info = Iterables.get(ec2Client.getAvailabilityZoneAndRegionServices()
-            .describeAvailabilityZonesInRegion(defaultRegion), 0);
-      defaultRegion = checkNotNull(Strings.emptyToNull(info.getRegion()), "region of " + info);
-      defaultZone = checkNotNull(Strings.emptyToNull(info.getZone()), "zone of " + info);
-   }
-
-   @Test
-   void testDescribeVolumes() {
-      for (String region : ec2Client.getConfiguredRegions()) {
-         SortedSet<Volume> allResults = Sets.newTreeSet(client.describeVolumesInRegion(region));
-         assertNotNull(allResults);
-         if (allResults.size() >= 1) {
-            Volume volume = allResults.last();
-            SortedSet<Volume> result = Sets.newTreeSet(client.describeVolumesInRegion(region, volume.getId()));
-            assertNotNull(result);
-            Volume compare = result.last();
-            assertEquals(compare, volume);
-         }
-      }
-   }
-
-   @Test
-   void testCreateVolumeInAvailabilityZone() {
-      Volume expected = client.createVolumeInAvailabilityZone(defaultZone, 1);
-      assertNotNull(expected);
-      assertEquals(expected.getAvailabilityZone(), defaultZone);
-
-      this.volumeId = expected.getId();
-
-      Set<Volume> result = Sets.newLinkedHashSet(client.describeVolumesInRegion(defaultRegion, expected.getId()));
-      assertNotNull(result);
-      assertEquals(result.size(), 1);
-      Volume volume = result.iterator().next();
-      assertEquals(volume.getId(), expected.getId());
-   }
-
-   @Test(dependsOnMethods = "testCreateVolumeInAvailabilityZone")
-   void testCreateSnapshotInRegion() {
-      Snapshot snapshot = client.createSnapshotInRegion(defaultRegion, volumeId);
-      Predicate<Snapshot> snapshotted = retry(new SnapshotCompleted(client), 600, 10, SECONDS);
-      assert snapshotted.apply(snapshot);
-
-      Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegion(snapshot.getRegion(),
-            snapshotIds(snapshot.getId())));
-
-      assertEquals(result.getProgress(), 100);
-      this.snapshot = result;
-   }
-
-   @Test(dependsOnMethods = "testCreateSnapshotInRegion")
-   void testCreateVolumeFromSnapshotInAvailabilityZone() {
-      Volume volume = client.createVolumeFromSnapshotInAvailabilityZone(defaultZone, snapshot.getId());
-      assertNotNull(volume);
-
-      Predicate<Volume> availabile = retry(new VolumeAvailable(client), 600, 10, SECONDS);
-      assert availabile.apply(volume);
-
-      Volume result = Iterables.getOnlyElement(client.describeVolumesInRegion(snapshot.getRegion(), volume.getId()));
-      assertEquals(volume.getId(), result.getId());
-      assertEquals(volume.getSnapshotId(), snapshot.getId());
-      assertEquals(volume.getAvailabilityZone(), defaultZone);
-      assertEquals(result.getStatus(), Volume.Status.AVAILABLE);
-
-      client.deleteVolumeInRegion(snapshot.getRegion(), volume.getId());
-   }
-
-   @Test(dependsOnMethods = "testCreateSnapshotInRegion")
-   void testCreateVolumeFromSnapshotInAvailabilityZoneWithSize() {
-      Volume volume = client.createVolumeFromSnapshotInAvailabilityZone(defaultZone, 2, snapshot.getId());
-      assertNotNull(volume);
-
-      Predicate<Volume> availabile = retry(new VolumeAvailable(client), 600, 10, SECONDS);
-      assert availabile.apply(volume);
-
-      Volume result = Iterables.getOnlyElement(client.describeVolumesInRegion(snapshot.getRegion(), volume.getId()));
-      assertEquals(volume.getId(), result.getId());
-      assertEquals(volume.getSnapshotId(), snapshot.getId());
-      assertEquals(volume.getAvailabilityZone(), defaultZone);
-      assertEquals(volume.getSize(), 2);
-      assertEquals(result.getStatus(), Volume.Status.AVAILABLE);
-
-      client.deleteVolumeInRegion(snapshot.getRegion(), volume.getId());
-   }
-
-   @Test
-   void testAttachVolumeInRegion() {
-      // TODO: need an instance
-   }
-
-   @Test
-   void testDetachVolumeInRegion() {
-      // TODO: need an instance
-   }
-
-   @Test
-   void testDescribeSnapshots() {
-      for (String region : ec2Client.getConfiguredRegions()) {
-         SortedSet<Snapshot> allResults = Sets.newTreeSet(client.describeSnapshotsInRegion(region));
-         assertNotNull(allResults);
-         if (allResults.size() >= 1) {
-            Snapshot snapshot = allResults.last();
-            Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegion(region,
-                  snapshotIds(snapshot.getId())));
-            assertNotNull(result);
-            assertEquals(result, snapshot);
-         }
-      }
-   }
-
-   @Test(enabled = false)
-   public void testAddCreateVolumePermissionsToSnapshot() {
-      // TODO client.addCreateVolumePermissionsToSnapshotInRegion(defaultRegion,
-      // userIds,
-      // userGroups,
-      // snapshotId);
-   }
-
-   @Test(enabled = false)
-   public void testRemoveCreateVolumePermissionsFromSnapshot() {
-      // TODO
-      // client.removeCreateVolumePermissionsFromSnapshotInRegion(defaultRegion,
-      // userIds,
-      // userGroups,
-      // snapshotId);
-   }
-
-   @Test(enabled = false)
-   public void testResetCreateVolumePermissionsOnSnapshot() {
-      // TODO
-      // client.resetCreateVolumePermissionsOnSnapshotInRegion(defaultRegion,
-      // snapshotId);
-   }
-
-   @Test(dependsOnMethods = "testCreateSnapshotInRegion")
-   public void testGetCreateVolumePermissionForSnapshot() {
-      client.getCreateVolumePermissionForSnapshotInRegion(snapshot.getRegion(), snapshot.getId());
-   }
-
-   @Test(dependsOnMethods = "testCreateSnapshotInRegion")
-   void testDeleteVolumeInRegion() {
-      client.deleteVolumeInRegion(defaultRegion, volumeId);
-      Set<Volume> result = Sets.newLinkedHashSet(client.describeVolumesInRegion(defaultRegion, volumeId));
-      assertEquals(result.size(), 1);
-      Volume volume = result.iterator().next();
-      assertEquals(volume.getStatus(), Volume.Status.DELETING);
-   }
-
-   @Test(dependsOnMethods = "testGetCreateVolumePermissionForSnapshot")
-   void testDeleteSnapshotInRegion() {
-      client.deleteSnapshotInRegion(snapshot.getRegion(), snapshot.getId());
-      assert client.describeSnapshotsInRegion(snapshot.getRegion(), snapshotIds(snapshot.getId())).size() == 0;
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticIPAddressAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticIPAddressAsyncClientTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticIPAddressAsyncClientTest.java
deleted file mode 100644
index 4ac89c2..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticIPAddressAsyncClientTest.java
+++ /dev/null
@@ -1,140 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.ec2.xml.AllocateAddressResponseHandler;
-import org.jclouds.ec2.xml.DescribeAddressesResponseHandler;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.http.functions.ReleasePayloadAndReturn;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.Lists;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code ElasticIPAddressAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "ElasticIPAddressAsyncClientTest")
-public class ElasticIPAddressAsyncClientTest extends BaseEC2AsyncClientTest<ElasticIPAddressAsyncClient> {
-
-   public void testDisassociateAddress() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticIPAddressAsyncClient.class, "disassociateAddressInRegion", String.class,
-            String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "127.0.0.1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DisassociateAddress&PublicIp=127.0.0.1",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest associateAddress = HttpRequest.builder().method("POST")
-                                             .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                             .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                             .addFormParam("Action", "AssociateAddress")
-                                             .addFormParam("InstanceId", "me")
-                                             .addFormParam("PublicIp", "127.0.0.1")
-                                             .addFormParam("Signature", "YmPyvEljuFw0INSUbQx5xAhC/1GQ4a1Ht6TdoXeMc9Y%3D")
-                                             .addFormParam("SignatureMethod", "HmacSHA256")
-                                             .addFormParam("SignatureVersion", "2")
-                                             .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                             .addFormParam("Version", "2010-06-15")
-                                             .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testAssociateAddress() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticIPAddressAsyncClient.class, "associateAddressInRegion", String.class,
-            String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "127.0.0.1", "me"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, associateAddress.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testReleaseAddress() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticIPAddressAsyncClient.class, "releaseAddressInRegion", String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "127.0.0.1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=ReleaseAddress&PublicIp=127.0.0.1",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeAddresses() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticIPAddressAsyncClient.class, "describeAddressesInRegion", String.class,
-            String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "127.0.0.1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeAddresses&PublicIp.1=127.0.0.1",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeAddressesResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testAllocateAddress() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(ElasticIPAddressAsyncClient.class, "allocateAddressInRegion", String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=AllocateAddress", "application/x-www-form-urlencoded",
-            false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, AllocateAddressResponseHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticIPAddressClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticIPAddressClientLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticIPAddressClientLiveTest.java
deleted file mode 100644
index b225e05..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/ElasticIPAddressClientLiveTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.services;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
-import java.util.SortedSet;
-
-import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.jclouds.ec2.EC2ApiMetadata;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.domain.PublicIpInstanceIdPair;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.Sets;
-
-/**
- * Tests behavior of {@code ElasticIPAddressClient}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true, testName = "ElasticIPAddressClientLiveTest")
-public class ElasticIPAddressClientLiveTest extends BaseComputeServiceContextLiveTest {
-   public ElasticIPAddressClientLiveTest() {
-      provider = "ec2";
-   }
-
-   private EC2Client ec2Client;
-   private ElasticIPAddressClient client;
-
-   @Override
-   @BeforeClass(groups = { "integration", "live" })
-   public void setupContext() {
-      super.setupContext();
-      ec2Client = view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi();
-      client = ec2Client.getElasticIPAddressServices();
-   }
-
-   @Test
-   void testDescribeAddresses() {
-      for (String region : ec2Client.getConfiguredRegions()) {
-         SortedSet<PublicIpInstanceIdPair> allResults = Sets.newTreeSet(client.describeAddressesInRegion(region));
-         assertNotNull(allResults);
-         if (allResults.size() >= 1) {
-            PublicIpInstanceIdPair pair = allResults.last();
-            SortedSet<PublicIpInstanceIdPair> result = Sets.newTreeSet(client.describeAddressesInRegion(region, pair
-                     .getPublicIp()));
-            assertNotNull(result);
-            PublicIpInstanceIdPair compare = result.last();
-            assertEquals(compare, pair);
-         }
-      }
-   }
-
-}


[15/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/CloudApplicationArchitecturesEC2ApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/CloudApplicationArchitecturesEC2ApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/CloudApplicationArchitecturesEC2ApiLiveTest.java
new file mode 100644
index 0000000..2a999da
--- /dev/null
+++ b/apis/ec2/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-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/CloudApplicationArchitecturesEC2ClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/CloudApplicationArchitecturesEC2ClientLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/CloudApplicationArchitecturesEC2ClientLiveTest.java
deleted file mode 100644
index 1fc8de9..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/CloudApplicationArchitecturesEC2ClientLiveTest.java
+++ /dev/null
@@ -1,427 +0,0 @@
-/*
- * 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 = "CloudApplicationArchitecturesEC2ClientLiveTest")
-public class CloudApplicationArchitecturesEC2ClientLiveTest extends BaseComputeServiceContextLiveTest {
-   public CloudApplicationArchitecturesEC2ClientLiveTest() {
-      provider = "ec2";
-   }
-
-   private EC2Client 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(EC2Client.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.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName);
-      } catch (Exception e) {
-      }
-
-      client.getSecurityGroupServices().createSecurityGroupInRegion(null, securityGroupName, securityGroupName);
-      for (int port : new int[] { 80, 443, 22 }) {
-         client.getSecurityGroupServices().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.getKeyPairServices().deleteKeyPairInRegion(null, keyName);
-      } catch (Exception e) {
-
-      }
-      client.getKeyPairServices().deleteKeyPairInRegion(null, keyName);
-
-      keyPair = client.getKeyPairServices().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.getInstanceServices().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.getInstanceServices().getUserDataForInstanceInRegion(null, instanceId));
-
-      assertEquals(null, client.getInstanceServices().getRootDeviceNameForInstanceInRegion(null, instanceId));
-
-      assert client.getInstanceServices().getRamdiskForInstanceInRegion(null, instanceId).startsWith("ari-");
-
-      assertEquals(false, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion(null, instanceId));
-
-      assert client.getInstanceServices().getKernelForInstanceInRegion(null, instanceId).startsWith("aki-");
-
-      assertEquals(InstanceType.M1_SMALL,
-            client.getInstanceServices().getInstanceTypeForInstanceInRegion(null, instanceId));
-
-      assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client.getInstanceServices()
-            .getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, instanceId));
-
-      assertEquals(ImmutableMap.<String, EbsBlockDevice> of(), client.getInstanceServices()
-            .getBlockDeviceMappingForInstanceInRegion(null, instanceId));
-   }
-
-   private void setApiTerminationDisabledForInstanceInRegion() {
-      client.getInstanceServices().setApiTerminationDisabledForInstanceInRegion(null, instanceId, true);
-      assertEquals(true, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion(null, instanceId));
-      client.getInstanceServices().setApiTerminationDisabledForInstanceInRegion(null, instanceId, false);
-      assertEquals(false, client.getInstanceServices().isApiTerminationDisabledForInstanceInRegion(null, instanceId));
-   }
-
-   private void tryToChangeStuff() {
-      setApiTerminationDisabledForInstanceInRegion();
-      setUserDataForInstanceInRegion();
-      setRamdiskForInstanceInRegion();
-      setKernelForInstanceInRegion();
-      setInstanceTypeForInstanceInRegion();
-      setInstanceInitiatedShutdownBehaviorForInstanceInRegion();
-      setBlockDeviceMappingForInstanceInRegion();
-   }
-
-   private void setUserDataForInstanceInRegion() {
-      try {
-         client.getInstanceServices().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.getInstanceServices().getRamdiskForInstanceInRegion(null, instanceId);
-         client.getInstanceServices().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.getInstanceServices().getKernelForInstanceInRegion(null, instanceId);
-         client.getInstanceServices().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.getInstanceServices().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.getInstanceServices().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.getInstanceServices().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.getInstanceServices().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.getElasticIPAddressServices().allocateAddressInRegion(null);
-      assertNotNull(address);
-
-      PublicIpInstanceIdPair compare = Iterables.getLast(client.getElasticIPAddressServices()
-            .describeAddressesInRegion(null, address));
-
-      assertEquals(compare.getPublicIp(), address);
-      assert compare.getInstanceId() == null;
-
-      client.getElasticIPAddressServices().associateAddressInRegion(null, address, instanceId);
-
-      compare = Iterables.getLast(client.getElasticIPAddressServices().describeAddressesInRegion(null, address));
-
-      assertEquals(compare.getPublicIp(), address);
-      assertEquals(compare.getInstanceId(), instanceId);
-
-      Reservation<? extends RunningInstance> reservation = Iterables.getOnlyElement(client.getInstanceServices()
-            .describeInstancesInRegion(null, instanceId));
-
-      assertNotNull(Iterables.getOnlyElement(reservation).getIpAddress());
-      assertNotEquals(address, Iterables.getOnlyElement(reservation).getIpAddress());
-
-      doCheckKey(address);
-
-      client.getElasticIPAddressServices().disassociateAddressInRegion(null, address);
-
-      compare = Iterables.getLast(client.getElasticIPAddressServices().describeAddressesInRegion(null, address));
-
-      assertEquals(compare.getPublicIp(), address);
-      assert compare.getInstanceId() == null;
-
-      reservation = Iterables.getOnlyElement(client.getInstanceServices().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.getInstanceServices()
-            .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.getElasticIPAddressServices().releaseAddressInRegion(null, address);
-      if (instanceId != null)
-         client.getInstanceServices().terminateInstancesInRegion(null, instanceId);
-      if (keyPair != null)
-         client.getKeyPairServices().deleteKeyPairInRegion(null, keyPair.getKeyName());
-      if (securityGroupName != null)
-         client.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName);
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ApiLiveTest.java
new file mode 100644
index 0000000..3cff3f2
--- /dev/null
+++ b/apis/ec2/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();
+         }
+      }
+   }
+
+}


[09/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceAsyncClientTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceAsyncClientTest.java
deleted file mode 100644
index 5e6da90..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceAsyncClientTest.java
+++ /dev/null
@@ -1,593 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-import java.util.Map;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.ec2.domain.BlockDevice;
-import org.jclouds.ec2.domain.InstanceType;
-import org.jclouds.ec2.domain.Volume.InstanceInitiatedShutdownBehavior;
-import org.jclouds.ec2.options.RunInstancesOptions;
-import org.jclouds.ec2.xml.BlockDeviceMappingHandler;
-import org.jclouds.ec2.xml.BooleanValueHandler;
-import org.jclouds.ec2.xml.DescribeInstancesResponseHandler;
-import org.jclouds.ec2.xml.GetConsoleOutputResponseHandler;
-import org.jclouds.ec2.xml.InstanceInitiatedShutdownBehaviorHandler;
-import org.jclouds.ec2.xml.InstanceStateChangeHandler;
-import org.jclouds.ec2.xml.InstanceTypeHandler;
-import org.jclouds.ec2.xml.RunInstancesResponseHandler;
-import org.jclouds.ec2.xml.StringValueHandler;
-import org.jclouds.ec2.xml.UnencodeStringValueHandler;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.http.functions.ReleasePayloadAndReturn;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.collect.Maps;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code InstanceAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "InstanceAsyncClientTest")
-public class InstanceAsyncClientTest extends BaseEC2AsyncClientTest<InstanceAsyncClient> {
-   public void testDescribeInstances() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "describeInstancesInRegion", String.class, String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeInstances", "application/x-www-form-urlencoded",
-               false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeInstancesResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeInstancesArgs() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "describeInstancesInRegion", String.class, String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeInstances&InstanceId.1=1&InstanceId.2=2",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeInstancesResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testTerminateInstances() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "terminateInstancesInRegion", String.class,
-               String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=TerminateInstances&InstanceId.1=1&InstanceId.2=2",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testRunInstances() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "runInstancesInRegion", String.class, String.class,
-               String.class, int.class, int.class, RunInstancesOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, null, "ami-voo", 1, 1));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      try {
-         assertPayloadEquals(request, "Action=RunInstances&ImageId=ami-voo&MinCount=1&MaxCount=1",
-                  "application/x-www-form-urlencoded", false);
-      } catch (AssertionError e) {
-         // mvn 3.0 osx 10.6.5 somehow sorts differently
-         assertPayloadEquals(request, "Action=RunInstances&ImageId=ami-voo&MaxCount=1&MinCount=1",
-                  "application/x-www-form-urlencoded", false);
-      }
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, RunInstancesResponseHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testRunInstancesOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "runInstancesInRegion", String.class, String.class,
-               String.class, int.class, int.class, RunInstancesOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, ImmutableList.<Object> of("eu-west-1", "eu-west-1a", "ami-voo",
-               1, 5, new RunInstancesOptions().withKernelId("kernelId").withSecurityGroups("group1", "group2")));
-
-      assertRequestLineEquals(request, "POST https://ec2.eu-west-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.eu-west-1.amazonaws.com\n");
-      try {
-         assertPayloadEquals(
-                  request,
-                  "Action=RunInstances&ImageId=ami-voo&MinCount=1&MaxCount=5&KernelId=kernelId&SecurityGroup.1=group1&SecurityGroup.2=group2&Placement.AvailabilityZone=eu-west-1a",
-                  "application/x-www-form-urlencoded", false);
-      } catch (AssertionError e) {
-         // mvn 3.0 osx 10.6.5 somehow sorts differently
-         assertPayloadEquals(
-                  request,
-                  "Action=RunInstances&ImageId=ami-voo&MaxCount=5&MinCount=1&KernelId=kernelId&SecurityGroup.1=group1&SecurityGroup.2=group2&Placement.AvailabilityZone=eu-west-1a",
-                  "application/x-www-form-urlencoded", false);
-      }
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, RunInstancesResponseHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testStopInstances() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "stopInstancesInRegion", String.class, boolean.class,
-               String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, true, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=StopInstances&Force=true&InstanceId.1=1&InstanceId.2=2",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testRebootInstances() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "rebootInstancesInRegion", String.class, String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=RebootInstances&InstanceId.1=1&InstanceId.2=2",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testStartInstances() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "startInstancesInRegion", String.class, String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=StartInstances&InstanceId.1=1&InstanceId.2=2",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetUserDataForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "getUserDataForInstanceInRegion", String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-               "Action=DescribeInstanceAttribute&Attribute=userData&InstanceId=1",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, UnencodeStringValueHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetRootDeviceNameForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "getRootDeviceNameForInstanceInRegion", String.class,
-               String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-               "Action=DescribeInstanceAttribute&Attribute=rootDeviceName&InstanceId=1",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, StringValueHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetRamdiskForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "getRamdiskForInstanceInRegion", String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-               "Action=DescribeInstanceAttribute&Attribute=ramdisk&InstanceId=1",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, StringValueHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetDisableApiTerminationForInstanceInRegion() throws SecurityException, NoSuchMethodException,
-            IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "isApiTerminationDisabledForInstanceInRegion", String.class,
-               String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-               "Action=DescribeInstanceAttribute&Attribute=disableApiTermination&InstanceId=1",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, BooleanValueHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetKernelForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "getKernelForInstanceInRegion", String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeInstanceAttribute&Attribute=kernel&InstanceId=1",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, StringValueHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetInstanceTypeForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "getInstanceTypeForInstanceInRegion", String.class,
-               String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-               "Action=DescribeInstanceAttribute&Attribute=instanceType&InstanceId=1",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, InstanceTypeHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetInstanceInitiatedShutdownBehaviorForInstanceInRegion() throws SecurityException,
-            NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "getInstanceInitiatedShutdownBehaviorForInstanceInRegion",
-               String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(
-               request,
-               "Action=DescribeInstanceAttribute&Attribute=instanceInitiatedShutdownBehavior&InstanceId=1",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, InstanceInitiatedShutdownBehaviorHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testGetBlockDeviceMappingForInstanceInRegion() throws SecurityException, NoSuchMethodException,
-            IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "getBlockDeviceMappingForInstanceInRegion", String.class,
-               String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-               "Action=DescribeInstanceAttribute&Attribute=blockDeviceMapping&InstanceId=1",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, BlockDeviceMappingHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest setUserDataForInstance = HttpRequest.builder().method("POST")
-                                                   .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                   .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                   .addFormParam("Action", "ModifyInstanceAttribute")
-                                                   .addFormParam("Attribute", "userData")
-                                                   .addFormParam("InstanceId", "1")
-                                                   .addFormParam("Signature", "LfUmzLM5DsACR5nQcEfGF5FPdznOwwhJ7tjhBWfHtGs%3D")
-                                                   .addFormParam("SignatureMethod", "HmacSHA256")
-                                                   .addFormParam("SignatureVersion", "2")
-                                                   .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                   .addFormParam("Value", "dGVzdA%3D%3D")
-                                                   .addFormParam("Version", "2010-06-15")
-                                                   .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testSetUserDataForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "setUserDataForInstanceInRegion", String.class, String.class,
-               byte[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "test".getBytes()));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, setUserDataForInstance.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest setRamdiskForInstance = HttpRequest.builder().method("POST")
-                                                  .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                  .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                  .addFormParam("Action", "ModifyInstanceAttribute")
-                                                  .addFormParam("Attribute", "ramdisk")
-                                                  .addFormParam("InstanceId", "1")
-                                                  .addFormParam("Signature", "qx6NeVbihiYrKvi5Oe5LzMsGHTjS7%2BqoNhh2abt275g%3D")
-                                                  .addFormParam("SignatureMethod", "HmacSHA256")
-                                                  .addFormParam("SignatureVersion", "2")
-                                                  .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                  .addFormParam("Value", "test")
-                                                  .addFormParam("Version", "2010-06-15")
-                                                  .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testSetRamdiskForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "setRamdiskForInstanceInRegion", String.class, String.class,
-               String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "test"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, setRamdiskForInstance.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest setKernelForInstance = HttpRequest.builder().method("POST")
-                                                 .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                 .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                 .addFormParam("Action", "ModifyInstanceAttribute")
-                                                 .addFormParam("Attribute", "kernel")
-                                                 .addFormParam("InstanceId", "1")
-                                                 .addFormParam("Signature", "juSiuoiXJzTxj3q0LUW2528HzDyP4JAcKin%2BI4AuIT0%3D")
-                                                 .addFormParam("SignatureMethod", "HmacSHA256")
-                                                 .addFormParam("SignatureVersion", "2")
-                                                 .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                 .addFormParam("Value", "test")
-                                                 .addFormParam("Version", "2010-06-15")
-                                                 .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testSetKernelForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "setKernelForInstanceInRegion", String.class, String.class,
-               String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "test"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, setKernelForInstance.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest setApiTerminationDisabled = HttpRequest.builder().method("POST")
-                                                      .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                      .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                      .addFormParam("Action", "ModifyInstanceAttribute")
-                                                      .addFormParam("Attribute", "disableApiTermination")
-                                                      .addFormParam("InstanceId", "1")
-                                                      .addFormParam("Signature", "tiBMWWTi22BWeAjsRfuzVom0tQgsOBeYTkatMuWRrbg%3D")
-                                                      .addFormParam("SignatureMethod", "HmacSHA256")
-                                                      .addFormParam("SignatureVersion", "2")
-                                                      .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                      .addFormParam("Value", "true")
-                                                      .addFormParam("Version", "2010-06-15")
-                                                      .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testSetApiTerminationDisabledForInstanceInRegion() throws SecurityException, NoSuchMethodException,
-            IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "setApiTerminationDisabledForInstanceInRegion", String.class,
-               String.class, boolean.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", true));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, setApiTerminationDisabled.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest instanceTypeForInstance = HttpRequest.builder().method("POST")
-                                                    .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                    .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                    .addFormParam("Action", "ModifyInstanceAttribute")
-                                                    .addFormParam("Attribute", "instanceType")
-                                                    .addFormParam("InstanceId", "1")
-                                                    .addFormParam("Signature", "XK%2BzQmQ0S57gXIgVRMqUkKunURN9TaCJD1YWiYMAOHo%3D")
-                                                    .addFormParam("SignatureMethod", "HmacSHA256")
-                                                    .addFormParam("SignatureVersion", "2")
-                                                    .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                    .addFormParam("Value", "c1.medium")
-                                                    .addFormParam("Version", "2010-06-15")
-                                                    .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testSetInstanceTypeForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "setInstanceTypeForInstanceInRegion", String.class,
-               String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", InstanceType.C1_MEDIUM));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, instanceTypeForInstance.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest setInstanceInitiatedShutdownBehavior = HttpRequest.builder().method("POST")
-                                                                 .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                                 .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                                 .addFormParam("Action", "ModifyInstanceAttribute")
-                                                                 .addFormParam("Attribute", "instanceInitiatedShutdownBehavior")
-                                                                 .addFormParam("InstanceId", "1")
-                                                                 .addFormParam("Signature", "s5xBMLd%2BXNVp44x7C6qVE58qBov//f6yvxoM757KcZU%3D")
-                                                                 .addFormParam("SignatureMethod", "HmacSHA256")
-                                                                 .addFormParam("SignatureVersion", "2")
-                                                                 .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                                 .addFormParam("Value", "terminate")
-                                                                 .addFormParam("Version", "2010-06-15")
-                                                                 .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testSetInstanceInitiatedShutdownBehaviorForInstanceInRegion() throws SecurityException,
-            NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "setInstanceInitiatedShutdownBehaviorForInstanceInRegion",
-               String.class, String.class, InstanceInitiatedShutdownBehavior.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", InstanceInitiatedShutdownBehavior.TERMINATE));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, setInstanceInitiatedShutdownBehavior.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest setBlockDeviceMapping = HttpRequest.builder().method("POST")
-                                                           .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                           .addFormParam("Action", "ModifyInstanceAttribute")
-                                                           .addFormParam("BlockDeviceMapping.1.DeviceName", "/dev/sda1")
-                                                           .addFormParam("BlockDeviceMapping.1.Ebs.DeleteOnTermination", "true")
-                                                           .addFormParam("BlockDeviceMapping.1.Ebs.VolumeId", "vol-test1")
-                                                           .addFormParam("InstanceId", "1").build();
-
-   public void testSetBlockDeviceMappingForInstanceInRegion() throws SecurityException, NoSuchMethodException,
-            IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "setBlockDeviceMappingForInstanceInRegion", String.class,
-               String.class, Map.class);
-
-      Map<String, BlockDevice> mapping = Maps.newLinkedHashMap();
-      mapping.put("/dev/sda1", new BlockDevice("vol-test1", true));
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", mapping));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, filter.filter(setBlockDeviceMapping).getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-
-      checkFilters(request);
-   }
-
-   public void testGetConsoleOutputForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(InstanceAsyncClient.class, "getConsoleOutputForInstanceInRegion", String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request,
-               "Action=GetConsoleOutput&InstanceId=1",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, GetConsoleOutputResponseHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceClientLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceClientLiveTest.java
deleted file mode 100644
index 2ca4b85..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/InstanceClientLiveTest.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.services;
-
-import static org.testng.Assert.assertNotNull;
-
-import java.util.Set;
-
-import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.jclouds.ec2.EC2ApiMetadata;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.domain.Reservation;
-import org.jclouds.ec2.domain.RunningInstance;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-/**
- * Tests behavior of {@code EC2Client}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true, testName = "InstanceClientLiveTest")
-public class InstanceClientLiveTest extends BaseComputeServiceContextLiveTest {
-   public InstanceClientLiveTest() {
-      provider = "ec2";
-   }
-
-   private EC2Client ec2Client;
-   private InstanceClient client;
-
-   @Override
-   @BeforeClass(groups = { "integration", "live" })
-   public void setupContext() {
-      super.setupContext();
-      ec2Client = view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi();
-      client = ec2Client.getInstanceServices();
-   }
-
-   @Test
-   void testDescribeInstances() {
-      for (String region : ec2Client.getConfiguredRegions()) {
-         Set<? extends Reservation<? extends RunningInstance>> allResults = client.describeInstancesInRegion(region);
-         assertNotNull(allResults);
-         assert allResults.size() >= 0 : allResults.size();
-      }
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/KeyPairAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/KeyPairAsyncClientTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/KeyPairAsyncClientTest.java
deleted file mode 100644
index ebc3b5e..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/KeyPairAsyncClientTest.java
+++ /dev/null
@@ -1,88 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.ec2.xml.DescribeKeyPairsResponseHandler;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.http.functions.ReleasePayloadAndReturn;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.Lists;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code KeyPairAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "KeyPairAsyncClientTest")
-public class KeyPairAsyncClientTest extends BaseEC2AsyncClientTest<KeyPairAsyncClient> {
-
-   public void testDeleteKeyPair() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(KeyPairAsyncClient.class, "deleteKeyPairInRegion", String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "mykey"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DeleteKeyPair&KeyName=mykey",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeKeyPairs() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(KeyPairAsyncClient.class, "describeKeyPairsInRegion", String.class, String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeKeyPairs", "application/x-www-form-urlencoded",
-            false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeKeyPairsResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeKeyPairsArgs() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(KeyPairAsyncClient.class, "describeKeyPairsInRegion", String.class, String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeKeyPairs&KeyName.1=1&KeyName.2=2",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeKeyPairsResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/KeyPairClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/KeyPairClientLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/KeyPairClientLiveTest.java
deleted file mode 100644
index 06201fc..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/KeyPairClientLiveTest.java
+++ /dev/null
@@ -1,97 +0,0 @@
-/*
- * 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.services;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-
-import java.util.Set;
-import java.util.SortedSet;
-
-import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.jclouds.ec2.EC2ApiMetadata;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.domain.KeyPair;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.Sets;
-
-/**
- * Tests behavior of {@code KeyPairClient}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true, testName = "KeyPairClientLiveTest")
-public class KeyPairClientLiveTest extends BaseComputeServiceContextLiveTest {
-   public KeyPairClientLiveTest() {
-      provider = "ec2";
-   }
-
-   private EC2Client ec2Client;
-   private KeyPairClient client;
-   
-   @Override
-   @BeforeClass(groups = { "integration", "live" })
-   public void setupContext() {
-      super.setupContext();
-      ec2Client = view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi();
-      client = ec2Client.getKeyPairServices();
-   }
-
-   @Test
-   void testDescribeKeyPairs() {
-      for (String region : ec2Client.getConfiguredRegions()) {
-         SortedSet<KeyPair> allResults = Sets.newTreeSet(client.describeKeyPairsInRegion(region));
-         assertNotNull(allResults);
-         if (allResults.size() >= 1) {
-            KeyPair pair = allResults.last();
-            SortedSet<KeyPair> result = Sets.newTreeSet(client.describeKeyPairsInRegion(region, pair.getKeyName()));
-            assertNotNull(result);
-            KeyPair compare = result.last();
-            assertEquals(compare, pair);
-         }
-      }
-   }
-
-   public static final String PREFIX = System.getProperty("user.name") + "-ec2";
-
-   @Test
-   void testCreateKeyPair() {
-      String keyName = PREFIX + "1";
-      try {
-         client.deleteKeyPairInRegion(null, keyName);
-      } catch (Exception e) {
-
-      }
-      client.deleteKeyPairInRegion(null, keyName);
-
-      KeyPair result = client.createKeyPairInRegion(null, keyName);
-      assertNotNull(result);
-      assertNotNull(result.getKeyMaterial());
-      assertNotNull(result.getSha1OfPrivateKey());
-      assertEquals(result.getKeyName(), keyName);
-
-      Set<KeyPair> twoResults = Sets.newLinkedHashSet(client.describeKeyPairsInRegion(null, keyName));
-      assertNotNull(twoResults);
-      assertEquals(twoResults.size(), 1);
-      KeyPair listPair = twoResults.iterator().next();
-      assertEquals(listPair.getKeyName(), result.getKeyName());
-      assertEquals(listPair.getSha1OfPrivateKey(), result.getSha1OfPrivateKey());
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/SecurityGroupAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/SecurityGroupAsyncClientTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/SecurityGroupAsyncClientTest.java
deleted file mode 100644
index c22a279..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/SecurityGroupAsyncClientTest.java
+++ /dev/null
@@ -1,236 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.ec2.domain.UserIdGroupPair;
-import org.jclouds.ec2.xml.DescribeSecurityGroupsResponseHandler;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.http.functions.ReleasePayloadAndReturn;
-import org.jclouds.net.domain.IpProtocol;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.Lists;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code SecurityGroupAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "SecurityGroupAsyncClientTest")
-public class SecurityGroupAsyncClientTest extends BaseEC2AsyncClientTest<SecurityGroupAsyncClient> {
-
-   public void testDeleteSecurityGroup() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(SecurityGroupAsyncClient.class, "deleteSecurityGroupInRegion", String.class,
-            String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DeleteSecurityGroup&GroupName=name",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, VoidOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   HttpRequest createSecurityGroup = HttpRequest.builder().method("POST")
-                                                .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                .addFormParam("Action", "CreateSecurityGroup")
-                                                .addFormParam("GroupDescription", "description")
-                                                .addFormParam("GroupName", "name")
-                                                .addFormParam("Signature", "F3o0gnZcX9sWrtDUhVwi3k5GY2JKLP0Dhi6CcEqK2vE%3D")
-                                                .addFormParam("SignatureMethod", "HmacSHA256")
-                                                .addFormParam("SignatureVersion", "2")
-                                                .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                .addFormParam("Version", "2010-06-15")
-                                                .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testCreateSecurityGroup() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(SecurityGroupAsyncClient.class, "createSecurityGroupInRegion", String.class,
-            String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "description"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, createSecurityGroup.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeSecurityGroups() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(SecurityGroupAsyncClient.class, "describeSecurityGroupsInRegion", String.class,
-            String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeSecurityGroups",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeSecurityGroupsResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeSecurityGroupsArgs() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(SecurityGroupAsyncClient.class, "describeSecurityGroupsInRegion", String.class,
-            String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeSecurityGroups&GroupName.1=1&GroupName.2=2",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeSecurityGroupsResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testAuthorizeSecurityGroupIngressGroup() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(SecurityGroupAsyncClient.class, "authorizeSecurityGroupIngressInRegion", String.class,
-            String.class, UserIdGroupPair.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", new UserIdGroupPair("sourceUser",
-            "sourceGroup")));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(
-            request,
-            "Action=AuthorizeSecurityGroupIngress&GroupName=group&SourceSecurityGroupOwnerId=sourceUser&SourceSecurityGroupName=sourceGroup",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest authorizeSecurityGroupIngressCidr = HttpRequest.builder().method("POST")
-                                                              .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                              .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                              .addFormParam("Action", "AuthorizeSecurityGroupIngress")
-                                                              .addFormParam("CidrIp", "0.0.0.0/0")
-                                                              .addFormParam("FromPort", "6000")
-                                                              .addFormParam("GroupName", "group")
-                                                              .addFormParam("IpProtocol", "tcp")
-                                                              .addFormParam("Signature", "6NQega9YUGDxdwk3Y0Hv71u/lHi%2B0D6qMCJLpJVD/aI%3D")
-                                                              .addFormParam("SignatureMethod", "HmacSHA256")
-                                                              .addFormParam("SignatureVersion", "2")
-                                                              .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                              .addFormParam("ToPort", "7000")
-                                                              .addFormParam("Version", "2010-06-15")
-                                                              .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testAuthorizeSecurityGroupIngressCidr() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(SecurityGroupAsyncClient.class, "authorizeSecurityGroupIngressInRegion", String.class,
-            String.class, IpProtocol.class, int.class, int.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", IpProtocol.TCP, 6000, 7000, "0.0.0.0/0"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertPayloadEquals(request, authorizeSecurityGroupIngressCidr.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testRevokeSecurityGroupIngressGroup() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(SecurityGroupAsyncClient.class, "revokeSecurityGroupIngressInRegion", String.class,
-            String.class, UserIdGroupPair.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", new UserIdGroupPair("sourceUser",
-            "sourceGroup")));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(
-            request,
-            "Action=RevokeSecurityGroupIngress&GroupName=group&SourceSecurityGroupOwnerId=sourceUser&SourceSecurityGroupName=sourceGroup",
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest revokeSecurityGroupIngressCidr = HttpRequest.builder().method("POST")
-                                                           .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                           .addFormParam("Action", "RevokeSecurityGroupIngress")
-                                                           .addFormParam("CidrIp", "0.0.0.0/0")
-                                                           .addFormParam("FromPort", "6000")
-                                                           .addFormParam("GroupName", "group")
-                                                           .addFormParam("IpProtocol", "tcp")
-                                                           .addFormParam("Signature", "WPlDYXI8P6Ip4F2JIEP3lWrVlP/7gxbZvlshKYlrvxk%3D")
-                                                           .addFormParam("SignatureMethod", "HmacSHA256")
-                                                           .addFormParam("SignatureVersion", "2")
-                                                           .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                           .addFormParam("ToPort", "7000")
-                                                           .addFormParam("Version", "2010-06-15")
-                                                           .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testRevokeSecurityGroupIngressCidr() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(SecurityGroupAsyncClient.class, "revokeSecurityGroupIngressInRegion", String.class,
-            String.class, IpProtocol.class, int.class, int.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", IpProtocol.TCP, 6000, 7000, "0.0.0.0/0"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, revokeSecurityGroupIngressCidr.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/SecurityGroupClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/SecurityGroupClientLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/SecurityGroupClientLiveTest.java
deleted file mode 100644
index c6d02d2..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/SecurityGroupClientLiveTest.java
+++ /dev/null
@@ -1,288 +0,0 @@
-/*
- * 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.services;
-
-import static com.google.common.base.Predicates.compose;
-import static com.google.common.base.Predicates.in;
-import static com.google.common.collect.Iterables.all;
-import static com.google.common.collect.Iterables.getLast;
-import static com.google.common.collect.Iterables.getOnlyElement;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import java.util.Set;
-
-import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.jclouds.ec2.EC2ApiMetadata;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.domain.SecurityGroup;
-import org.jclouds.ec2.domain.UserIdGroupPair;
-import org.jclouds.net.domain.IpPermission;
-import org.jclouds.net.domain.IpProtocol;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Function;
-import com.google.common.base.Predicate;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMultimap;
-import com.google.common.collect.ImmutableSet;
-
-/**
- * Tests behavior of {@code SecurityGroupClient}
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true, testName = "SecurityGroupClientLiveTest")
-public class SecurityGroupClientLiveTest extends BaseComputeServiceContextLiveTest {
-   public SecurityGroupClientLiveTest() {
-      provider = "ec2";
-   }
-
-   private EC2Client ec2Client;
-   protected SecurityGroupClient client;
-
-   @Override
-   @BeforeClass(groups = { "integration", "live" })
-   public void setupContext() {
-      super.setupContext();
-      ec2Client = view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi();
-      client = ec2Client.getSecurityGroupServices();
-   }
-
-   @Test
-   void testDescribe() {
-      for (String region : ec2Client.getConfiguredRegions()) {
-         Set<SecurityGroup> allResults = client.describeSecurityGroupsInRegion(region);
-         assertNotNull(allResults);
-         if (allResults.size() >= 1) {
-            final SecurityGroup group = getLast(allResults);
-            // in case there are multiple groups with the same name, which is the case with VPC
-            ImmutableSet<SecurityGroup> expected = FluentIterable.from(allResults)
-                  .filter(new Predicate<SecurityGroup>() {
-                     @Override
-                     public boolean apply(SecurityGroup in) {
-                        return group.getName().equals(in.getName());
-                     }
-                  }).toSet();
-            ImmutableSet<SecurityGroup> result = ImmutableSet.copyOf(client.describeSecurityGroupsInRegion(region,
-                  group.getName()));
-            // the above command has a chance of returning less groups than the original
-            assertTrue(expected.containsAll(result));
-         }
-      }
-   }
-
-   @Test
-   void testCreateSecurityGroup() {
-      String groupName = PREFIX + "1";
-      cleanupAndSleep(groupName);
-      try {
-         String groupDescription = PREFIX + "1 description";
-         client.deleteSecurityGroupInRegion(null, groupName);
-         client.createSecurityGroupInRegion(null, groupName, groupDescription);
-         verifySecurityGroup(groupName, groupDescription);
-      } finally {
-         client.deleteSecurityGroupInRegion(null, groupName);
-      }
-   }
-
-   protected void cleanupAndSleep(String groupName) {
-      try {
-         client.deleteSecurityGroupInRegion(null, groupName);
-         Thread.sleep(2000);
-      } catch (Exception e) {
-
-      }
-   }
-
-   @Test
-   void testAuthorizeSecurityGroupIngressCidr() {
-      String groupName = PREFIX + "ingress";
-      cleanupAndSleep(groupName);
-      try {
-         client.createSecurityGroupInRegion(null, groupName, groupName);
-         client.authorizeSecurityGroupIngressInRegion(null, groupName, IpProtocol.TCP, 80, 80, "0.0.0.0/0");
-         assertEventually(new GroupHasPermission(client, groupName, new TCPPort80AllIPs()));
-
-         client.revokeSecurityGroupIngressInRegion(null, groupName, IpProtocol.TCP, 80, 80, "0.0.0.0/0");
-         assertEventually(new GroupHasNoPermissions(client, groupName));
-      } finally {
-         client.deleteSecurityGroupInRegion(null, groupName);
-      }
-   }
-
-   @Test
-   void testAuthorizeSecurityGroupIngressSourcePort() {
-      String groupName = PREFIX + "ingress";
-      cleanupAndSleep(groupName);
-      try {
-         client.createSecurityGroupInRegion(null, groupName, groupName);
-         client.authorizeSecurityGroupIngressInRegion(null, groupName, IpProtocol.TCP, 80, 80, "0.0.0.0/0");
-         assertEventually(new GroupHasPermission(client, groupName, new TCPPort80AllIPs()));
-
-         client.revokeSecurityGroupIngressInRegion(null, groupName, IpProtocol.TCP, 80, 80, "0.0.0.0/0");
-         assertEventually(new GroupHasNoPermissions(client, groupName));
-      } finally {
-         client.deleteSecurityGroupInRegion(null, groupName);
-      }
-   }
-
-   private void verifySecurityGroup(String groupName, String description) {
-      Set<SecurityGroup> oneResult = client.describeSecurityGroupsInRegion(null, groupName);
-      assertNotNull(oneResult);
-      assertEquals(oneResult.size(), 1);
-      SecurityGroup listPair = oneResult.iterator().next();
-      assertEquals(listPair.getName(), groupName);
-      assertEquals(listPair.getDescription(), description);
-   }
-
-   @Test
-   void testAuthorizeSecurityGroupIngressSourceGroup() {
-      final String group1Name = PREFIX + "ingress1";
-      String group2Name = PREFIX + "ingress2";
-      cleanupAndSleep(group2Name);
-      cleanupAndSleep(group1Name);
-      try {
-         client.createSecurityGroupInRegion(null, group1Name, group1Name);
-         client.createSecurityGroupInRegion(null, group2Name, group2Name);
-         ensureGroupsExist(group1Name, group2Name);
-         client.authorizeSecurityGroupIngressInRegion(null, group1Name, IpProtocol.TCP, 80, 80, "0.0.0.0/0");
-         assertEventually(new GroupHasPermission(client, group1Name, new TCPPort80AllIPs()));
-         Set<SecurityGroup> oneResult = client.describeSecurityGroupsInRegion(null, group1Name);
-         assertNotNull(oneResult);
-         assertEquals(oneResult.size(), 1);
-         final SecurityGroup group = oneResult.iterator().next();
-         assertEquals(group.getName(), group1Name);
-         final UserIdGroupPair to = new UserIdGroupPair(group.getOwnerId(), group1Name);
-         client.authorizeSecurityGroupIngressInRegion(null, group2Name, to);
-         assertEventually(new GroupHasPermission(client, group2Name, new Predicate<IpPermission>() {
-            @Override
-            public boolean apply(IpPermission arg0) {
-               return arg0.getTenantIdGroupNamePairs().equals(ImmutableMultimap.of(group.getOwnerId(), group1Name));
-            }
-         }));
-
-         client.revokeSecurityGroupIngressInRegion(null, group2Name,
-               new UserIdGroupPair(group.getOwnerId(), group1Name));
-         assertEventually(new GroupHasNoPermissions(client, group2Name));
-      } finally {
-         client.deleteSecurityGroupInRegion(null, group2Name);
-         client.deleteSecurityGroupInRegion(null, group1Name);
-      }
-   }
-
-   public final class TCPPort80AllIPs implements Predicate<IpPermission> {
-      @Override
-      public boolean apply(IpPermission arg0) {
-         return arg0.getIpProtocol() == IpProtocol.TCP && arg0.getFromPort() == 80 && arg0.getToPort() == 80
-               && arg0.getCidrBlocks().equals(ImmutableSet.of("0.0.0.0/0"));
-      }
-   }
-
-   public static final class GroupHasPermission implements Runnable {
-      private final SecurityGroupClient client;
-      private final String group;
-      private final Predicate<IpPermission> permission;
-
-      public GroupHasPermission(SecurityGroupClient client, String group, Predicate<IpPermission> permission) {
-         this.client = client;
-         this.group = group;
-         this.permission = permission;
-      }
-
-      public void run() {
-         try {
-            Set<SecurityGroup> oneResult = client.describeSecurityGroupsInRegion(null, group);
-            assert all(getOnlyElement(oneResult), permission) : permission
-                  + ": " + oneResult;
-         } catch (Exception e) {
-            throw new AssertionError(e);
-         }
-      }
-   }
-
-   public static final class GroupHasNoPermissions implements Runnable {
-      private final SecurityGroupClient client;
-      private final String group;
-
-      public GroupHasNoPermissions(SecurityGroupClient client, String group) {
-         this.client = client;
-         this.group = group;
-      }
-
-      public void run() {
-         try {
-            Set<SecurityGroup> oneResult = client.describeSecurityGroupsInRegion(null, group);
-            assertNotNull(oneResult);
-            assertEquals(oneResult.size(), 1);
-            SecurityGroup listPair = oneResult.iterator().next();
-            assertEquals(listPair.size(), 0);
-         } catch (Exception e) {
-            throw new AssertionError(e);
-         }
-      }
-   }
-
-   protected void ensureGroupsExist(String group1Name, String group2Name) {
-      Set<SecurityGroup> twoResults = client.describeSecurityGroupsInRegion(null, group1Name, group2Name);
-      assertNotNull(twoResults);
-      assertTrue(twoResults.size() >= 2);// in VPC could be multiple groups with the same name
-
-      assertTrue(all(twoResults, compose(in(ImmutableSet.of(group1Name, group2Name)),
-            new Function<SecurityGroup, String>() {
-               @Override
-               public String apply(SecurityGroup in) {
-                  return in.getName();
-               }
-            })));
-   }
-
-   private static final int INCONSISTENCY_WINDOW = 5000;
-
-   /**
-    * Due to eventual consistency, container commands may not return correctly
-    * immediately. Hence, we will try up to the inconsistency window to see if
-    * the assertion completes.
-    */
-   protected static void assertEventually(Runnable assertion) {
-      long start = System.currentTimeMillis();
-      AssertionError error = null;
-      for (int i = 0; i < 30; i++) {
-         try {
-            assertion.run();
-            if (i > 0)
-               System.err.printf("%d attempts and %dms asserting %s%n", i + 1, System.currentTimeMillis() - start,
-                     assertion.getClass().getSimpleName());
-            return;
-         } catch (AssertionError e) {
-            error = e;
-         }
-         try {
-            Thread.sleep(INCONSISTENCY_WINDOW / 30);
-         } catch (InterruptedException e) {
-         }
-      }
-      if (error != null)
-         throw error;
-
-   }
-
-   public static final String PREFIX = System.getProperty("user.name") + "-ec2";
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/WindowsAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/WindowsAsyncClientTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/WindowsAsyncClientTest.java
deleted file mode 100644
index fb825cb..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/WindowsAsyncClientTest.java
+++ /dev/null
@@ -1,162 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.ec2.options.BundleInstanceS3StorageOptions;
-import org.jclouds.ec2.xml.BundleTaskHandler;
-import org.jclouds.ec2.xml.DescribeBundleTasksResponseHandler;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.Lists;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code WindowsAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "WindowsAsyncClientTest")
-public class WindowsAsyncClientTest extends BaseEC2AsyncClientTest<WindowsAsyncClient> {
-
-   HttpRequest bundleInstanceInRegion = HttpRequest.builder().method("POST")
-                                                   .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                   .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                   .addFormParam("Action", "BundleInstance")
-                                                   .addFormParam("InstanceId", "i-e468cd8d")
-                                                   .addFormParam("Signature", "Uw5gH4eN3H8KXeFfIVLDDt88ApYn8L4pkf31hpojpcM%3D")
-                                                   .addFormParam("SignatureMethod", "HmacSHA256")
-                                                   .addFormParam("SignatureVersion", "2")
-                                                   .addFormParam("Storage.S3.Bucket", "my-bucket")
-                                                   .addFormParam("Storage.S3.Prefix", "winami")
-                                                   .addFormParam("Storage.S3.UploadPolicy", "eyJleHBpcmF0aW9uIjogIjIwMDgtMDgtMzBUMDg6NDk6MDlaIiwiY29uZGl0aW9ucyI6IFt7ImJ1Y2tldCI6ICJteS1idWNrZXQifSxbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAibXktbmV3LWltYWdlIl1dfQ%3D%3D")
-                                                   .addFormParam("Storage.S3.UploadPolicySignature", "ih/iohGe0A7y4QVRbKaq6BZShzUsmBEJEa9AdFbxM6Y%3D")
-                                                   .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                   .addFormParam("Version", "2010-06-15")
-                                                   .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testBundleInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(WindowsAsyncClient.class, "bundleInstanceInRegion", String.class, String.class,
-               String.class, String.class, String.class, BundleInstanceS3StorageOptions[].class);
-      GeneratedHttpRequest request = processor
-               .createRequest(
-                        method,
-                        Lists.<Object> newArrayList(
-                        null,
-                        "i-e468cd8d",
-                        "winami",
-                        "my-bucket",
-                        "{\"expiration\": \"2008-08-30T08:49:09Z\",\"conditions\": [{\"bucket\": \"my-bucket\"},[\"starts-with\", \"$key\", \"my-new-image\"]]}"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, bundleInstanceInRegion.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, BundleTaskHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest bundleInstanceInRegionOptions = HttpRequest.builder().method("POST")
-                                                          .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                          .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                          .addFormParam("Action", "BundleInstance")
-                                                          .addFormParam("InstanceId","i-e468cd8d")
-                                                          .addFormParam("Signature", "ahFjX9Tv/DGMFq9EFdF1mWSAnTKyQyyIj7dWJxBOhaE%3D")
-                                                          .addFormParam("SignatureMethod", "HmacSHA256")
-                                                          .addFormParam("SignatureVersion", "2")
-                                                          .addFormParam("Storage.S3.AWSAccessKeyId", "10QMXFEV71ZS32XQFTR2")
-                                                          .addFormParam("Storage.S3.Bucket", "my-bucket")
-                                                          .addFormParam("Storage.S3.Prefix", "winami")
-                                                          .addFormParam("Storage.S3.UploadPolicy", "eyJleHBpcmF0aW9uIjogIjIwMDgtMDgtMzBUMDg6NDk6MDlaIiwiY29uZGl0aW9ucyI6IFt7ImJ1Y2tldCI6ICJteS1idWNrZXQifSxbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAibXktbmV3LWltYWdlIl1dfQ%3D%3D")
-                                                          .addFormParam("Storage.S3.UploadPolicySignature", "ih/iohGe0A7y4QVRbKaq6BZShzUsmBEJEa9AdFbxM6Y%3D")
-                                                          .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                          .addFormParam("Version", "2010-06-15")
-                                                          .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testBundleInstanceInRegionOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(WindowsAsyncClient.class, "bundleInstanceInRegion", String.class, String.class,
-               String.class, String.class, String.class, BundleInstanceS3StorageOptions[].class);
-      GeneratedHttpRequest request = processor
-               .createRequest(
-                        method,
-                        Lists.<Object> newArrayList(
-                        null,
-                        "i-e468cd8d",
-                        "winami",
-                        "my-bucket",
-                        "{\"expiration\": \"2008-08-30T08:49:09Z\",\"conditions\": [{\"bucket\": \"my-bucket\"},[\"starts-with\", \"$key\", \"my-new-image\"]]}",
-                        BundleInstanceS3StorageOptions.Builder.bucketOwnedBy("10QMXFEV71ZS32XQFTR2")));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, bundleInstanceInRegionOptions.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, BundleTaskHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeBundleTasks() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(WindowsAsyncClient.class, "describeBundleTasksInRegion", String.class, String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeBundleTasks",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeBundleTasksResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   public void testDescribeBundleTasksArgs() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(WindowsAsyncClient.class, "describeBundleTasksInRegion", String.class, String[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
-
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, "Action=DescribeBundleTasks&BundleId.1=1&BundleId.2=2",
-               "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeBundleTasksResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-}


[05/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/SpotInstanceAsyncClient.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/SpotInstanceAsyncClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/SpotInstanceAsyncClient.java
deleted file mode 100644
index bf773cd..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/SpotInstanceAsyncClient.java
+++ /dev/null
@@ -1,128 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.aws.ec2.binders.BindLaunchSpecificationToFormParams;
-import org.jclouds.aws.ec2.binders.BindSpotInstanceRequestIdsToIndexedFormParams;
-import org.jclouds.aws.ec2.domain.LaunchSpecification;
-import org.jclouds.aws.ec2.domain.Spot;
-import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
-import org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions;
-import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions;
-import org.jclouds.aws.ec2.xml.DescribeSpotPriceHistoryResponseHandler;
-import org.jclouds.aws.ec2.xml.SpotInstanceHandler;
-import org.jclouds.aws.ec2.xml.SpotInstancesHandler;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to EC2 Spot Instances via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface SpotInstanceAsyncClient {
-
-   /**
-    * @see SpotInstanceClient#describeSpotInstanceRequestsInRegion
-    */
-   @Named("DescribeSpotInstanceRequests")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeSpotInstanceRequests")
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   @XMLResponseParser(SpotInstancesHandler.class)
-   ListenableFuture<? extends Set<SpotInstanceRequest>> describeSpotInstanceRequestsInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @BinderParam(BindSpotInstanceRequestIdsToIndexedFormParams.class) String... requestIds);
-
-   /**
-    * @see SpotInstanceClient#requestSpotInstanceInRegion
-    */
-   @Named("RequestSpotInstances")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "RequestSpotInstances")
-   @XMLResponseParser(SpotInstanceHandler.class)
-   ListenableFuture<SpotInstanceRequest> requestSpotInstanceInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("SpotPrice") float spotPrice, @FormParam("LaunchSpecification.ImageId") String imageId,
-         @FormParam("LaunchSpecification.InstanceType") String instanceType);
-
-   /**
-    * @see SpotInstanceClient#requestSpotInstancesInRegion
-    */
-   @Named("RequestSpotInstances")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "RequestSpotInstances")
-   @XMLResponseParser(SpotInstancesHandler.class)
-   ListenableFuture<? extends Set<SpotInstanceRequest>> requestSpotInstancesInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("SpotPrice") float spotPrice, @FormParam("InstanceCount") int instanceCount,
-         @BinderParam(BindLaunchSpecificationToFormParams.class) LaunchSpecification launchSpec,
-         RequestSpotInstancesOptions... options);
-
-   /**
-    * @see SpotInstanceClient#describeSpotPriceHistoryInRegion
-    */
-   @Named("DescribeSpotPriceHistory")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeSpotPriceHistory")
-   @XMLResponseParser(DescribeSpotPriceHistoryResponseHandler.class)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<? extends Set<Spot>> describeSpotPriceHistoryInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         DescribeSpotPriceHistoryOptions... options);
-
-   /**
-    * @see SpotInstanceClient#cancelSpotInstanceRequestsInRegion
-    */
-   @Named("CancelSpotInstanceRequests")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "CancelSpotInstanceRequests")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> cancelSpotInstanceRequestsInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @BinderParam(BindSpotInstanceRequestIdsToIndexedFormParams.class) String... requestIds);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/SpotInstanceClient.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/SpotInstanceClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/SpotInstanceClient.java
deleted file mode 100644
index d7ee047..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/SpotInstanceClient.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import java.util.Set;
-import org.jclouds.aws.ec2.domain.LaunchSpecification;
-import org.jclouds.aws.ec2.domain.Spot;
-import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
-import org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions;
-import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions;
-import org.jclouds.javax.annotation.Nullable;
-
-/**
- * Provides Spot Instance services for EC2. For more information, refer to the Amazon EC2 Developer
- * Guide.
- * <p/>
- * 
- * @author Adrian Cole
- */
-public interface SpotInstanceClient {
-   /**
-    * Describes Spot Instance requests. Spot Instances are instances that Amazon EC2 starts on your
-    * behalf when the maximum price that you specify exceeds the current Spot Price. Amazon EC2
-    * periodically sets the Spot Price based on available Spot Instance capacity and current spot
-    * instance requests. For conceptual information about Spot Instances, refer to the Amazon
-    * Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
-    * 
-    * @param region
-    *           Region where the spot instance service is running
-    * @param requestIds
-    *           Specifies the ID of the Spot Instance request.
-    * 
-    * @see #requestSpotInstancesInRegion
-    * @see #cancelSpotInstanceRequestsInRegion
-    * @see #describeSpotPriceHistoryInRegion
-    * @see <a href=
-    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSpotInstanceRequests.html"
-    *      />
-    * @return TODO
-    */
-   Set<SpotInstanceRequest> describeSpotInstanceRequestsInRegion(@Nullable String region, String... requestIds);
-
-   /**
-    * request a single spot instance
-    * 
-    * @param region
-    *           Region where the spot instance service is running
-    * @param spotPrice
-    *           Specifies the maximum hourly price for any Spot Instance launched to fulfill the
-    *           request.
-    * @param imageId
-    *           The AMI ID.
-    * @param instanceType
-    *           The instance type (ex. m1.small)
-    * @return spot instance request
-    * @see #requestSpotInstancesInRegion
-    */
-   SpotInstanceRequest requestSpotInstanceInRegion(@Nullable String region, float spotPrice, String imageId,
-         String instanceType);
-
-   /**
-    * Creates a Spot Instance request. Spot Instances are instances that Amazon EC2 starts on your
-    * behalf when the maximum price that you specify exceeds the current Spot Price. Amazon EC2
-    * periodically sets the Spot Price based on available Spot Instance capacity and current spot
-    * instance requests. For conceptual information about Spot Instances, refer to the Amazon
-    * Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
-    * 
-    * @param region
-    *           Region where the spot instance service is running
-    * @param spotPrice
-    *           Specifies the maximum hourly price for any Spot Instance launched to fulfill the
-    *           request.
-    * @param instanceCount
-    *           number of instances to request
-    * @param launchSpec
-    *           includes at least The AMI ID and instance type (ex. m1.small)
-    * @param options
-    *           options including expiration time or grouping
-    * 
-    * @see #describeSpotInstanceRequestsInRegion
-    * @see #cancelSpotInstanceRequestsInRegion
-    * @see #describeSpotPriceHistoryInRegion
-    * @see <a href=
-    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RequestSpotInstances.html"
-    *      />
-    * @return set of spot instance requests
-    */
-   Set<SpotInstanceRequest> requestSpotInstancesInRegion(@Nullable String region, float spotPrice, int instanceCount,
-         LaunchSpecification launchSpec, RequestSpotInstancesOptions... options);
-
-   /**
-    * 
-    * Describes Spot Price history. Spot Instances are instances that Amazon EC2 starts on your
-    * behalf when the maximum price that you specify exceeds the current Spot Price. Amazon EC2
-    * periodically sets the Spot Price based on available Spot Instance capacity and current spot
-    * instance requests. For conceptual information about Spot Instances, refer to the Amazon
-    * Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
-    * 
-    * @param region
-    *           Region where the spot instance service is running
-    * @param options
-    *           options to control the list
-    * 
-    * @see #describeSpotInstanceRequestsInRegion
-    * @see #requestSpotInstancesInRegion
-    * @see #cancelSpotInstanceRequestsInRegion
-    * @see <a href=
-    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSpotInstanceRequests.html"
-    *      />
-    * @return TODO
-    */
-   Set<Spot> describeSpotPriceHistoryInRegion(@Nullable String region, DescribeSpotPriceHistoryOptions... options);
-
-   /**
-    * Cancels one or more Spot Instance requests. Spot Instances are instances that Amazon EC2
-    * starts on your behalf when the maximum price that you specify exceeds the current Spot Price.
-    * Amazon EC2 periodically sets the Spot Price based on available Spot Instance capacity and
-    * current spot instance requests. For conceptual information about Spot Instances, refer to the
-    * Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
-    * 
-    * @param region
-    *           Region where the spot instance service is running
-    * @param requestIds
-    *           Specifies the ID of the Spot Instance request.
-    * 
-    * @see #describeSpotInstanceRequestsInRegion
-    * @see #requestSpotInstancesInRegion
-    * @see #describeSpotPriceHistoryInRegion
-    * @see <a href=
-    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CancelSpotInstanceRequests.html"
-    *      />
-    * @return TODO
-    */
-   String cancelSpotInstanceRequestsInRegion(@Nullable String region, String... requestIds);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/AWSEC2AsyncClientTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/AWSEC2AsyncClientTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/AWSEC2AsyncClientTest.java
deleted file mode 100644
index 838fa54..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/AWSEC2AsyncClientTest.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * 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.aws.ec2;
-
-import java.io.IOException;
-import java.util.concurrent.ExecutionException;
-
-import org.jclouds.aws.ec2.services.BaseAWSEC2AsyncClientTest;
-import org.jclouds.http.HttpRequest;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-/**
- * Tests behavior of {@code AWSEC2AsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "AWSEC2AsyncClientTest")
-public class AWSEC2AsyncClientTest extends BaseAWSEC2AsyncClientTest<AWSEC2AsyncClient> {
-
-   private AWSEC2AsyncClient asyncClient;
-   private AWSEC2Client syncClient;
-
-   public void testSync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException {
-      assert syncClient.getAMIServices() != null;
-      assert syncClient.getAvailabilityZoneAndRegionServices() != null;
-      assert syncClient.getElasticBlockStoreServices() != null;
-      assert syncClient.getElasticIPAddressServices() != null;
-      assert syncClient.getInstanceServices() != null;
-      assert syncClient.getKeyPairServices() != null;
-      assert syncClient.getMonitoringServices() != null;
-      assert syncClient.getSecurityGroupServices() != null;
-      assert syncClient.getPlacementGroupServices() != null;
-      assert syncClient.getWindowsServices() != null;
-
-   }
-
-   public void testAsync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException {
-      assert asyncClient.getAMIServices() != null;
-      assert asyncClient.getAvailabilityZoneAndRegionServices() != null;
-      assert asyncClient.getElasticBlockStoreServices() != null;
-      assert asyncClient.getElasticIPAddressServices() != null;
-      assert asyncClient.getInstanceServices() != null;
-      assert asyncClient.getKeyPairServices() != null;
-      assert asyncClient.getMonitoringServices() != null;
-      assert asyncClient.getSecurityGroupServices() != null;
-      assert asyncClient.getPlacementGroupServices() != null;
-      assert asyncClient.getWindowsServices() != null;
-   }
-
-   @BeforeClass
-   @Override
-   protected void setupFactory() throws IOException {
-      super.setupFactory();
-      asyncClient = injector.getInstance(AWSEC2AsyncClient.class);
-      syncClient = injector.getInstance(AWSEC2Client.class);
-   }
-
-   @Override
-   protected void checkFilters(HttpRequest request) {
-
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceLiveTest.java
index ae39523..235e596 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceLiveTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceLiveTest.java
@@ -30,10 +30,10 @@ import java.util.concurrent.TimeUnit;
 import org.jclouds.ContextBuilder;
 import org.jclouds.aws.cloudwatch.AWSCloudWatchProviderMetadata;
 import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
-import org.jclouds.aws.ec2.AWSEC2Client;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.domain.AWSRunningInstance;
 import org.jclouds.aws.ec2.domain.MonitoringState;
-import org.jclouds.aws.ec2.services.AWSSecurityGroupClient;
+import org.jclouds.aws.ec2.features.AWSSecurityGroupApi;
 import org.jclouds.cloudwatch.CloudWatchApi;
 import org.jclouds.cloudwatch.domain.Dimension;
 import org.jclouds.cloudwatch.domain.EC2Constants;
@@ -46,12 +46,12 @@ import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.domain.Template;
 import org.jclouds.compute.predicates.NodePredicates;
 import org.jclouds.domain.LoginCredentials;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.EC2ComputeServiceLiveTest;
 import org.jclouds.ec2.domain.KeyPair;
 import org.jclouds.ec2.domain.SecurityGroup;
-import org.jclouds.ec2.services.InstanceClient;
-import org.jclouds.ec2.services.KeyPairClient;
+import org.jclouds.ec2.features.InstanceApi;
+import org.jclouds.ec2.features.KeyPairApi;
 import org.jclouds.net.domain.IpProtocol;
 import org.jclouds.scriptbuilder.domain.Statements;
 import org.testng.annotations.Test;
@@ -78,14 +78,11 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
    public void testExtendedOptionsAndLogin() throws Exception {
       String region = "us-west-2";
 
-      AWSSecurityGroupClient securityGroupClient = AWSEC2Client.class.cast(
-               view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi()).getSecurityGroupServices();
+      AWSSecurityGroupApi securityGroupApi = view.unwrapApi(AWSEC2Api.class).getSecurityGroupApi().get();
 
-      KeyPairClient keyPairClient = EC2Client.class.cast(view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi())
-               .getKeyPairServices();
+      KeyPairApi keyPairApi = view.unwrapApi(AWSEC2Api.class).getKeyPairApi().get();
 
-      InstanceClient instanceClient = EC2Client.class.cast(view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN).getApi())
-               .getInstanceServices();
+      InstanceApi instanceApi = view.unwrapApi(AWSEC2Api.class).getInstanceApi().get();
 
       String group = this.group + "o";
 
@@ -105,20 +102,20 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
 
       String startedId = null;
       try {
-         cleanupExtendedStuffInRegion(region, securityGroupClient, keyPairClient, group);
+         cleanupExtendedStuffInRegion(region, securityGroupApi, keyPairApi, group);
 
          Thread.sleep(3000);// eventual consistency if deletes actually occurred.
 
          // create a security group that allows ssh in so that our scripts later
          // will work
-         String groupId = securityGroupClient.createSecurityGroupInRegionAndReturnId(region, group, group);
+         String groupId = securityGroupApi.createSecurityGroupInRegionAndReturnId(region, group, group);
 
-         securityGroupClient.authorizeSecurityGroupIngressInRegion(region, groupId, permit(IpProtocol.TCP).port(22));
+         securityGroupApi.authorizeSecurityGroupIngressInRegion(region, groupId, permit(IpProtocol.TCP).port(22));
 
          template.getOptions().as(AWSEC2TemplateOptions.class).securityGroupIds(groupId);
 
          // create a keypair to pass in as well
-         KeyPair result = keyPairClient.createKeyPairInRegion(region, group);
+         KeyPair result = keyPairApi.createKeyPairInRegion(region, group);
          template.getOptions().as(AWSEC2TemplateOptions.class).keyPair(result.getKeyName());
 
          // pass in the private key, so that we can run a script with it
@@ -136,7 +133,7 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
 
          startedId = first.getProviderId();
 
-         AWSRunningInstance instance = AWSRunningInstance.class.cast(getOnlyElement(getOnlyElement(instanceClient
+         AWSRunningInstance instance = AWSRunningInstance.class.cast(getOnlyElement(getOnlyElement(instanceApi
                   .describeInstancesInRegion(region, startedId))));
 
          assertEquals(instance.getKeyName(), group);
@@ -179,7 +176,7 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
          assertEquals(newTreeSet(instance.getGroupNames()), ImmutableSortedSet.<String> of("jclouds#" + group, group));
 
          // make sure our dummy group has no rules
-         SecurityGroup secgroup = getOnlyElement(securityGroupClient.describeSecurityGroupsInRegion(instance
+         SecurityGroup secgroup = getOnlyElement(securityGroupApi.describeSecurityGroupsInRegion(instance
                   .getRegion(), "jclouds#" + group));
 
          assert secgroup.size() == 0 : secgroup;
@@ -192,10 +189,10 @@ public class AWSEC2ComputeServiceLiveTest extends EC2ComputeServiceLiveTest {
          client.destroyNodesMatching(NodePredicates.inGroup(group));
          if (startedId != null) {
             // ensure we didn't delete these resources!
-            assertEquals(keyPairClient.describeKeyPairsInRegion(region, group).size(), 1);
-            assertEquals(securityGroupClient.describeSecurityGroupsInRegion(region, group).size(), 1);
+            assertEquals(keyPairApi.describeKeyPairsInRegion(region, group).size(), 1);
+            assertEquals(securityGroupApi.describeSecurityGroupsInRegion(region, group).size(), 1);
          }
-         cleanupExtendedStuffInRegion(region, securityGroupClient, keyPairClient, group);
+         cleanupExtendedStuffInRegion(region, securityGroupApi, keyPairApi, group);
       }
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateBuilderLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateBuilderLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateBuilderLiveTest.java
index 240105f..ca94b70 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateBuilderLiveTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateBuilderLiveTest.java
@@ -26,12 +26,14 @@ import java.util.Properties;
 import java.util.Set;
 
 import org.jclouds.aws.domain.Region;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
 import org.jclouds.aws.ec2.reference.AWSEC2Constants;
 import org.jclouds.compute.ComputeServiceContext;
 import org.jclouds.compute.domain.OsFamily;
 import org.jclouds.compute.domain.OsFamilyVersion64Bit;
 import org.jclouds.compute.domain.Template;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.EC2ApiMetadata;
 import org.jclouds.ec2.compute.EC2TemplateBuilderLiveTest;
 import org.jclouds.ec2.compute.predicates.EC2ImagePredicates;
@@ -40,7 +42,7 @@ import org.jclouds.ec2.domain.RootDeviceType;
 import org.jclouds.ec2.options.DescribeAvailabilityZonesOptions;
 import org.jclouds.ec2.options.DescribeRegionsOptions;
 import org.jclouds.ec2.reference.EC2Constants;
-import org.jclouds.ec2.services.AvailabilityZoneAndRegionAsyncClient;
+import org.jclouds.ec2.features.AvailabilityZoneAndRegionApi;
 import org.jclouds.http.HttpCommand;
 import org.jclouds.http.internal.TrackingJavaUrlHttpCommandExecutorService;
 import org.jclouds.location.reference.LocationConstants;
@@ -336,9 +338,9 @@ public class AWSEC2TemplateBuilderLiveTest extends EC2TemplateBuilderLiveTest {
          throws NoSuchMethodException {
       assert commandsInvoked.size() == 2 : commandsInvoked;
       assertEquals(getInvokerOfRequestAtIndex(commandsInvoked, 0),
-            AvailabilityZoneAndRegionAsyncClient.class.getMethod("describeRegions", DescribeRegionsOptions[].class));
+            AvailabilityZoneAndRegionApi.class.getMethod("describeRegions", DescribeRegionsOptions[].class));
       assertEquals(getInvokerOfRequestAtIndex(commandsInvoked, 1),
-            AvailabilityZoneAndRegionAsyncClient.class.getMethod("describeAvailabilityZonesInRegion", String.class,
+            AvailabilityZoneAndRegionApi.class.getMethod("describeAvailabilityZonesInRegion", String.class,
                   DescribeAvailabilityZonesOptions[].class));
    }
 
@@ -355,8 +357,8 @@ public class AWSEC2TemplateBuilderLiveTest extends EC2TemplateBuilderLiveTest {
    
    @Test
    public void testAssignability() {
-      view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN);
-      view.unwrap(AWSEC2ApiMetadata.CONTEXT_TOKEN);
+      view.unwrapApi(EC2Api.class);
+      view.unwrapApi(AWSEC2Api.class);
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2ImageExtensionLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2ImageExtensionLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2ImageExtensionLiveTest.java
index ae303c6..6481efd 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2ImageExtensionLiveTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2ImageExtensionLiveTest.java
@@ -18,7 +18,7 @@ package org.jclouds.aws.ec2.compute.extensions;
 
 import static com.google.common.collect.Iterables.transform;
 
-import org.jclouds.aws.ec2.AWSEC2Client;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.util.AWSUtils;
 import org.jclouds.compute.domain.Image;
 import org.jclouds.compute.extensions.ImageExtension;
@@ -45,13 +45,13 @@ public class AWSEC2ImageExtensionLiveTest extends BaseImageExtensionLiveTest {
 
    @Override
    protected Iterable<? extends Image> listImages() {
-      AWSEC2Client client = view.utils().injector().getInstance(AWSEC2Client.class);
+      AWSEC2Api client = view.unwrapApi(AWSEC2Api.class);
       String[] parts = AWSUtils.parseHandle(imageId);
       String region = parts[0];
       String imageId = parts[1];
       EC2ImageParser parser = view.utils().injector().getInstance(EC2ImageParser.class);
       return transform(
-            client.getAMIServices().describeImagesInRegion(region, new DescribeImagesOptions().imageIds(imageId)),
+                       client.getAMIApi().get().describeImagesInRegion(region, new DescribeImagesOptions().imageIds(imageId)),
             parser);
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/functions/PresentSpotRequestsAndInstancesTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/functions/PresentSpotRequestsAndInstancesTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/functions/PresentSpotRequestsAndInstancesTest.java
index de7360d..babe978 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/functions/PresentSpotRequestsAndInstancesTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/functions/PresentSpotRequestsAndInstancesTest.java
@@ -24,17 +24,18 @@ import static org.testng.Assert.assertEquals;
 
 import java.util.Set;
 
-import org.jclouds.aws.ec2.AWSEC2Client;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.domain.AWSRunningInstance;
 import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
-import org.jclouds.aws.ec2.services.AWSInstanceClient;
-import org.jclouds.aws.ec2.services.SpotInstanceClient;
+import org.jclouds.aws.ec2.features.AWSInstanceApi;
+import org.jclouds.aws.ec2.features.SpotInstanceApi;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.domain.Reservation;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Function;
 import com.google.common.base.Functions;
+import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 
@@ -50,25 +51,25 @@ public class PresentSpotRequestsAndInstancesTest {
    @Test
    public void testWhenInstancesPresentSingleCall() {
 
-      AWSEC2Client client = createMock(AWSEC2Client.class);
-      AWSInstanceClient instanceClient = createMock(AWSInstanceClient.class);
+      AWSEC2Api client = createMock(AWSEC2Api.class);
+      AWSInstanceApi instanceApi = createMock(AWSInstanceApi.class);
       Function<SpotInstanceRequest, AWSRunningInstance> converter = createMock(Function.class);
 
-      expect(client.getInstanceServices()).andReturn(instanceClient);
+      expect(client.getInstanceApi()).andReturn((Optional) Optional.of(instanceApi));
       
       // avoid imatcher fail.  if you change this, be sure to check multiple jres
-      expect(instanceClient.describeInstancesInRegion("us-east-1", "i-aaaa", "i-bbbb")).andReturn(
+      expect(instanceApi.describeInstancesInRegion("us-east-1", "i-aaaa", "i-bbbb")).andReturn(
             Set.class.cast(ImmutableSet.of(Reservation.<AWSRunningInstance> builder().region("us-east-1")
                   .instances(ImmutableSet.of(instance1, instance2)).build())));
 
-      replay(client, instanceClient, converter);
+      replay(client, instanceApi, converter);
 
       PresentSpotRequestsAndInstances fn = new PresentSpotRequestsAndInstances(client, converter);
 
       assertEquals(fn.apply(ImmutableSet.of(new RegionAndName("us-east-1", "i-aaaa"), new RegionAndName("us-east-1",
             "i-bbbb"))), ImmutableSet.of(instance1, instance2));
 
-      verify(client, instanceClient, converter);
+      verify(client, instanceApi, converter);
    }
 
    SpotInstanceRequest spot1 = createMock(SpotInstanceRequest.class);
@@ -80,20 +81,20 @@ public class PresentSpotRequestsAndInstancesTest {
       Function<SpotInstanceRequest, AWSRunningInstance> converter = Functions.forMap(ImmutableMap.of(spot1, instance1,
             spot2, instance2));
 
-      AWSEC2Client client = createMock(AWSEC2Client.class);
-      SpotInstanceClient spotClient = createMock(SpotInstanceClient.class);
+      AWSEC2Api client = createMock(AWSEC2Api.class);
+      SpotInstanceApi spotApi = createMock(SpotInstanceApi.class);
 
-      expect(client.getSpotInstanceServices()).andReturn(spotClient);
-      expect(spotClient.describeSpotInstanceRequestsInRegion("us-east-1", "sir-aaaa", "sir-bbbb")).andReturn(
+      expect(client.getSpotInstanceApi()).andReturn((Optional) Optional.of(spotApi));
+      expect(spotApi.describeSpotInstanceRequestsInRegion("us-east-1", "sir-aaaa", "sir-bbbb")).andReturn(
             ImmutableSet.of(spot1, spot2));
 
-      replay(client, spotClient);
+      replay(client, spotApi);
 
       PresentSpotRequestsAndInstances fn = new PresentSpotRequestsAndInstances(client, converter);
 
       assertEquals(fn.apply(ImmutableSet.of(new RegionAndName("us-east-1", "sir-aaaa"), new RegionAndName("us-east-1",
             "sir-bbbb"))), ImmutableSet.of(instance1, instance2));
 
-      verify(client, spotClient);
+      verify(client, spotApi);
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/internal/BaseAWSEC2ComputeServiceExpectTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/internal/BaseAWSEC2ComputeServiceExpectTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/internal/BaseAWSEC2ComputeServiceExpectTest.java
index 193cd72..e643f9e 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/internal/BaseAWSEC2ComputeServiceExpectTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/internal/BaseAWSEC2ComputeServiceExpectTest.java
@@ -22,11 +22,11 @@ import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_GENERATE_INSTA
 import java.util.Properties;
 import java.util.concurrent.atomic.AtomicInteger;
 
-import org.jclouds.aws.ec2.config.AWSEC2RestClientModule;
+import org.jclouds.aws.ec2.config.AWSEC2HttpApiModule;
 import org.jclouds.date.DateService;
 import org.jclouds.ec2.compute.internal.BaseEC2ComputeServiceExpectTest;
 import org.jclouds.http.HttpRequest;
-import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.rest.ConfiguresHttpApi;
 import org.testng.annotations.BeforeClass;
 
 import com.google.common.base.Supplier;
@@ -100,8 +100,8 @@ public abstract class BaseAWSEC2ComputeServiceExpectTest extends BaseEC2ComputeS
                           .addFormParam("Filter.3.Value.1", "machine").build());
    }
 
-   @ConfiguresRestClient
-   protected static class TestAWSEC2RestClientModule extends AWSEC2RestClientModule {
+   @ConfiguresHttpApi
+   protected static class TestAWSEC2HttpApiModule extends AWSEC2HttpApiModule {
 
       @Override
       protected void configure() {
@@ -128,6 +128,6 @@ public abstract class BaseAWSEC2ComputeServiceExpectTest extends BaseEC2ComputeS
 
    @Override
    protected Module createModule() {
-      return new TestAWSEC2RestClientModule();
+      return new TestAWSEC2HttpApiModule();
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeededTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeededTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeededTest.java
index 269a8f0..f61bf2e 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeededTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeededTest.java
@@ -27,7 +27,7 @@ import static org.testng.Assert.assertEquals;
 import java.util.Set;
 import java.util.concurrent.ExecutionException;
 
-import org.jclouds.aws.ec2.services.AWSSecurityGroupClient;
+import org.jclouds.aws.ec2.features.AWSSecurityGroupApi;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
 import org.jclouds.ec2.domain.SecurityGroup;
@@ -51,7 +51,7 @@ public class AWSEC2CreateSecurityGroupIfNeededTest {
    @Test
    public void testWhenPort22AndToItselfAuthorizesIngressOnce() throws ExecutionException {
 
-      AWSSecurityGroupClient client = createMock(AWSSecurityGroupClient.class);
+      AWSSecurityGroupApi client = createMock(AWSSecurityGroupApi.class);
       Predicate<RegionAndName> tester = Predicates.alwaysTrue();
 
       SecurityGroup group = createNiceMock(SecurityGroup.class);

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSAMIApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSAMIApiLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSAMIApiLiveTest.java
new file mode 100644
index 0000000..747e224
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSAMIApiLiveTest.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.aws.ec2.features;
+
+import static org.jclouds.aws.ec2.options.AWSDescribeImagesOptions.Builder.filters;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.Set;
+
+import org.jclouds.aws.domain.Region;
+import org.jclouds.ec2.domain.Image;
+import org.jclouds.ec2.features.AMIApiLiveTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Tests behavior of {@code AMIApi}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true)
+public class AWSAMIApiLiveTest extends AMIApiLiveTest {
+
+   public AWSAMIApiLiveTest() {
+      provider = "aws-ec2";
+   }
+
+   public void testDescribeImagesCC() {
+      Set<? extends Image> ccResults = client.describeImagesInRegion(Region.US_EAST_1,
+            filters(ImmutableMultimap.<String, String> builder()//
+                  .put("virtualization-type", "hvm")//
+                  .put("architecture", "x86_64")//
+                  .putAll("owner-id", ImmutableSet.<String> of("137112412989", "099720109477"))//
+                  .put("hypervisor", "xen")//
+                  .put("state", "available")//
+                  .put("image-type", "machine")//
+                  .put("root-device-type", "ebs")//
+                  .build()).ownedBy("137112412989", "099720109477"));
+      assertNotNull(ccResults);
+      assert (ccResults.size() >= 34) : ccResults;
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSAMIApiTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSAMIApiTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSAMIApiTest.java
new file mode 100644
index 0000000..8f8a856
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSAMIApiTest.java
@@ -0,0 +1,497 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.executableBy;
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.aws.ec2.xml.ProductCodesHandler;
+import org.jclouds.ec2.options.CreateImageOptions;
+import org.jclouds.ec2.options.DescribeImagesOptions;
+import org.jclouds.ec2.options.RegisterImageBackedByEbsOptions;
+import org.jclouds.ec2.options.RegisterImageOptions;
+import org.jclouds.ec2.xml.BlockDeviceMappingHandler;
+import org.jclouds.ec2.xml.DescribeImagesResponseHandler;
+import org.jclouds.ec2.xml.ImageIdHandler;
+import org.jclouds.ec2.xml.PermissionHandler;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.http.functions.ReleasePayloadAndReturn;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.Lists;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code AWSAMIApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "AWSAMIApiTest")
+public class AWSAMIApiTest extends BaseAWSEC2ApiTest<AWSAMIApi> {
+   public AWSAMIApiTest() {
+      provider = "aws-ec2";
+   }
+
+   HttpRequest createImage = HttpRequest.builder().method("POST")
+                                        .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                        .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                        .addFormParam("Action", "CreateImage")
+                                        .addFormParam("InstanceId", "instanceId")
+                                        .addFormParam("Name", "name").build();
+
+   public void testCreateImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "createImageInRegion", String.class, String.class, String.class,
+               CreateImageOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "instanceId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(createImage).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest createImageOptions = HttpRequest.builder().method("POST")
+                                               .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                               .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                               .addFormParam("Action", "CreateImage")
+                                               .addFormParam("Description", "description")
+                                               .addFormParam("InstanceId", "instanceId")
+                                               .addFormParam("Name", "name")
+                                               .addFormParam("NoReboot", "true").build();
+
+   public void testCreateImageOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "createImageInRegion", String.class, String.class, String.class,
+               CreateImageOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "instanceId", new CreateImageOptions()
+               .withDescription("description").noReboot()));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(createImageOptions).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest describeImages = HttpRequest.builder().method("POST")
+                                           .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                           .addFormParam("Action", "DescribeImages").build();
+
+   public void testDescribeImages() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "describeImagesInRegion", String.class,
+               DescribeImagesOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(describeImages).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeImagesResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   HttpRequest describeImagesOptions = HttpRequest.builder().method("POST")
+                                                  .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                  .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                  .addFormParam("Action", "DescribeImages")
+                                                  .addFormParam("ExecutableBy", "me")
+                                                  .addFormParam("ImageId.1", "1")
+                                                  .addFormParam("ImageId.2", "2")
+                                                  .addFormParam("Owner.1", "fred")
+                                                  .addFormParam("Owner.2", "nancy").build();
+
+   public void testDescribeImagesOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "describeImagesInRegion", String.class,
+               DescribeImagesOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, executableBy("me").ownedBy("fred", "nancy").imageIds(
+               "1", "2")));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(describeImagesOptions).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeImagesResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   HttpRequest deregisterImage = HttpRequest.builder().method("POST")
+                                            .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                            .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                            .addFormParam("Action", "DeregisterImage")
+                                            .addFormParam("ImageId", "imageId").build();
+
+   public void testDeregisterImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "deregisterImageInRegion", String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(deregisterImage).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest registerImageFromManifest = HttpRequest.builder().method("POST")
+                                                      .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                      .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                      .addFormParam("Action", "RegisterImage")
+                                                      .addFormParam("ImageLocation", "pathToManifest")
+                                                      .addFormParam("Name", "name").build();
+
+   public void testRegisterImageFromManifest() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "registerImageFromManifestInRegion", String.class, String.class,
+               String.class, RegisterImageOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "pathToManifest"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(registerImageFromManifest).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest registerImageFromManifestOptions = HttpRequest.builder().method("POST")
+                                                             .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                             .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                             .addFormParam("Action", "RegisterImage")
+                                                             .addFormParam("Description", "description")
+                                                             .addFormParam("ImageLocation", "pathToManifest")
+                                                             .addFormParam("Name", "name").build();
+
+   public void testRegisterImageFromManifestOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "registerImageFromManifestInRegion", String.class, String.class,
+               String.class, RegisterImageOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "pathToManifest", new RegisterImageOptions()
+               .withDescription("description")));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(registerImageFromManifestOptions).getPayload().getRawContent()
+            .toString(), "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest registerImageBackedByEBS = HttpRequest.builder().method("POST")
+                                                     .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                     .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                     .addFormParam("Action", "RegisterImage")
+                                                     .addFormParam("BlockDeviceMapping.0.DeviceName", "/dev/sda1")
+                                                     .addFormParam("BlockDeviceMapping.0.Ebs.SnapshotId", "snapshotId")
+                                                     .addFormParam("Name", "imageName")
+                                                     .addFormParam("RootDeviceName", "/dev/sda1").build();
+
+   public void testRegisterImageBackedByEBS() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "registerUnixImageBackedByEbsInRegion", String.class,
+               String.class, String.class, RegisterImageBackedByEbsOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageName", "snapshotId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(registerImageBackedByEBS).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest registerImageBackedByEBSOptions = HttpRequest.builder().method("POST")
+                                                            .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                            .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                            .addFormParam("Action", "RegisterImage")
+                                                            .addFormParam("BlockDeviceMapping.0.DeviceName", "/dev/sda1")
+                                                            .addFormParam("BlockDeviceMapping.0.Ebs.SnapshotId", "snapshotId")
+                                                            .addFormParam("BlockDeviceMapping.1.DeviceName", "/dev/device")
+                                                            .addFormParam("BlockDeviceMapping.1.Ebs.DeleteOnTermination", "false")
+                                                            .addFormParam("BlockDeviceMapping.1.Ebs.SnapshotId", "snapshot")
+                                                            .addFormParam("BlockDeviceMapping.2.DeviceName", "/dev/newdevice")
+                                                            .addFormParam("BlockDeviceMapping.2.Ebs.DeleteOnTermination", "false")
+                                                            .addFormParam("BlockDeviceMapping.2.Ebs.VolumeSize", "100")
+                                                            .addFormParam("BlockDeviceMapping.2.VirtualName", "newblock")
+                                                            .addFormParam("Description", "description")
+                                                            .addFormParam("Name", "imageName")
+                                                            .addFormParam("RootDeviceName", "/dev/sda1").build();
+
+   public void testRegisterImageBackedByEBSOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "registerUnixImageBackedByEbsInRegion", String.class,
+               String.class, String.class, RegisterImageBackedByEbsOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageName", "snapshotId",
+               new RegisterImageBackedByEbsOptions().withDescription("description").addBlockDeviceFromSnapshot(
+                        "/dev/device", null, "snapshot").addNewBlockDevice("/dev/newdevice", "newblock", 100)));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(registerImageBackedByEBSOptions).getPayload().getRawContent()
+            .toString(), "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest getBlockDeviceMappingsForImage = HttpRequest.builder().method("POST")
+                                                           .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                           .addFormParam("Action", "DescribeImageAttribute")
+                                                           .addFormParam("Attribute", "blockDeviceMapping")
+                                                           .addFormParam("ImageId", "imageId").build();
+
+   public void testGetBlockDeviceMappingsForImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "getBlockDeviceMappingsForImageInRegion", String.class,
+               String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(getBlockDeviceMappingsForImage).getPayload().getRawContent()
+            .toString(), "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, BlockDeviceMappingHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest getLaunchPermissionForImage = HttpRequest.builder().method("POST")
+                                                        .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                        .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                        .addFormParam("Action", "DescribeImageAttribute")
+                                                        .addFormParam("Attribute", "launchPermission")
+                                                        .addFormParam("ImageId", "imageId").build();
+
+   public void testGetLaunchPermissionForImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "getLaunchPermissionForImageInRegion", String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(getLaunchPermissionForImage).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, PermissionHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest addLaunchPermission = HttpRequest.builder().method("POST")
+                                                          .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                          .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                          .addFormParam("Action", "ModifyImageAttribute")
+                                                          .addFormParam("Attribute", "launchPermission")
+                                                          .addFormParam("ImageId", "imageId")
+                                                          .addFormParam("OperationType", "add")
+                                                          .addFormParam("UserGroup.1", "all")
+                                                          .addFormParam("UserId.1", "bob")
+                                                          .addFormParam("UserId.2", "sue").build();
+
+   public void testAddLaunchPermissionsToImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "addLaunchPermissionsToImageInRegion", String.class,
+               Iterable.class, Iterable.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("bob", "sue"), ImmutableList
+               .of("all"), "imageId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(addLaunchPermission).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest removeLaunchPermission = HttpRequest.builder().method("POST")
+                                                   .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                   .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                   .addFormParam("Action", "ModifyImageAttribute")
+                                                   .addFormParam("Attribute", "launchPermission")
+                                                   .addFormParam("ImageId", "imageId")
+                                                   .addFormParam("OperationType", "remove")
+                                                   .addFormParam("UserGroup.1", "all")
+                                                   .addFormParam("UserId.1", "bob")
+                                                   .addFormParam("UserId.2", "sue").build();
+
+   public void testRemoveLaunchPermissionsFromImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "removeLaunchPermissionsFromImageInRegion", String.class,
+               Iterable.class, Iterable.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("bob", "sue"), ImmutableList
+               .of("all"), "imageId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(removeLaunchPermission).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest resetLaunchPermissionsOnImage = HttpRequest.builder().method("POST")
+                                                          .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                          .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                          .addFormParam("Action", "ResetImageAttribute")
+                                                          .addFormParam("Attribute", "launchPermission")
+                                                          .addFormParam("ImageId", "imageId").build();
+
+   public void testResetLaunchPermissionsOnImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "resetLaunchPermissionsOnImageInRegion", String.class,
+               String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+            filter.filter(resetLaunchPermissionsOnImage).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetProductCodesForImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "getProductCodesForImageInRegion", String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+            "Action=DescribeImageAttribute&Attribute=productCodes&ImageId=imageId",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, ProductCodesHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testAddProductCodesToImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "addProductCodesToImageInRegion", String.class, Iterable.class,
+            String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("code1", "code2"), "imageId"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(
+            request,
+            "Action=ModifyImageAttribute&OperationType=add&Attribute=productCodes&ImageId=imageId&ProductCode.1=code1&ProductCode.2=code2",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testRemoveProductCodesFromImage() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSAMIApi.class, "removeProductCodesFromImageInRegion", String.class,
+            Iterable.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("code1", "code2"), "imageId"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(
+            request,
+            "Action=ModifyImageAttribute&OperationType=remove&Attribute=productCodes&ImageId=imageId&ProductCode.1=code1&ProductCode.2=code2",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSInstanceApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSInstanceApiLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSInstanceApiLiveTest.java
new file mode 100644
index 0000000..468de54
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSInstanceApiLiveTest.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.aws.ec2.features;
+
+import static org.testng.Assert.assertNotNull;
+
+import java.util.Set;
+
+import org.jclouds.aws.ec2.AWSEC2Api;
+import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.ec2.domain.Reservation;
+import org.jclouds.ec2.domain.RunningInstance;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code AWSEC2Api}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true)
+public class AWSInstanceApiLiveTest extends BaseComputeServiceContextLiveTest {
+   public AWSInstanceApiLiveTest() {
+      provider = "aws-ec2";
+   }
+   
+   public static final String PREFIX = System.getProperty("user.name") + "-ec2";
+
+   private AWSInstanceApi client;
+   
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      client = view.unwrapApi(AWSEC2Api.class).getInstanceApi().get();
+   }
+
+   @Test
+   void testDescribeInstances() {
+      for (String region : view.unwrapApi(AWSEC2Api.class).getAvailabilityZoneAndRegionApi().get().describeRegions().keySet()) {
+         Set<? extends Reservation<? extends RunningInstance>> allResults = client.describeInstancesInRegion(region);
+         assertNotNull(allResults);
+         assert allResults.size() >= 0 : allResults.size();
+      }
+   }
+
+}


[04/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSInstanceApiTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSInstanceApiTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSInstanceApiTest.java
new file mode 100644
index 0000000..c59037d
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSInstanceApiTest.java
@@ -0,0 +1,539 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+import java.util.Map;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.aws.ec2.options.AWSRunInstancesOptions;
+import org.jclouds.aws.ec2.xml.AWSDescribeInstancesResponseHandler;
+import org.jclouds.aws.ec2.xml.AWSRunInstancesResponseHandler;
+import org.jclouds.ec2.domain.BlockDevice;
+import org.jclouds.ec2.domain.InstanceType;
+import org.jclouds.ec2.domain.Volume.InstanceInitiatedShutdownBehavior;
+import org.jclouds.ec2.options.RunInstancesOptions;
+import org.jclouds.ec2.xml.BlockDeviceMappingHandler;
+import org.jclouds.ec2.xml.BooleanValueHandler;
+import org.jclouds.ec2.xml.InstanceInitiatedShutdownBehaviorHandler;
+import org.jclouds.ec2.xml.InstanceStateChangeHandler;
+import org.jclouds.ec2.xml.InstanceTypeHandler;
+import org.jclouds.ec2.xml.StringValueHandler;
+import org.jclouds.ec2.xml.UnencodeStringValueHandler;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.http.functions.ReleasePayloadAndReturn;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Lists;
+import com.google.common.collect.Maps;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code AWSInstanceApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during
+// surefire
+@Test(groups = "unit", testName = "AWSInstanceApiTest")
+public class AWSInstanceApiTest extends BaseAWSEC2ApiTest<AWSInstanceApi> {
+   public void testDescribeInstances() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "describeInstancesInRegion", String.class, String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeInstances", "application/x-www-form-urlencoded",
+            false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, AWSDescribeInstancesResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeInstancesArgs() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "describeInstancesInRegion", String.class, String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeInstances&InstanceId.1=1&InstanceId.2=2",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, AWSDescribeInstancesResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testTerminateInstances() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "terminateInstancesInRegion", String.class, String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=TerminateInstances&InstanceId.1=1&InstanceId.2=2",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testRunInstances() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "runInstancesInRegion", String.class, String.class,
+            String.class, int.class, int.class, RunInstancesOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, null, "ami-voo", 1, 1));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=RunInstances&ImageId=ami-voo&MinCount=1&MaxCount=1",
+            "application/x-www-form-urlencoded", false);
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, AWSRunInstancesResponseHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testRunInstancesOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "runInstancesInRegion", String.class, String.class,
+            String.class, int.class, int.class, RunInstancesOptions[].class);
+      GeneratedHttpRequest request = processor.createRequest(
+            method,
+            Lists.<Object> newArrayList("us-east-1",
+            "us-east-1a",
+            "ami-voo",
+            1,
+            5,
+            new AWSRunInstancesOptions().withKernelId("kernelId").enableMonitoring()
+                  .withSecurityGroups("group1", "group2")));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(
+            request,
+            "Action=RunInstances&ImageId=ami-voo&MinCount=1&MaxCount=5&KernelId=kernelId&Monitoring.Enabled=true&SecurityGroup.1=group1&SecurityGroup.2=group2&Placement.AvailabilityZone=us-east-1a",
+            "application/x-www-form-urlencoded", false);
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, AWSRunInstancesResponseHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testStopInstances() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "stopInstancesInRegion", String.class, boolean.class,
+            String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, true, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=StopInstances&Force=true&InstanceId.1=1&InstanceId.2=2",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testRebootInstances() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "rebootInstancesInRegion", String.class,
+            String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=RebootInstances&InstanceId.1=1&InstanceId.2=2",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testStartInstances() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "startInstancesInRegion", String.class,
+            String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=StartInstances&InstanceId.1=1&InstanceId.2=2",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, InstanceStateChangeHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetUserDataForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "getUserDataForInstanceInRegion", String.class,
+            String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+            "Action=DescribeInstanceAttribute&Attribute=userData&InstanceId=1",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, UnencodeStringValueHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetRootDeviceNameForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "getRootDeviceNameForInstanceInRegion", String.class,
+            String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+            "Action=DescribeInstanceAttribute&Attribute=rootDeviceName&InstanceId=1",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, StringValueHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetRamdiskForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "getRamdiskForInstanceInRegion", String.class,
+            String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+            "Action=DescribeInstanceAttribute&Attribute=ramdisk&InstanceId=1",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, StringValueHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetDisableApiTerminationForInstanceInRegion() throws SecurityException, NoSuchMethodException,
+         IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "isApiTerminationDisabledForInstanceInRegion",
+            String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+            "Action=DescribeInstanceAttribute&Attribute=disableApiTermination&InstanceId=1",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, BooleanValueHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetKernelForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "getKernelForInstanceInRegion", String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeInstanceAttribute&Attribute=kernel&InstanceId=1",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, StringValueHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetInstanceTypeForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "getInstanceTypeForInstanceInRegion", String.class,
+            String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+            "Action=DescribeInstanceAttribute&Attribute=instanceType&InstanceId=1",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, InstanceTypeHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetInstanceInitiatedShutdownBehaviorForInstanceInRegion() throws SecurityException,
+         NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "getInstanceInitiatedShutdownBehaviorForInstanceInRegion",
+            String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(
+            request,
+            "Action=DescribeInstanceAttribute&Attribute=instanceInitiatedShutdownBehavior&InstanceId=1",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, InstanceInitiatedShutdownBehaviorHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testGetBlockDeviceMappingForInstanceInRegion() throws SecurityException, NoSuchMethodException,
+         IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "getBlockDeviceMappingForInstanceInRegion", String.class,
+            String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+            "Action=DescribeInstanceAttribute&Attribute=blockDeviceMapping&InstanceId=1",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, BlockDeviceMappingHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest setUserDataForInstance = HttpRequest.builder().method("POST")
+                                                   .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                   .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                   .addFormParam("Action", "ModifyInstanceAttribute")
+                                                   .addFormParam("Attribute", "userData")
+                                                   .addFormParam("InstanceId", "1")
+                                                   .addFormParam("Value", "dGVzdA%3D%3D").build();
+
+   public void testSetUserDataForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "setUserDataForInstanceInRegion", String.class, String.class,
+               byte[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "test".getBytes()));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(setUserDataForInstance).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest setRamdiskForInstance = HttpRequest.builder().method("POST")
+                                                  .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                  .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                  .addFormParam("Action", "ModifyInstanceAttribute")
+                                                  .addFormParam("Attribute", "ramdisk")
+                                                  .addFormParam("InstanceId", "1")
+                                                  .addFormParam("Value", "test").build();
+
+   public void testSetRamdiskForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "setRamdiskForInstanceInRegion", String.class, String.class,
+               String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "test"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(setRamdiskForInstance).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest setKernelForInstance = HttpRequest.builder().method("POST")
+                                                 .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                 .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                 .addFormParam("Action", "ModifyInstanceAttribute")
+                                                 .addFormParam("Attribute", "kernel")
+                                                 .addFormParam("InstanceId", "1")
+                                                 .addFormParam("Value", "test").build();
+
+   public void testSetKernelForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "setKernelForInstanceInRegion", String.class, String.class,
+               String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "test"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(setKernelForInstance).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest setApiTerminationDisabled = HttpRequest.builder().method("POST")
+                                                      .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                      .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                      .addFormParam("Action", "ModifyInstanceAttribute")
+                                                      .addFormParam("Attribute", "disableApiTermination")
+                                                      .addFormParam("InstanceId", "1")
+                                                      .addFormParam("Value", "true").build();
+
+   public void testSetApiTerminationDisabledForInstanceInRegion() throws SecurityException, NoSuchMethodException,
+            IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "setApiTerminationDisabledForInstanceInRegion", String.class,
+               String.class, boolean.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", true));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(setApiTerminationDisabled).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest instanceTypeForInstance = HttpRequest.builder().method("POST")
+                                                    .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                    .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                    .addFormParam("Action", "ModifyInstanceAttribute")
+                                                    .addFormParam("Attribute", "instanceType")
+                                                    .addFormParam("InstanceId", "1")
+                                                    .addFormParam("Value", "c1.medium").build();
+
+   public void testSetInstanceTypeForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "setInstanceTypeForInstanceInRegion", String.class,
+               String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", InstanceType.C1_MEDIUM));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(instanceTypeForInstance).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest setInstanceInitiatedShutdownBehavior = HttpRequest.builder().method("POST")
+                                                                 .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                                 .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                                 .addFormParam("Action", "ModifyInstanceAttribute")
+                                                                 .addFormParam("Attribute", "instanceInitiatedShutdownBehavior")
+                                                                 .addFormParam("InstanceId", "1")
+                                                                 .addFormParam("Value", "terminate").build();
+
+   public void testSetInstanceInitiatedShutdownBehaviorForInstanceInRegion() throws SecurityException,
+            NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "setInstanceInitiatedShutdownBehaviorForInstanceInRegion",
+               String.class, String.class, InstanceInitiatedShutdownBehavior.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", InstanceInitiatedShutdownBehavior.TERMINATE));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(setInstanceInitiatedShutdownBehavior).getPayload().getRawContent()
+            .toString(), "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest setBlockDeviceMapping = HttpRequest.builder().method("POST")
+                                                           .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                           .addFormParam("Action", "ModifyInstanceAttribute")
+                                                           .addFormParam("BlockDeviceMapping.1.DeviceName", "/dev/sda1")
+                                                           .addFormParam("BlockDeviceMapping.1.Ebs.DeleteOnTermination", "true")
+                                                           .addFormParam("BlockDeviceMapping.1.Ebs.VolumeId", "vol-test1")
+                                                           .addFormParam("InstanceId", "1").build();
+
+   public void testSetBlockDeviceMappingForInstanceInRegion() throws SecurityException, NoSuchMethodException,
+         IOException {
+      Invokable<?, ?> method = method(AWSInstanceApi.class, "setBlockDeviceMappingForInstanceInRegion", String.class,
+            String.class, Map.class);
+
+      Map<String, BlockDevice> mapping = Maps.newLinkedHashMap();
+      mapping.put("/dev/sda1", new BlockDevice("vol-test1", true));
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", mapping));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(setBlockDeviceMapping).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSKeyPairApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSKeyPairApiLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSKeyPairApiLiveTest.java
new file mode 100644
index 0000000..e629e7f
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSKeyPairApiLiveTest.java
@@ -0,0 +1,209 @@
+/*
+ * 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.aws.ec2.features;
+
+import static com.google.common.collect.Iterables.get;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.collect.Sets.newTreeSet;
+import static org.jclouds.compute.options.TemplateOptions.Builder.overrideLoginCredentials;
+import static org.jclouds.compute.predicates.NodePredicates.inGroup;
+import static org.jclouds.compute.predicates.NodePredicates.runningInGroup;
+import static org.jclouds.scriptbuilder.domain.Statements.exec;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.fail;
+
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+
+import org.jclouds.aws.domain.Region;
+import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
+import org.jclouds.aws.ec2.AWSEC2Api;
+import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
+import org.jclouds.aws.ec2.domain.AWSRunningInstance;
+import org.jclouds.compute.ComputeServiceContext;
+import org.jclouds.compute.ComputeTestUtils;
+import org.jclouds.compute.domain.ExecResponse;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.compute.options.TemplateOptions;
+import org.jclouds.domain.LoginCredentials;
+import org.jclouds.ec2.domain.KeyPair;
+import org.jclouds.logging.log4j.config.Log4JLoggingModule;
+import org.jclouds.sshj.config.SshjSshClientModule;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+
+/**
+ * Tests behavior of {@code AWSKeyPairApi}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true)
+public class AWSKeyPairApiLiveTest extends BaseComputeServiceContextLiveTest {
+   public AWSKeyPairApiLiveTest() {
+      provider = "aws-ec2";
+   }
+
+   private AWSKeyPairApi client;
+   
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      client = view.unwrapApi(AWSEC2Api.class).getKeyPairApi().get();
+   }
+
+   public void testNoSsh() throws Exception {
+
+      Map<String, String> keyPair = ComputeTestUtils.setupKeyPair();
+
+      AWSInstanceApi instanceApi = view.unwrapApi(AWSEC2Api.class).getInstanceApi().get();
+
+      String group = PREFIX + "unssh";
+      view.getComputeService().destroyNodesMatching(inGroup(group));
+
+      TemplateOptions options = view.getComputeService().templateOptions();
+
+      options.authorizePublicKey(keyPair.get("public")).as(AWSEC2TemplateOptions.class);
+
+      ComputeServiceContext noSshContext = null;
+      try {
+         noSshContext = createView(setupProperties(), ImmutableSet.<Module> of(new Log4JLoggingModule()));
+
+         Set<? extends NodeMetadata> nodes = noSshContext.getComputeService().createNodesInGroup(group, 1, options);
+
+         NodeMetadata first = get(nodes, 0);
+         assert first.getCredentials() != null : first;
+         assert first.getCredentials().identity != null : first;
+         // credentials should not be present as the import public key call doesn't have access to
+         // the related private key
+         assert first.getCredentials().credential == null : first;
+
+         AWSRunningInstance instance = getInstance(instanceApi, first.getProviderId());
+
+         assertEquals(instance.getKeyName(), "jclouds#" + group);
+
+         Map<? extends NodeMetadata, ExecResponse> responses = view.getComputeService()
+               .runScriptOnNodesMatching(
+                     runningInGroup(group),
+                     exec("echo hello"),
+                     overrideLoginCredentials(
+                           LoginCredentials.builder().user(first.getCredentials().identity)
+                                 .privateKey(keyPair.get("private")).build()).wrapInInitScript(false).runAsRoot(false));
+
+         ExecResponse hello = getOnlyElement(responses.values());
+         assertEquals(hello.getOutput().trim(), "hello");
+
+      } finally {
+         noSshContext.close();
+         view.getComputeService().destroyNodesMatching(inGroup(group));
+      }
+   }
+
+   @Test
+   void testDescribeAWSKeyPairs() {
+      for (String region : Region.DEFAULT_REGIONS) {
+
+         SortedSet<KeyPair> allResults = newTreeSet(client.describeKeyPairsInRegion(region));
+         assertNotNull(allResults);
+         if (allResults.size() >= 1) {
+            KeyPair pair = allResults.last();
+            SortedSet<KeyPair> result = newTreeSet(client.describeKeyPairsInRegion(region, pair.getKeyName()));
+            assertNotNull(result);
+            KeyPair compare = result.last();
+            assertEquals(compare, pair);
+         }
+      }
+   }
+
+   public static final String PREFIX = System.getProperty("user.name") + "-ec2";
+
+   @Test
+   void testCreateKeyPair() {
+      String keyName = PREFIX + "1";
+      cleanupKeyPair(keyName);
+      try {
+         KeyPair keyPair = client.createKeyPairInRegion(null, keyName);
+         checkKeyPair(keyName, keyPair);
+         assertNotNull(keyPair.getKeyMaterial());
+      } finally {
+         cleanupKeyPair(keyName);
+      }
+   }
+
+   protected void cleanupKeyPair(String keyName) {
+      try {
+         client.deleteKeyPairInRegion(null, keyName);
+      } catch (Exception e) {
+
+      }
+      client.deleteKeyPairInRegion(null, keyName);
+   }
+
+   @Test
+   void testImportKeyPair() throws FileNotFoundException, IOException {
+      String keyName = PREFIX + "2";
+      cleanupKeyPair(keyName);
+      Map<String, String> myKey = ComputeTestUtils.setupKeyPair();
+      try {
+         KeyPair keyPair = client.importKeyPairInRegion(null, keyName, myKey.get("public"));
+         checkKeyPair(keyName, keyPair);
+         // TODO generate correct fingerprint and check
+         // assertEquals(keyPair.getKeyFingerprint(),
+         // CryptoStreams.hex(CryptoStreams.md5(myKey.get("public").getBytes())));
+
+         // try again to see if there's an error
+         try {
+            client.importKeyPairInRegion(null, keyName, myKey.get("public"));
+            fail("Expected IllegalStateException");
+         } catch (IllegalStateException e) {
+
+         }
+      } finally {
+         cleanupKeyPair(keyName);
+      }
+   }
+
+   protected void checkKeyPair(String keyName, KeyPair keyPair) {
+      assertNotNull(keyPair);
+      assertNotNull(keyPair.getSha1OfPrivateKey());
+      assertEquals(keyPair.getKeyName(), keyName);
+
+      Set<KeyPair> twoResults = client.describeKeyPairsInRegion(null, keyName);
+      assertNotNull(twoResults);
+      assertEquals(twoResults.size(), 1);
+      KeyPair listPair = twoResults.iterator().next();
+      assertEquals(listPair.getKeyName(), keyPair.getKeyName());
+      assertEquals(listPair.getSha1OfPrivateKey(), keyPair.getSha1OfPrivateKey());
+   }
+
+   protected AWSRunningInstance getInstance(AWSInstanceApi instanceApi, String id) {
+      return getOnlyElement(getOnlyElement(instanceApi.describeInstancesInRegion(null, id)));
+   }
+   
+   @Override
+   protected Module getSshModule() {
+      return new SshjSshClientModule();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSKeyPairApiTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSKeyPairApiTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSKeyPairApiTest.java
new file mode 100644
index 0000000..d97ee6e
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSKeyPairApiTest.java
@@ -0,0 +1,134 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.ec2.xml.DescribeKeyPairsResponseHandler;
+import org.jclouds.ec2.xml.KeyPairResponseHandler;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.http.functions.ReleasePayloadAndReturn;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Lists;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code AWSKeyPairApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "AWSKeyPairApiTest")
+public class AWSKeyPairApiTest extends BaseAWSEC2ApiTest<AWSKeyPairApi> {
+
+   public void testCreateKeyPair() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSKeyPairApi.class, "createKeyPairInRegion", String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "mykey"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=CreateKeyPair&KeyName=mykey",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, KeyPairResponseHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest importKeyPair = HttpRequest.builder().method("POST")
+                                          .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                          .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                          .addFormParam("Action", "ImportKeyPair")
+                                          .addFormParam("KeyName", "mykey")
+                                          .addFormParam("PublicKeyMaterial", "c3NoLXJzYSBBQQ%3D%3D").build();
+
+   public void testImportKeyPair() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSKeyPairApi.class, "importKeyPairInRegion", String.class, String.class,
+            String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "mykey", "ssh-rsa AA"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(importKeyPair).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, KeyPairResponseHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testDeleteKeyPair() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSKeyPairApi.class, "deleteKeyPairInRegion", String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "mykey"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DeleteKeyPair&KeyName=mykey",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeKeyPairs() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSKeyPairApi.class, "describeKeyPairsInRegion", String.class,
+            String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeKeyPairs", "application/x-www-form-urlencoded",
+            false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeKeyPairsResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeKeyPairsArgs() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSKeyPairApi.class, "describeKeyPairsInRegion", String.class,
+            String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeKeyPairs&KeyName.1=1&KeyName.2=2",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeKeyPairsResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiLiveTest.java
new file mode 100644
index 0000000..731c703
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiLiveTest.java
@@ -0,0 +1,85 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.Set;
+
+import org.jclouds.ec2.domain.SecurityGroup;
+import org.jclouds.ec2.features.SecurityGroupApiLiveTest;
+import org.jclouds.ec2.util.IpPermissions;
+import org.jclouds.net.domain.IpPermission;
+import org.jclouds.net.domain.IpProtocol;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMultimap;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true)
+public class AWSSecurityGroupApiLiveTest extends SecurityGroupApiLiveTest {
+   public AWSSecurityGroupApiLiveTest() {
+      provider = "aws-ec2";
+   }
+
+   @Test
+   void testAuthorizeSecurityGroupIngressIpPermission() throws InterruptedException {
+      final String group1Name = PREFIX + "ingress11";
+      String group2Name = PREFIX + "ingress12";
+      cleanupAndSleep(group2Name);
+      cleanupAndSleep(group1Name);
+      try {
+         String group1Id = AWSSecurityGroupApi.class.cast(client).createSecurityGroupInRegionAndReturnId(null,
+               group1Name, group1Name);
+         String group2Id = AWSSecurityGroupApi.class.cast(client).createSecurityGroupInRegionAndReturnId(null,
+               group2Name, group2Name);
+         Thread.sleep(100);// eventual consistent
+         ensureGroupsExist(group1Name, group2Name);
+         AWSSecurityGroupApi.class.cast(client).authorizeSecurityGroupIngressInRegion(null, group1Id,
+               IpPermissions.permit(IpProtocol.TCP).port(80));
+         assertEventually(new GroupHasPermission(client, group1Name, new TCPPort80AllIPs()));
+         Set<SecurityGroup> oneResult = client.describeSecurityGroupsInRegion(null, group1Name);
+         assertNotNull(oneResult);
+         assertEquals(oneResult.size(), 1);
+         final SecurityGroup group = oneResult.iterator().next();
+         assertEquals(group.getName(), group1Name);
+         IpPermissions group2CanHttpGroup1 = IpPermissions.permit(IpProtocol.TCP).port(80)
+               .originatingFromSecurityGroupId(group1Id);
+         AWSSecurityGroupApi.class.cast(client).authorizeSecurityGroupIngressInRegion(null, group2Id,
+               group2CanHttpGroup1);
+         assertEventually(new GroupHasPermission(client, group2Name, new Predicate<IpPermission>() {
+            @Override
+            public boolean apply(IpPermission arg0) {
+               return arg0.getTenantIdGroupNamePairs().equals(ImmutableMultimap.of(group.getOwnerId(), group1Name))
+                     && arg0.getFromPort() == 80 && arg0.getToPort() == 80 && arg0.getIpProtocol() == IpProtocol.TCP;
+            }
+         }));
+
+         AWSSecurityGroupApi.class.cast(client).revokeSecurityGroupIngressInRegion(null, group2Id,
+               group2CanHttpGroup1);
+         assertEventually(new GroupHasNoPermissions(client, group2Name));
+      } finally {
+         client.deleteSecurityGroupInRegion(null, group2Name);
+         client.deleteSecurityGroupInRegion(null, group1Name);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiTest.java
new file mode 100644
index 0000000..93798aa
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiTest.java
@@ -0,0 +1,207 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.ec2.util.IpPermissions;
+import org.jclouds.ec2.xml.DescribeSecurityGroupsResponseHandler;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.http.functions.ReleasePayloadAndReturn;
+import org.jclouds.net.domain.IpPermission;
+import org.jclouds.net.domain.IpProtocol;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Lists;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code AWSSecurityGroupApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during
+// surefire
+@Test(groups = "unit", testName = "AWSSecurityGroupApiTest")
+public class AWSSecurityGroupApiTest extends BaseAWSEC2ApiTest<AWSSecurityGroupApi> {
+   public AWSSecurityGroupApiTest() {
+      provider = "aws-ec2";
+   }
+
+   public void testDeleteSecurityGroup() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSSecurityGroupApi.class, "deleteSecurityGroupInRegionById", String.class,
+            String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "id"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DeleteSecurityGroup&GroupId=id",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, VoidOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeSecurityGroups() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSSecurityGroupApi.class, "describeSecurityGroupsInRegionById", String.class,
+            String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeSecurityGroups",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeSecurityGroupsResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeSecurityGroupsArgs() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSSecurityGroupApi.class, "describeSecurityGroupsInRegionById", String.class,
+            String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeSecurityGroups&GroupId.1=1&GroupId.2=2",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeSecurityGroupsResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   HttpRequest createSecurityGroup = HttpRequest.builder().method("POST")
+                                                .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                .addFormParam("Action", "CreateSecurityGroup")
+                                                .addFormParam("GroupDescription", "description")
+                                                .addFormParam("GroupName", "name").build();
+
+   public void testCreateSecurityGroup() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSSecurityGroupApi.class, "createSecurityGroupInRegion", String.class,
+            String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "description"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, filter.filter(createSecurityGroup).getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testAuthorizeSecurityGroupIpPermission() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSSecurityGroupApi.class, "authorizeSecurityGroupIngressInRegion",
+            String.class, String.class, IpPermission.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", IpPermissions.permitAnyProtocol()));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(
+            request,
+            "Action=AuthorizeSecurityGroupIngress&GroupId=group&IpPermissions.0.IpProtocol=-1&IpPermissions.0.FromPort=1&IpPermissions.0.ToPort=65535&IpPermissions.0.IpRanges.0.CidrIp=0.0.0.0/0",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testAuthorizeSecurityGroupIpPermissions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSSecurityGroupApi.class, "authorizeSecurityGroupIngressInRegion",
+            String.class, String.class, Iterable.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", ImmutableSet.<IpPermission> of(IpPermissions
+            .permit(IpProtocol.TCP).originatingFromCidrBlock("1.1.1.1/32"), IpPermissions.permitICMP().type(8).andCode(0)
+            .originatingFromSecurityGroupId("groupId"))));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(
+            request,
+            "Action=AuthorizeSecurityGroupIngress&GroupId=group&IpPermissions.0.IpProtocol=tcp&IpPermissions.0.FromPort=1&IpPermissions.0.ToPort=65535&IpPermissions.0.IpRanges.0.CidrIp=1.1.1.1/32&IpPermissions.1.IpProtocol=icmp&IpPermissions.1.FromPort=8&IpPermissions.1.ToPort=0&IpPermissions.1.Groups.0.GroupId=groupId",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testRevokeSecurityGroupIpPermission() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSSecurityGroupApi.class, "revokeSecurityGroupIngressInRegion", String.class,
+            String.class, IpPermission.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", IpPermissions.permitAnyProtocol()));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(
+            request,
+            "Action=RevokeSecurityGroupIngress&GroupId=group&IpPermissions.0.IpProtocol=-1&IpPermissions.0.FromPort=1&IpPermissions.0.ToPort=65535&IpPermissions.0.IpRanges.0.CidrIp=0.0.0.0/0",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testRevokeSecurityGroupIpPermissions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(AWSSecurityGroupApi.class, "revokeSecurityGroupIngressInRegion", String.class,
+            String.class, Iterable.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", ImmutableSet.<IpPermission> of(IpPermissions
+            .permit(IpProtocol.TCP).originatingFromCidrBlock("1.1.1.1/32"), IpPermissions.permitICMP().type(8).andCode(0)
+            .originatingFromSecurityGroupId("groupId"))));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(
+            request,
+            "Action=RevokeSecurityGroupIngress&GroupId=group&IpPermissions.0.IpProtocol=tcp&IpPermissions.0.FromPort=1&IpPermissions.0.ToPort=65535&IpPermissions.0.IpRanges.0.CidrIp=1.1.1.1/32&IpPermissions.1.IpProtocol=icmp&IpPermissions.1.FromPort=8&IpPermissions.1.ToPort=0&IpPermissions.1.Groups.0.GroupId=groupId",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/BaseAWSEC2ApiTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/BaseAWSEC2ApiTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/BaseAWSEC2ApiTest.java
new file mode 100644
index 0000000..aa79621
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/BaseAWSEC2ApiTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.aws.ec2.features;
+
+import static com.google.common.collect.Maps.transformValues;
+import static org.testng.Assert.assertEquals;
+
+import java.io.IOException;
+import java.net.URI;
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Singleton;
+
+import org.jclouds.aws.domain.Region;
+import org.jclouds.aws.ec2.AWSEC2ProviderMetadata;
+import org.jclouds.aws.ec2.config.AWSEC2HttpApiModule;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.compute.domain.Image;
+import org.jclouds.date.DateService;
+import org.jclouds.ec2.compute.domain.RegionAndName;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.location.config.LocationModule;
+import org.jclouds.location.suppliers.RegionIdToURISupplier;
+import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.internal.BaseAsyncApiTest;
+import org.jclouds.util.Suppliers2;
+import org.testng.annotations.BeforeTest;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Supplier;
+import com.google.common.cache.CacheBuilder;
+import com.google.common.cache.CacheLoader;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Module;
+import com.google.inject.Provides;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit")
+public abstract class BaseAWSEC2ApiTest<T> extends BaseAsyncApiTest<T> {
+
+      @ConfiguresHttpApi
+   protected static class StubAWSEC2HttpApiModule extends AWSEC2HttpApiModule {
+
+      @Override
+      protected String provideTimeStamp(DateService dateService) {
+         return "2009-11-08T15:54:08.897Z";
+      }
+
+      @Provides
+      @Singleton
+      LoadingCache<RegionAndName, Image> provide() {
+         return CacheBuilder.newBuilder().build(new CacheLoader<RegionAndName, Image>() {
+
+            @Override
+            public Image load(RegionAndName key) throws Exception {
+               return null;
+            }
+
+         });
+      }
+
+      @Override
+      protected void installLocations() {
+         install(new LocationModule());
+         bind(RegionIdToURISupplier.class).toInstance(new RegionIdToURISupplier() {
+
+            @Override
+            public Map<String, Supplier<URI>> get() {
+               return transformValues(ImmutableMap.<String, URI> of(Region.EU_WEST_1, URI
+                        .create("https://ec2.eu-west-1.amazonaws.com"), Region.US_EAST_1, URI
+                        .create("https://ec2.us-east-1.amazonaws.com"), Region.US_WEST_1, URI
+                        .create("https://ec2.us-west-1.amazonaws.com")), Suppliers2.<URI> ofInstanceFunction());
+            }
+
+         });
+         bind(RegionIdToZoneIdsSupplier.class).toInstance(new RegionIdToZoneIdsSupplier() {
+
+            @Override
+            public Map<String, Supplier<Set<String>>> get() {
+               return transformValues(ImmutableMap.<String, Set<String>> of("us-east-1", ImmutableSet.of("us-east-1a",
+                        "us-east-1b", "us-east-1c", "us-east-1b")), Suppliers2.<Set<String>> ofInstanceFunction());
+            }
+
+         });
+      }
+   }
+
+   protected FormSigner filter;
+
+   @Override
+   protected void checkFilters(HttpRequest request) {
+      assertEquals(request.getFilters().size(), 1);
+      assertEquals(request.getFilters().get(0).getClass(), FormSigner.class);
+   }
+
+   @Override
+   @BeforeTest
+   protected void setupFactory() throws IOException {
+      super.setupFactory();
+      this.filter = injector.getInstance(FormSigner.class);
+   }
+
+   @Override
+   protected Module createModule() {
+      return new StubAWSEC2HttpApiModule();
+   }
+
+   protected String provider = "aws-ec2";
+
+   @Override
+   public AWSEC2ProviderMetadata createProviderMetadata(){
+      return new AWSEC2ProviderMetadata();
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/MonitoringApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/MonitoringApiLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/MonitoringApiLiveTest.java
new file mode 100644
index 0000000..6d5e917
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/MonitoringApiLiveTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Map;
+
+import org.jclouds.aws.ec2.AWSEC2Api;
+import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
+import org.jclouds.aws.ec2.domain.MonitoringState;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code MonitoringApi}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true)
+public class MonitoringApiLiveTest extends BaseComputeServiceContextLiveTest {
+   public MonitoringApiLiveTest() {
+      provider = "aws-ec2";
+   }
+
+   private MonitoringApi client;
+   private static final String DEFAULT_INSTANCE = "i-TODO";
+
+   
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      client = view.unwrapApi(AWSEC2Api.class).getMonitoringApi().get();
+   }
+
+   @Test(enabled = false)
+   // TODO get instance
+   public void testMonitorInstances() {
+      Map<String, MonitoringState> monitoringState = client.monitorInstancesInRegion(null, DEFAULT_INSTANCE);
+      assertEquals(monitoringState.get(DEFAULT_INSTANCE), MonitoringState.PENDING);
+   }
+
+   @Test(enabled = false)
+   // TODO get instance
+   public void testUnmonitorInstances() {
+      Map<String, MonitoringState> monitoringState = client.unmonitorInstancesInRegion(null, DEFAULT_INSTANCE);
+      assertEquals(monitoringState.get(DEFAULT_INSTANCE), MonitoringState.PENDING);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/MonitoringApiTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/MonitoringApiTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/MonitoringApiTest.java
new file mode 100644
index 0000000..1d10906
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/MonitoringApiTest.java
@@ -0,0 +1,73 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.aws.ec2.xml.MonitoringStateHandler;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Lists;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code MonitoringApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "MonitoringApiTest")
+public class MonitoringApiTest extends BaseAWSEC2ApiTest<MonitoringApi> {
+
+   public void testUnmonitorInstances() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(MonitoringApi.class, "unmonitorInstancesInRegion", String.class, String.class,
+            String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "instance1", "instance2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      String payload = "Action=UnmonitorInstances&InstanceId.0=instance1&InstanceId.1=instance2";
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, payload, "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, MonitoringStateHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testMonitorInstances() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(MonitoringApi.class, "monitorInstancesInRegion", String.class, String.class,
+            String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "instance1", "instance2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request,
+            "Action=MonitorInstances&InstanceId.0=instance1&InstanceId.1=instance2",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, MonitoringStateHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiLiveTest.java
new file mode 100644
index 0000000..b39813e
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiLiveTest.java
@@ -0,0 +1,184 @@
+/*
+ * 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.aws.ec2.features;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static com.google.common.collect.Lists.newArrayList;
+import static com.google.common.collect.Sets.newTreeSet;
+import static java.util.concurrent.TimeUnit.SECONDS;
+import static org.jclouds.util.Predicates2.retry;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.fail;
+
+import java.util.ArrayList;
+import java.util.Set;
+import java.util.SortedSet;
+
+import org.jclouds.aws.domain.Region;
+import org.jclouds.aws.ec2.AWSEC2ApiMetadata;
+import org.jclouds.aws.ec2.AWSEC2Api;
+import org.jclouds.aws.ec2.domain.PlacementGroup;
+import org.jclouds.aws.ec2.domain.PlacementGroup.State;
+import org.jclouds.aws.ec2.predicates.PlacementGroupAvailable;
+import org.jclouds.aws.ec2.predicates.PlacementGroupDeleted;
+import org.jclouds.compute.RunNodesException;
+import org.jclouds.compute.domain.NodeMetadata;
+import org.jclouds.compute.domain.OsFamily;
+import org.jclouds.compute.domain.Template;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.compute.predicates.NodePredicates;
+import org.jclouds.ec2.compute.domain.EC2HardwareBuilder;
+import org.jclouds.ec2.domain.InstanceType;
+import org.jclouds.scriptbuilder.domain.Statements;
+import org.jclouds.scriptbuilder.statements.java.InstallJDK;
+import org.jclouds.scriptbuilder.statements.login.AdminAccess;
+import org.jclouds.sshj.config.SshjSshClientModule;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Predicate;
+import com.google.common.base.Throwables;
+import com.google.inject.Module;
+
+/**
+ * Tests behavior of {@code PlacementGroupApi}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "PlacementGroupApiLiveTest")
+public class PlacementGroupApiLiveTest extends BaseComputeServiceContextLiveTest {
+   ArrayList<String> supportedRegions = newArrayList(Region.US_EAST_1, Region.US_WEST_2, Region.EU_WEST_1);
+
+   public PlacementGroupApiLiveTest() {
+      provider = "aws-ec2";
+   }
+
+   private AWSEC2Api client;
+   private Predicate<PlacementGroup> availableTester;
+   private Predicate<PlacementGroup> deletedTester;
+   private PlacementGroup group;
+
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      client = view.unwrapApi(AWSEC2Api.class);;
+      availableTester = retry(new PlacementGroupAvailable(client), 60, 1, SECONDS);
+      deletedTester = retry(new PlacementGroupDeleted(client), 60, 1, SECONDS);
+   }
+
+   @Test
+   void testDescribe() {
+      for (String region : supportedRegions) {
+         SortedSet<PlacementGroup> allResults = newTreeSet(client.getPlacementGroupApi().get()
+                  .describePlacementGroupsInRegion(region));
+         assertNotNull(allResults);
+         if (allResults.size() >= 1) {
+            PlacementGroup group = allResults.last();
+            SortedSet<PlacementGroup> result = newTreeSet(client.getPlacementGroupApi().get()
+                     .describePlacementGroupsInRegion(region, group.getName()));
+            assertNotNull(result);
+            PlacementGroup compare = result.last();
+            assertEquals(compare, group);
+         }
+      }
+
+      for (String region : client.getAvailabilityZoneAndRegionApi().get().describeRegions().keySet()) {
+         if (!supportedRegions.contains(region))
+            try {
+               client.getPlacementGroupApi().get().describePlacementGroupsInRegion(region);
+               fail("should be unsupported for region: " + region);
+            } catch (UnsupportedOperationException e) {
+            }
+      }
+   }
+
+   @Test
+   void testCreatePlacementGroup() {
+      String groupName = PREFIX + "1";
+      for (String region : supportedRegions) {
+
+         client.getPlacementGroupApi().get().deletePlacementGroupInRegion(region, groupName);
+         client.getPlacementGroupApi().get().createPlacementGroupInRegion(region, groupName);
+
+         verifyPlacementGroup(region, groupName);
+      }
+   }
+
+   private void verifyPlacementGroup(String region, String groupName) {
+      assert availableTester.apply(new PlacementGroup(region, groupName, "cluster", State.PENDING)) : group;
+      Set<PlacementGroup> oneResult = client.getPlacementGroupApi().get().describePlacementGroupsInRegion(region,
+               groupName);
+      assertNotNull(oneResult);
+      assertEquals(oneResult.size(), 1);
+      group = oneResult.iterator().next();
+      assertEquals(group.getName(), groupName);
+      assertEquals(group.getStrategy(), "cluster");
+      assert availableTester.apply(group) : group;
+   }
+
+   public void testStartCCInstance() throws Exception {
+
+      Template template = view.getComputeService().templateBuilder()
+               .fromHardware(EC2HardwareBuilder.cc2_8xlarge().build()).osFamily(OsFamily.AMZN_LINUX).build();
+      assert template != null : "The returned template was null, but it should have a value.";
+      assertEquals(template.getHardware().getProviderId(), InstanceType.CC2_8XLARGE);
+      assertEquals(template.getImage().getUserMetadata().get("rootDeviceType"), "ebs");
+      assertEquals(template.getImage().getUserMetadata().get("virtualizationType"), "hvm");
+      assertEquals(template.getImage().getUserMetadata().get("hypervisor"), "xen");
+
+      template.getOptions().runScript(Statements.newStatementList(AdminAccess.standard(), InstallJDK.fromOpenJDK()));
+
+      String group = PREFIX + "cccluster";
+      view.getComputeService().destroyNodesMatching(NodePredicates.inGroup(group));
+      // TODO make this not lookup an explicit region
+      client.getPlacementGroupApi().get().deletePlacementGroupInRegion(null, "jclouds#" + group + "#us-east-1");
+
+      try {
+         Set<? extends NodeMetadata> nodes = view.getComputeService().createNodesInGroup(group, 1, template);
+         NodeMetadata node = getOnlyElement(nodes);
+
+         getOnlyElement(getOnlyElement(client.getInstanceApi().get().describeInstancesInRegion(null,
+                  node.getProviderId())));
+
+      } catch (RunNodesException e) {
+         System.err.println(e.getNodeErrors().keySet());
+         Throwables.propagate(e);
+      } finally {
+         view.getComputeService().destroyNodesMatching(NodePredicates.inGroup(group));
+      }
+   }
+
+   public static final String PREFIX = System.getProperty("user.name") + "ec2";
+
+   @Override
+   @AfterClass(groups = { "integration", "live" })
+   protected void tearDownContext() {
+      if (group != null) {
+         client.getPlacementGroupApi().get().deletePlacementGroupInRegion(group.getRegion(), group.getName());
+         assert deletedTester.apply(group) : group;
+      }
+      super.tearDownContext();
+   }
+
+   @Override
+   protected Module getSshModule() {
+      return new SshjSshClientModule();
+   }
+}


[06/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApi.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApi.java
new file mode 100644
index 0000000..d71d544
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApi.java
@@ -0,0 +1,125 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.aws.ec2.options.CreateSecurityGroupOptions;
+import org.jclouds.aws.ec2.xml.CreateSecurityGroupResponseHandler;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindGroupIdsToIndexedFormParams;
+import org.jclouds.ec2.binders.BindIpPermissionToIndexedFormParams;
+import org.jclouds.ec2.binders.BindIpPermissionsToIndexedFormParams;
+import org.jclouds.ec2.domain.SecurityGroup;
+import org.jclouds.ec2.features.SecurityGroupApi;
+import org.jclouds.ec2.xml.DescribeSecurityGroupsResponseHandler;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.net.domain.IpPermission;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+import com.google.common.annotations.Beta;
+
+/**
+ * Provides access to EC2 SecurityGroup Services via their REST API.
+ * <p/>
+ * 
+ * @author Adrian Cole
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+@Beta
+public interface AWSSecurityGroupApi extends SecurityGroupApi {
+
+   @Named("CreateSecurityGroup")
+   @POST
+   @Path("/")
+   @XMLResponseParser(CreateSecurityGroupResponseHandler.class)
+   @FormParams(keys = ACTION, values = "CreateSecurityGroup")
+   String createSecurityGroupInRegionAndReturnId(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("GroupName") String name, @FormParam("GroupDescription") String description,
+         CreateSecurityGroupOptions... options);
+
+   @Named("AuthorizeSecurityGroupIngress")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "AuthorizeSecurityGroupIngress")
+   void authorizeSecurityGroupIngressInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("GroupId") String groupId, @BinderParam(BindIpPermissionToIndexedFormParams.class) IpPermission perm);
+
+   @Named("AuthorizeSecurityGroupIngress")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "AuthorizeSecurityGroupIngress")
+   void authorizeSecurityGroupIngressInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("GroupId") String groupId,
+         @BinderParam(BindIpPermissionsToIndexedFormParams.class) Iterable<IpPermission> perms);
+
+   @Named("RevokeSecurityGroupIngress")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "RevokeSecurityGroupIngress")
+   void revokeSecurityGroupIngressInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("GroupId") String groupId, @BinderParam(BindIpPermissionToIndexedFormParams.class) IpPermission perm);
+
+   @Named("RevokeSecurityGroupIngress")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "RevokeSecurityGroupIngress")
+   void revokeSecurityGroupIngressInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("GroupId") String groupId,
+         @BinderParam(BindIpPermissionsToIndexedFormParams.class) Iterable<IpPermission> perms);
+
+   @Named("DeleteSecurityGroup")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DeleteSecurityGroup")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void deleteSecurityGroupInRegionById(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, @FormParam("GroupId") String name);
+
+   @Named("DescribeSecurityGroups")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeSecurityGroups")
+   @XMLResponseParser(DescribeSecurityGroupsResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<SecurityGroup> describeSecurityGroupsInRegionById(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @BinderParam(BindGroupIdsToIndexedFormParams.class) String... securityGroupNames);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/MonitoringApi.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/MonitoringApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/MonitoringApi.java
new file mode 100644
index 0000000..bb1de8a
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/MonitoringApi.java
@@ -0,0 +1,97 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import java.util.Map;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.aws.ec2.domain.MonitoringState;
+import org.jclouds.aws.ec2.xml.MonitoringStateHandler;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindInstanceIdsToIndexedFormParams;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+/**
+ * Provides access to EC2 Monitoring Services via their REST API.
+ * <p/>
+ * 
+ * @author Adrian Cole
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+public interface MonitoringApi {
+
+   /**
+    * Enables monitoring for a running instance. For more information, refer to the Amazon
+    * CloudWatch Developer Guide.
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance ID is tied to the
+    *           Region.
+    * @see InstanceApi#runInstances
+    * @see #unmonitorInstances
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-MonitorInstances.html"
+    *      />
+    */
+   @Named("MonitorInstances")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "MonitorInstances")
+   @XMLResponseParser(MonitoringStateHandler.class)
+   Map<String, MonitoringState> monitorInstancesInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("InstanceId.0") String instanceId,
+            @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
+
+   /**
+    * Disables monitoring for a running instance. For more information, refer to the Amazon
+    * CloudWatch Developer Guide.
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance ID is tied to the
+    *           Region.
+    * 
+    * @see InstanceApi#runInstances
+    * @see #monitorInstances
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-UnmonitorInstances.html"
+    *      />
+    */
+   @Named("UnmonitorInstances")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "UnmonitorInstances")
+   @XMLResponseParser(MonitoringStateHandler.class)
+   Map<String, MonitoringState> unmonitorInstancesInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("InstanceId.0") String instanceId,
+            @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/PlacementGroupApi.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/PlacementGroupApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/PlacementGroupApi.java
new file mode 100644
index 0000000..1acc121
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/PlacementGroupApi.java
@@ -0,0 +1,136 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.aws.ec2.domain.PlacementGroup;
+import org.jclouds.aws.ec2.xml.DescribePlacementGroupsResponseHandler;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindGroupNamesToIndexedFormParams;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+/**
+ * Provides access to EC2 Placement Groups via their REST API.
+ * <p/>
+ * 
+ * @author Adrian Cole
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+public interface PlacementGroupApi {
+
+   /**
+    * Creates a placement group that you launch cluster compute instances into. You must give the
+    * group a name unique within the scope of your account.
+    * 
+    * @param region
+    *           Region to create the placement group in.
+    * @param name
+    *           The name of the placement group..
+    * @param strategy
+    *           The placement group strategy.
+    * @see #describePlacementGroupsInRegion
+    * @see #deletePlacementGroupInRegion
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreatePlacementGroup.html"
+    *      />
+    */
+   @Named("CreatePlacementGroup")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "CreatePlacementGroup")
+   void createPlacementGroupInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("GroupName") String name, @FormParam("Strategy") String strategy);
+
+   /**
+    * like {@link #createPlacementGroupInRegion(String,String,String) except that the strategy is default: "cluster".
+    */
+   @Named("CreatePlacementGroup")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Strategy" }, values = { "CreatePlacementGroup", "cluster" })
+   void createPlacementGroupInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, @FormParam("GroupName") String name);
+
+   /**
+    * Deletes a placement group from your account. You must terminate all instances in the placement group before deleting it.
+    * 
+    * @param region
+    *           Region to delete the placement from from
+    * @param name
+    *           Name of the security group to delete.
+    * 
+    * @see #describePlacementGroupsInRegion
+    * @see #createPlacementGroupInRegion
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeletePlacementGroup.html"
+    *      />
+    */
+   @Named("DeletePlacementGroup")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DeletePlacementGroup")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void deletePlacementGroupInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, @FormParam("GroupName") String name);
+
+   /**
+    * 
+    * Returns information about one or more placement groups in your account.
+    * 
+    * @param region
+    *           The bundleTask ID is tied to the Region.
+    * @param groupNames
+    *           The name of the placement group. You can specify more than one in the request, or
+    *           omit the parameter if you want information about all your placement groups. By
+    *           default, all placement groups are described
+    * 
+    * @see #deletePlacementGroupInRegion
+    * @see #createPlacementGroupInRegion
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribePlacementGroups.html"
+    *      />
+    */
+   @Named("DescribePlacementGroups")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribePlacementGroups")
+   @XMLResponseParser(DescribePlacementGroupsResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<PlacementGroup> describePlacementGroupsInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @BinderParam(BindGroupNamesToIndexedFormParams.class) String... placementGroupIds);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/SpotInstanceApi.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/SpotInstanceApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/SpotInstanceApi.java
new file mode 100644
index 0000000..2d728e4
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/SpotInstanceApi.java
@@ -0,0 +1,214 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.aws.ec2.binders.BindLaunchSpecificationToFormParams;
+import org.jclouds.aws.ec2.binders.BindSpotInstanceRequestIdsToIndexedFormParams;
+import org.jclouds.aws.ec2.domain.LaunchSpecification;
+import org.jclouds.aws.ec2.domain.Spot;
+import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
+import org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions;
+import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions;
+import org.jclouds.aws.ec2.xml.DescribeSpotPriceHistoryResponseHandler;
+import org.jclouds.aws.ec2.xml.SpotInstanceHandler;
+import org.jclouds.aws.ec2.xml.SpotInstancesHandler;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+/**
+ * Provides access to EC2 Spot Instances via their REST API.
+ * <p/>
+ * 
+ * @author Adrian Cole
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+public interface SpotInstanceApi {
+
+   /**
+    * Describes Spot Instance requests. Spot Instances are instances that Amazon EC2 starts on your
+    * behalf when the maximum price that you specify exceeds the current Spot Price. Amazon EC2
+    * periodically sets the Spot Price based on available Spot Instance capacity and current spot
+    * instance requests. For conceptual information about Spot Instances, refer to the Amazon
+    * Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
+    * 
+    * @param region
+    *           Region where the spot instance service is running
+    * @param requestIds
+    *           Specifies the ID of the Spot Instance request.
+    * 
+    * @see #requestSpotInstancesInRegion
+    * @see #cancelSpotInstanceRequestsInRegion
+    * @see #describeSpotPriceHistoryInRegion
+    * @see <a href=
+    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSpotInstanceRequests.html"
+    *      />
+    * @return TODO
+    */
+   @Named("DescribeSpotInstanceRequests")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeSpotInstanceRequests")
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   @XMLResponseParser(SpotInstancesHandler.class)
+   Set<SpotInstanceRequest> describeSpotInstanceRequestsInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @BinderParam(BindSpotInstanceRequestIdsToIndexedFormParams.class) String... requestIds);
+
+   /**
+    * request a single spot instance
+    * 
+    * @param region
+    *           Region where the spot instance service is running
+    * @param spotPrice
+    *           Specifies the maximum hourly price for any Spot Instance launched to fulfill the
+    *           request.
+    * @param imageId
+    *           The AMI ID.
+    * @param instanceType
+    *           The instance type (ex. m1.small)
+    * @return spot instance request
+    * @see #requestSpotInstancesInRegion
+    */
+   @Named("RequestSpotInstances")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "RequestSpotInstances")
+   @XMLResponseParser(SpotInstanceHandler.class)
+   SpotInstanceRequest requestSpotInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("SpotPrice") float spotPrice, @FormParam("LaunchSpecification.ImageId") String imageId,
+         @FormParam("LaunchSpecification.InstanceType") String instanceType);
+
+   /**
+    * Creates a Spot Instance request. Spot Instances are instances that Amazon EC2 starts on your
+    * behalf when the maximum price that you specify exceeds the current Spot Price. Amazon EC2
+    * periodically sets the Spot Price based on available Spot Instance capacity and current spot
+    * instance requests. For conceptual information about Spot Instances, refer to the Amazon
+    * Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
+    * 
+    * @param region
+    *           Region where the spot instance service is running
+    * @param spotPrice
+    *           Specifies the maximum hourly price for any Spot Instance launched to fulfill the
+    *           request.
+    * @param instanceCount
+    *           number of instances to request
+    * @param launchSpec
+    *           includes at least The AMI ID and instance type (ex. m1.small)
+    * @param options
+    *           options including expiration time or grouping
+    * 
+    * @see #describeSpotInstanceRequestsInRegion
+    * @see #cancelSpotInstanceRequestsInRegion
+    * @see #describeSpotPriceHistoryInRegion
+    * @see <a href=
+    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RequestSpotInstances.html"
+    *      />
+    * @return set of spot instance requests
+    */
+   @Named("RequestSpotInstances")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "RequestSpotInstances")
+   @XMLResponseParser(SpotInstancesHandler.class)
+   Set<SpotInstanceRequest> requestSpotInstancesInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("SpotPrice") float spotPrice, @FormParam("InstanceCount") int instanceCount,
+         @BinderParam(BindLaunchSpecificationToFormParams.class) LaunchSpecification launchSpec,
+         RequestSpotInstancesOptions... options);
+
+   /**
+    * 
+    * Describes Spot Price history. Spot Instances are instances that Amazon EC2 starts on your
+    * behalf when the maximum price that you specify exceeds the current Spot Price. Amazon EC2
+    * periodically sets the Spot Price based on available Spot Instance capacity and current spot
+    * instance requests. For conceptual information about Spot Instances, refer to the Amazon
+    * Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
+    * 
+    * @param region
+    *           Region where the spot instance service is running
+    * @param options
+    *           options to control the list
+    * 
+    * @see #describeSpotInstanceRequestsInRegion
+    * @see #requestSpotInstancesInRegion
+    * @see #cancelSpotInstanceRequestsInRegion
+    * @see <a href=
+    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSpotInstanceRequests.html"
+    *      />
+    * @return TODO
+    */
+   @Named("DescribeSpotPriceHistory")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeSpotPriceHistory")
+   @XMLResponseParser(DescribeSpotPriceHistoryResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<Spot> describeSpotPriceHistoryInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         DescribeSpotPriceHistoryOptions... options);
+
+   /**
+    * Cancels one or more Spot Instance requests. Spot Instances are instances that Amazon EC2
+    * starts on your behalf when the maximum price that you specify exceeds the current Spot Price.
+    * Amazon EC2 periodically sets the Spot Price based on available Spot Instance capacity and
+    * current spot instance requests. For conceptual information about Spot Instances, refer to the
+    * Amazon Elastic Compute Cloud Developer Guide or Amazon Elastic Compute Cloud User Guide.
+    * 
+    * @param region
+    *           Region where the spot instance service is running
+    * @param requestIds
+    *           Specifies the ID of the Spot Instance request.
+    * 
+    * @see #describeSpotInstanceRequestsInRegion
+    * @see #requestSpotInstancesInRegion
+    * @see #describeSpotPriceHistoryInRegion
+    * @see <a href=
+    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CancelSpotInstanceRequests.html"
+    *      />
+    * @return TODO
+    */
+   @Named("CancelSpotInstanceRequests")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "CancelSpotInstanceRequests")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void cancelSpotInstanceRequestsInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @BinderParam(BindSpotInstanceRequestIdsToIndexedFormParams.class) String... requestIds);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/functions/CreatePlacementGroupIfNeeded.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/functions/CreatePlacementGroupIfNeeded.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/functions/CreatePlacementGroupIfNeeded.java
index 86eee54..0143aae 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/functions/CreatePlacementGroupIfNeeded.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/functions/CreatePlacementGroupIfNeeded.java
@@ -25,7 +25,7 @@ import javax.inject.Named;
 import javax.inject.Singleton;
 
 import org.jclouds.aws.AWSResponseException;
-import org.jclouds.aws.ec2.AWSEC2Client;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.domain.PlacementGroup;
 import org.jclouds.aws.ec2.domain.PlacementGroup.State;
 import org.jclouds.compute.reference.ComputeServiceConstants;
@@ -44,13 +44,13 @@ public class CreatePlacementGroupIfNeeded extends CacheLoader<RegionAndName, Str
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;
-   protected final AWSEC2Client ec2Client;
+   protected final AWSEC2Api ec2Api;
    protected final Predicate<PlacementGroup> placementGroupAvailable;
 
    @Inject
-   public CreatePlacementGroupIfNeeded(AWSEC2Client ec2Client,
+   public CreatePlacementGroupIfNeeded(AWSEC2Api ec2Api,
             @Named("AVAILABLE") Predicate<PlacementGroup> placementGroupAvailable) {
-      this.ec2Client = ec2Client;
+      this.ec2Api = ec2Api;
       this.placementGroupAvailable = placementGroupAvailable;
    }
 
@@ -65,7 +65,7 @@ public class CreatePlacementGroupIfNeeded extends CacheLoader<RegionAndName, Str
       checkNotNull(name, "name");
       logger.debug(">> creating placementGroup region(%s) name(%s)", region, name);
       try {
-         ec2Client.getPlacementGroupServices().createPlacementGroupInRegion(region, name);
+         ec2Api.getPlacementGroupApi().get().createPlacementGroupInRegion(region, name);
          logger.debug("<< created placementGroup(%s)", name);
          checkState(placementGroupAvailable.apply(new PlacementGroup(region, name, "cluster", State.PENDING)), String
                   .format("placementGroup region(%s) name(%s) failed to become available", region, name));

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/functions/ImportOrReturnExistingKeypair.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/functions/ImportOrReturnExistingKeypair.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/functions/ImportOrReturnExistingKeypair.java
index f194cfa..52bef6c 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/functions/ImportOrReturnExistingKeypair.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/functions/ImportOrReturnExistingKeypair.java
@@ -24,7 +24,7 @@ import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
-import org.jclouds.aws.ec2.AWSEC2Client;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.domain.RegionNameAndPublicKeyMaterial;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.ec2.domain.KeyPair;
@@ -43,11 +43,11 @@ public class ImportOrReturnExistingKeypair implements Function<RegionNameAndPubl
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;
-   protected final AWSEC2Client ec2Client;
+   protected final AWSEC2Api ec2Api;
 
    @Inject
-   public ImportOrReturnExistingKeypair(AWSEC2Client ec2Client) {
-      this.ec2Client = ec2Client;
+   public ImportOrReturnExistingKeypair(AWSEC2Api ec2Api) {
+      this.ec2Api = ec2Api;
    }
 
    @Override
@@ -66,12 +66,12 @@ public class ImportOrReturnExistingKeypair implements Function<RegionNameAndPubl
       // as this command is idempotent, it should be ok
       while (keyPair == null)
          try {
-            keyPair = ec2Client.getKeyPairServices().importKeyPairInRegion(region, "jclouds#" + group,
+            keyPair = ec2Api.getKeyPairApi().get().importKeyPairInRegion(region, "jclouds#" + group,
                      publicKeyMaterial);
             keyPair = addFingerprintToKeyPair(publicKeyMaterial, keyPair);
             logger.debug("<< imported keyPair(%s)", keyPair);
          } catch (IllegalStateException e) {
-            keyPair = Iterables.getFirst(ec2Client.getKeyPairServices().describeKeyPairsInRegion(region,
+            keyPair = Iterables.getFirst(ec2Api.getKeyPairApi().get().describeKeyPairsInRegion(region,
                      "jclouds#" + group), null);
             if (keyPair != null) {
                keyPair = addFingerprintToKeyPair(publicKeyMaterial, keyPair);

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/AWSRunInstancesOptions.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/AWSRunInstancesOptions.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/AWSRunInstancesOptions.java
index 92d4faf..5d06ba5 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/AWSRunInstancesOptions.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/AWSRunInstancesOptions.java
@@ -37,7 +37,7 @@ import com.google.common.collect.ImmutableSet;
  * <code>
  * import static org.jclouds.aws.ec2.options.RunInstancesOptions.Builder.*
  * <p/>
- * EC2Client connection = // get connection
+ * EC2Api connection = // get connection
  * Future<ReservationInfo> instances = connection.runInstances(executableBy("123125").imageIds(1000, 1004));
  * <code>
  * 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/CreateSecurityGroupOptions.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/CreateSecurityGroupOptions.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/CreateSecurityGroupOptions.java
index be409eb..3a929bf 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/CreateSecurityGroupOptions.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/CreateSecurityGroupOptions.java
@@ -30,7 +30,7 @@ import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
  * <code>
  * import static org.jclouds.aws.ec2.options.CreateSecurityGroupOptions.Builder.*
  * <p/>
- * AWSEC2Client connection = // get connection
+ * AWSEC2Api connection = // get connection
  * group = connection.getAMIServices().createSecurityGroup(vpcId("123125").noReboot());
  * <code>
  * 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/DescribeSpotPriceHistoryOptions.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/DescribeSpotPriceHistoryOptions.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/DescribeSpotPriceHistoryOptions.java
index d7cc9b1..228f681 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/DescribeSpotPriceHistoryOptions.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/DescribeSpotPriceHistoryOptions.java
@@ -33,7 +33,7 @@ import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
  * <code>
  * import static org.jclouds.aws.ec2.options.DescribeSpotPriceHistoryOptions.Builder.*
  * <p/>
- * AWSEC2Client client = // get connection
+ * AWSEC2Api client = // get connection
  * history = client.getSpotInstanceServices().describeSpotPriceHistoryInRegion(from(yesterday).instanceType("m1.small"));
  * <code>
  * 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/RequestSpotInstancesOptions.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/RequestSpotInstancesOptions.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/RequestSpotInstancesOptions.java
index 9bbe248..7f90269 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/RequestSpotInstancesOptions.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/RequestSpotInstancesOptions.java
@@ -34,7 +34,7 @@ import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
  * <code>
  * import static org.jclouds.aws.ec2.options.RequestSpotInstancesOptions.Builder.*
  * <p/>
- * AWSEC2Client client = // get connection
+ * AWSEC2Api client = // get connection
  * history = client.getSpotInstanceServices().requestSpotInstancesInRegion("us-east-1",validFrom(yesterday).type("m1.small"));
  * <code>
  * 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/predicates/PlacementGroupAvailable.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/predicates/PlacementGroupAvailable.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/predicates/PlacementGroupAvailable.java
index 5f9d024..c04b8d5 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/predicates/PlacementGroupAvailable.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/predicates/PlacementGroupAvailable.java
@@ -21,7 +21,7 @@ import java.util.NoSuchElementException;
 import javax.annotation.Resource;
 import javax.inject.Singleton;
 
-import org.jclouds.aws.ec2.AWSEC2Client;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.domain.PlacementGroup;
 import org.jclouds.logging.Logger;
 import org.jclouds.rest.ResourceNotFoundException;
@@ -38,13 +38,13 @@ import com.google.inject.Inject;
 @Singleton
 public class PlacementGroupAvailable implements Predicate<PlacementGroup> {
 
-   private final AWSEC2Client client;
+   private final AWSEC2Api client;
 
    @Resource
    protected Logger logger = Logger.NULL;
 
    @Inject
-   public PlacementGroupAvailable(AWSEC2Client client) {
+   public PlacementGroupAvailable(AWSEC2Api client) {
       this.client = client;
    }
 
@@ -63,7 +63,7 @@ public class PlacementGroupAvailable implements Predicate<PlacementGroup> {
    }
 
    private PlacementGroup refresh(PlacementGroup group) {
-      return Iterables.getOnlyElement(client.getPlacementGroupServices().describePlacementGroupsInRegion(
+      return Iterables.getOnlyElement(client.getPlacementGroupApi().get().describePlacementGroupsInRegion(
                group.getRegion(), group.getName()));
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/predicates/PlacementGroupDeleted.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/predicates/PlacementGroupDeleted.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/predicates/PlacementGroupDeleted.java
index ad116f5..b8257eb 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/predicates/PlacementGroupDeleted.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/predicates/PlacementGroupDeleted.java
@@ -21,7 +21,7 @@ import java.util.NoSuchElementException;
 import javax.annotation.Resource;
 import javax.inject.Singleton;
 
-import org.jclouds.aws.ec2.AWSEC2Client;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.domain.PlacementGroup;
 import org.jclouds.logging.Logger;
 
@@ -37,13 +37,13 @@ import com.google.inject.Inject;
 @Singleton
 public class PlacementGroupDeleted implements Predicate<PlacementGroup> {
 
-   private final AWSEC2Client client;
+   private final AWSEC2Api client;
 
    @Resource
    protected Logger logger = Logger.NULL;
 
    @Inject
-   public PlacementGroupDeleted(AWSEC2Client client) {
+   public PlacementGroupDeleted(AWSEC2Api client) {
       this.client = client;
    }
 
@@ -60,7 +60,7 @@ public class PlacementGroupDeleted implements Predicate<PlacementGroup> {
    }
 
    private PlacementGroup refresh(PlacementGroup group) {
-      return Iterables.getOnlyElement(client.getPlacementGroupServices().describePlacementGroupsInRegion(
+      return Iterables.getOnlyElement(client.getPlacementGroupApi().get().describePlacementGroupsInRegion(
                group.getRegion(), group.getName()));
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/predicates/SpotInstanceRequestActive.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/predicates/SpotInstanceRequestActive.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/predicates/SpotInstanceRequestActive.java
index 9ec31ae..8395161 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/predicates/SpotInstanceRequestActive.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/predicates/SpotInstanceRequestActive.java
@@ -21,7 +21,7 @@ import java.util.NoSuchElementException;
 import javax.annotation.Resource;
 import javax.inject.Singleton;
 
-import org.jclouds.aws.ec2.AWSEC2Client;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
 import org.jclouds.logging.Logger;
 import org.jclouds.rest.ResourceNotFoundException;
@@ -38,13 +38,13 @@ import com.google.inject.Inject;
 @Singleton
 public class SpotInstanceRequestActive implements Predicate<SpotInstanceRequest> {
 
-   private final AWSEC2Client client;
+   private final AWSEC2Api client;
 
    @Resource
    protected Logger logger = Logger.NULL;
 
    @Inject
-   public SpotInstanceRequestActive(AWSEC2Client client) {
+   public SpotInstanceRequestActive(AWSEC2Api client) {
       this.client = client;
    }
 
@@ -69,7 +69,7 @@ public class SpotInstanceRequestActive implements Predicate<SpotInstanceRequest>
    }
 
    private SpotInstanceRequest refresh(SpotInstanceRequest spot) {
-      return Iterables.getOnlyElement(client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(
+      return Iterables.getOnlyElement(client.getSpotInstanceApi().get().describeSpotInstanceRequestsInRegion(
                spot.getRegion(), spot.getId()));
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSAMIAsyncClient.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSAMIAsyncClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSAMIAsyncClient.java
deleted file mode 100644
index 0a1c48b..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSAMIAsyncClient.java
+++ /dev/null
@@ -1,91 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.aws.ec2.xml.ProductCodesHandler;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.binders.BindProductCodesToIndexedFormParams;
-import org.jclouds.ec2.services.AMIAsyncClient;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to AMI Services.
- * <p/>
- * 
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface AWSAMIAsyncClient extends AMIAsyncClient {
-   // TODO make AWSImage as it has product codes...
-
-   /**
-    * @see AMIClient#getProductCodesForImageInRegion
-    */
-   @Named("DescribeImageAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeImageAttribute", "productCodes" })
-   @XMLResponseParser(ProductCodesHandler.class)
-   ListenableFuture<Set<String>> getProductCodesForImageInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("ImageId") String imageId);
-
-   /**
-    * @see AMIClient#addProductCodesToImageInRegion
-    */
-   @Named("ModifyImageAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "OperationType", "Attribute" }, values = { "ModifyImageAttribute", "add",
-            "productCodes" })
-   ListenableFuture<Void> addProductCodesToImageInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindProductCodesToIndexedFormParams.class) Iterable<String> productCodes,
-            @FormParam("ImageId") String imageId);
-
-   /**
-    * @see AMIClient#removeProductCodesToImageInRegion
-    */
-   @Named("ModifyImageAttribute")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "OperationType", "Attribute" }, values = { "ModifyImageAttribute", "remove",
-            "productCodes" })
-   ListenableFuture<Void> removeProductCodesFromImageInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindProductCodesToIndexedFormParams.class) Iterable<String> productCodes,
-            @FormParam("ImageId") String imageId);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSAMIClient.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSAMIClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSAMIClient.java
deleted file mode 100644
index 75247ad..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSAMIClient.java
+++ /dev/null
@@ -1,85 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import java.util.Set;
-import org.jclouds.ec2.services.AMIClient;
-import org.jclouds.javax.annotation.Nullable;
-
-/**
- * Provides access to EC2 via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-public interface AWSAMIClient extends AMIClient {
-
-
-   /**
-    * Returns the Product Codes of an image.
-    * 
-    * @param region
-    *           AMIs are tied to the Region where its files are located within Amazon S3.
-    * @param imageId
-    *           The ID of the AMI for which an attribute will be described
-    * @see #describeImages
-    * @see #modifyImageAttribute
-    * @see #resetImageAttribute
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeImageAttribute.html"
-    *      />
-    * @see DescribeImagesOptions
-    */
-   Set<String> getProductCodesForImageInRegion(@Nullable String region, String imageId);
-
-
-   /**
-    * Adds {@code productCode}s to an AMI.
-    * 
-    * @param region
-    *           AMIs are tied to the Region where its files are located within Amazon S3.
-    * @param productCodes
-    *           Product Codes
-    * @param imageId
-    *           The AMI ID.
-    * 
-    * @see #removeProductCodesFromImage
-    * @see #describeImageAttribute
-    * @see #resetImageAttribute
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyImageAttribute.html"
-    *      />
-    */
-   void addProductCodesToImageInRegion(@Nullable String region, Iterable<String> productCodes, String imageId);
-
-   /**
-    * Removes {@code productCode}s from an AMI.
-    * 
-    * @param region
-    *           AMIs are tied to the Region where its files are located within Amazon S3.
-    * @param productCodes
-    *           Product Codes
-    * @param imageId
-    *           The AMI ID.
-    * 
-    * @see #addProductCodesToImage
-    * @see #describeImageAttribute
-    * @see #resetImageAttribute
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyImageAttribute.html"
-    *      />
-    */
-   void removeProductCodesFromImageInRegion(@Nullable String region, Iterable<String> productCodes,
-            String imageId);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSInstanceAsyncClient.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSInstanceAsyncClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSInstanceAsyncClient.java
deleted file mode 100644
index de55b01..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSInstanceAsyncClient.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.aws.ec2.domain.AWSRunningInstance;
-import org.jclouds.aws.ec2.xml.AWSDescribeInstancesResponseHandler;
-import org.jclouds.aws.ec2.xml.AWSRunInstancesResponseHandler;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.binders.BindInstanceIdsToIndexedFormParams;
-import org.jclouds.ec2.binders.IfNotNullBindAvailabilityZoneToFormParam;
-import org.jclouds.ec2.domain.Reservation;
-import org.jclouds.ec2.options.RunInstancesOptions;
-import org.jclouds.ec2.services.InstanceAsyncClient;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to EC2 Instance Services via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface AWSInstanceAsyncClient extends InstanceAsyncClient {
-
-   /**
-    * @see AWSInstanceClient#describeInstancesInRegion
-    */
-   @Named("DescribeInstances")
-   @Override
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeInstances")
-   @XMLResponseParser(AWSDescribeInstancesResponseHandler.class)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<Set<? extends Reservation<? extends AWSRunningInstance>>> describeInstancesInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
-
-   /**
-    * @see AWSInstanceClient#runInstancesInRegion
-    */
-   @Named("RunInstances")
-   @Override
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "RunInstances")
-   @XMLResponseParser(AWSRunInstancesResponseHandler.class)
-   ListenableFuture<Reservation<? extends AWSRunningInstance>> runInstancesInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @Nullable @BinderParam(IfNotNullBindAvailabilityZoneToFormParam.class) String nullableAvailabilityZone,
-            @FormParam("ImageId") String imageId, @FormParam("MinCount") int minCount,
-            @FormParam("MaxCount") int maxCount, RunInstancesOptions... options);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSInstanceClient.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSInstanceClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSInstanceClient.java
deleted file mode 100644
index deb911b..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSInstanceClient.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import java.util.Set;
-import org.jclouds.aws.ec2.domain.AWSRunningInstance;
-import org.jclouds.ec2.domain.Reservation;
-import org.jclouds.ec2.options.RunInstancesOptions;
-import org.jclouds.ec2.services.InstanceClient;
-import org.jclouds.javax.annotation.Nullable;
-
-/**
- * Provides access to EC2 via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-public interface AWSInstanceClient extends InstanceClient {
-
-   @Override
-   Set<? extends Reservation<? extends AWSRunningInstance>> describeInstancesInRegion(@Nullable String region,
-            String... instanceIds);
-
-   @Override
-   Reservation<? extends AWSRunningInstance> runInstancesInRegion(@Nullable String region,
-            @Nullable String nullableAvailabilityZone, String imageId, int minCount, int maxCount,
-            RunInstancesOptions... options);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSKeyPairAsyncClient.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSKeyPairAsyncClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSKeyPairAsyncClient.java
deleted file mode 100644
index 8cb9abd..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSKeyPairAsyncClient.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.domain.KeyPair;
-import org.jclouds.ec2.functions.EncodedRSAPublicKeyToBase64;
-import org.jclouds.ec2.services.KeyPairAsyncClient;
-import org.jclouds.ec2.xml.KeyPairResponseHandler;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.ParamParser;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface AWSKeyPairAsyncClient extends KeyPairAsyncClient {
-
-   /**
-    * @see AWSKeyPairClient#importKeyPairInRegion
-    */
-   @Named("ImportKeyPair")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "ImportKeyPair")
-   @XMLResponseParser(KeyPairResponseHandler.class)
-   ListenableFuture<KeyPair> importKeyPairInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("KeyName") String keyName,
-         @FormParam("PublicKeyMaterial") @ParamParser(EncodedRSAPublicKeyToBase64.class) String publicKeyMaterial);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSKeyPairClient.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSKeyPairClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSKeyPairClient.java
deleted file mode 100644
index 3d23d0b..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSKeyPairClient.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import org.jclouds.ec2.domain.KeyPair;
-import org.jclouds.ec2.services.KeyPairClient;
-import org.jclouds.javax.annotation.Nullable;
-
-/**
- * 
- * @author Adrian Cole
- */
-public interface AWSKeyPairClient extends KeyPairClient {
-
-   /**
-    * Imports the public key from an RSA key pair that you created with a third-party tool. Compare
-    * this with CreateKeyPair, in which AWS creates the key pair and gives the keys to you (AWS
-    * keeps a copy of the public key). With ImportKeyPair, you create the key pair and give AWS just
-    * the public key. The private key is never transferred between you and AWS.
-    * 
-    * <p/>
-    * You can easily create an RSA key pair on Windows and Linux using the ssh-keygen command line
-    * tool (provided with the standard OpenSSH installation). Standard library support for RSA key
-    * pair creation is also available in Java, Ruby, Python, and many other programming languages.
-    * 
-    * <p/>
-    * <h4>Supported Formats</h4>
-    * <ul>
-    * <li>OpenSSH public key format (e.g., the format in ~/.ssh/authorized_keys)</li>
-    * <li>Base64 encoded DER format</li>
-    * <li>SSH public key file format as specified in RFC4716</li>
-    * </ul>
-    * DSA keys are not supported. Make sure your key generator is set up to create RSA keys.
-    * <p/>
-    * Supported lengths: 1024, 2048, and 4096.
-    * <p/>
-    * 
-    * @param region
-    *           region to import the key into
-    * @param keyName
-    *           A unique name for the key pair. Accepts alphanumeric characters, spaces, dashes, and
-    *           underscores.
-    * @param publicKeyMaterial
-    *           The public key
-    * @return imported key including fingerprint
-    */
-   KeyPair importKeyPairInRegion(@Nullable String region, String keyName, String publicKeyMaterial);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSSecurityGroupAsyncClient.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSSecurityGroupAsyncClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSSecurityGroupAsyncClient.java
deleted file mode 100644
index 25acb03..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSSecurityGroupAsyncClient.java
+++ /dev/null
@@ -1,150 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.aws.ec2.options.CreateSecurityGroupOptions;
-import org.jclouds.aws.ec2.xml.CreateSecurityGroupResponseHandler;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.binders.BindGroupIdsToIndexedFormParams;
-import org.jclouds.ec2.binders.BindIpPermissionToIndexedFormParams;
-import org.jclouds.ec2.binders.BindIpPermissionsToIndexedFormParams;
-import org.jclouds.ec2.domain.SecurityGroup;
-import org.jclouds.ec2.services.SecurityGroupAsyncClient;
-import org.jclouds.ec2.xml.DescribeSecurityGroupsResponseHandler;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.net.domain.IpPermission;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.annotations.Beta;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to EC2 SecurityGroup Services via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-@Beta
-public interface AWSSecurityGroupAsyncClient extends SecurityGroupAsyncClient {
-   /**
-    * @see AWSSecurityGroupClient#createSecurityGroupInRegion
-    */
-   @Named("CreateSecurityGroup")
-   @POST
-   @Path("/")
-   @XMLResponseParser(CreateSecurityGroupResponseHandler.class)
-   @FormParams(keys = ACTION, values = "CreateSecurityGroup")
-   ListenableFuture<String> createSecurityGroupInRegionAndReturnId(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("GroupName") String name, @FormParam("GroupDescription") String description,
-         CreateSecurityGroupOptions... options);
-
-   /**
-    * @see AWSSecurityGroupClient#authorizeSecurityGroupIngressInRegion(String,
-    *      String,IpPermission)
-    */
-   @Named("AuthorizeSecurityGroupIngress")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "AuthorizeSecurityGroupIngress")
-   ListenableFuture<Void> authorizeSecurityGroupIngressInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("GroupId") String groupId, @BinderParam(BindIpPermissionToIndexedFormParams.class) IpPermission perm);
-
-   /**
-    * @see AWSSecurityGroupClient#authorizeSecurityGroupIngressInRegion(String,
-    *      String,Iterable)
-    */
-   @Named("AuthorizeSecurityGroupIngress")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "AuthorizeSecurityGroupIngress")
-   ListenableFuture<Void> authorizeSecurityGroupIngressInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("GroupId") String groupId,
-         @BinderParam(BindIpPermissionsToIndexedFormParams.class) Iterable<IpPermission> perms);
-
-   /**
-    * @see AWSSecurityGroupClient#revokeSecurityGroupIngressInRegion(@Nullable
-    *      Region, String,IpPermission)
-    */
-   @Named("RevokeSecurityGroupIngress")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "RevokeSecurityGroupIngress")
-   ListenableFuture<Void> revokeSecurityGroupIngressInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("GroupId") String groupId, @BinderParam(BindIpPermissionToIndexedFormParams.class) IpPermission perm);
-
-   /**
-    * @see AWSSecurityGroupClient#revokeSecurityGroupIngressInRegion(@Nullable
-    *      Region, String,Iterable)
-    */
-   @Named("RevokeSecurityGroupIngress")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "RevokeSecurityGroupIngress")
-   ListenableFuture<Void> revokeSecurityGroupIngressInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("GroupId") String groupId,
-         @BinderParam(BindIpPermissionsToIndexedFormParams.class) Iterable<IpPermission> perms);
-
-   /**
-    * @see AWSSecurityGroupClient#deleteSecurityGroupInRegionById
-    */
-   @Named("DeleteSecurityGroup")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DeleteSecurityGroup")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> deleteSecurityGroupInRegionById(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, @FormParam("GroupId") String name);
-
-   /**
-    * @see AWSSecurityGroupClient#describeSecurityGroupsInRegionById
-    */
-   @Named("DescribeSecurityGroups")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeSecurityGroups")
-   @XMLResponseParser(DescribeSecurityGroupsResponseHandler.class)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<? extends Set<SecurityGroup>> describeSecurityGroupsInRegionById(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindGroupIdsToIndexedFormParams.class) String... securityGroupNames);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSSecurityGroupClient.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSSecurityGroupClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSSecurityGroupClient.java
deleted file mode 100644
index ac3b301..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/AWSSecurityGroupClient.java
+++ /dev/null
@@ -1,51 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import java.util.Set;
-import org.jclouds.aws.ec2.options.CreateSecurityGroupOptions;
-import org.jclouds.ec2.domain.SecurityGroup;
-import org.jclouds.ec2.services.SecurityGroupClient;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.net.domain.IpPermission;
-
-import com.google.common.annotations.Beta;
-
-/**
- * Provides access to EC2 via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-@Beta
-public interface AWSSecurityGroupClient extends SecurityGroupClient {
-   
-   String createSecurityGroupInRegionAndReturnId(@Nullable String region, String name, String desc,
-         CreateSecurityGroupOptions... options);
-
-   void authorizeSecurityGroupIngressInRegion(@Nullable String region, String groupId, IpPermission perm);
-
-   void authorizeSecurityGroupIngressInRegion(@Nullable String region, String groupId, Iterable<IpPermission> perm);
-
-   void revokeSecurityGroupIngressInRegion(@Nullable String region, String groupId, IpPermission perm);
-
-   void revokeSecurityGroupIngressInRegion(@Nullable String region, String groupId, Iterable<IpPermission> perm);
-
-   Set<SecurityGroup> describeSecurityGroupsInRegionById(@Nullable String region, String... securityGroupIds);
-
-   void deleteSecurityGroupInRegionById(@Nullable String region, String name);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/MonitoringAsyncClient.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/MonitoringAsyncClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/MonitoringAsyncClient.java
deleted file mode 100644
index 61d96b4..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/MonitoringAsyncClient.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import java.util.Map;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.aws.ec2.domain.MonitoringState;
-import org.jclouds.aws.ec2.xml.MonitoringStateHandler;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.binders.BindInstanceIdsToIndexedFormParams;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to EC2 Monitoring Services via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface MonitoringAsyncClient {
-
-   /**
-    * @see Monitoring#monitorInstancesInRegion
-    */
-   @Named("MonitorInstances")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "MonitorInstances")
-   @XMLResponseParser(MonitoringStateHandler.class)
-   ListenableFuture<? extends Map<String, MonitoringState>> monitorInstancesInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("InstanceId.0") String instanceId,
-            @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
-
-   /**
-    * @see Monitoring#monitorInstancesInRegion
-    */
-   @Named("UnmonitorInstances")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "UnmonitorInstances")
-   @XMLResponseParser(MonitoringStateHandler.class)
-   ListenableFuture<? extends Map<String, MonitoringState>> unmonitorInstancesInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("InstanceId.0") String instanceId,
-            @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/MonitoringClient.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/MonitoringClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/MonitoringClient.java
deleted file mode 100644
index 66c44ee..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/MonitoringClient.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import java.util.Map;
-import org.jclouds.aws.ec2.domain.MonitoringState;
-import org.jclouds.javax.annotation.Nullable;
-
-/**
- * Provides monitoring services for EC2. For more information, refer to the Amazon CloudWatch
- * Developer Guide.
- * <p/>
- * 
- * @author Adrian Cole
- */
-public interface MonitoringClient {
-
-   /**
-    * Enables monitoring for a running instance. For more information, refer to the Amazon
-    * CloudWatch Developer Guide.
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance ID is tied to the
-    *           Region.
-    * @see InstanceClient#runInstances
-    * @see #unmonitorInstances
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-MonitorInstances.html"
-    *      />
-    */
-   Map<String, MonitoringState> monitorInstancesInRegion(@Nullable String region, String instanceId,
-            String... instanceIds);
-
-   /**
-    * Disables monitoring for a running instance. For more information, refer to the Amazon
-    * CloudWatch Developer Guide.
-    * 
-    * @param region
-    *           Instances are tied to Availability Zones. However, the instance ID is tied to the
-    *           Region.
-    * 
-    * @see InstanceClient#runInstances
-    * @see #monitorInstances
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-UnmonitorInstances.html"
-    *      />
-    */
-   Map<String, MonitoringState> unmonitorInstancesInRegion(@Nullable String region, String instanceId,
-            String... instanceIds);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/PlacementGroupAsyncClient.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/PlacementGroupAsyncClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/PlacementGroupAsyncClient.java
deleted file mode 100644
index bd79cb4..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/PlacementGroupAsyncClient.java
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import java.util.Set;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
-import org.jclouds.aws.ec2.domain.PlacementGroup;
-import org.jclouds.aws.ec2.xml.DescribePlacementGroupsResponseHandler;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.binders.BindGroupNamesToIndexedFormParams;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to EC2 Placement Groups via their REST API.
- * <p/>
- * 
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface PlacementGroupAsyncClient {
-
-   /**
-    * @see PlacementGroupClient#createPlacementGroupInRegion(String,String,String)
-    */
-   @Named("CreatePlacementGroup")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "CreatePlacementGroup")
-   ListenableFuture<Void> createPlacementGroupInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @FormParam("GroupName") String name, @FormParam("Strategy") String strategy);
-
-   /**
-    * @see PlacementGroupClient#createPlacementGroupInRegion(String,String)
-    */
-   @Named("CreatePlacementGroup")
-   @POST
-   @Path("/")
-   @FormParams(keys = { ACTION, "Strategy" }, values = { "CreatePlacementGroup", "cluster" })
-   ListenableFuture<Void> createPlacementGroupInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, @FormParam("GroupName") String name);
-
-   /**
-    * @see PlacementGroupClient#deletePlacementGroupInRegion
-    */
-   @Named("DeletePlacementGroup")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DeletePlacementGroup")
-   @Fallback(VoidOnNotFoundOr404.class)
-   ListenableFuture<Void> deletePlacementGroupInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, @FormParam("GroupName") String name);
-
-   /**
-    * @see PlacementGroupClient#describePlacementGroupsInRegion
-    */
-   @Named("DescribePlacementGroups")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribePlacementGroups")
-   @XMLResponseParser(DescribePlacementGroupsResponseHandler.class)
-   @Fallback(EmptySetOnNotFoundOr404.class)
-   ListenableFuture<? extends Set<PlacementGroup>> describePlacementGroupsInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindGroupNamesToIndexedFormParams.class) String... placementGroupIds);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/PlacementGroupClient.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/PlacementGroupClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/PlacementGroupClient.java
deleted file mode 100644
index 3dfd8cc..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/services/PlacementGroupClient.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * 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.aws.ec2.services;
-
-import java.util.Set;
-import org.jclouds.aws.ec2.domain.PlacementGroup;
-import org.jclouds.javax.annotation.Nullable;
-
-/**
- * Provides Placement Group services for EC2. For more information, refer to the Amazon EC2
- * Developer Guide.
- * <p/>
- * 
- * @author Adrian Cole
- */
-public interface PlacementGroupClient {
-
-   /**
-    * Creates a placement group that you launch cluster compute instances into. You must give the
-    * group a name unique within the scope of your account.
-    * 
-    * @param region
-    *           Region to create the placement group in.
-    * @param name
-    *           The name of the placement group..
-    * @param strategy
-    *           The placement group strategy.
-    * @see #describePlacementGroupsInRegion
-    * @see #deletePlacementGroupInRegion
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreatePlacementGroup.html"
-    *      />
-    */
-   void createPlacementGroupInRegion(@Nullable String region, String name, String strategy);
-
-   /**
-    * like {@link #createPlacementGroupInRegion(String,String,String) except that the strategy is default: "cluster".
-    */
-   void createPlacementGroupInRegion(@Nullable String region, String name);
-   
-   /**
-    * Deletes a placement group from your account. You must terminate all instances in the placement group before deleting it.
-    * 
-    * @param region
-    *           Region to delete the placement from from
-    * @param name
-    *           Name of the security group to delete.
-    * 
-    * @see #describePlacementGroupsInRegion
-    * @see #createPlacementGroupInRegion
-    * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeletePlacementGroup.html"
-    *      />
-    */
-   void deletePlacementGroupInRegion(@Nullable String region, String name);
-
-   /**
-    * 
-    * Returns information about one or more placement groups in your account.
-    * 
-    * @param region
-    *           The bundleTask ID is tied to the Region.
-    * @param groupNames
-    *           The name of the placement group. You can specify more than one in the request, or
-    *           omit the parameter if you want information about all your placement groups. By
-    *           default, all placement groups are described
-    * 
-    * @see #deletePlacementGroupInRegion
-    * @see #createPlacementGroupInRegion
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribePlacementGroups.html"
-    *      />
-    */
-   Set<PlacementGroup> describePlacementGroupsInRegion(@Nullable String region,
-            String... groupNames);
-}


[11/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiLiveTest.java
new file mode 100644
index 0000000..220e14f
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiLiveTest.java
@@ -0,0 +1,288 @@
+/*
+ * 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.features;
+
+import static com.google.common.base.Predicates.compose;
+import static com.google.common.base.Predicates.in;
+import static com.google.common.collect.Iterables.all;
+import static com.google.common.collect.Iterables.getLast;
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Set;
+
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.EC2ApiMetadata;
+import org.jclouds.ec2.domain.SecurityGroup;
+import org.jclouds.ec2.domain.UserIdGroupPair;
+import org.jclouds.net.domain.IpPermission;
+import org.jclouds.net.domain.IpProtocol;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * Tests behavior of {@code SecurityGroupApi}
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "SecurityGroupApiLiveTest")
+public class SecurityGroupApiLiveTest extends BaseComputeServiceContextLiveTest {
+   public SecurityGroupApiLiveTest() {
+      provider = "ec2";
+   }
+
+   private EC2Api ec2Api;
+   protected SecurityGroupApi client;
+
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      ec2Api = view.unwrapApi(EC2Api.class);
+      client = ec2Api.getSecurityGroupApi().get();
+   }
+
+   @Test
+   void testDescribe() {
+      for (String region : ec2Api.getConfiguredRegions()) {
+         Set<SecurityGroup> allResults = client.describeSecurityGroupsInRegion(region);
+         assertNotNull(allResults);
+         if (allResults.size() >= 1) {
+            final SecurityGroup group = getLast(allResults);
+            // in case there are multiple groups with the same name, which is the case with VPC
+            ImmutableSet<SecurityGroup> expected = FluentIterable.from(allResults)
+                  .filter(new Predicate<SecurityGroup>() {
+                     @Override
+                     public boolean apply(SecurityGroup in) {
+                        return group.getName().equals(in.getName());
+                     }
+                  }).toSet();
+            ImmutableSet<SecurityGroup> result = ImmutableSet.copyOf(client.describeSecurityGroupsInRegion(region,
+                  group.getName()));
+            // the above command has a chance of returning less groups than the original
+            assertTrue(expected.containsAll(result));
+         }
+      }
+   }
+
+   @Test
+   void testCreateSecurityGroup() {
+      String groupName = PREFIX + "1";
+      cleanupAndSleep(groupName);
+      try {
+         String groupDescription = PREFIX + "1 description";
+         client.deleteSecurityGroupInRegion(null, groupName);
+         client.createSecurityGroupInRegion(null, groupName, groupDescription);
+         verifySecurityGroup(groupName, groupDescription);
+      } finally {
+         client.deleteSecurityGroupInRegion(null, groupName);
+      }
+   }
+
+   protected void cleanupAndSleep(String groupName) {
+      try {
+         client.deleteSecurityGroupInRegion(null, groupName);
+         Thread.sleep(2000);
+      } catch (Exception e) {
+
+      }
+   }
+
+   @Test
+   void testAuthorizeSecurityGroupIngressCidr() {
+      String groupName = PREFIX + "ingress";
+      cleanupAndSleep(groupName);
+      try {
+         client.createSecurityGroupInRegion(null, groupName, groupName);
+         client.authorizeSecurityGroupIngressInRegion(null, groupName, IpProtocol.TCP, 80, 80, "0.0.0.0/0");
+         assertEventually(new GroupHasPermission(client, groupName, new TCPPort80AllIPs()));
+
+         client.revokeSecurityGroupIngressInRegion(null, groupName, IpProtocol.TCP, 80, 80, "0.0.0.0/0");
+         assertEventually(new GroupHasNoPermissions(client, groupName));
+      } finally {
+         client.deleteSecurityGroupInRegion(null, groupName);
+      }
+   }
+
+   @Test
+   void testAuthorizeSecurityGroupIngressSourcePort() {
+      String groupName = PREFIX + "ingress";
+      cleanupAndSleep(groupName);
+      try {
+         client.createSecurityGroupInRegion(null, groupName, groupName);
+         client.authorizeSecurityGroupIngressInRegion(null, groupName, IpProtocol.TCP, 80, 80, "0.0.0.0/0");
+         assertEventually(new GroupHasPermission(client, groupName, new TCPPort80AllIPs()));
+
+         client.revokeSecurityGroupIngressInRegion(null, groupName, IpProtocol.TCP, 80, 80, "0.0.0.0/0");
+         assertEventually(new GroupHasNoPermissions(client, groupName));
+      } finally {
+         client.deleteSecurityGroupInRegion(null, groupName);
+      }
+   }
+
+   private void verifySecurityGroup(String groupName, String description) {
+      Set<SecurityGroup> oneResult = client.describeSecurityGroupsInRegion(null, groupName);
+      assertNotNull(oneResult);
+      assertEquals(oneResult.size(), 1);
+      SecurityGroup listPair = oneResult.iterator().next();
+      assertEquals(listPair.getName(), groupName);
+      assertEquals(listPair.getDescription(), description);
+   }
+
+   @Test
+   void testAuthorizeSecurityGroupIngressSourceGroup() {
+      final String group1Name = PREFIX + "ingress1";
+      String group2Name = PREFIX + "ingress2";
+      cleanupAndSleep(group2Name);
+      cleanupAndSleep(group1Name);
+      try {
+         client.createSecurityGroupInRegion(null, group1Name, group1Name);
+         client.createSecurityGroupInRegion(null, group2Name, group2Name);
+         ensureGroupsExist(group1Name, group2Name);
+         client.authorizeSecurityGroupIngressInRegion(null, group1Name, IpProtocol.TCP, 80, 80, "0.0.0.0/0");
+         assertEventually(new GroupHasPermission(client, group1Name, new TCPPort80AllIPs()));
+         Set<SecurityGroup> oneResult = client.describeSecurityGroupsInRegion(null, group1Name);
+         assertNotNull(oneResult);
+         assertEquals(oneResult.size(), 1);
+         final SecurityGroup group = oneResult.iterator().next();
+         assertEquals(group.getName(), group1Name);
+         final UserIdGroupPair to = new UserIdGroupPair(group.getOwnerId(), group1Name);
+         client.authorizeSecurityGroupIngressInRegion(null, group2Name, to);
+         assertEventually(new GroupHasPermission(client, group2Name, new Predicate<IpPermission>() {
+            @Override
+            public boolean apply(IpPermission arg0) {
+               return arg0.getTenantIdGroupNamePairs().equals(ImmutableMultimap.of(group.getOwnerId(), group1Name));
+            }
+         }));
+
+         client.revokeSecurityGroupIngressInRegion(null, group2Name,
+               new UserIdGroupPair(group.getOwnerId(), group1Name));
+         assertEventually(new GroupHasNoPermissions(client, group2Name));
+      } finally {
+         client.deleteSecurityGroupInRegion(null, group2Name);
+         client.deleteSecurityGroupInRegion(null, group1Name);
+      }
+   }
+
+   public final class TCPPort80AllIPs implements Predicate<IpPermission> {
+      @Override
+      public boolean apply(IpPermission arg0) {
+         return arg0.getIpProtocol() == IpProtocol.TCP && arg0.getFromPort() == 80 && arg0.getToPort() == 80
+               && arg0.getCidrBlocks().equals(ImmutableSet.of("0.0.0.0/0"));
+      }
+   }
+
+   public static final class GroupHasPermission implements Runnable {
+      private final SecurityGroupApi client;
+      private final String group;
+      private final Predicate<IpPermission> permission;
+
+      public GroupHasPermission(SecurityGroupApi client, String group, Predicate<IpPermission> permission) {
+         this.client = client;
+         this.group = group;
+         this.permission = permission;
+      }
+
+      public void run() {
+         try {
+            Set<SecurityGroup> oneResult = client.describeSecurityGroupsInRegion(null, group);
+            assert all(getOnlyElement(oneResult), permission) : permission
+                  + ": " + oneResult;
+         } catch (Exception e) {
+            throw new AssertionError(e);
+         }
+      }
+   }
+
+   public static final class GroupHasNoPermissions implements Runnable {
+      private final SecurityGroupApi client;
+      private final String group;
+
+      public GroupHasNoPermissions(SecurityGroupApi client, String group) {
+         this.client = client;
+         this.group = group;
+      }
+
+      public void run() {
+         try {
+            Set<SecurityGroup> oneResult = client.describeSecurityGroupsInRegion(null, group);
+            assertNotNull(oneResult);
+            assertEquals(oneResult.size(), 1);
+            SecurityGroup listPair = oneResult.iterator().next();
+            assertEquals(listPair.size(), 0);
+         } catch (Exception e) {
+            throw new AssertionError(e);
+         }
+      }
+   }
+
+   protected void ensureGroupsExist(String group1Name, String group2Name) {
+      Set<SecurityGroup> twoResults = client.describeSecurityGroupsInRegion(null, group1Name, group2Name);
+      assertNotNull(twoResults);
+      assertTrue(twoResults.size() >= 2);// in VPC could be multiple groups with the same name
+
+      assertTrue(all(twoResults, compose(in(ImmutableSet.of(group1Name, group2Name)),
+            new Function<SecurityGroup, String>() {
+               @Override
+               public String apply(SecurityGroup in) {
+                  return in.getName();
+               }
+            })));
+   }
+
+   private static final int INCONSISTENCY_WINDOW = 5000;
+
+   /**
+    * Due to eventual consistency, container commands may not return correctly
+    * immediately. Hence, we will try up to the inconsistency window to see if
+    * the assertion completes.
+    */
+   protected static void assertEventually(Runnable assertion) {
+      long start = System.currentTimeMillis();
+      AssertionError error = null;
+      for (int i = 0; i < 30; i++) {
+         try {
+            assertion.run();
+            if (i > 0)
+               System.err.printf("%d attempts and %dms asserting %s%n", i + 1, System.currentTimeMillis() - start,
+                     assertion.getClass().getSimpleName());
+            return;
+         } catch (AssertionError e) {
+            error = e;
+         }
+         try {
+            Thread.sleep(INCONSISTENCY_WINDOW / 30);
+         } catch (InterruptedException e) {
+         }
+      }
+      if (error != null)
+         throw error;
+
+   }
+
+   public static final String PREFIX = System.getProperty("user.name") + "-ec2";
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiTest.java
new file mode 100644
index 0000000..85b7374
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiTest.java
@@ -0,0 +1,236 @@
+/*
+ * 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.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.ec2.domain.UserIdGroupPair;
+import org.jclouds.ec2.xml.DescribeSecurityGroupsResponseHandler;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.http.functions.ReleasePayloadAndReturn;
+import org.jclouds.net.domain.IpProtocol;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Lists;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code SecurityGroupApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "SecurityGroupApiTest")
+public class SecurityGroupApiTest extends BaseEC2ApiTest<SecurityGroupApi> {
+
+   public void testDeleteSecurityGroup() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(SecurityGroupApi.class, "deleteSecurityGroupInRegion", String.class,
+            String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DeleteSecurityGroup&GroupName=name",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, VoidOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   HttpRequest createSecurityGroup = HttpRequest.builder().method("POST")
+                                                .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                .addFormParam("Action", "CreateSecurityGroup")
+                                                .addFormParam("GroupDescription", "description")
+                                                .addFormParam("GroupName", "name")
+                                                .addFormParam("Signature", "F3o0gnZcX9sWrtDUhVwi3k5GY2JKLP0Dhi6CcEqK2vE%3D")
+                                                .addFormParam("SignatureMethod", "HmacSHA256")
+                                                .addFormParam("SignatureVersion", "2")
+                                                .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                .addFormParam("Version", "2010-06-15")
+                                                .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testCreateSecurityGroup() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(SecurityGroupApi.class, "createSecurityGroupInRegion", String.class,
+            String.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "description"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, createSecurityGroup.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeSecurityGroups() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(SecurityGroupApi.class, "describeSecurityGroupsInRegion", String.class,
+            String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeSecurityGroups",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeSecurityGroupsResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeSecurityGroupsArgs() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(SecurityGroupApi.class, "describeSecurityGroupsInRegion", String.class,
+            String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeSecurityGroups&GroupName.1=1&GroupName.2=2",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeSecurityGroupsResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testAuthorizeSecurityGroupIngressGroup() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(SecurityGroupApi.class, "authorizeSecurityGroupIngressInRegion", String.class,
+            String.class, UserIdGroupPair.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", new UserIdGroupPair("sourceUser",
+            "sourceGroup")));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(
+            request,
+            "Action=AuthorizeSecurityGroupIngress&GroupName=group&SourceSecurityGroupOwnerId=sourceUser&SourceSecurityGroupName=sourceGroup",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest authorizeSecurityGroupIngressCidr = HttpRequest.builder().method("POST")
+                                                              .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                              .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                              .addFormParam("Action", "AuthorizeSecurityGroupIngress")
+                                                              .addFormParam("CidrIp", "0.0.0.0/0")
+                                                              .addFormParam("FromPort", "6000")
+                                                              .addFormParam("GroupName", "group")
+                                                              .addFormParam("IpProtocol", "tcp")
+                                                              .addFormParam("Signature", "6NQega9YUGDxdwk3Y0Hv71u/lHi%2B0D6qMCJLpJVD/aI%3D")
+                                                              .addFormParam("SignatureMethod", "HmacSHA256")
+                                                              .addFormParam("SignatureVersion", "2")
+                                                              .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                              .addFormParam("ToPort", "7000")
+                                                              .addFormParam("Version", "2010-06-15")
+                                                              .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testAuthorizeSecurityGroupIngressCidr() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(SecurityGroupApi.class, "authorizeSecurityGroupIngressInRegion", String.class,
+            String.class, IpProtocol.class, int.class, int.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", IpProtocol.TCP, 6000, 7000, "0.0.0.0/0"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertPayloadEquals(request, authorizeSecurityGroupIngressCidr.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testRevokeSecurityGroupIngressGroup() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(SecurityGroupApi.class, "revokeSecurityGroupIngressInRegion", String.class,
+            String.class, UserIdGroupPair.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", new UserIdGroupPair("sourceUser",
+            "sourceGroup")));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(
+            request,
+            "Action=RevokeSecurityGroupIngress&GroupName=group&SourceSecurityGroupOwnerId=sourceUser&SourceSecurityGroupName=sourceGroup",
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest revokeSecurityGroupIngressCidr = HttpRequest.builder().method("POST")
+                                                           .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                           .addFormParam("Action", "RevokeSecurityGroupIngress")
+                                                           .addFormParam("CidrIp", "0.0.0.0/0")
+                                                           .addFormParam("FromPort", "6000")
+                                                           .addFormParam("GroupName", "group")
+                                                           .addFormParam("IpProtocol", "tcp")
+                                                           .addFormParam("Signature", "WPlDYXI8P6Ip4F2JIEP3lWrVlP/7gxbZvlshKYlrvxk%3D")
+                                                           .addFormParam("SignatureMethod", "HmacSHA256")
+                                                           .addFormParam("SignatureVersion", "2")
+                                                           .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                           .addFormParam("ToPort", "7000")
+                                                           .addFormParam("Version", "2010-06-15")
+                                                           .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testRevokeSecurityGroupIngressCidr() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(SecurityGroupApi.class, "revokeSecurityGroupIngressInRegion", String.class,
+            String.class, IpProtocol.class, int.class, int.class, String.class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "group", IpProtocol.TCP, 6000, 7000, "0.0.0.0/0"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, revokeSecurityGroupIngressCidr.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
+      assertSaxResponseParserClassEquals(method, null);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiTest.java
new file mode 100644
index 0000000..572b247
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiTest.java
@@ -0,0 +1,162 @@
+/*
+ * 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.features;
+
+import static org.jclouds.reflect.Reflection2.method;
+
+import java.io.IOException;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.ec2.options.BundleInstanceS3StorageOptions;
+import org.jclouds.ec2.xml.BundleTaskHandler;
+import org.jclouds.ec2.xml.DescribeBundleTasksResponseHandler;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.functions.ParseSax;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Lists;
+import com.google.common.reflect.Invokable;
+/**
+ * Tests behavior of {@code WindowsApi}
+ * 
+ * @author Adrian Cole
+ */
+// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
+@Test(groups = "unit", testName = "WindowsApiTest")
+public class WindowsApiTest extends BaseEC2ApiTest<WindowsApi> {
+
+   HttpRequest bundleInstanceInRegion = HttpRequest.builder().method("POST")
+                                                   .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                   .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                   .addFormParam("Action", "BundleInstance")
+                                                   .addFormParam("InstanceId", "i-e468cd8d")
+                                                   .addFormParam("Signature", "Uw5gH4eN3H8KXeFfIVLDDt88ApYn8L4pkf31hpojpcM%3D")
+                                                   .addFormParam("SignatureMethod", "HmacSHA256")
+                                                   .addFormParam("SignatureVersion", "2")
+                                                   .addFormParam("Storage.S3.Bucket", "my-bucket")
+                                                   .addFormParam("Storage.S3.Prefix", "winami")
+                                                   .addFormParam("Storage.S3.UploadPolicy", "eyJleHBpcmF0aW9uIjogIjIwMDgtMDgtMzBUMDg6NDk6MDlaIiwiY29uZGl0aW9ucyI6IFt7ImJ1Y2tldCI6ICJteS1idWNrZXQifSxbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAibXktbmV3LWltYWdlIl1dfQ%3D%3D")
+                                                   .addFormParam("Storage.S3.UploadPolicySignature", "ih/iohGe0A7y4QVRbKaq6BZShzUsmBEJEa9AdFbxM6Y%3D")
+                                                   .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                   .addFormParam("Version", "2010-06-15")
+                                                   .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testBundleInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(WindowsApi.class, "bundleInstanceInRegion", String.class, String.class,
+               String.class, String.class, String.class, BundleInstanceS3StorageOptions[].class);
+      GeneratedHttpRequest request = processor
+               .createRequest(
+                        method,
+                        Lists.<Object> newArrayList(
+                        null,
+                        "i-e468cd8d",
+                        "winami",
+                        "my-bucket",
+                        "{\"expiration\": \"2008-08-30T08:49:09Z\",\"conditions\": [{\"bucket\": \"my-bucket\"},[\"starts-with\", \"$key\", \"my-new-image\"]]}"));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, bundleInstanceInRegion.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, BundleTaskHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   HttpRequest bundleInstanceInRegionOptions = HttpRequest.builder().method("POST")
+                                                          .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                                                          .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                                                          .addFormParam("Action", "BundleInstance")
+                                                          .addFormParam("InstanceId","i-e468cd8d")
+                                                          .addFormParam("Signature", "ahFjX9Tv/DGMFq9EFdF1mWSAnTKyQyyIj7dWJxBOhaE%3D")
+                                                          .addFormParam("SignatureMethod", "HmacSHA256")
+                                                          .addFormParam("SignatureVersion", "2")
+                                                          .addFormParam("Storage.S3.AWSAccessKeyId", "10QMXFEV71ZS32XQFTR2")
+                                                          .addFormParam("Storage.S3.Bucket", "my-bucket")
+                                                          .addFormParam("Storage.S3.Prefix", "winami")
+                                                          .addFormParam("Storage.S3.UploadPolicy", "eyJleHBpcmF0aW9uIjogIjIwMDgtMDgtMzBUMDg6NDk6MDlaIiwiY29uZGl0aW9ucyI6IFt7ImJ1Y2tldCI6ICJteS1idWNrZXQifSxbInN0YXJ0cy13aXRoIiwgIiRrZXkiLCAibXktbmV3LWltYWdlIl1dfQ%3D%3D")
+                                                          .addFormParam("Storage.S3.UploadPolicySignature", "ih/iohGe0A7y4QVRbKaq6BZShzUsmBEJEa9AdFbxM6Y%3D")
+                                                          .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
+                                                          .addFormParam("Version", "2010-06-15")
+                                                          .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testBundleInstanceInRegionOptions() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(WindowsApi.class, "bundleInstanceInRegion", String.class, String.class,
+               String.class, String.class, String.class, BundleInstanceS3StorageOptions[].class);
+      GeneratedHttpRequest request = processor
+               .createRequest(
+                        method,
+                        Lists.<Object> newArrayList(
+                        null,
+                        "i-e468cd8d",
+                        "winami",
+                        "my-bucket",
+                        "{\"expiration\": \"2008-08-30T08:49:09Z\",\"conditions\": [{\"bucket\": \"my-bucket\"},[\"starts-with\", \"$key\", \"my-new-image\"]]}",
+                        BundleInstanceS3StorageOptions.Builder.bucketOwnedBy("10QMXFEV71ZS32XQFTR2")));
+
+      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
+      
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, bundleInstanceInRegionOptions.getPayload().getRawContent().toString(),
+            "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, BundleTaskHandler.class);
+      assertFallbackClassEquals(method, null);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeBundleTasks() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(WindowsApi.class, "describeBundleTasksInRegion", String.class, String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeBundleTasks",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeBundleTasksResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+
+   public void testDescribeBundleTasksArgs() throws SecurityException, NoSuchMethodException, IOException {
+      Invokable<?, ?> method = method(WindowsApi.class, "describeBundleTasksInRegion", String.class, String[].class);
+      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "1", "2"));
+
+      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
+      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
+      assertPayloadEquals(request, "Action=DescribeBundleTasks&BundleId.1=1&BundleId.2=2",
+               "application/x-www-form-urlencoded", false);
+
+      assertResponseParserClassEquals(method, request, ParseSax.class);
+      assertSaxResponseParserClassEquals(method, DescribeBundleTasksResponseHandler.class);
+      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
+
+      checkFilters(request);
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ApiExpectTest.java
index bb84890..574ef6b 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ApiExpectTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ApiExpectTest.java
@@ -20,9 +20,8 @@ import java.util.concurrent.atomic.AtomicInteger;
 
 import org.jclouds.date.DateService;
 import org.jclouds.ec2.EC2Api;
-import org.jclouds.ec2.EC2AsyncApi;
-import org.jclouds.ec2.config.EC2RestClientModule;
-import org.jclouds.rest.ConfiguresRestClient;
+import org.jclouds.ec2.config.BaseEC2HttpApiModule;
+import org.jclouds.rest.ConfiguresHttpApi;
 
 import com.google.common.base.Supplier;
 import com.google.inject.Module;
@@ -31,9 +30,13 @@ import com.google.inject.TypeLiteral;
 
 public abstract class BaseEC2ApiExpectTest<T> extends BaseEC2ExpectTest<T> {
    
-   @ConfiguresRestClient
-   protected static class TestEC2RestClientModule extends EC2RestClientModule<EC2Api, EC2AsyncApi> {
+   @ConfiguresHttpApi
+   protected static class TestEC2HttpApiModule extends BaseEC2HttpApiModule<EC2Api> {
 
+      protected TestEC2HttpApiModule() {
+         super(EC2Api.class);
+      }
+      
       @Override
       protected void configure() {
          super.configure();
@@ -59,6 +62,6 @@ public abstract class BaseEC2ApiExpectTest<T> extends BaseEC2ExpectTest<T> {
 
    @Override
    protected Module createModule() {
-      return new TestEC2RestClientModule();
+      return new TestEC2HttpApiModule();
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ClientExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ClientExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ClientExpectTest.java
deleted file mode 100644
index 15b8b27..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ClientExpectTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.internal;
-
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.jclouds.date.DateService;
-import org.jclouds.ec2.EC2AsyncClient;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.config.EC2RestClientModule;
-import org.jclouds.rest.ConfiguresRestClient;
-
-import com.google.common.base.Supplier;
-import com.google.inject.Module;
-import com.google.inject.Provides;
-import com.google.inject.TypeLiteral;
-
-public abstract class BaseEC2ClientExpectTest<T> extends BaseEC2ExpectTest<T> {
-
-   @ConfiguresRestClient
-   protected static class TestEC2RestClientModule extends EC2RestClientModule<EC2Client, EC2AsyncClient> {
-
-      @Override
-      protected void configure() {
-         super.configure();
-         // predictable node names
-         final AtomicInteger suffix = new AtomicInteger();
-         bind(new TypeLiteral<Supplier<String>>() {
-         }).toInstance(new Supplier<String>() {
-
-            @Override
-            public String get() {
-               return suffix.getAndIncrement() + "";
-            }
-
-         });
-      }
-
-      @Override
-      @Provides
-      protected String provideTimeStamp(DateService dateService) {
-         return CONSTANT_DATE;
-      }
-   }
-
-   @Override
-   protected Module createModule() {
-      return new TestEC2RestClientModule();
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/predicates/VolumeDetachedTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/predicates/VolumeDetachedTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/predicates/VolumeDetachedTest.java
index a30c1e0..3d3d70f 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/predicates/VolumeDetachedTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/predicates/VolumeDetachedTest.java
@@ -30,7 +30,7 @@ import java.util.Set;
 import org.jclouds.ec2.domain.Attachment;
 import org.jclouds.ec2.domain.Attachment.Status;
 import org.jclouds.ec2.domain.Volume;
-import org.jclouds.ec2.services.ElasticBlockStoreClient;
+import org.jclouds.ec2.features.ElasticBlockStoreApi;
 import org.testng.annotations.BeforeMethod;
 import org.testng.annotations.DataProvider;
 import org.testng.annotations.Test;
@@ -41,12 +41,12 @@ import org.testng.annotations.Test;
 @Test(groups = "unit", singleThreaded = true)
 public class VolumeDetachedTest {
 
-   private ElasticBlockStoreClient client;
+   private ElasticBlockStoreApi client;
    private VolumeDetached volumeDetached;
 
    @BeforeMethod
    public void setUp() {
-      client = createMock(ElasticBlockStoreClient.class);
+      client = createMock(ElasticBlockStoreApi.class);
       volumeDetached = new VolumeDetached(client);
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/services/AMIAsyncClientTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/services/AMIAsyncClientTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/services/AMIAsyncClientTest.java
deleted file mode 100644
index 8f53b2e..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/services/AMIAsyncClientTest.java
+++ /dev/null
@@ -1,521 +0,0 @@
-/*
- * 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.services;
-
-import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.executableBy;
-import static org.jclouds.reflect.Reflection2.method;
-
-import java.io.IOException;
-
-import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
-import org.jclouds.ec2.options.CreateImageOptions;
-import org.jclouds.ec2.options.DescribeImagesOptions;
-import org.jclouds.ec2.options.RegisterImageBackedByEbsOptions;
-import org.jclouds.ec2.options.RegisterImageOptions;
-import org.jclouds.ec2.xml.BlockDeviceMappingHandler;
-import org.jclouds.ec2.xml.DescribeImagesResponseHandler;
-import org.jclouds.ec2.xml.ImageIdHandler;
-import org.jclouds.ec2.xml.PermissionHandler;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.functions.ParseSax;
-import org.jclouds.http.functions.ReleasePayloadAndReturn;
-import org.jclouds.rest.internal.GeneratedHttpRequest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableList;
-import com.google.common.collect.Lists;
-import com.google.common.reflect.Invokable;
-/**
- * Tests behavior of {@code AMIAsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "AMIAsyncClientTest")
-public class AMIAsyncClientTest extends BaseEC2AsyncClientTest<AMIAsyncClient> {
-
-   HttpRequest createImage = HttpRequest.builder().method("POST")
-                                        .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                        .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                        .addFormParam("Action", "CreateImage")
-                                        .addFormParam("InstanceId", "instanceId")
-                                        .addFormParam("Name", "name")
-                                        .addFormParam("Signature", "hBIUf4IUOiCKGQKehaNwwbZUjRN4NC4RSNfJ%2B8kvJdY%3D")
-                                        .addFormParam("SignatureMethod", "HmacSHA256")
-                                        .addFormParam("SignatureVersion", "2")
-                                        .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                        .addFormParam("Version", "2010-06-15")
-                                        .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testCreateImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AMIAsyncClient.class, "createImageInRegion", String.class, String.class, String.class,
-               CreateImageOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "instanceId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, createImage.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest createImageOptions = HttpRequest.builder().method("POST")
-                                               .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                               .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                               .addFormParam("Action", "CreateImage")
-                                               .addFormParam("Description", "description")
-                                               .addFormParam("InstanceId", "instanceId")
-                                               .addFormParam("Name", "name")
-                                               .addFormParam("NoReboot", "true")
-                                               .addFormParam("Signature", "fz3KW27JxlSq9ivmVOl4IujcHXXw1cOhdig80I7wR6o%3D")
-                                               .addFormParam("SignatureMethod", "HmacSHA256")
-                                               .addFormParam("SignatureVersion", "2")
-                                               .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                               .addFormParam("Version", "2010-06-15")
-                                               .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testCreateImageOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AMIAsyncClient.class, "createImageInRegion", String.class, String.class, String.class,
-               CreateImageOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "instanceId", new CreateImageOptions()
-               .withDescription("description").noReboot()));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, createImageOptions.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest describeImages = HttpRequest.builder().method("POST")
-                                           .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                           .addFormParam("Action", "DescribeImages")
-                                           .addFormParam("Signature", "qE4vexSFJqS0UWK%2BccV3s%2BP9woL3M5HI5bTBoM7s/LY%3D")
-                                           .addFormParam("SignatureMethod", "HmacSHA256")
-                                           .addFormParam("SignatureVersion", "2")
-                                           .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                           .addFormParam("Version", "2010-06-15")
-                                           .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testDescribeImages() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AMIAsyncClient.class, "describeImagesInRegion", String.class,
-               DescribeImagesOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList((String) null));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, describeImages.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeImagesResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   HttpRequest describeImagesOptions = HttpRequest.builder().method("POST")
-                                                  .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                  .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                  .addFormParam("Action", "DescribeImages")
-                                                  .addFormParam("ExecutableBy", "me")
-                                                  .addFormParam("ImageId.1", "1")
-                                                  .addFormParam("ImageId.2", "2")
-                                                  .addFormParam("Owner.1", "fred")
-                                                  .addFormParam("Owner.2", "nancy")
-                                                  .addFormParam("Signature", "%2BE9wji7oFnNUaGmOBggYNNp6v%2BL8OzSGjuI4nx1l2Jw%3D")
-                                                  .addFormParam("SignatureMethod", "HmacSHA256")
-                                                  .addFormParam("SignatureVersion", "2")
-                                                  .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                  .addFormParam("Version", "2010-06-15")
-                                                  .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testDescribeImagesOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AMIAsyncClient.class, "describeImagesInRegion", String.class,
-               DescribeImagesOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, executableBy("me").ownedBy("fred", "nancy").imageIds(
-               "1", "2")));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, describeImagesOptions.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, DescribeImagesResponseHandler.class);
-      assertFallbackClassEquals(method, EmptySetOnNotFoundOr404.class);
-
-      checkFilters(request);
-   }
-
-   HttpRequest deregisterImage = HttpRequest.builder().method("POST")
-                                            .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                            .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                            .addFormParam("Action", "DeregisterImage")
-                                            .addFormParam("ImageId", "imageId")
-                                            .addFormParam("Signature", "3sk9LAJAIr2lG04OMuI0qtzCoBtCU1Ac9I6TTmAWjyA%3D")
-                                            .addFormParam("SignatureMethod", "HmacSHA256")
-                                            .addFormParam("SignatureVersion", "2")
-                                            .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                            .addFormParam("Version", "2010-06-15")
-                                            .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testDeregisterImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AMIAsyncClient.class, "deregisterImageInRegion", String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, deregisterImage.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest registerImageFromManifest = HttpRequest.builder().method("POST")
-                                                      .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                      .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                      .addFormParam("Action", "RegisterImage")
-                                                      .addFormParam("ImageLocation", "pathToManifest")
-                                                      .addFormParam("Name", "name")
-                                                      .addFormParam("Signature", "alGqfUiV/bpmpCAj/YzG9VxdTeCwOYyoPjNfwYhm7os%3D")
-                                                      .addFormParam("SignatureMethod", "HmacSHA256")
-                                                      .addFormParam("SignatureVersion", "2")
-                                                      .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                      .addFormParam("Version", "2010-06-15")
-                                                      .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testRegisterImageFromManifest() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AMIAsyncClient.class, "registerImageFromManifestInRegion", String.class, String.class,
-               String.class, RegisterImageOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "pathToManifest"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, registerImageFromManifest.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest registerImageFromManifestOptions = HttpRequest.builder().method("POST")
-                                                             .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                             .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                             .addFormParam("Action", "RegisterImage")
-                                                             .addFormParam("Description", "description")
-                                                             .addFormParam("ImageLocation", "pathToManifest")
-                                                             .addFormParam("Name", "name")
-                                                             .addFormParam("Signature", "p77vQLVlPoak6cP/8eoM%2Bz6zkSXx9e2iSlGgLvIwP7I%3D")
-                                                             .addFormParam("SignatureMethod", "HmacSHA256")
-                                                             .addFormParam("SignatureVersion", "2")
-                                                             .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                             .addFormParam("Version", "2010-06-15")
-                                                             .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testRegisterImageFromManifestOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AMIAsyncClient.class, "registerImageFromManifestInRegion", String.class, String.class,
-               String.class, RegisterImageOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "name", "pathToManifest", new RegisterImageOptions()
-               .withDescription("description")));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, registerImageFromManifestOptions.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest registerImageBackedByEBS = HttpRequest.builder().method("POST")
-                                                     .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                     .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                     .addFormParam("Action", "RegisterImage")
-                                                     .addFormParam("BlockDeviceMapping.0.DeviceName", "/dev/sda1")
-                                                     .addFormParam("BlockDeviceMapping.0.Ebs.SnapshotId", "snapshotId")
-                                                     .addFormParam("Name", "imageName")
-                                                     .addFormParam("RootDeviceName", "/dev/sda1")
-                                                     .addFormParam("Signature", "KGqYXGpJ/UQVTM172Y2TwU4tlG21JXd3Qrx5nSLBVuA%3D")
-                                                     .addFormParam("SignatureMethod", "HmacSHA256")
-                                                     .addFormParam("SignatureVersion", "2")
-                                                     .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                     .addFormParam("Version", "2010-06-15")
-                                                     .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testRegisterImageBackedByEBS() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AMIAsyncClient.class, "registerUnixImageBackedByEbsInRegion", String.class,
-               String.class, String.class, RegisterImageBackedByEbsOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageName", "snapshotId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, registerImageBackedByEBS.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest registerImageBackedByEBSOptions = HttpRequest.builder().method("POST")
-                                                            .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                            .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                            .addFormParam("Action", "RegisterImage")
-                                                            .addFormParam("BlockDeviceMapping.0.DeviceName", "/dev/sda1")
-                                                            .addFormParam("BlockDeviceMapping.0.Ebs.SnapshotId", "snapshotId")
-                                                            .addFormParam("BlockDeviceMapping.1.DeviceName", "/dev/device")
-                                                            .addFormParam("BlockDeviceMapping.1.Ebs.DeleteOnTermination", "false")
-                                                            .addFormParam("BlockDeviceMapping.1.Ebs.SnapshotId", "snapshot")
-                                                            .addFormParam("BlockDeviceMapping.2.DeviceName", "/dev/newdevice")
-                                                            .addFormParam("BlockDeviceMapping.2.Ebs.DeleteOnTermination", "false")
-                                                            .addFormParam("BlockDeviceMapping.2.Ebs.VolumeSize", "100")
-                                                            .addFormParam("BlockDeviceMapping.2.VirtualName", "newblock")
-                                                            .addFormParam("Description", "description")
-                                                            .addFormParam("Name", "imageName")
-                                                            .addFormParam("RootDeviceName", "/dev/sda1")
-                                                            .addFormParam("Signature", "xuWi0w8iODQrg4E0azwqNm2lz/Rf4hBa7m%2BunDTZvVI%3D")
-                                                            .addFormParam("SignatureMethod", "HmacSHA256")
-                                                            .addFormParam("SignatureVersion", "2")
-                                                            .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                            .addFormParam("Version", "2010-06-15")
-                                                            .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testRegisterImageBackedByEBSOptions() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AMIAsyncClient.class, "registerUnixImageBackedByEbsInRegion", String.class,
-               String.class, String.class, RegisterImageBackedByEbsOptions[].class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageName", "snapshotId",
-               new RegisterImageBackedByEbsOptions().withDescription("description").addBlockDeviceFromSnapshot(
-                        "/dev/device", null, "snapshot").addNewBlockDevice("/dev/newdevice", "newblock", 100)));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, registerImageBackedByEBSOptions.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, ImageIdHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest getBlockDeviceMappingsForImage = HttpRequest.builder().method("POST")
-                                                           .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                           .addFormParam("Action", "DescribeImageAttribute")
-                                                           .addFormParam("Attribute", "blockDeviceMapping")
-                                                           .addFormParam("ImageId", "imageId")
-                                                           .addFormParam("Signature", "puwfzm8BlfeKiEZ9CNn5ax86weZ6SQ2xyZhN6etu4gA%3D")
-                                                           .addFormParam("SignatureMethod", "HmacSHA256")
-                                                           .addFormParam("SignatureVersion", "2")
-                                                           .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                           .addFormParam("Version", "2010-06-15")
-                                                           .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testGetBlockDeviceMappingsForImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AMIAsyncClient.class, "getBlockDeviceMappingsForImageInRegion", String.class,
-               String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, getBlockDeviceMappingsForImage.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, BlockDeviceMappingHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest getLaunchPermissionForImage = HttpRequest.builder().method("POST")
-                                                        .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                        .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                        .addFormParam("Action", "DescribeImageAttribute")
-                                                        .addFormParam("Attribute", "launchPermission")
-                                                        .addFormParam("ImageId", "imageId")
-                                                        .addFormParam("Signature", "ocCMlLh3Kpg6HwIcPKlrwoPPg9C5rt5nD0dl717mOq8%3D")
-                                                        .addFormParam("SignatureMethod", "HmacSHA256")
-                                                        .addFormParam("SignatureVersion", "2")
-                                                        .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                        .addFormParam("Version", "2010-06-15")
-                                                        .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testGetLaunchPermissionForImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AMIAsyncClient.class, "getLaunchPermissionForImageInRegion", String.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, getLaunchPermissionForImage.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ParseSax.class);
-      assertSaxResponseParserClassEquals(method, PermissionHandler.class);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest addLaunchPermission = HttpRequest.builder().method("POST")
-                                                          .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                          .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                          .addFormParam("Action", "ModifyImageAttribute")
-                                                          .addFormParam("Attribute", "launchPermission")
-                                                          .addFormParam("ImageId", "imageId")
-                                                          .addFormParam("OperationType", "add")
-                                                          .addFormParam("Signature", "WZzNWOC1KHbuySvXEuLTiBA%2BVUfKpSBN2Lud6MrhlCQ%3D")
-                                                          .addFormParam("SignatureMethod", "HmacSHA256")
-                                                          .addFormParam("SignatureVersion", "2")
-                                                          .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                          .addFormParam("UserGroup.1", "all")
-                                                          .addFormParam("UserId.1", "bob")
-                                                          .addFormParam("UserId.2", "sue")
-                                                          .addFormParam("Version", "2010-06-15")
-                                                          .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testAddLaunchPermissionsToImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AMIAsyncClient.class, "addLaunchPermissionsToImageInRegion", String.class,
-               Iterable.class, Iterable.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("bob", "sue"), ImmutableList
-               .of("all"), "imageId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, addLaunchPermission.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest removeLaunchPermission = HttpRequest.builder().method("POST")
-                                                   .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                   .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                   .addFormParam("Action", "ModifyImageAttribute")
-                                                   .addFormParam("Attribute", "launchPermission")
-                                                   .addFormParam("ImageId", "imageId")
-                                                   .addFormParam("OperationType", "remove")
-                                                   .addFormParam("Signature", "z8OYGQBAwu4HwXV6VF/vuOZlBtptxLxtCQiLXY7UvMU%3D")
-                                                   .addFormParam("SignatureMethod", "HmacSHA256")
-                                                   .addFormParam("SignatureVersion", "2")
-                                                   .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                   .addFormParam("UserGroup.1", "all")
-                                                   .addFormParam("UserId.1", "bob")
-                                                   .addFormParam("UserId.2", "sue")
-                                                   .addFormParam("Version", "2010-06-15")
-                                                   .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testRemoveLaunchPermissionsFromImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AMIAsyncClient.class, "removeLaunchPermissionsFromImageInRegion", String.class,
-               Iterable.class, Iterable.class, String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, ImmutableList.of("bob", "sue"), ImmutableList
-               .of("all"), "imageId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, removeLaunchPermission.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-
-   HttpRequest resetLaunchPermissionsOnImage = HttpRequest.builder().method("POST")
-                                                          .endpoint("https://ec2.us-east-1.amazonaws.com/")
-                                                          .addHeader("Host", "ec2.us-east-1.amazonaws.com")
-                                                          .addFormParam("Action", "ResetImageAttribute")
-                                                          .addFormParam("Attribute", "launchPermission")
-                                                          .addFormParam("ImageId", "imageId")
-                                                          .addFormParam("Signature", "mOVwrqAzidhz%2B4E1dqOJAzG9G9ZX7eDpi8BobN4dA%2BE%3D")
-                                                          .addFormParam("SignatureMethod", "HmacSHA256")
-                                                          .addFormParam("SignatureVersion", "2")
-                                                          .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                          .addFormParam("Version", "2010-06-15")
-                                                          .addFormParam("AWSAccessKeyId", "identity").build();
-
-   public void testResetLaunchPermissionsOnImage() throws SecurityException, NoSuchMethodException, IOException {
-      Invokable<?, ?> method = method(AMIAsyncClient.class, "resetLaunchPermissionsOnImageInRegion", String.class,
-               String.class);
-      GeneratedHttpRequest request = processor.createRequest(method, Lists.<Object> newArrayList(null, "imageId"));
-
-      request = (GeneratedHttpRequest) request.getFilters().get(0).filter(request);
-      
-      assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
-      assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
-      assertPayloadEquals(request, resetLaunchPermissionsOnImage.getPayload().getRawContent().toString(),
-            "application/x-www-form-urlencoded", false);
-      assertResponseParserClassEquals(method, request, ReleasePayloadAndReturn.class);
-      assertSaxResponseParserClassEquals(method, null);
-      assertFallbackClassEquals(method, null);
-
-      checkFilters(request);
-   }
-}


[08/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/suppliers/DescribeAvailabilityZonesInRegionTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/suppliers/DescribeAvailabilityZonesInRegionTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/suppliers/DescribeAvailabilityZonesInRegionTest.java
index ecc9ace..8914805 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/suppliers/DescribeAvailabilityZonesInRegionTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/suppliers/DescribeAvailabilityZonesInRegionTest.java
@@ -25,13 +25,14 @@ import java.util.Map;
 import java.util.Set;
 
 import org.easymock.classextension.IMocksControl;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.domain.AvailabilityZoneInfo;
-import org.jclouds.ec2.services.AvailabilityZoneAndRegionClient;
+import org.jclouds.ec2.features.AvailabilityZoneAndRegionApi;
 import org.jclouds.http.HttpCommand;
 import org.jclouds.http.HttpResponseException;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Optional;
 import com.google.common.base.Suppliers;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
@@ -46,15 +47,15 @@ public class DescribeAvailabilityZonesInRegionTest {
    @Test
    public void testDescribeAvailabilityZonesInRegion_BestEffort() {
       IMocksControl control = createControl();
-      EC2Client client = control.createMock(EC2Client.class);
-      AvailabilityZoneAndRegionClient regionClient = control.createMock(AvailabilityZoneAndRegionClient.class);
+      EC2Api client = control.createMock(EC2Api.class);
+      AvailabilityZoneAndRegionApi regionClient = control.createMock(AvailabilityZoneAndRegionApi.class);
       AvailabilityZoneInfo info1 = control.createMock(AvailabilityZoneInfo.class);
       AvailabilityZoneInfo info2 = control.createMock(AvailabilityZoneInfo.class);
       HttpCommand command = control.createMock(HttpCommand.class);
       HttpResponseException exception = new HttpResponseException("Error: Unable to tunnel through proxy: ...",
                command, null);
 
-      expect(client.getAvailabilityZoneAndRegionServices()).andStubReturn(regionClient);
+      expect(client.getAvailabilityZoneAndRegionApi()).andStubReturn((Optional) Optional.of(regionClient));
       expect(regionClient.describeAvailabilityZonesInRegion("accessibleRegion1")).andReturn(
                ImmutableSet.of(info1));
       expect(regionClient.describeAvailabilityZonesInRegion("inaccessibleRegion")).andThrow(exception);
@@ -79,13 +80,13 @@ public class DescribeAvailabilityZonesInRegionTest {
    @Test
    public void testDescribeAvailabilityZonesInRegion_RethrowIfNoneFound() {
       IMocksControl control = createControl();
-      EC2Client client = control.createMock(EC2Client.class);
-      AvailabilityZoneAndRegionClient regionClient = control.createMock(AvailabilityZoneAndRegionClient.class);
+      EC2Api client = control.createMock(EC2Api.class);
+      AvailabilityZoneAndRegionApi regionClient = control.createMock(AvailabilityZoneAndRegionApi.class);
       HttpCommand command = control.createMock(HttpCommand.class);
       HttpResponseException exception = new HttpResponseException("Error: Unable to tunnel through proxy: ...",
                command, null);
 
-      expect(client.getAvailabilityZoneAndRegionServices()).andStubReturn(regionClient);
+      expect(client.getAvailabilityZoneAndRegionApi()).andStubReturn((Optional) Optional.of(regionClient));
       expect(regionClient.describeAvailabilityZonesInRegion("inaccessibleRegion")).andThrow(exception);
 
       Set<String> regions = ImmutableSet.of("inaccessibleRegion");
@@ -105,10 +106,10 @@ public class DescribeAvailabilityZonesInRegionTest {
    @Test
    public void testDescribeAvailabilityZonesInRegion_NoZones() {
       IMocksControl control = createControl();
-      EC2Client client = control.createMock(EC2Client.class);
-      AvailabilityZoneAndRegionClient regionClient = control.createMock(AvailabilityZoneAndRegionClient.class);
+      EC2Api client = control.createMock(EC2Api.class);
+      AvailabilityZoneAndRegionApi regionClient = control.createMock(AvailabilityZoneAndRegionApi.class);
 
-      expect(client.getAvailabilityZoneAndRegionServices()).andStubReturn(regionClient);
+      expect(client.getAvailabilityZoneAndRegionApi()).andStubReturn((Optional) Optional.of(regionClient));
       expect(regionClient.describeAvailabilityZonesInRegion("emptyRegion")).andReturn(
                ImmutableSet.<AvailabilityZoneInfo> of());
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2Api.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2Api.java b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2Api.java
new file mode 100644
index 0000000..47800ac
--- /dev/null
+++ b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2Api.java
@@ -0,0 +1,47 @@
+/*
+ * 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.openstack.nova.ec2;
+
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.openstack.nova.ec2.features.NovaEC2KeyPairApi;
+import org.jclouds.rest.annotations.Delegate;
+import org.jclouds.rest.annotations.EndpointParam;
+
+import com.google.common.base.Optional;
+
+/**
+ * Provides synchronous access to EC2 services.
+ * 
+ * @author Adam Lowe
+ */
+public interface NovaEC2Api extends EC2Api {
+
+   /**
+    * {@inheritDoc}
+    */
+   @Delegate
+   @Override
+   Optional<? extends NovaEC2KeyPairApi> getKeyPairApi();
+   
+   @Delegate
+   @Override
+   Optional<? extends NovaEC2KeyPairApi> getKeyPairApiForRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2ApiMetadata.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2ApiMetadata.java b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2ApiMetadata.java
index 5c6a22c..d24e334 100644
--- a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2ApiMetadata.java
+++ b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2ApiMetadata.java
@@ -30,7 +30,7 @@ import org.jclouds.ec2.EC2ApiMetadata;
 import org.jclouds.ec2.compute.config.EC2ResolveImagesModule;
 import org.jclouds.openstack.nova.ec2.config.HyphenToNullIso8601Module;
 import org.jclouds.openstack.nova.ec2.config.NovaEC2ComputeServiceContextModule;
-import org.jclouds.openstack.nova.ec2.config.NovaEC2RestClientModule;
+import org.jclouds.openstack.nova.ec2.config.NovaEC2HttpApiModule;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.reflect.TypeToken;
@@ -43,15 +43,6 @@ import com.google.inject.Module;
  */
 public class NovaEC2ApiMetadata extends EC2ApiMetadata {
 
-   /**
-    * @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(NovaEC2Client.class)} as
-    *             {@link NovaEC2AsyncClient} interface will be removed in jclouds 1.7.
-    */
-   @Deprecated
-   public static final TypeToken<org.jclouds.rest.RestContext<NovaEC2Client, NovaEC2AsyncClient>> CONTEXT_TOKEN = new TypeToken<org.jclouds.rest.RestContext<NovaEC2Client, NovaEC2AsyncClient>>() {
-      private static final long serialVersionUID = 1L;
-   };
-
    @Override
    public Builder toBuilder() {
       return new Builder().fromApiMetadata(this);
@@ -85,15 +76,13 @@ public class NovaEC2ApiMetadata extends EC2ApiMetadata {
    public static class Builder extends EC2ApiMetadata.Builder<Builder> {
       @SuppressWarnings("deprecation")
       protected Builder(){
-         super(NovaEC2Client.class, NovaEC2AsyncClient.class);
          id("openstack-nova-ec2")
          .name("OpenStack Nova's EC2-clone API")
          .version("2009-04-04")
          .defaultEndpoint("http://localhost:8773/services/Cloud")
          .defaultProperties(NovaEC2ApiMetadata.defaultProperties())
-         .context(CONTEXT_TOKEN)
          .defaultModules(ImmutableSet.<Class<? extends Module>>builder()
-                                     .add(NovaEC2RestClientModule.class)
+                                     .add(NovaEC2HttpApiModule.class)
                                      .add(EC2ResolveImagesModule.class)
                                      .add(NovaEC2ComputeServiceContextModule.class)
                                      .add(HyphenToNullIso8601Module.class).build());

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2AsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2AsyncClient.java b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2AsyncClient.java
deleted file mode 100644
index 0e208e9..0000000
--- a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2AsyncClient.java
+++ /dev/null
@@ -1,38 +0,0 @@
-/*
- * 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.openstack.nova.ec2;
-
-import org.jclouds.ec2.EC2AsyncClient;
-import org.jclouds.openstack.nova.ec2.services.NovaEC2KeyPairAsyncClient;
-import org.jclouds.rest.annotations.Delegate;
-
-/**
- * Provides asynchronous access to EC2 services.
- * 
- * @author Adam Lowe
- * @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(NovaEC2Client.class)} as
- *             {@link NovaEC2AsyncClient} interface will be removed in jclouds 1.7.
- */
-@Deprecated
-public interface NovaEC2AsyncClient extends EC2AsyncClient {
-   /**
-    * {@inheritDoc}
-    */
-   @Delegate
-   @Override
-   NovaEC2KeyPairAsyncClient getKeyPairServices();
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2Client.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2Client.java b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2Client.java
deleted file mode 100644
index f0c0bea..0000000
--- a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/NovaEC2Client.java
+++ /dev/null
@@ -1,36 +0,0 @@
-/*
- * 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.openstack.nova.ec2;
-
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.openstack.nova.ec2.services.NovaEC2KeyPairClient;
-import org.jclouds.rest.annotations.Delegate;
-
-/**
- * Provides synchronous access to EC2 services.
- * 
- * @author Adam Lowe
- */
-public interface NovaEC2Client extends EC2Client {
-
-   /**
-    * {@inheritDoc}
-    */
-   @Delegate
-   @Override
-   NovaEC2KeyPairClient getKeyPairServices();   
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/config/NovaEC2HttpApiModule.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/config/NovaEC2HttpApiModule.java b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/config/NovaEC2HttpApiModule.java
new file mode 100644
index 0000000..08ff665
--- /dev/null
+++ b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/config/NovaEC2HttpApiModule.java
@@ -0,0 +1,81 @@
+/*
+ * 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.openstack.nova.ec2.config;
+
+import static org.jclouds.reflect.Reflection2.typeToken;
+
+import java.util.Map;
+
+import javax.inject.Singleton;
+
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.config.BaseEC2HttpApiModule;
+import org.jclouds.ec2.features.SubnetApi;
+import org.jclouds.ec2.features.TagApi;
+import org.jclouds.ec2.features.WindowsApi;
+import org.jclouds.ec2.features.AMIApi;
+import org.jclouds.ec2.features.AvailabilityZoneAndRegionApi;
+import org.jclouds.ec2.features.ElasticBlockStoreApi;
+import org.jclouds.ec2.features.ElasticIPAddressApi;
+import org.jclouds.ec2.features.InstanceApi;
+import org.jclouds.ec2.features.SecurityGroupApi;
+import org.jclouds.ec2.suppliers.DescribeAvailabilityZonesInRegion;
+import org.jclouds.ec2.xml.CreateVolumeResponseHandler;
+import org.jclouds.ec2.xml.DescribeImagesResponseHandler;
+import org.jclouds.location.config.LocationModule;
+import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
+import org.jclouds.location.suppliers.ZoneIdsSupplier;
+import org.jclouds.location.suppliers.derived.ZoneIdsFromRegionIdToZoneIdsValues;
+import org.jclouds.openstack.nova.ec2.NovaEC2Api;
+import org.jclouds.openstack.nova.ec2.features.NovaEC2KeyPairApi;
+import org.jclouds.openstack.nova.ec2.xml.NovaCreateVolumeResponseHandler;
+import org.jclouds.openstack.nova.ec2.xml.NovaDescribeImagesResponseHandler;
+import org.jclouds.rest.ConfiguresHttpApi;
+
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Provides;
+import com.google.inject.Scopes;
+
+/**
+ * 
+ * @author Adrian Cole
+ * @author Adam Lowe
+ */
+@ConfiguresHttpApi
+public class NovaEC2HttpApiModule extends BaseEC2HttpApiModule<NovaEC2Api> {
+
+   public NovaEC2HttpApiModule() {
+      super(NovaEC2Api.class);
+   }
+   
+   @Override
+   protected void configure() {
+      bind(EC2Api.class).to(NovaEC2Api.class);
+      super.configure();
+      bind(CreateVolumeResponseHandler.class).to(NovaCreateVolumeResponseHandler.class).in(Scopes.SINGLETON);
+      bind(DescribeImagesResponseHandler.class).to(NovaDescribeImagesResponseHandler.class);
+   }
+
+   @Override
+   protected void installLocations() {
+      install(new LocationModule());
+      bind(RegionIdToZoneIdsSupplier.class).to(DescribeAvailabilityZonesInRegion.class).in(Scopes.SINGLETON);
+      // there is only one region, and its endpoint is the same as the provider
+      bind(ZoneIdsSupplier.class).to(ZoneIdsFromRegionIdToZoneIdsValues.class).in(Scopes.SINGLETON);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/config/NovaEC2RestClientModule.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/config/NovaEC2RestClientModule.java b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/config/NovaEC2RestClientModule.java
deleted file mode 100644
index 0669f14..0000000
--- a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/config/NovaEC2RestClientModule.java
+++ /dev/null
@@ -1,118 +0,0 @@
-/*
- * 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.openstack.nova.ec2.config;
-
-import static org.jclouds.reflect.Reflection2.typeToken;
-
-import java.util.Map;
-
-import javax.inject.Singleton;
-
-import org.jclouds.ec2.EC2AsyncClient;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.config.EC2RestClientModule;
-import org.jclouds.ec2.features.SubnetApi;
-import org.jclouds.ec2.features.SubnetAsyncApi;
-import org.jclouds.ec2.features.TagApi;
-import org.jclouds.ec2.features.TagAsyncApi;
-import org.jclouds.ec2.features.WindowsApi;
-import org.jclouds.ec2.features.WindowsAsyncApi;
-import org.jclouds.ec2.services.AMIAsyncClient;
-import org.jclouds.ec2.services.AMIClient;
-import org.jclouds.ec2.services.AvailabilityZoneAndRegionAsyncClient;
-import org.jclouds.ec2.services.AvailabilityZoneAndRegionClient;
-import org.jclouds.ec2.services.ElasticBlockStoreAsyncClient;
-import org.jclouds.ec2.services.ElasticBlockStoreClient;
-import org.jclouds.ec2.services.ElasticIPAddressAsyncClient;
-import org.jclouds.ec2.services.ElasticIPAddressClient;
-import org.jclouds.ec2.services.InstanceAsyncClient;
-import org.jclouds.ec2.services.InstanceClient;
-import org.jclouds.ec2.services.SecurityGroupAsyncClient;
-import org.jclouds.ec2.services.SecurityGroupClient;
-import org.jclouds.ec2.services.WindowsAsyncClient;
-import org.jclouds.ec2.services.WindowsClient;
-import org.jclouds.ec2.suppliers.DescribeAvailabilityZonesInRegion;
-import org.jclouds.ec2.xml.CreateVolumeResponseHandler;
-import org.jclouds.ec2.xml.DescribeImagesResponseHandler;
-import org.jclouds.location.config.LocationModule;
-import org.jclouds.location.suppliers.RegionIdToZoneIdsSupplier;
-import org.jclouds.location.suppliers.ZoneIdsSupplier;
-import org.jclouds.location.suppliers.derived.ZoneIdsFromRegionIdToZoneIdsValues;
-import org.jclouds.openstack.nova.ec2.NovaEC2AsyncClient;
-import org.jclouds.openstack.nova.ec2.NovaEC2Client;
-import org.jclouds.openstack.nova.ec2.services.NovaEC2KeyPairAsyncClient;
-import org.jclouds.openstack.nova.ec2.services.NovaEC2KeyPairClient;
-import org.jclouds.openstack.nova.ec2.xml.NovaCreateVolumeResponseHandler;
-import org.jclouds.openstack.nova.ec2.xml.NovaDescribeImagesResponseHandler;
-import org.jclouds.rest.ConfiguresRestClient;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.inject.Provides;
-import com.google.inject.Scopes;
-
-/**
- * 
- * @author Adrian Cole
- * @author Adam Lowe
- */
-@ConfiguresRestClient
-public class NovaEC2RestClientModule extends EC2RestClientModule<NovaEC2Client, NovaEC2AsyncClient> {
-   public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
-         .put(AMIClient.class, AMIAsyncClient.class)//
-         .put(ElasticIPAddressClient.class, ElasticIPAddressAsyncClient.class)//
-         .put(InstanceClient.class, InstanceAsyncClient.class)//
-         .put(NovaEC2KeyPairClient.class, NovaEC2KeyPairAsyncClient.class)//
-         .put(SecurityGroupClient.class, SecurityGroupAsyncClient.class)//
-         .put(WindowsClient.class, WindowsAsyncClient.class)//
-         .put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)//
-         .put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
-         .put(WindowsApi.class, WindowsAsyncApi.class)//
-         .put(TagApi.class, TagAsyncApi.class)//
-         .put(SubnetApi.class, SubnetAsyncApi.class)//
-         .build();
-
-   public NovaEC2RestClientModule() {
-      super(typeToken(NovaEC2Client.class), typeToken(NovaEC2AsyncClient.class), DELEGATE_MAP);
-   }
-   
-   @Override
-   protected void configure() {
-      super.configure();
-      bind(CreateVolumeResponseHandler.class).to(NovaCreateVolumeResponseHandler.class).in(Scopes.SINGLETON);
-      bind(DescribeImagesResponseHandler.class).to(NovaDescribeImagesResponseHandler.class);
-   }
-
-   @Override
-   protected void installLocations() {
-      install(new LocationModule());
-      bind(RegionIdToZoneIdsSupplier.class).to(DescribeAvailabilityZonesInRegion.class).in(Scopes.SINGLETON);
-      // there is only one region, and its endpoint is the same as the provider
-      bind(ZoneIdsSupplier.class).to(ZoneIdsFromRegionIdToZoneIdsValues.class).in(Scopes.SINGLETON);
-   }
-
-   @Singleton
-   @Provides
-   EC2Client provide(NovaEC2Client in) {
-      return in;
-   }
-
-   @Singleton
-   @Provides
-   EC2AsyncClient provide(NovaEC2AsyncClient in) {
-      return in;
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/features/NovaEC2KeyPairApi.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/features/NovaEC2KeyPairApi.java b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/features/NovaEC2KeyPairApi.java
new file mode 100644
index 0000000..b1a21c4
--- /dev/null
+++ b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/features/NovaEC2KeyPairApi.java
@@ -0,0 +1,88 @@
+/*
+ * 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.openstack.nova.ec2.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.domain.KeyPair;
+import org.jclouds.ec2.features.KeyPairApi;
+import org.jclouds.ec2.functions.EncodedRSAPublicKeyToBase64;
+import org.jclouds.ec2.xml.KeyPairResponseHandler;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.ParamParser;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+/**
+ * @author Adrian Cole
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+public interface NovaEC2KeyPairApi extends KeyPairApi {
+
+   /**
+    * Imports the public key from an RSA key pair that you created with a third-party tool. Compare
+    * this with CreateKeyPair, in which AWS creates the key pair and gives the keys to you (Nova
+    * keeps a copy of the public key). With ImportKeyPair, you create the key pair and give Nova just
+    * the public key. The private key is never transferred between you and Nova.
+    * 
+    * <p/>
+    * You can easily create an RSA key pair on Windows and Linux using the ssh-keygen command line
+    * tool (provided with the standard OpenSSH installation). Standard library support for RSA key
+    * pair creation is also available in Java, Ruby, Python, and many other programming languages.
+    * 
+    * <p/>
+    * <h4>Supported Formats</h4>
+    * <ul>
+    * <li>OpenSSH public key format (e.g., the format in ~/.ssh/authorized_keys)</li>
+    * <li>Base64 encoded DER format</li>
+    * <li>SSH public key file format as specified in RFC4716</li>
+    * </ul>
+    * DSA keys are not supported. Make sure your key generator is set up to create RSA keys.
+    * <p/>
+    * Supported lengths: 1024, 2048, and 4096.
+    * <p/>
+    * 
+    * @param region
+    *           region to import the key into
+    * @param keyName
+    *           A unique name for the key pair. Accepts alphanumeric characters, spaces, dashes, and
+    *           underscores.
+    * @param publicKeyMaterial
+    *           The public key
+    * @return imported key including fingerprint
+    */
+   @Named("keypair:import")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "ImportKeyPair")
+   @XMLResponseParser(KeyPairResponseHandler.class)
+   KeyPair importKeyPairInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("KeyName") String keyName,
+         @FormParam("PublicKeyMaterial") @ParamParser(EncodedRSAPublicKeyToBase64.class) String publicKeyMaterial);
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/loaders/NovaCreateSecurityGroupIfNeeded.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/loaders/NovaCreateSecurityGroupIfNeeded.java b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/loaders/NovaCreateSecurityGroupIfNeeded.java
index b9c1e76..77c9a29 100644
--- a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/loaders/NovaCreateSecurityGroupIfNeeded.java
+++ b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/loaders/NovaCreateSecurityGroupIfNeeded.java
@@ -23,7 +23,7 @@ import javax.inject.Named;
 import javax.inject.Singleton;
 
 import org.jclouds.aws.AWSResponseException;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.compute.loaders.CreateSecurityGroupIfNeeded;
 
@@ -37,9 +37,9 @@ import com.google.common.base.Predicate;
 public class NovaCreateSecurityGroupIfNeeded extends CreateSecurityGroupIfNeeded {
 
    @Inject
-   public NovaCreateSecurityGroupIfNeeded(EC2Client ec2Client,
+   public NovaCreateSecurityGroupIfNeeded(EC2Api ec2Client,
             @Named("SECURITY") Predicate<RegionAndName> securityGroupEventualConsistencyDelay) {
-      super(checkNotNull(ec2Client, "ec2Client").getSecurityGroupServices(), securityGroupEventualConsistencyDelay);
+      super(checkNotNull(ec2Client, "ec2Client").getSecurityGroupApi().get(), securityGroupEventualConsistencyDelay);
    }
 
    protected void authorizeGroupToItself(String region, String name) {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairAsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairAsyncClient.java b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairAsyncClient.java
deleted file mode 100644
index d1fcd46..0000000
--- a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairAsyncClient.java
+++ /dev/null
@@ -1,61 +0,0 @@
-/*
- * 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.openstack.nova.ec2.services;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.domain.KeyPair;
-import org.jclouds.ec2.functions.EncodedRSAPublicKeyToBase64;
-import org.jclouds.ec2.services.KeyPairAsyncClient;
-import org.jclouds.ec2.xml.KeyPairResponseHandler;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.rest.annotations.EndpointParam;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.ParamParser;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface NovaEC2KeyPairAsyncClient extends KeyPairAsyncClient {
-
-   /**
-    * @see NovaEC2KeyPairClient#importKeyPairInRegion(String, String, String)
-    */
-   @Named("keypair:import")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "ImportKeyPair")
-   @XMLResponseParser(KeyPairResponseHandler.class)
-   ListenableFuture<KeyPair> importKeyPairInRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-         @FormParam("KeyName") String keyName,
-         @FormParam("PublicKeyMaterial") @ParamParser(EncodedRSAPublicKeyToBase64.class) String publicKeyMaterial);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairClient.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairClient.java b/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairClient.java
deleted file mode 100644
index bb20296..0000000
--- a/apis/openstack-nova-ec2/src/main/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairClient.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * 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.openstack.nova.ec2.services;
-
-import org.jclouds.ec2.domain.KeyPair;
-import org.jclouds.ec2.services.KeyPairClient;
-import org.jclouds.javax.annotation.Nullable;
-
-/**
- * 
- * @author Adrian Cole
- */
-public interface NovaEC2KeyPairClient extends KeyPairClient {
-
-   /**
-    * Imports the public key from an RSA key pair that you created with a third-party tool. Compare
-    * this with CreateKeyPair, in which AWS creates the key pair and gives the keys to you (Nova
-    * keeps a copy of the public key). With ImportKeyPair, you create the key pair and give Nova just
-    * the public key. The private key is never transferred between you and Nova.
-    * 
-    * <p/>
-    * You can easily create an RSA key pair on Windows and Linux using the ssh-keygen command line
-    * tool (provided with the standard OpenSSH installation). Standard library support for RSA key
-    * pair creation is also available in Java, Ruby, Python, and many other programming languages.
-    * 
-    * <p/>
-    * <h4>Supported Formats</h4>
-    * <ul>
-    * <li>OpenSSH public key format (e.g., the format in ~/.ssh/authorized_keys)</li>
-    * <li>Base64 encoded DER format</li>
-    * <li>SSH public key file format as specified in RFC4716</li>
-    * </ul>
-    * DSA keys are not supported. Make sure your key generator is set up to create RSA keys.
-    * <p/>
-    * Supported lengths: 1024, 2048, and 4096.
-    * <p/>
-    * 
-    * @param region
-    *           region to import the key into
-    * @param keyName
-    *           A unique name for the key pair. Accepts alphanumeric characters, spaces, dashes, and
-    *           underscores.
-    * @param publicKeyMaterial
-    *           The public key
-    * @return imported key including fingerprint
-    */
-   KeyPair importKeyPairInRegion(@Nullable String region, String keyName, String publicKeyMaterial);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2AMIApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2AMIApiExpectTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2AMIApiExpectTest.java
new file mode 100644
index 0000000..492346a
--- /dev/null
+++ b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2AMIApiExpectTest.java
@@ -0,0 +1,53 @@
+/*
+ * 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.openstack.nova.ec2.features;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Set;
+
+import org.jclouds.ec2.domain.Image;
+import org.jclouds.ec2.features.AMIApi;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.openstack.nova.ec2.internal.BaseNovaEC2RestApiExpectTest;
+import org.testng.annotations.Test;
+
+/**
+ * @author Adam Lowe
+ */
+@Test(groups = "unit", testName = "NovaEC2ElasticBlockStoreApiTest")
+public class NovaEC2AMIApiExpectTest extends BaseNovaEC2RestApiExpectTest {
+
+   public void testDescribeImagesWithNonMachineTypes() {
+      AMIApi client = requestsSendResponses(
+            describeAvailabilityZonesRequest,
+            describeAvailabilityZonesResponse,
+            HttpRequest.builder().method("POST")
+                  .endpoint("http://localhost:8773/services/Cloud/")
+                  .addHeader("Host", "localhost:8773")
+                  .payload(payloadFromStringWithContentType("Action=DescribeImages&Signature=Z3q3jSutwlfgvbcINT0Ed3AjrjxM4WMvQloXu/1kd40%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
+            HttpResponse.builder().statusCode(200).payload(payloadFromResource("/nova_ec2_images_with_ramdisk.xml")).build()
+                                               ).getAMIApi().get();
+
+      Set<? extends Image> images = client.describeImagesInRegion("nova");
+      
+      assertEquals(images.size(), 1);
+      
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2AMIApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2AMIApiLiveTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2AMIApiLiveTest.java
new file mode 100644
index 0000000..4110467
--- /dev/null
+++ b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2AMIApiLiveTest.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.openstack.nova.ec2.features;
+
+import org.jclouds.ec2.features.AMIApiLiveTest;
+import org.testng.annotations.Test;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "NovaEC2AMIApiLiveTest")
+public class NovaEC2AMIApiLiveTest extends AMIApiLiveTest {
+   public NovaEC2AMIApiLiveTest() {
+      provider = "openstack-nova-ec2";
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2AvailabilityZoneAndRegionApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2AvailabilityZoneAndRegionApiLiveTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2AvailabilityZoneAndRegionApiLiveTest.java
new file mode 100644
index 0000000..be4ac8d
--- /dev/null
+++ b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2AvailabilityZoneAndRegionApiLiveTest.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.openstack.nova.ec2.features;
+
+import org.jclouds.ec2.features.AvailabilityZoneAndRegionApiLiveTest;
+import org.testng.annotations.Test;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "NovaEC2AvailabilityZoneAndRegionApiLiveTest")
+public class NovaEC2AvailabilityZoneAndRegionApiLiveTest extends AvailabilityZoneAndRegionApiLiveTest {
+   public NovaEC2AvailabilityZoneAndRegionApiLiveTest() {
+      provider = "openstack-nova-ec2";
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2ElasticBlockStoreApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2ElasticBlockStoreApiLiveTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2ElasticBlockStoreApiLiveTest.java
new file mode 100644
index 0000000..7714579
--- /dev/null
+++ b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2ElasticBlockStoreApiLiveTest.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.openstack.nova.ec2.features;
+
+import org.jclouds.ec2.features.ElasticBlockStoreApiLiveTest;
+import org.testng.annotations.Test;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "NovaEC2ElasticBlockStoreApiLiveTest")
+public class NovaEC2ElasticBlockStoreApiLiveTest extends ElasticBlockStoreApiLiveTest {
+   public NovaEC2ElasticBlockStoreApiLiveTest() {
+      provider = "openstack-nova-ec2";
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2ElasticBlockStoreExpectApiTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2ElasticBlockStoreExpectApiTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2ElasticBlockStoreExpectApiTest.java
new file mode 100644
index 0000000..0c6151e
--- /dev/null
+++ b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2ElasticBlockStoreExpectApiTest.java
@@ -0,0 +1,64 @@
+/*
+ * 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.openstack.nova.ec2.features;
+
+import static org.testng.Assert.assertEquals;
+
+import java.util.Set;
+
+import org.jclouds.ec2.domain.Attachment;
+import org.jclouds.ec2.domain.Volume;
+import org.jclouds.ec2.features.ElasticBlockStoreApi;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.openstack.nova.ec2.internal.BaseNovaEC2RestApiExpectTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Adam Lowe
+ */
+@Test(groups = "unit", testName = "NovaEC2ElasticBlockStoreApiTest")
+public class NovaEC2ElasticBlockStoreExpectApiTest extends BaseNovaEC2RestApiExpectTest {
+
+   public void testDescribeVolumesWithNovaEC2Status() {
+      ElasticBlockStoreApi client = requestsSendResponses(
+            describeAvailabilityZonesRequest,
+            describeAvailabilityZonesResponse,
+            HttpRequest.builder().method("POST")
+                  .endpoint("http://localhost:8773/services/Cloud/")
+                  .addHeader("Host", "localhost:8773")
+                  .payload(payloadFromStringWithContentType("Action=DescribeVolumes&Signature=AvRznSzGExM%2Buaj2JJj66wq4v4f%2BakicyLooRDtC0t0%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
+            HttpResponse.builder().statusCode(200).payload(payloadFromResource("/nova_ec2_describe_volumes.xml")).build()
+                                                          ).getElasticBlockStoreApi().get();
+
+      Set<Volume> expected = ImmutableSet.of(Volume
+            .builder()
+            .status(Volume.Status.AVAILABLE)
+            .availabilityZone("nova")
+            .region("nova")
+            .id("vol-00000007")
+            .size(1)
+            .attachments(Attachment.builder().region("nova").build())
+            .createTime(dateService.iso8601SecondsDateParse("2012-04-10T10:39:52Z"))
+            .build());
+
+      assertEquals(client.describeVolumesInRegion("nova"), expected);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2ElasticIPAddressApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2ElasticIPAddressApiLiveTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2ElasticIPAddressApiLiveTest.java
new file mode 100644
index 0000000..96aaa25
--- /dev/null
+++ b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2ElasticIPAddressApiLiveTest.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.openstack.nova.ec2.features;
+
+import org.jclouds.ec2.features.ElasticIPAddressApiLiveTest;
+import org.testng.annotations.Test;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "NovaEC2ElasticIPAddressApiLiveTest")
+public class NovaEC2ElasticIPAddressApiLiveTest extends ElasticIPAddressApiLiveTest {
+   public NovaEC2ElasticIPAddressApiLiveTest() {
+      provider = "openstack-nova-ec2";
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2InstanceApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2InstanceApiExpectTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2InstanceApiExpectTest.java
new file mode 100644
index 0000000..7f32f0a
--- /dev/null
+++ b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2InstanceApiExpectTest.java
@@ -0,0 +1,67 @@
+/*
+ * 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.openstack.nova.ec2.features;
+
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNull;
+
+import java.util.Set;
+
+import org.jclouds.ec2.domain.BlockDevice;
+import org.jclouds.ec2.domain.Reservation;
+import org.jclouds.ec2.domain.RunningInstance;
+import org.jclouds.ec2.features.InstanceApi;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.openstack.nova.ec2.internal.BaseNovaEC2RestApiExpectTest;
+
+import com.google.common.collect.Iterables;
+
+/**
+ * @author Adam Lowe
+ */
+public class NovaEC2InstanceApiExpectTest extends BaseNovaEC2RestApiExpectTest {
+
+   public void testDescribeInstancesWithDashesInPlaceOfNullDates() {
+      InstanceApi client = requestsSendResponses(
+            describeAvailabilityZonesRequest,
+            describeAvailabilityZonesResponse,
+            HttpRequest.builder().method("POST")
+                  .endpoint("http://localhost:8773/services/Cloud/")
+                  .addHeader("Host", "localhost:8773")
+                  .payload(payloadFromStringWithContentType("Action=DescribeInstances&Signature=kkCE1HzyntmkICEidOizw50B9yjLdNZvAWUXVse1c8o%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
+            HttpResponse.builder().statusCode(200).payload(payloadFromResource("/nova_ec2_describe_instances.xml")).build()
+                                                    ).getInstanceApi().get();
+
+      Set<? extends Reservation<? extends RunningInstance>> response = client.describeInstancesInRegion("nova");
+      
+      assertEquals(response.size(), 3);
+
+      Reservation<? extends RunningInstance> target = Iterables.get(response, 2);
+      RunningInstance runningInstance = Iterables.getOnlyElement(target);
+      BlockDevice bd = Iterables.getOnlyElement(runningInstance.getEbsBlockDevices().values());
+      
+      // this is a '-' in the nova_ec2_describe_instances.xml
+      assertNull(bd.getAttachTime());
+
+      // double-check the other fields
+      assertFalse(bd.isDeleteOnTermination());
+      assertEquals(bd.getVolumeId(), "1");
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2InstanceApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2InstanceApiLiveTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2InstanceApiLiveTest.java
new file mode 100644
index 0000000..6a2b236
--- /dev/null
+++ b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2InstanceApiLiveTest.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.openstack.nova.ec2.features;
+
+import org.jclouds.ec2.features.InstanceApiLiveTest;
+import org.testng.annotations.Test;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "NovaEC2InstanceApiLiveTest")
+public class NovaEC2InstanceApiLiveTest extends InstanceApiLiveTest {
+   public NovaEC2InstanceApiLiveTest() {
+      provider = "openstack-nova-ec2";
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2KeyPairApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2KeyPairApiExpectTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2KeyPairApiExpectTest.java
new file mode 100644
index 0000000..8bc493e
--- /dev/null
+++ b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2KeyPairApiExpectTest.java
@@ -0,0 +1,78 @@
+/*
+ * 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.openstack.nova.ec2.features;
+
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.ec2.domain.KeyPair;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.openstack.nova.ec2.internal.BaseNovaEC2RestApiExpectTest;
+import org.jclouds.rest.ResourceNotFoundException;
+import org.testng.annotations.Test;
+
+/**
+ * @author Adam Lowe
+ */
+public class NovaEC2KeyPairApiExpectTest extends BaseNovaEC2RestApiExpectTest {
+
+   public void testImportKeyPair() {
+      NovaEC2KeyPairApi client = requestsSendResponses(
+            describeAvailabilityZonesRequest,
+            describeAvailabilityZonesResponse,
+            HttpRequest.builder().method("POST")
+                  .endpoint("http://localhost:8773/services/Cloud/")
+                  .addHeader("Host", "localhost:8773")
+                  .payload(payloadFromStringWithContentType("Action=ImportKeyPair&KeyName=mykey&PublicKeyMaterial=c3NoLXJzYSBBQQ%3D%3D&Signature=wOOKOlDfJezRkx7NKcyOyaBQuY7PoVE3HFa9495RL7s%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
+            HttpResponse.builder().statusCode(200).payload(payloadFromResource("/nova_ec2_import_keypair_response.xml")).build()
+      ).getKeyPairApi().get();
+
+      KeyPair result = client.importKeyPairInRegion(null, "mykey", "ssh-rsa AA");
+      assertEquals(result.getKeyName(), "aplowe-nova-ec22");
+      assertEquals(result.getSha1OfPrivateKey(), "e3:fd:de:f6:4c:36:7d:9b:8f:2f:4c:20:f8:ae:b0:ea");
+   }
+
+   @Test(expectedExceptions = ResourceNotFoundException.class)
+   public void testImportKeyPairFailsNotFound() {
+      NovaEC2KeyPairApi client = requestsSendResponses(
+            describeAvailabilityZonesRequest,
+            describeAvailabilityZonesResponse,
+            HttpRequest.builder().method("POST")
+                  .endpoint("http://localhost:8773/services/Cloud/")
+                  .addHeader("Host", "localhost:8773")
+                  .payload(payloadFromStringWithContentType("Action=ImportKeyPair&KeyName=mykey&PublicKeyMaterial=c3NoLXJzYSBBQQ%3D%3D&Signature=wOOKOlDfJezRkx7NKcyOyaBQuY7PoVE3HFa9495RL7s%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
+            HttpResponse.builder().statusCode(404).build()
+      ).getKeyPairApi().get();
+
+      client.importKeyPairInRegion(null, "mykey", "ssh-rsa AA");
+   }
+
+   @Test(expectedExceptions = IllegalStateException.class)
+   public void testImportKeyPairFailsAlreadyExists() {
+      NovaEC2KeyPairApi client = requestsSendResponses(
+            describeAvailabilityZonesRequest,
+            describeAvailabilityZonesResponse,
+            HttpRequest.builder().method("POST")
+                  .endpoint("http://localhost:8773/services/Cloud/")
+                  .addHeader("Host", "localhost:8773")
+                  .payload(payloadFromStringWithContentType("Action=ImportKeyPair&KeyName=mykey&PublicKeyMaterial=c3NoLXJzYSBBQQ%3D%3D&Signature=wOOKOlDfJezRkx7NKcyOyaBQuY7PoVE3HFa9495RL7s%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
+            HttpResponse.builder().statusCode(409).build()
+      ).getKeyPairApi().get();
+
+      client.importKeyPairInRegion(null, "mykey", "ssh-rsa AA");
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2KeyPairApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2KeyPairApiLiveTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2KeyPairApiLiveTest.java
new file mode 100644
index 0000000..7b02d12
--- /dev/null
+++ b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2KeyPairApiLiveTest.java
@@ -0,0 +1,135 @@
+/*
+ * 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.openstack.nova.ec2.features;
+
+import static com.google.common.collect.Sets.newTreeSet;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.fail;
+
+import java.io.IOException;
+import java.util.Map;
+import java.util.Set;
+import java.util.SortedSet;
+
+import org.jclouds.compute.ComputeTestUtils;
+import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
+import org.jclouds.ec2.domain.KeyPair;
+import org.jclouds.openstack.nova.ec2.NovaEC2Api;
+import org.jclouds.openstack.nova.ec2.NovaEC2ApiMetadata;
+import org.jclouds.ssh.SshKeys;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+/**
+ * Tests behavior of {@code NovaKeyPairApi}
+ * 
+ * @author Adam Lowe
+ */
+@Test(groups = "live", singleThreaded = true)
+public class NovaEC2KeyPairApiLiveTest extends BaseComputeServiceContextLiveTest {
+
+   public static final String PREFIX = System.getProperty("user.name") + "-nova-ec2";
+
+   public NovaEC2KeyPairApiLiveTest() {
+      provider = "openstack-nova-ec2";
+   }
+
+   private NovaEC2KeyPairApi client;
+   private Set<String> regions;
+   
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      client = view.unwrapApi(NovaEC2Api.class).getKeyPairApi().get();
+      regions = view.unwrapApi(NovaEC2Api.class).getAvailabilityZoneAndRegionApi().get().describeRegions().keySet();
+   }
+
+   @Test
+   void testDescribeKeyPairs() {
+      for (String region : regions) {
+         SortedSet<KeyPair> allResults = newTreeSet(client.describeKeyPairsInRegion(region));
+         assertNotNull(allResults);
+         if (allResults.size() >= 1) {
+            KeyPair pair = allResults.last();
+            SortedSet<KeyPair> result = newTreeSet(client.describeKeyPairsInRegion(region, pair.getKeyName()));
+            assertNotNull(result);
+            KeyPair compare = result.last();
+            assertEquals(compare, pair);
+         }
+      }
+   }
+
+   @Test
+   void testCreateKeyPair() {
+      String keyName = PREFIX + "1";
+      cleanupKeyPair(keyName);
+      try {
+         KeyPair keyPair = client.createKeyPairInRegion(null, keyName);
+         checkKeyPair(keyName, keyPair);
+         assertNotNull(keyPair.getKeyMaterial());
+      } finally {
+         cleanupKeyPair(keyName);
+      }
+   }
+
+   protected void cleanupKeyPair(String keyName) {
+      try {
+         client.deleteKeyPairInRegion(null, keyName);
+      } catch (Exception e) {
+
+      }
+      client.deleteKeyPairInRegion(null, keyName);
+   }
+
+   @Test
+   void testImportKeyPair() throws IOException {
+      String keyName = PREFIX + "2";
+      cleanupKeyPair(keyName);
+      Map<String, String> myKey = ComputeTestUtils.setupKeyPair();
+      try {
+         KeyPair keyPair = client.importKeyPairInRegion(null, keyName, myKey.get("public"));
+         checkKeyPair(keyName, keyPair);
+
+         // check the fingerprint of public key (in the sha10OfPrivateKey field)
+         assertEquals(keyPair.getSha1OfPrivateKey(), SshKeys.fingerprintPublicKey(myKey.get("public")));
+
+         // try again to see if there's an error
+         try {
+            client.importKeyPairInRegion(null, keyName, myKey.get("public"));
+            fail("Duplicate call importKeyPairInRegion should have failed!");
+         } catch (IllegalStateException e) {
+         }
+      } finally {
+         cleanupKeyPair(keyName);
+      }
+   }
+
+   protected void checkKeyPair(String keyName, KeyPair keyPair) {
+      assertNotNull(keyPair);
+      assertNotNull(keyPair.getSha1OfPrivateKey());
+      assertEquals(keyPair.getKeyName(), keyName);
+
+      Set<KeyPair> twoResults = client.describeKeyPairsInRegion(null, keyName);
+      assertNotNull(twoResults);
+      assertEquals(twoResults.size(), 1);
+      KeyPair listPair = twoResults.iterator().next();
+      assertEquals(listPair.getKeyName(), keyPair.getKeyName());
+      assertEquals(listPair.getSha1OfPrivateKey(), keyPair.getSha1OfPrivateKey());
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2SecurityGroupApiLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2SecurityGroupApiLiveTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2SecurityGroupApiLiveTest.java
new file mode 100644
index 0000000..11b30a8
--- /dev/null
+++ b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/features/NovaEC2SecurityGroupApiLiveTest.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.openstack.nova.ec2.features;
+
+import org.jclouds.ec2.features.SecurityGroupApiLiveTest;
+import org.testng.annotations.Test;
+
+/**
+ * 
+ * @author Adrian Cole
+ */
+@Test(groups = "live", singleThreaded = true, testName = "NovaEC2SecurityGroupApiLiveTest")
+public class NovaEC2SecurityGroupApiLiveTest extends SecurityGroupApiLiveTest {
+   public NovaEC2SecurityGroupApiLiveTest() {
+      provider = "openstack-nova-ec2";
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/internal/BaseNovaEC2RestApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/internal/BaseNovaEC2RestApiExpectTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/internal/BaseNovaEC2RestApiExpectTest.java
new file mode 100644
index 0000000..462bd53
--- /dev/null
+++ b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/internal/BaseNovaEC2RestApiExpectTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.openstack.nova.ec2.internal;
+
+import java.net.URI;
+
+import javax.ws.rs.core.MediaType;
+
+import org.jclouds.date.DateService;
+import org.jclouds.date.internal.SimpleDateFormatDateService;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.openstack.nova.ec2.NovaEC2Api;
+import org.jclouds.openstack.nova.ec2.config.NovaEC2HttpApiModule;
+import org.jclouds.rest.ConfiguresHttpApi;
+import org.jclouds.rest.internal.BaseRestApiExpectTest;
+
+import com.google.inject.Module;
+import com.google.inject.Provides;
+
+public abstract class BaseNovaEC2RestApiExpectTest extends BaseRestApiExpectTest<NovaEC2Api> {
+   protected static final String CONSTANT_DATE = "2012-04-16T15:54:08.897Z";
+   
+   protected DateService dateService = new SimpleDateFormatDateService();
+   protected URI endpoint = URI.create("http://localhost:8773/services/Cloud/");
+
+   protected HttpRequest describeAvailabilityZonesRequest = HttpRequest
+            .builder()
+            .method("POST")
+            .endpoint(endpoint)
+            .addHeader("Host", "localhost:8773")
+            .payload(payloadFromStringWithContentType(
+                     "Action=DescribeAvailabilityZones&Signature=S3fa5fybw4KAq4o11IpKHlqwx3cVJdKfeAKw3FIJYvM%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity",
+                     MediaType.APPLICATION_FORM_URLENCODED)).build();
+   protected HttpResponse describeAvailabilityZonesResponse = HttpResponse.builder().statusCode(200)
+            .payload(payloadFromResourceWithContentType("/nova_ec2_availabilityZones.xml", MediaType.APPLICATION_XML))
+            .build();
+
+   public BaseNovaEC2RestApiExpectTest() {
+      provider = "openstack-nova-ec2";
+   }
+
+   @ConfiguresHttpApi
+   private static final class TestNovaEC2HttpApiModule extends NovaEC2HttpApiModule {
+
+      @Override
+      @Provides
+      protected String provideTimeStamp(DateService dateService) {
+         return CONSTANT_DATE;
+      }
+   }
+
+   @Override
+   protected Module createModule() {
+      return new TestNovaEC2HttpApiModule();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/internal/BaseNovaEC2RestClientExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/internal/BaseNovaEC2RestClientExpectTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/internal/BaseNovaEC2RestClientExpectTest.java
deleted file mode 100644
index c57e383..0000000
--- a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/internal/BaseNovaEC2RestClientExpectTest.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * 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.openstack.nova.ec2.internal;
-
-import java.net.URI;
-
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.date.DateService;
-import org.jclouds.date.internal.SimpleDateFormatDateService;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.openstack.nova.ec2.NovaEC2Client;
-import org.jclouds.openstack.nova.ec2.config.NovaEC2RestClientModule;
-import org.jclouds.rest.ConfiguresRestClient;
-import org.jclouds.rest.internal.BaseRestClientExpectTest;
-
-import com.google.inject.Module;
-import com.google.inject.Provides;
-
-public abstract class BaseNovaEC2RestClientExpectTest extends BaseRestClientExpectTest<NovaEC2Client> {
-   protected static final String CONSTANT_DATE = "2012-04-16T15:54:08.897Z";
-   
-   protected DateService dateService = new SimpleDateFormatDateService();
-   protected URI endpoint = URI.create("http://localhost:8773/services/Cloud/");
-
-   protected HttpRequest describeAvailabilityZonesRequest = HttpRequest
-            .builder()
-            .method("POST")
-            .endpoint(endpoint)
-            .addHeader("Host", "localhost:8773")
-            .payload(payloadFromStringWithContentType(
-                     "Action=DescribeAvailabilityZones&Signature=S3fa5fybw4KAq4o11IpKHlqwx3cVJdKfeAKw3FIJYvM%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity",
-                     MediaType.APPLICATION_FORM_URLENCODED)).build();
-   protected HttpResponse describeAvailabilityZonesResponse = HttpResponse.builder().statusCode(200)
-            .payload(payloadFromResourceWithContentType("/nova_ec2_availabilityZones.xml", MediaType.APPLICATION_XML))
-            .build();
-
-   public BaseNovaEC2RestClientExpectTest() {
-      provider = "openstack-nova-ec2";
-   }
-
-   @ConfiguresRestClient
-   private static final class TestNovaEC2RestClientModule extends NovaEC2RestClientModule {
-      @Override
-      @Provides
-      protected String provideTimeStamp(DateService dateService) {
-         return CONSTANT_DATE;
-      }
-   }
-
-   @Override
-   protected Module createModule() {
-      return new TestNovaEC2RestClientModule();
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AMIClientExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AMIClientExpectTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AMIClientExpectTest.java
deleted file mode 100644
index 54e4404..0000000
--- a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AMIClientExpectTest.java
+++ /dev/null
@@ -1,53 +0,0 @@
-/*
- * 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.openstack.nova.ec2.services;
-
-import static org.testng.Assert.assertEquals;
-
-import java.util.Set;
-
-import org.jclouds.ec2.domain.Image;
-import org.jclouds.ec2.services.AMIClient;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.openstack.nova.ec2.internal.BaseNovaEC2RestClientExpectTest;
-import org.testng.annotations.Test;
-
-/**
- * @author Adam Lowe
- */
-@Test(groups = "unit", testName = "NovaEC2ElasticBlockStoreClientTest")
-public class NovaEC2AMIClientExpectTest extends BaseNovaEC2RestClientExpectTest {
-
-   public void testDescribeImagesWithNonMachineTypes() {
-      AMIClient client = requestsSendResponses(
-            describeAvailabilityZonesRequest,
-            describeAvailabilityZonesResponse,
-            HttpRequest.builder().method("POST")
-                  .endpoint("http://localhost:8773/services/Cloud/")
-                  .addHeader("Host", "localhost:8773")
-                  .payload(payloadFromStringWithContentType("Action=DescribeImages&Signature=Z3q3jSutwlfgvbcINT0Ed3AjrjxM4WMvQloXu/1kd40%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
-            HttpResponse.builder().statusCode(200).payload(payloadFromResource("/nova_ec2_images_with_ramdisk.xml")).build()
-      ).getAMIServices();
-
-      Set<? extends Image> images = client.describeImagesInRegion("nova");
-      
-      assertEquals(images.size(), 1);
-      
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AMIClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AMIClientLiveTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AMIClientLiveTest.java
deleted file mode 100644
index 4b15421..0000000
--- a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AMIClientLiveTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.openstack.nova.ec2.services;
-
-import org.jclouds.ec2.services.AMIClientLiveTest;
-import org.testng.annotations.Test;
-
-/**
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true, testName = "NovaEC2AMIClientLiveTest")
-public class NovaEC2AMIClientLiveTest extends AMIClientLiveTest {
-   public NovaEC2AMIClientLiveTest() {
-      provider = "openstack-nova-ec2";
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AvailabilityZoneAndRegionClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AvailabilityZoneAndRegionClientLiveTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AvailabilityZoneAndRegionClientLiveTest.java
deleted file mode 100644
index bff8248..0000000
--- a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2AvailabilityZoneAndRegionClientLiveTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.openstack.nova.ec2.services;
-
-import org.jclouds.ec2.services.AvailabilityZoneAndRegionClientLiveTest;
-import org.testng.annotations.Test;
-
-/**
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true, testName = "NovaEC2AvailabilityZoneAndRegionClientLiveTest")
-public class NovaEC2AvailabilityZoneAndRegionClientLiveTest extends AvailabilityZoneAndRegionClientLiveTest {
-   public NovaEC2AvailabilityZoneAndRegionClientLiveTest() {
-      provider = "openstack-nova-ec2";
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2ElasticBlockStoreClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2ElasticBlockStoreClientLiveTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2ElasticBlockStoreClientLiveTest.java
deleted file mode 100644
index 6a8f27d..0000000
--- a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2ElasticBlockStoreClientLiveTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.openstack.nova.ec2.services;
-
-import org.jclouds.ec2.services.ElasticBlockStoreClientLiveTest;
-import org.testng.annotations.Test;
-
-/**
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true, testName = "NovaEC2ElasticBlockStoreClientLiveTest")
-public class NovaEC2ElasticBlockStoreClientLiveTest extends ElasticBlockStoreClientLiveTest {
-   public NovaEC2ElasticBlockStoreClientLiveTest() {
-      provider = "openstack-nova-ec2";
-   }
-
-}


[14/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ClientLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ClientLiveTest.java
deleted file mode 100644
index 3b8bd75..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/EBSBootEC2ClientLiveTest.java
+++ /dev/null
@@ -1,607 +0,0 @@
-/*
- * 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 = "EBSBootEC2ClientLiveTest")
-public class EBSBootEC2ClientLiveTest extends BaseComputeServiceContextLiveTest {
-   public EBSBootEC2ClientLiveTest() {
-      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 EC2Client 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(EC2Client.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.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName);
-      } catch (Exception e) {
-      }
-
-      client.getSecurityGroupServices().createSecurityGroupInRegion(null, securityGroupName, securityGroupName);
-      client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, securityGroupName, IpProtocol.TCP,
-            80, 80, "0.0.0.0/0");
-      client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, securityGroupName, IpProtocol.TCP,
-            443, 443, "0.0.0.0/0");
-      client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(null, securityGroupName, IpProtocol.TCP,
-            22, 22, "0.0.0.0/0");
-   }
-
-   @Test(enabled = false)
-   void testCreateKeyPair() {
-      String keyName = INSTANCE_PREFIX + "1";
-      try {
-         client.getKeyPairServices().deleteKeyPairInRegion(null, keyName);
-      } catch (Exception e) {
-
-      }
-
-      keyPair = client.getKeyPairServices().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.getInstanceServices().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.getElasticBlockStoreServices().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.getElasticBlockStoreServices().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.getElasticBlockStoreServices().describeVolumesInRegion(
-            volume.getRegion(), volume.getId()));
-      if (volume.getAttachments().size() > 0) {
-         // should be cleanly unmounted, so force is not necessary.
-         client.getElasticBlockStoreServices().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.getElasticBlockStoreServices().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.getAMIServices().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.getAMIServices().registerUnixImageBackedByEbsInRegion(
-            snapshot.getRegion(),
-            "ebsboot-" + image.getId(),
-            snapshot.getId(),
-            withKernelId(image.getKernelId()).withRamdisk(image.getRamdiskId()).withDescription(description)
-                  .asArchitecture(Architecture.I386));
-      try {
-         ebsImage = Iterables.getOnlyElement(client.getAMIServices().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.getAMIServices().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.getInstanceServices().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.getInstanceServices().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.getInstanceServices().setUserDataForInstanceInRegion(null, ebsInstance.getId(), "test".getBytes());
-      assertEquals("test", client.getInstanceServices().getUserDataForInstanceInRegion(null, ebsInstance.getId()));
-   }
-
-   private void setRamdiskForInstanceInRegion() {
-      String ramdisk = client.getInstanceServices().getRamdiskForInstanceInRegion(null, ebsInstance.getId());
-      client.getInstanceServices().setRamdiskForInstanceInRegion(null, ebsInstance.getId(), ramdisk);
-      assertEquals(ramdisk, client.getInstanceServices().getRamdiskForInstanceInRegion(null, ebsInstance.getId()));
-   }
-
-   private void setKernelForInstanceInRegion() {
-      String oldKernel = client.getInstanceServices().getKernelForInstanceInRegion(null, ebsInstance.getId());
-      client.getInstanceServices().setKernelForInstanceInRegion(null, ebsInstance.getId(), oldKernel);
-      assertEquals(oldKernel, client.getInstanceServices().getKernelForInstanceInRegion(null, ebsInstance.getId()));
-   }
-
-   private void setInstanceTypeForInstanceInRegion() {
-      client.getInstanceServices()
-            .setInstanceTypeForInstanceInRegion(null, ebsInstance.getId(), InstanceType.C1_MEDIUM);
-      assertEquals(InstanceType.C1_MEDIUM,
-            client.getInstanceServices().getInstanceTypeForInstanceInRegion(null, ebsInstance.getId()));
-      client.getInstanceServices().setInstanceTypeForInstanceInRegion(null, ebsInstance.getId(), InstanceType.M1_SMALL);
-      assertEquals(InstanceType.M1_SMALL,
-            client.getInstanceServices().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.getInstanceServices().setBlockDeviceMappingForInstanceInRegion(null, ebsInstance.getId(), mapping);
-
-         Map<String, BlockDevice> devices = client.getInstanceServices().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.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
-               ebsInstance.getId(), InstanceInitiatedShutdownBehavior.STOP);
-
-         assertEquals(InstanceInitiatedShutdownBehavior.STOP, client.getInstanceServices()
-               .getInstanceInitiatedShutdownBehaviorForInstanceInRegion(null, ebsInstance.getId()));
-         client.getInstanceServices().setInstanceInitiatedShutdownBehaviorForInstanceInRegion(null,
-               ebsInstance.getId(), InstanceInitiatedShutdownBehavior.TERMINATE);
-
-         assertEquals(InstanceInitiatedShutdownBehavior.TERMINATE, client.getInstanceServices()
-               .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.getInstanceServices()
-            .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.getInstanceServices().terminateInstancesInRegion(ebsInstance.getRegion(), ebsInstance.getId());
-            terminatedTester.apply(ebsInstance);
-         } catch (Exception e) {
-            e.printStackTrace();
-         }
-      }
-      if (ebsImage != null) {
-         try {
-            client.getAMIServices().deregisterImageInRegion(ebsImage.getRegion(), ebsImage.getId());
-         } catch (Exception e) {
-            e.printStackTrace();
-         }
-      }
-
-      if (snapshot != null) {
-         try {
-            client.getElasticBlockStoreServices().deleteSnapshotInRegion(snapshot.getRegion(), snapshot.getId());
-         } catch (Exception e) {
-            e.printStackTrace();
-         }
-      }
-      if (attachment != null) {
-         try {
-            client.getElasticBlockStoreServices().detachVolumeInRegion(volume.getRegion(), volume.getId(), true);
-            assert volumeTester.apply(volume);
-         } catch (Exception e) {
-            e.printStackTrace();
-         }
-      }
-      if (instance != null) {
-         try {
-            client.getInstanceServices().terminateInstancesInRegion(instance.getRegion(), instance.getId());
-            terminatedTester.apply(instance);
-         } catch (Exception e) {
-            e.printStackTrace();
-         }
-      }
-      if (volume != null) {
-         try {
-            client.getElasticBlockStoreServices().deleteVolumeInRegion(volume.getRegion(), volume.getId());
-         } catch (Exception e) {
-            e.printStackTrace();
-         }
-      }
-      if (keyPair != null) {
-         try {
-            client.getKeyPairServices().deleteKeyPairInRegion(keyPair.getRegion(), keyPair.getKeyName());
-         } catch (Exception e) {
-            e.printStackTrace();
-         }
-      }
-      if (securityGroupName != null) {
-         try {
-            client.getSecurityGroupServices().deleteSecurityGroupInRegion(null, securityGroupName);
-         } catch (Exception e) {
-            e.printStackTrace();
-         }
-      }
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/EC2AsyncClientTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/EC2AsyncClientTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/EC2AsyncClientTest.java
deleted file mode 100644
index 17299b7..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/EC2AsyncClientTest.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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 java.io.IOException;
-import java.util.concurrent.ExecutionException;
-
-import org.jclouds.ec2.services.BaseEC2AsyncClientTest;
-import org.jclouds.http.HttpRequest;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-/**
- * Tests behavior of {@code EC2AsyncClient}
- * 
- * @author Adrian Cole
- */
-// NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
-@Test(groups = "unit", testName = "EC2AsyncClientTest")
-public class EC2AsyncClientTest extends BaseEC2AsyncClientTest<EC2AsyncClient> {
-
-   private EC2AsyncClient asyncClient;
-   private EC2Client syncClient;
-
-   public void testSync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException {
-      assert syncClient.getAMIServices() != null;
-      assert syncClient.getAvailabilityZoneAndRegionServices() != null;
-      assert syncClient.getElasticBlockStoreServices() != null;
-      assert syncClient.getElasticIPAddressServices() != null;
-      assert syncClient.getInstanceServices() != null;
-      assert syncClient.getKeyPairServices() != null;
-      assert syncClient.getSecurityGroupServices() != null;
-      assert syncClient.getWindowsServices() != null;
-
-   }
-
-   public void testAsync() throws SecurityException, NoSuchMethodException, InterruptedException, ExecutionException {
-      assert asyncClient.getAMIServices() != null;
-      assert asyncClient.getAvailabilityZoneAndRegionServices() != null;
-      assert asyncClient.getElasticBlockStoreServices() != null;
-      assert asyncClient.getElasticIPAddressServices() != null;
-      assert asyncClient.getInstanceServices() != null;
-      assert asyncClient.getKeyPairServices() != null;
-      assert asyncClient.getSecurityGroupServices() != null;
-      assert asyncClient.getWindowsServices() != null;
-   }
-
-   @BeforeClass
-   @Override
-   protected void setupFactory() throws IOException {
-      super.setupFactory();
-      asyncClient = injector.getInstance(EC2AsyncClient.class);
-      syncClient = injector.getInstance(EC2Client.class);
-   }
-
-   @Override
-   protected void checkFilters(HttpRequest request) {
-
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/binders/BindS3UploadPolicyAndSignatureTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/binders/BindS3UploadPolicyAndSignatureTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/binders/BindS3UploadPolicyAndSignatureTest.java
index e4290f6..5c92aec 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/binders/BindS3UploadPolicyAndSignatureTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/binders/BindS3UploadPolicyAndSignatureTest.java
@@ -20,8 +20,8 @@ import static org.testng.Assert.assertEquals;
 
 import java.io.IOException;
 
-import org.jclouds.ec2.services.BaseEC2AsyncClientTest;
-import org.jclouds.ec2.services.InstanceAsyncClient;
+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;
@@ -33,7 +33,7 @@ import org.testng.annotations.Test;
  */
 // NOTE:without testName, this will not call @Before* and fail w/NPE during surefire
 @Test(groups = "unit", testName = "BindS3UploadPolicyAndSignatureTest")
-public class BindS3UploadPolicyAndSignatureTest extends BaseEC2AsyncClientTest<InstanceAsyncClient> {
+public class BindS3UploadPolicyAndSignatureTest extends BaseEC2ApiTest<InstanceApi> {
    private BindS3UploadPolicyAndSignature binder;
 
    @BeforeClass

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceLiveTest.java
index 6334c9a..c2753d72 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceLiveTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceLiveTest.java
@@ -36,7 +36,7 @@ import org.jclouds.domain.Location;
 import org.jclouds.domain.LocationScope;
 import org.jclouds.domain.LoginCredentials;
 import org.jclouds.ec2.EC2ApiMetadata;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.options.EC2TemplateOptions;
 import org.jclouds.ec2.domain.BlockDevice;
 import org.jclouds.ec2.domain.KeyPair;
@@ -46,10 +46,10 @@ import org.jclouds.ec2.domain.SecurityGroup;
 import org.jclouds.ec2.domain.Snapshot;
 import org.jclouds.ec2.domain.Volume;
 import org.jclouds.ec2.reference.EC2Constants;
-import org.jclouds.ec2.services.ElasticBlockStoreClient;
-import org.jclouds.ec2.services.InstanceClient;
-import org.jclouds.ec2.services.KeyPairClient;
-import org.jclouds.ec2.services.SecurityGroupClient;
+import org.jclouds.ec2.features.ElasticBlockStoreApi;
+import org.jclouds.ec2.features.InstanceApi;
+import org.jclouds.ec2.features.KeyPairApi;
+import org.jclouds.ec2.features.SecurityGroupApi;
 import org.jclouds.net.domain.IpProtocol;
 import org.jclouds.scriptbuilder.domain.Statements;
 import org.jclouds.sshj.config.SshjSshClientModule;
@@ -85,7 +85,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
 
    @Override
    protected void checkUserMetadataContains(NodeMetadata node, ImmutableMap<String, String> userMetadata) {
-      if (view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi().getTagApi().isPresent()) {
+      if (view.unwrapApi(EC2Api.class).getTagApi().isPresent()) {
          super.checkUserMetadataContains(node, userMetadata);
       } else {
          assertTrue(node.getUserMetadata().isEmpty(), "not expecting metadata when tag extension isn't present" + node);
@@ -103,14 +103,14 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
 
    @Test(enabled = true, dependsOnMethods = "testCompareSizes")
    public void testExtendedOptionsAndLogin() throws Exception {
-      SecurityGroupClient securityGroupClient = EC2Client.class.cast(view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi())
-               .getSecurityGroupServices();
+      SecurityGroupApi securityGroupClient = view.unwrapApi(EC2Api.class)
+               .getSecurityGroupApi().get();
 
-      KeyPairClient keyPairClient = EC2Client.class.cast(view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi())
-               .getKeyPairServices();
+      KeyPairApi keyPairClient = view.unwrapApi(EC2Api.class)
+               .getKeyPairApi().get();
 
-      InstanceClient instanceClient = EC2Client.class.cast(view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi())
-               .getInstanceServices();
+      InstanceApi instanceClient = view.unwrapApi(EC2Api.class)
+               .getInstanceApi().get();
 
       String group = this.group + "o";
 
@@ -203,9 +203,9 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
          assertTrue(socketTester.apply(socket), String.format("failed to open socket %s on node %s", socket, node));
 
          // check that there is an elastic ip correlating to it
-         EC2Client ec2 = EC2Client.class.cast(context.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi());
+         EC2Api ec2 = context.unwrapApi(EC2Api.class);
          Set<PublicIpInstanceIdPair> ipidpairs =
-               ec2.getElasticIPAddressServices().describeAddressesInRegion(region, publicIps.toArray(new String[0]));
+               ec2.getElasticIPAddressApi().get().describeAddressesInRegion(region, publicIps.toArray(new String[0]));
          assertEquals(ipidpairs.size(), 1, String.format("there should only be one address pair (%s)",
                Iterables.toString(ipidpairs)));
 
@@ -218,7 +218,7 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
 
          // check that the ip is deallocated
          Set<PublicIpInstanceIdPair> ipidcheck =
-                 ec2.getElasticIPAddressServices().describeAddressesInRegion(region, ipidpair.getPublicIp());
+                 ec2.getElasticIPAddressApi().get().describeAddressesInRegion(region, ipidpair.getPublicIp());
          assertTrue(Iterables.isEmpty(ipidcheck), String.format("there should be no address pairs (%s)",
                Iterables.toString(ipidcheck)));
       } finally {
@@ -246,11 +246,11 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
          throw new SkipException("Test cannot run without the parameter test." + provider
                + ".ebs-template; this property should be in the format defined in TemplateBuilderSpec");
       }
-      InstanceClient instanceClient = EC2Client.class.cast(view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi())
-               .getInstanceServices();
+      InstanceApi instanceClient = view.unwrapApi(EC2Api.class)
+               .getInstanceApi().get();
 
-      ElasticBlockStoreClient ebsClient = EC2Client.class.cast(view.unwrap(EC2ApiMetadata.CONTEXT_TOKEN).getApi())
-               .getElasticBlockStoreServices();
+      ElasticBlockStoreApi ebsClient = view.unwrapApi(EC2Api.class)
+               .getElasticBlockStoreApi().get();
 
       String group = this.group + "e";
       int volumeSize = 8;
@@ -317,14 +317,14 @@ public class EC2ComputeServiceLiveTest extends BaseComputeServiceLiveTest {
     * 
     * @throws NoSuchElementException If no instance with that id exists, or the instance is in a different region
     */
-   public static RunningInstance getInstance(InstanceClient instanceClient, String id) {
+   public static RunningInstance getInstance(InstanceApi instanceClient, String id) {
       RunningInstance instance = Iterables.getOnlyElement(Iterables.getOnlyElement(instanceClient
                .describeInstancesInRegion(null, id)));
       return instance;
    }
 
-   protected static void cleanupExtendedStuffInRegion(String region, SecurityGroupClient securityGroupClient,
-            KeyPairClient keyPairClient, String group) throws InterruptedException {
+   protected static void cleanupExtendedStuffInRegion(String region, SecurityGroupApi securityGroupClient,
+            KeyPairApi keyPairClient, String group) throws InterruptedException {
       try {
          for (SecurityGroup secgroup : securityGroupClient.describeSecurityGroupsInRegion(region))
             if (secgroup.getName().startsWith("jclouds#" + group) || secgroup.getName().equals(group)) {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2TemplateBuilderLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2TemplateBuilderLiveTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2TemplateBuilderLiveTest.java
index 8062033..349da8e 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2TemplateBuilderLiveTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2TemplateBuilderLiveTest.java
@@ -31,8 +31,8 @@ import org.jclouds.compute.internal.BaseTemplateBuilderLiveTest;
 import org.jclouds.ec2.options.DescribeAvailabilityZonesOptions;
 import org.jclouds.ec2.options.DescribeImagesOptions;
 import org.jclouds.ec2.options.DescribeRegionsOptions;
-import org.jclouds.ec2.services.AMIAsyncClient;
-import org.jclouds.ec2.services.AvailabilityZoneAndRegionAsyncClient;
+import org.jclouds.ec2.features.AMIApi;
+import org.jclouds.ec2.features.AvailabilityZoneAndRegionApi;
 import org.jclouds.http.HttpCommand;
 import org.jclouds.http.internal.TrackingJavaUrlHttpCommandExecutorService;
 import org.jclouds.logging.log4j.config.Log4JLoggingModule;
@@ -67,8 +67,8 @@ public abstract class EC2TemplateBuilderLiveTest extends BaseTemplateBuilderLive
 
          Collection<HttpCommand> filteredCommandsInvoked = Collections2.filter(commandsInvoked, new Predicate<HttpCommand>() {
             private final Collection<Method> ignored = ImmutableSet.of(
-                     AvailabilityZoneAndRegionAsyncClient.class.getMethod("describeRegions", DescribeRegionsOptions[].class),
-                     AvailabilityZoneAndRegionAsyncClient.class.getMethod("describeAvailabilityZonesInRegion", String.class, DescribeAvailabilityZonesOptions[].class));
+                     AvailabilityZoneAndRegionApi.class.getMethod("describeRegions", DescribeRegionsOptions[].class),
+                     AvailabilityZoneAndRegionApi.class.getMethod("describeAvailabilityZonesInRegion", String.class, DescribeAvailabilityZonesOptions[].class));
             @Override
             public boolean apply(HttpCommand input) {
                return !ignored.contains(getInvokerOfRequest(input));
@@ -76,7 +76,7 @@ public abstract class EC2TemplateBuilderLiveTest extends BaseTemplateBuilderLive
          });
          
          assert filteredCommandsInvoked.size() == 1 : commandsInvoked;
-         assertEquals(getInvokerOfRequestAtIndex(filteredCommandsInvoked, 0), AMIAsyncClient.class
+         assertEquals(getInvokerOfRequestAtIndex(filteredCommandsInvoked, 0), AMIApi.class
                   .getMethod("describeImagesInRegion", String.class, DescribeImagesOptions[].class));
          assertDescribeImagesOptionsEquals((DescribeImagesOptions[])getArgsForRequestAtIndex(filteredCommandsInvoked, 0).get(1), 
                   defaultImageProviderId);

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/CreateUniqueKeyPairTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/CreateUniqueKeyPairTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/CreateUniqueKeyPairTest.java
index 789f8bc..ddee5e1 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/CreateUniqueKeyPairTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/CreateUniqueKeyPairTest.java
@@ -25,11 +25,12 @@ import static org.testng.Assert.assertEquals;
 import java.net.UnknownHostException;
 
 import org.jclouds.ec2.EC2ApiMetadata;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.domain.KeyPair;
-import org.jclouds.ec2.services.KeyPairClient;
+import org.jclouds.ec2.features.KeyPairApi;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Optional;
 import com.google.common.base.Supplier;
 import com.google.common.base.Suppliers;
 import com.google.inject.AbstractModule;
@@ -45,11 +46,11 @@ public class CreateUniqueKeyPairTest {
    
    @Test
    public void testApply() throws UnknownHostException {
-      final EC2Client client = createMock(EC2Client.class);
-      KeyPairClient keyClient = createMock(KeyPairClient.class);
+      final EC2Api client = createMock(EC2Api.class);
+      KeyPairApi keyClient = createMock(KeyPairApi.class);
       KeyPair pair = createMock(KeyPair.class);
 
-      expect(client.getKeyPairServices()).andReturn(keyClient).atLeastOnce();
+      expect(client.getKeyPairApi()).andReturn((Optional) Optional.of(keyClient)).atLeastOnce();
 
       expect(keyClient.createKeyPairInRegion("region", "jclouds#group#1")).andReturn(pair);
 
@@ -63,7 +64,7 @@ public class CreateUniqueKeyPairTest {
             Names.bindProperties(binder(),new EC2ApiMetadata().getDefaultProperties());
             bind(new TypeLiteral<Supplier<String>>() {
             }).toInstance(Suppliers.ofInstance("1"));
-            bind(EC2Client.class).toInstance(client);
+            bind(EC2Api.class).toInstance(client);
          }
 
       }).getInstance(CreateUniqueKeyPair.class);
@@ -77,13 +78,13 @@ public class CreateUniqueKeyPairTest {
    @SuppressWarnings( { "unchecked" })
    @Test
    public void testApplyWithIllegalStateException() throws UnknownHostException {
-      final EC2Client client = createMock(EC2Client.class);
-      KeyPairClient keyClient = createMock(KeyPairClient.class);
+      final EC2Api client = createMock(EC2Api.class);
+      KeyPairApi keyClient = createMock(KeyPairApi.class);
       final Supplier<String> uniqueIdSupplier = createMock(Supplier.class);
 
       KeyPair pair = createMock(KeyPair.class);
 
-      expect(client.getKeyPairServices()).andReturn(keyClient).atLeastOnce();
+      expect(client.getKeyPairApi()).andReturn((Optional) Optional.of(keyClient)).atLeastOnce();
 
       expect(uniqueIdSupplier.get()).andReturn("1");
       expect(keyClient.createKeyPairInRegion("region", "jclouds#group#1")).andThrow(new IllegalStateException());
@@ -101,7 +102,7 @@ public class CreateUniqueKeyPairTest {
             Names.bindProperties(binder(),new EC2ApiMetadata().getDefaultProperties());
             bind(new TypeLiteral<Supplier<String>>() {
             }).toInstance(uniqueIdSupplier);
-            bind(EC2Client.class).toInstance(client);
+            bind(EC2Api.class).toInstance(client);
          }
 
       }).getInstance(CreateUniqueKeyPair.class);

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/PresentInstancesTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/PresentInstancesTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/PresentInstancesTest.java
index cf5be25..d27b4e9 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/PresentInstancesTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/functions/PresentInstancesTest.java
@@ -24,13 +24,14 @@ import static org.testng.Assert.assertEquals;
 
 import java.util.Set;
 
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.domain.Reservation;
 import org.jclouds.ec2.domain.RunningInstance;
-import org.jclouds.ec2.services.InstanceClient;
+import org.jclouds.ec2.features.InstanceApi;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableSet;
 
 /**
@@ -45,10 +46,10 @@ public class PresentInstancesTest {
    @Test
    public void testWhenInstancesPresentSingleCall() {
 
-      EC2Client client = createMock(EC2Client.class);
-      InstanceClient instanceClient = createMock(InstanceClient.class);
+      EC2Api client = createMock(EC2Api.class);
+      InstanceApi instanceClient = createMock(InstanceApi.class);
 
-      expect(client.getInstanceServices()).andReturn(instanceClient);
+      expect(client.getInstanceApi()).andReturn((Optional) Optional.of(instanceClient));
 
       // avoid imatcher fail.  if you change this, be sure to check multiple jres
       expect(instanceClient.describeInstancesInRegion("us-east-1", "i-aaaa", "i-bbbb")).andReturn(

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/compute/internal/BaseEC2ComputeServiceContextExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/internal/BaseEC2ComputeServiceContextExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/internal/BaseEC2ComputeServiceContextExpectTest.java
index 9cd6b45..cc9790b 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/internal/BaseEC2ComputeServiceContextExpectTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/internal/BaseEC2ComputeServiceContextExpectTest.java
@@ -19,14 +19,14 @@ package org.jclouds.ec2.compute.internal;
 import java.util.Properties;
 
 import org.jclouds.compute.ComputeServiceContext;
-import org.jclouds.ec2.internal.BaseEC2ClientExpectTest;
+import org.jclouds.ec2.internal.BaseEC2ApiExpectTest;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 
 import com.google.common.base.Function;
 import com.google.inject.Module;
 
-public abstract class BaseEC2ComputeServiceContextExpectTest<T> extends BaseEC2ClientExpectTest<T> implements
+public abstract class BaseEC2ComputeServiceContextExpectTest<T> extends BaseEC2ApiExpectTest<T> implements
          Function<ComputeServiceContext, T> {
 
    @Override

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/compute/loaders/CreateSecurityGroupIfNeededTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/loaders/CreateSecurityGroupIfNeededTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/loaders/CreateSecurityGroupIfNeededTest.java
index 9597e1a..1a2b9b3 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/loaders/CreateSecurityGroupIfNeededTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/loaders/CreateSecurityGroupIfNeededTest.java
@@ -31,7 +31,7 @@ import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
 import org.jclouds.ec2.domain.SecurityGroup;
 import org.jclouds.ec2.domain.UserIdGroupPair;
-import org.jclouds.ec2.services.SecurityGroupClient;
+import org.jclouds.ec2.features.SecurityGroupApi;
 import org.jclouds.net.domain.IpProtocol;
 import org.testng.annotations.Test;
 
@@ -49,7 +49,7 @@ public class CreateSecurityGroupIfNeededTest {
    @Test
    public void testWhenPort22AndToItselfAuthorizesIngressTwice() throws ExecutionException {
 
-      SecurityGroupClient client = createMock(SecurityGroupClient.class);
+      SecurityGroupApi client = createMock(SecurityGroupApi.class);
       Predicate<RegionAndName> tester = Predicates.alwaysTrue();
 
       SecurityGroup group = createNiceMock(SecurityGroup.class);
@@ -76,7 +76,7 @@ public class CreateSecurityGroupIfNeededTest {
    @Test
    public void testIllegalStateExceptionCreatingGroupJustReturns() throws ExecutionException {
 
-      SecurityGroupClient client = createMock(SecurityGroupClient.class);
+      SecurityGroupApi client = createMock(SecurityGroupApi.class);
       Predicate<RegionAndName> tester = Predicates.alwaysTrue();
 
       client.createSecurityGroupInRegion("region", "group", "group");
@@ -95,7 +95,7 @@ public class CreateSecurityGroupIfNeededTest {
    @Test(expectedExceptions = RuntimeException.class)
    public void testWhenEventualConsistencyExpiresIllegalStateException() throws ExecutionException {
 
-      SecurityGroupClient client = createMock(SecurityGroupClient.class);
+      SecurityGroupApi client = createMock(SecurityGroupApi.class);
       Predicate<RegionAndName> tester = Predicates.alwaysFalse();
 
       client.createSecurityGroupInRegion("region", "group", "group");

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/compute/loaders/LoadPublicIpForInstanceOrNullTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/loaders/LoadPublicIpForInstanceOrNullTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/loaders/LoadPublicIpForInstanceOrNullTest.java
index 5389e86..9d3feff 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/loaders/LoadPublicIpForInstanceOrNullTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/loaders/LoadPublicIpForInstanceOrNullTest.java
@@ -22,12 +22,13 @@ import static org.easymock.EasyMock.replay;
 import static org.easymock.EasyMock.verify;
 import static org.testng.Assert.assertEquals;
 
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.domain.PublicIpInstanceIdPair;
-import org.jclouds.ec2.services.ElasticIPAddressClient;
+import org.jclouds.ec2.features.ElasticIPAddressApi;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableSet;
 
 /**
@@ -38,10 +39,10 @@ public class LoadPublicIpForInstanceOrNullTest {
 
    @Test
    public void testReturnsPublicIpOnMatch() throws Exception {
-      EC2Client client = createMock(EC2Client.class);
-      ElasticIPAddressClient ipClient = createMock(ElasticIPAddressClient.class);
+      EC2Api client = createMock(EC2Api.class);
+      ElasticIPAddressApi ipClient = createMock(ElasticIPAddressApi.class);
 
-      expect(client.getElasticIPAddressServices()).andReturn(ipClient).atLeastOnce();
+      expect(client.getElasticIPAddressApi()).andReturn((Optional) Optional.of(ipClient)).atLeastOnce();
       expect(ipClient.describeAddressesInRegion("region")).andReturn(
                ImmutableSet.<PublicIpInstanceIdPair> of(new PublicIpInstanceIdPair("region", "1.1.1.1", "i-blah")))
                .atLeastOnce();
@@ -59,10 +60,10 @@ public class LoadPublicIpForInstanceOrNullTest {
 
    @Test
    public void testReturnsNullWhenNotFound() throws Exception {
-      EC2Client client = createMock(EC2Client.class);
-      ElasticIPAddressClient ipClient = createMock(ElasticIPAddressClient.class);
+      EC2Api client = createMock(EC2Api.class);
+      ElasticIPAddressApi ipClient = createMock(ElasticIPAddressApi.class);
 
-      expect(client.getElasticIPAddressServices()).andReturn(ipClient).atLeastOnce();
+      expect(client.getElasticIPAddressApi()).andReturn((Optional) Optional.of(ipClient)).atLeastOnce();
 
       expect(ipClient.describeAddressesInRegion("region")).andReturn(ImmutableSet.<PublicIpInstanceIdPair> of())
                .atLeastOnce();
@@ -81,10 +82,10 @@ public class LoadPublicIpForInstanceOrNullTest {
 
    @Test
    public void testReturnsNullWhenNotAssigned() throws Exception {
-      EC2Client client = createMock(EC2Client.class);
-      ElasticIPAddressClient ipClient = createMock(ElasticIPAddressClient.class);
+      EC2Api client = createMock(EC2Api.class);
+      ElasticIPAddressApi ipClient = createMock(ElasticIPAddressApi.class);
 
-      expect(client.getElasticIPAddressServices()).andReturn(ipClient).atLeastOnce();
+      expect(client.getElasticIPAddressApi()).andReturn((Optional) Optional.of(ipClient)).atLeastOnce();
 
       expect(ipClient.describeAddressesInRegion("region")).andReturn(
                ImmutableSet.<PublicIpInstanceIdPair> of(new PublicIpInstanceIdPair("region", "1.1.1.1", null)))

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/compute/loaders/RegionAndIdToImageTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/loaders/RegionAndIdToImageTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/loaders/RegionAndIdToImageTest.java
index 64a76e9..5c1c2aa 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/loaders/RegionAndIdToImageTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/loaders/RegionAndIdToImageTest.java
@@ -29,13 +29,14 @@ import java.util.Set;
 import java.util.concurrent.ExecutionException;
 
 import org.jclouds.compute.domain.Image;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.compute.functions.EC2ImageParser;
-import org.jclouds.ec2.services.AMIClient;
+import org.jclouds.ec2.features.AMIApi;
 import org.jclouds.rest.ResourceNotFoundException;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Optional;
 import com.google.common.collect.ImmutableSet;
 
 /**
@@ -49,14 +50,14 @@ public class RegionAndIdToImageTest {
    public void testApply() throws ExecutionException {
 
       EC2ImageParser parser = createMock(EC2ImageParser.class);
-      EC2Client caller = createMock(EC2Client.class);
-      AMIClient client = createMock(AMIClient.class);
+      EC2Api caller = createMock(EC2Api.class);
+      AMIApi client = createMock(AMIApi.class);
 
       org.jclouds.ec2.domain.Image ec2Image = createMock(org.jclouds.ec2.domain.Image.class);
       Image image = createNiceMock(Image.class);
       Set<? extends org.jclouds.ec2.domain.Image> images = ImmutableSet.<org.jclouds.ec2.domain.Image> of(ec2Image);
 
-      expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
+      expect(caller.getAMIApi()).andReturn((Optional) Optional.of(client)).atLeastOnce();
       expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn(Set.class.cast(images));
       expect(parser.apply(ec2Image)).andReturn(image);
 
@@ -81,14 +82,14 @@ public class RegionAndIdToImageTest {
    public void testApplyNotFoundMakesExecutionException() throws ExecutionException {
 
       EC2ImageParser parser = createMock(EC2ImageParser.class);
-      EC2Client caller = createMock(EC2Client.class);
-      AMIClient client = createMock(AMIClient.class);
+      EC2Api caller = createMock(EC2Api.class);
+      AMIApi client = createMock(AMIApi.class);
 
       org.jclouds.ec2.domain.Image ec2Image = createMock(org.jclouds.ec2.domain.Image.class);
       Image image = createNiceMock(Image.class);
       Set<? extends org.jclouds.ec2.domain.Image> images = ImmutableSet.<org.jclouds.ec2.domain.Image> of(ec2Image);
 
-      expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
+      expect(caller.getAMIApi()).andReturn((Optional) Optional.of(client)).atLeastOnce();
       expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn(Set.class.cast(images));
       expect(parser.apply(ec2Image)).andThrow(new ResourceNotFoundException());
 
@@ -113,14 +114,14 @@ public class RegionAndIdToImageTest {
    public void testApplyNoSuchElementExceptionMakesExecutionException() throws ExecutionException {
 
       EC2ImageParser parser = createMock(EC2ImageParser.class);
-      EC2Client caller = createMock(EC2Client.class);
-      AMIClient client = createMock(AMIClient.class);
+      EC2Api caller = createMock(EC2Api.class);
+      AMIApi client = createMock(AMIApi.class);
 
       org.jclouds.ec2.domain.Image ec2Image = createMock(org.jclouds.ec2.domain.Image.class);
       Image image = createNiceMock(Image.class);
       Set<? extends org.jclouds.ec2.domain.Image> images = ImmutableSet.<org.jclouds.ec2.domain.Image> of(ec2Image);
 
-      expect(caller.getAMIServices()).andReturn(client).atLeastOnce();
+      expect(caller.getAMIApi()).andReturn((Optional) Optional.of(client)).atLeastOnce();
       expect(client.describeImagesInRegion("region", imageIds("ami"))).andReturn(Set.class.cast(images));
       expect(parser.apply(ec2Image)).andThrow(new NoSuchElementException());
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/compute/strategy/EC2CreateNodesInGroupThenAddToSetTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/strategy/EC2CreateNodesInGroupThenAddToSetTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/strategy/EC2CreateNodesInGroupThenAddToSetTest.java
index 2a8bb45..b2ec12d 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/strategy/EC2CreateNodesInGroupThenAddToSetTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/strategy/EC2CreateNodesInGroupThenAddToSetTest.java
@@ -42,7 +42,7 @@ import org.jclouds.domain.Location;
 import org.jclouds.domain.LocationBuilder;
 import org.jclouds.domain.LocationScope;
 import org.jclouds.domain.LoginCredentials;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.compute.functions.PresentInstances;
 import org.jclouds.ec2.compute.functions.RunningInstanceToNodeMetadata;
@@ -50,8 +50,8 @@ import org.jclouds.ec2.compute.options.EC2TemplateOptions;
 import org.jclouds.ec2.domain.Reservation;
 import org.jclouds.ec2.domain.RunningInstance;
 import org.jclouds.ec2.options.RunInstancesOptions;
-import org.jclouds.ec2.services.ElasticIPAddressClient;
-import org.jclouds.ec2.services.InstanceClient;
+import org.jclouds.ec2.features.ElasticIPAddressApi;
+import org.jclouds.ec2.features.InstanceApi;
 import org.testng.Assert;
 import org.testng.annotations.Test;
 
@@ -80,8 +80,8 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
       // setup mocks
       EC2CreateNodesInGroupThenAddToSet strategy = setupStrategy(nodeMetadata);
       InputParams input = new InputParams(location);
-      InstanceClient instanceClient = createMock(InstanceClient.class);
-      ElasticIPAddressClient ipClient = createMock(ElasticIPAddressClient.class);
+      InstanceApi instanceClient = createMock(InstanceApi.class);
+      ElasticIPAddressApi ipClient = createMock(ElasticIPAddressApi.class);
       RunInstancesOptions ec2Options = createMock(RunInstancesOptions.class);
       RunningInstance instance = createMock(RunningInstance.class);
       Reservation<? extends RunningInstance> reservation = new Reservation<RunningInstance>(region,
@@ -93,11 +93,11 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
 
       // setup expectations
       expect(input.template.clone()).andReturn(input.template);
-      expect(strategy.client.getInstanceServices()).andReturn(instanceClient).atLeastOnce();
+      expect(strategy.client.getInstanceApi()).andReturn((Optional) Optional.of(instanceClient)).atLeastOnce();
       expect(
             strategy.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize
                   .execute(region, input.tag, input.template)).andReturn(ec2Options);
-      expect(strategy.client.getElasticIPAddressServices()).andReturn(ipClient).atLeastOnce();
+      expect(strategy.client.getElasticIPAddressApi()).andReturn((Optional) Optional.of(ipClient)).atLeastOnce();
 
       expect(input.template.getLocation()).andReturn(input.location).atLeastOnce();
       expect(input.template.getImage()).andReturn(input.image).atLeastOnce();
@@ -191,7 +191,7 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
       // setup mocks
       EC2CreateNodesInGroupThenAddToSet strategy = setupStrategy(nodeMetadata);
       InputParams input = new InputParams(location);
-      InstanceClient instanceClient = createMock(InstanceClient.class);
+      InstanceApi instanceClient = createMock(InstanceApi.class);
       RunInstancesOptions ec2Options = createMock(RunInstancesOptions.class);
       RunningInstance instance = createMock(RunningInstance.class);
       Reservation<? extends RunningInstance> reservation = new Reservation<RunningInstance>(region,
@@ -200,7 +200,7 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
 
       // setup expectations
       expect(input.template.clone()).andReturn(input.template);
-      expect(strategy.client.getInstanceServices()).andReturn(instanceClient).atLeastOnce();
+      expect(strategy.client.getInstanceApi()).andReturn((Optional) Optional.of(instanceClient)).atLeastOnce();
       expect(
             strategy.createKeyPairAndSecurityGroupsAsNeededAndReturncustomize
                   .execute(region, input.tag, input.template)).andReturn(ec2Options);
@@ -307,7 +307,7 @@ public class EC2CreateNodesInGroupThenAddToSetTest {
 
    @SuppressWarnings("unchecked")
    private EC2CreateNodesInGroupThenAddToSet setupStrategy(final NodeMetadata node) {
-      EC2Client client = createMock(EC2Client.class);
+      EC2Api client = createMock(EC2Api.class);
       CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize = createMock(CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions.class);
       PresentInstances presentInstances = createMock(PresentInstances.class);
       RunningInstanceToNodeMetadata runningInstanceToNodeMetadata = createMock(RunningInstanceToNodeMetadata.class);

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/compute/strategy/EC2DestroyNodeStrategyTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/strategy/EC2DestroyNodeStrategyTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/strategy/EC2DestroyNodeStrategyTest.java
index 8e892f2..6bc929c 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/strategy/EC2DestroyNodeStrategyTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/strategy/EC2DestroyNodeStrategyTest.java
@@ -26,12 +26,13 @@ import java.util.concurrent.ExecutionException;
 
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
-import org.jclouds.ec2.services.ElasticIPAddressClient;
-import org.jclouds.ec2.services.InstanceClient;
+import org.jclouds.ec2.features.ElasticIPAddressApi;
+import org.jclouds.ec2.features.InstanceApi;
 import org.testng.annotations.Test;
 
+import com.google.common.base.Optional;
 import com.google.common.cache.CacheLoader;
 import com.google.common.cache.LoadingCache;
 
@@ -44,14 +45,14 @@ public class EC2DestroyNodeStrategyTest {
    @SuppressWarnings("unchecked")
    @Test
    public void testDestroyNodeTerminatesInstanceAndReturnsRefreshedNode() throws Exception {
-      EC2Client client = createMock(EC2Client.class);
-      InstanceClient instanceClient = createMock(InstanceClient.class);
+      EC2Api client = createMock(EC2Api.class);
+      InstanceApi instanceClient = createMock(InstanceApi.class);
       GetNodeMetadataStrategy getNode = createMock(GetNodeMetadataStrategy.class);
       LoadingCache<RegionAndName, String> elasticIpCache = createMock(LoadingCache.class);
 
       NodeMetadata node = createMock(NodeMetadata.class);
 
-      expect(client.getInstanceServices()).andReturn(instanceClient).atLeastOnce();
+      expect(client.getInstanceApi()).andReturn((Optional) Optional.of(instanceClient)).atLeastOnce();
       expect(instanceClient.terminateInstancesInRegion("region", "i-blah")).andReturn(null);
       expect(getNode.getNode("region/i-blah")).andReturn(node);
 
@@ -74,23 +75,23 @@ public class EC2DestroyNodeStrategyTest {
    @Test
    public void testDestroyNodeDisassociatesAndReleasesIpThenTerminatesInstanceAndReturnsRefreshedNode()
             throws Exception {
-      EC2Client client = createMock(EC2Client.class);
+      EC2Api client = createMock(EC2Api.class);
       GetNodeMetadataStrategy getNode = createMock(GetNodeMetadataStrategy.class);
       LoadingCache<RegionAndName, String> elasticIpCache = createMock(LoadingCache.class);
-      ElasticIPAddressClient ipClient = createMock(ElasticIPAddressClient.class);
-      InstanceClient instanceClient = createMock(InstanceClient.class);
+      ElasticIPAddressApi ipClient = createMock(ElasticIPAddressApi.class);
+      InstanceApi instanceClient = createMock(InstanceApi.class);
 
       NodeMetadata node = createMock(NodeMetadata.class);
 
       expect(elasticIpCache.get(new RegionAndName("region", "i-blah"))).andReturn("1.1.1.1");
 
-      expect(client.getElasticIPAddressServices()).andReturn(ipClient).atLeastOnce();
+      expect(client.getElasticIPAddressApi()).andReturn((Optional) Optional.of(ipClient)).atLeastOnce();
       ipClient.disassociateAddressInRegion("region", "1.1.1.1");
       ipClient.releaseAddressInRegion("region", "1.1.1.1");
       elasticIpCache.invalidate(new RegionAndName("region", "i-blah"));
 
 
-      expect(client.getInstanceServices()).andReturn(instanceClient).atLeastOnce();
+      expect(client.getInstanceApi()).andReturn((Optional) Optional.of(instanceClient)).atLeastOnce();
       expect(instanceClient.terminateInstancesInRegion("region", "i-blah")).andReturn(null);
       expect(getNode.getNode("region/i-blah")).andReturn(node);
 
@@ -117,17 +118,17 @@ public class EC2DestroyNodeStrategyTest {
    @Test
    public void testDestroyNodeSafeOnCacheMissThenTerminatesInstanceAndReturnsRefreshedNode()
             throws Exception {
-      EC2Client client = createMock(EC2Client.class);
+      EC2Api client = createMock(EC2Api.class);
       GetNodeMetadataStrategy getNode = createMock(GetNodeMetadataStrategy.class);
       LoadingCache<RegionAndName, String> elasticIpCache = createMock(LoadingCache.class);
-      ElasticIPAddressClient ipClient = createMock(ElasticIPAddressClient.class);
-      InstanceClient instanceClient = createMock(InstanceClient.class);
+      ElasticIPAddressApi ipClient = createMock(ElasticIPAddressApi.class);
+      InstanceApi instanceClient = createMock(InstanceApi.class);
 
       NodeMetadata node = createMock(NodeMetadata.class);
 
       expect(elasticIpCache.get(new RegionAndName("region", "i-blah"))).andThrow(new CacheLoader.InvalidCacheLoadException(null));
 
-      expect(client.getInstanceServices()).andReturn(instanceClient).atLeastOnce();
+      expect(client.getInstanceApi()).andReturn((Optional) Optional.of(instanceClient)).atLeastOnce();
       expect(instanceClient.terminateInstancesInRegion("region", "i-blah")).andReturn(null);
       expect(getNode.getNode("region/i-blah")).andReturn(node);
 
@@ -154,17 +155,17 @@ public class EC2DestroyNodeStrategyTest {
    @Test
    public void testDestroyNodeSafeOnCacheExecutionExceptionThenTerminatesInstanceAndReturnsRefreshedNode()
             throws Exception {
-      EC2Client client = createMock(EC2Client.class);
+      EC2Api client = createMock(EC2Api.class);
       GetNodeMetadataStrategy getNode = createMock(GetNodeMetadataStrategy.class);
       LoadingCache<RegionAndName, String> elasticIpCache = createMock(LoadingCache.class);
-      ElasticIPAddressClient ipClient = createMock(ElasticIPAddressClient.class);
-      InstanceClient instanceClient = createMock(InstanceClient.class);
+      ElasticIPAddressApi ipClient = createMock(ElasticIPAddressApi.class);
+      InstanceApi instanceClient = createMock(InstanceApi.class);
 
       NodeMetadata node = createMock(NodeMetadata.class);
 
       expect(elasticIpCache.get(new RegionAndName("region", "i-blah"))).andThrow(new ExecutionException(null));
 
-      expect(client.getInstanceServices()).andReturn(instanceClient).atLeastOnce();
+      expect(client.getInstanceApi()).andReturn((Optional) Optional.of(instanceClient)).atLeastOnce();
       expect(instanceClient.terminateInstancesInRegion("region", "i-blah")).andReturn(null);
       expect(getNode.getNode("region/i-blah")).andReturn(node);
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/config/EC2HttpApiModuleExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/config/EC2HttpApiModuleExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/config/EC2HttpApiModuleExpectTest.java
new file mode 100644
index 0000000..0785228
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/config/EC2HttpApiModuleExpectTest.java
@@ -0,0 +1,145 @@
+/*
+ * 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.config;
+
+import static org.testng.Assert.assertEquals;
+
+import java.net.URI;
+import java.util.Map;
+import java.util.Properties;
+import java.util.Set;
+
+import org.jclouds.ec2.internal.BaseEC2ApiExpectTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.location.Region;
+import org.jclouds.location.Zone;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.location.functions.ZoneToEndpoint;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Function;
+import com.google.common.base.Supplier;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.ImmutableSet;
+import com.google.inject.Injector;
+import com.google.inject.Key;
+import com.google.inject.Module;
+import com.google.inject.TypeLiteral;
+
+/**
+ * @author Adrian Cole
+ */
+@Test(groups = "unit", testName = "EC2HttpApiModuleExpectTest")
+public class EC2HttpApiModuleExpectTest extends BaseEC2ApiExpectTest<Injector> {
+   private Injector injector;
+
+   @BeforeClass
+   @Override
+   protected void setupDefaultRequests() {
+      super.setupDefaultRequests();
+      Builder<HttpRequest, HttpResponse> builder = ImmutableMap.<HttpRequest, HttpResponse> builder();
+      builder.put(describeRegionsRequest, describeRegionsResponse);
+      builder.putAll(describeAvailabilityZonesRequestResponse);
+
+      injector = requestsSendResponses(builder.build());
+   }
+
+   public void testLocationIdAndURIBindings() {
+
+      assertEquals(injector.getInstance(Key.get(new TypeLiteral<Supplier<Set<String>>>() {
+      }, Region.class)).get(), ImmutableSet.<String> of("sa-east-1", "ap-northeast-1", "eu-west-1", "us-east-1",
+            "us-west-1", "us-west-2", "ap-southeast-1"));
+
+      assertEquals(injector.getInstance(Key.get(new TypeLiteral<Supplier<Set<String>>>() {
+      }, Zone.class)).get(), ImmutableSet.<String> of("sa-east-1a", "sa-east-1b", "ap-northeast-1a", "ap-northeast-1b",
+            "eu-west-1a", "eu-west-1b", "eu-west-1c", "us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d",
+            "us-east-1e", "us-west-1a", "us-west-1b", "us-west-1c", "us-west-2a", "us-west-2b", "us-west-2c",
+            "ap-southeast-1a", "ap-southeast-1b"));
+
+      Map<String, Supplier<URI>> regionToURISupplier = injector.getInstance(
+            Key.get(new TypeLiteral<Supplier<Map<String, Supplier<URI>>>>() {
+            }, Region.class)).get();
+
+      assertEquals(regionToURISupplier.get("sa-east-1").get(), URI.create("https://ec2.sa-east-1.amazonaws.com"));
+      assertEquals(regionToURISupplier.get("ap-northeast-1").get(),
+            URI.create("https://ec2.ap-northeast-1.amazonaws.com"));
+      assertEquals(regionToURISupplier.get("eu-west-1").get(), URI.create("https://ec2.eu-west-1.amazonaws.com"));
+      assertEquals(regionToURISupplier.get("us-east-1").get(), URI.create("https://ec2.us-east-1.amazonaws.com"));
+      assertEquals(regionToURISupplier.get("us-west-1").get(), URI.create("https://ec2.us-west-1.amazonaws.com"));
+      assertEquals(regionToURISupplier.get("us-west-2").get(), URI.create("https://ec2.us-west-2.amazonaws.com"));
+      assertEquals(regionToURISupplier.get("ap-southeast-1").get(),
+            URI.create("https://ec2.ap-southeast-1.amazonaws.com"));
+
+      Map<String, Supplier<Set<String>>> regionToZoneIdSupplier = injector.getInstance(
+            Key.get(new TypeLiteral<Supplier<Map<String, Supplier<Set<String>>>>>() {
+            }, Zone.class)).get();
+
+      assertEquals(regionToZoneIdSupplier.get("sa-east-1").get(), ImmutableSet.of("sa-east-1a", "sa-east-1b"));
+      assertEquals(regionToZoneIdSupplier.get("ap-northeast-1").get(),
+            ImmutableSet.of("ap-northeast-1a", "ap-northeast-1b"));
+      assertEquals(regionToZoneIdSupplier.get("eu-west-1").get(),
+            ImmutableSet.of("eu-west-1a", "eu-west-1b", "eu-west-1c"));
+      assertEquals(regionToZoneIdSupplier.get("us-east-1").get(),
+            ImmutableSet.of("us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d", "us-east-1e"));
+      assertEquals(regionToZoneIdSupplier.get("us-west-1").get(),
+            ImmutableSet.of("us-west-1a", "us-west-1b", "us-west-1c"));
+      assertEquals(regionToZoneIdSupplier.get("us-west-2").get(),
+            ImmutableSet.of("us-west-2a", "us-west-2b", "us-west-2c"));
+      assertEquals(regionToZoneIdSupplier.get("ap-southeast-1").get(),
+            ImmutableSet.of("ap-southeast-1a", "ap-southeast-1b"));
+
+      Map<String, Supplier<URI>> zoneToURISupplier = injector.getInstance(
+            Key.get(new TypeLiteral<Supplier<Map<String, Supplier<URI>>>>() {
+            }, Zone.class)).get();
+
+      assertEquals(zoneToURISupplier.get("sa-east-1a").get(), URI.create("https://ec2.sa-east-1.amazonaws.com"));
+
+      assertEquals(zoneToURISupplier.get("ap-northeast-1a").get(),
+            URI.create("https://ec2.ap-northeast-1.amazonaws.com"));
+
+      assertEquals(zoneToURISupplier.get("eu-west-1a").get(), URI.create("https://ec2.eu-west-1.amazonaws.com"));
+
+      assertEquals(zoneToURISupplier.get("us-east-1a").get(), URI.create("https://ec2.us-east-1.amazonaws.com"));
+
+      assertEquals(zoneToURISupplier.get("us-west-1a").get(), URI.create("https://ec2.us-west-1.amazonaws.com"));
+
+      assertEquals(zoneToURISupplier.get("us-west-2a").get(), URI.create("https://ec2.us-west-2.amazonaws.com"));
+
+      assertEquals(zoneToURISupplier.get("ap-southeast-1a").get(),
+            URI.create("https://ec2.ap-southeast-1.amazonaws.com"));
+
+   }
+
+   public void testZoneToEndpoint() {
+      assertEquals(injector.getInstance(ZoneToEndpoint.class).apply("us-west-2a"),
+            URI.create("https://ec2.us-west-2.amazonaws.com"));
+   }
+   
+   public void testRegionToEndpointOrProviderIfNull() {
+      assertEquals(injector.getInstance(RegionToEndpointOrProviderIfNull.class).apply("us-west-2"),
+            URI.create("https://ec2.us-west-2.amazonaws.com"));
+   }
+   
+   @Override
+   public Injector createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
+      return createInjector(fn, module, props);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/test/java/org/jclouds/ec2/config/EC2RestClientModuleExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/config/EC2RestClientModuleExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/config/EC2RestClientModuleExpectTest.java
deleted file mode 100644
index a0c1975..0000000
--- a/apis/ec2/src/test/java/org/jclouds/ec2/config/EC2RestClientModuleExpectTest.java
+++ /dev/null
@@ -1,145 +0,0 @@
-/*
- * 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.config;
-
-import static org.testng.Assert.assertEquals;
-
-import java.net.URI;
-import java.util.Map;
-import java.util.Properties;
-import java.util.Set;
-
-import org.jclouds.ec2.internal.BaseEC2ClientExpectTest;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.location.Region;
-import org.jclouds.location.Zone;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.location.functions.ZoneToEndpoint;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import com.google.common.base.Function;
-import com.google.common.base.Supplier;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMap.Builder;
-import com.google.common.collect.ImmutableSet;
-import com.google.inject.Injector;
-import com.google.inject.Key;
-import com.google.inject.Module;
-import com.google.inject.TypeLiteral;
-
-/**
- * @author Adrian Cole
- */
-@Test(groups = "unit", testName = "EC2RestClientModuleExpectTest")
-public class EC2RestClientModuleExpectTest extends BaseEC2ClientExpectTest<Injector> {
-   private Injector injector;
-
-   @BeforeClass
-   @Override
-   protected void setupDefaultRequests() {
-      super.setupDefaultRequests();
-      Builder<HttpRequest, HttpResponse> builder = ImmutableMap.<HttpRequest, HttpResponse> builder();
-      builder.put(describeRegionsRequest, describeRegionsResponse);
-      builder.putAll(describeAvailabilityZonesRequestResponse);
-
-      injector = requestsSendResponses(builder.build());
-   }
-
-   public void testLocationIdAndURIBindings() {
-
-      assertEquals(injector.getInstance(Key.get(new TypeLiteral<Supplier<Set<String>>>() {
-      }, Region.class)).get(), ImmutableSet.<String> of("sa-east-1", "ap-northeast-1", "eu-west-1", "us-east-1",
-            "us-west-1", "us-west-2", "ap-southeast-1"));
-
-      assertEquals(injector.getInstance(Key.get(new TypeLiteral<Supplier<Set<String>>>() {
-      }, Zone.class)).get(), ImmutableSet.<String> of("sa-east-1a", "sa-east-1b", "ap-northeast-1a", "ap-northeast-1b",
-            "eu-west-1a", "eu-west-1b", "eu-west-1c", "us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d",
-            "us-east-1e", "us-west-1a", "us-west-1b", "us-west-1c", "us-west-2a", "us-west-2b", "us-west-2c",
-            "ap-southeast-1a", "ap-southeast-1b"));
-
-      Map<String, Supplier<URI>> regionToURISupplier = injector.getInstance(
-            Key.get(new TypeLiteral<Supplier<Map<String, Supplier<URI>>>>() {
-            }, Region.class)).get();
-
-      assertEquals(regionToURISupplier.get("sa-east-1").get(), URI.create("https://ec2.sa-east-1.amazonaws.com"));
-      assertEquals(regionToURISupplier.get("ap-northeast-1").get(),
-            URI.create("https://ec2.ap-northeast-1.amazonaws.com"));
-      assertEquals(regionToURISupplier.get("eu-west-1").get(), URI.create("https://ec2.eu-west-1.amazonaws.com"));
-      assertEquals(regionToURISupplier.get("us-east-1").get(), URI.create("https://ec2.us-east-1.amazonaws.com"));
-      assertEquals(regionToURISupplier.get("us-west-1").get(), URI.create("https://ec2.us-west-1.amazonaws.com"));
-      assertEquals(regionToURISupplier.get("us-west-2").get(), URI.create("https://ec2.us-west-2.amazonaws.com"));
-      assertEquals(regionToURISupplier.get("ap-southeast-1").get(),
-            URI.create("https://ec2.ap-southeast-1.amazonaws.com"));
-
-      Map<String, Supplier<Set<String>>> regionToZoneIdSupplier = injector.getInstance(
-            Key.get(new TypeLiteral<Supplier<Map<String, Supplier<Set<String>>>>>() {
-            }, Zone.class)).get();
-
-      assertEquals(regionToZoneIdSupplier.get("sa-east-1").get(), ImmutableSet.of("sa-east-1a", "sa-east-1b"));
-      assertEquals(regionToZoneIdSupplier.get("ap-northeast-1").get(),
-            ImmutableSet.of("ap-northeast-1a", "ap-northeast-1b"));
-      assertEquals(regionToZoneIdSupplier.get("eu-west-1").get(),
-            ImmutableSet.of("eu-west-1a", "eu-west-1b", "eu-west-1c"));
-      assertEquals(regionToZoneIdSupplier.get("us-east-1").get(),
-            ImmutableSet.of("us-east-1a", "us-east-1b", "us-east-1c", "us-east-1d", "us-east-1e"));
-      assertEquals(regionToZoneIdSupplier.get("us-west-1").get(),
-            ImmutableSet.of("us-west-1a", "us-west-1b", "us-west-1c"));
-      assertEquals(regionToZoneIdSupplier.get("us-west-2").get(),
-            ImmutableSet.of("us-west-2a", "us-west-2b", "us-west-2c"));
-      assertEquals(regionToZoneIdSupplier.get("ap-southeast-1").get(),
-            ImmutableSet.of("ap-southeast-1a", "ap-southeast-1b"));
-
-      Map<String, Supplier<URI>> zoneToURISupplier = injector.getInstance(
-            Key.get(new TypeLiteral<Supplier<Map<String, Supplier<URI>>>>() {
-            }, Zone.class)).get();
-
-      assertEquals(zoneToURISupplier.get("sa-east-1a").get(), URI.create("https://ec2.sa-east-1.amazonaws.com"));
-
-      assertEquals(zoneToURISupplier.get("ap-northeast-1a").get(),
-            URI.create("https://ec2.ap-northeast-1.amazonaws.com"));
-
-      assertEquals(zoneToURISupplier.get("eu-west-1a").get(), URI.create("https://ec2.eu-west-1.amazonaws.com"));
-
-      assertEquals(zoneToURISupplier.get("us-east-1a").get(), URI.create("https://ec2.us-east-1.amazonaws.com"));
-
-      assertEquals(zoneToURISupplier.get("us-west-1a").get(), URI.create("https://ec2.us-west-1.amazonaws.com"));
-
-      assertEquals(zoneToURISupplier.get("us-west-2a").get(), URI.create("https://ec2.us-west-2.amazonaws.com"));
-
-      assertEquals(zoneToURISupplier.get("ap-southeast-1a").get(),
-            URI.create("https://ec2.ap-southeast-1.amazonaws.com"));
-
-   }
-
-   public void testZoneToEndpoint() {
-      assertEquals(injector.getInstance(ZoneToEndpoint.class).apply("us-west-2a"),
-            URI.create("https://ec2.us-west-2.amazonaws.com"));
-   }
-   
-   public void testRegionToEndpointOrProviderIfNull() {
-      assertEquals(injector.getInstance(RegionToEndpointOrProviderIfNull.class).apply("us-west-2"),
-            URI.create("https://ec2.us-west-2.amazonaws.com"));
-   }
-   
-   @Override
-   public Injector createClient(Function<HttpRequest, HttpResponse> fn, Module module, Properties props) {
-      return createInjector(fn, module, props);
-   }
-
-}


[20/20] git commit: JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
JCLOUDS-150 - Removal of async from AWS - specifically EC2

...and EC2-related elsewhere. Also moved *Client -> *Api, and moved
everything from .../services to .../features, and threw in a bunch of
Optionals to fit the EC2Api approach.

And a very big tip of the hat to nacx for figuring out the generics
stuff my brain just could not handle. =)


Project: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/commit/5f3b8d3f
Tree: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/tree/5f3b8d3f
Diff: http://git-wip-us.apache.org/repos/asf/incubator-jclouds/diff/5f3b8d3f

Branch: refs/heads/master
Commit: 5f3b8d3fa7e5ee0f17096138eb5f80919f8c350f
Parents: 5f524ee
Author: Andrew Bayer <an...@gmail.com>
Authored: Mon Jul 1 12:12:26 2013 -0700
Committer: Andrew Bayer <an...@gmail.com>
Committed: Mon Jul 1 12:12:26 2013 -0700

----------------------------------------------------------------------
 .../src/main/clojure/org/jclouds/ec2/ami2.clj   |   6 +-
 .../clojure/org/jclouds/ec2/elastic_ip2.clj     |   6 +-
 .../clojure/org/jclouds/ec2/security_group2.clj |   8 +-
 .../src/main/java/org/jclouds/ec2/EC2Api.java   |  81 +-
 .../java/org/jclouds/ec2/EC2ApiMetadata.java    |  27 +-
 .../main/java/org/jclouds/ec2/EC2AsyncApi.java  |  78 --
 .../java/org/jclouds/ec2/EC2AsyncClient.java    |  87 ---
 .../main/java/org/jclouds/ec2/EC2Client.java    |  84 --
 .../jclouds/ec2/compute/EC2ComputeService.java  |  16 +-
 .../compute/extensions/EC2ImageExtension.java   |  14 +-
 .../extensions/EC2SecurityGroupExtension.java   |  34 +-
 .../compute/functions/CreateUniqueKeyPair.java  |  10 +-
 .../PasswordCredentialsFromWindowsInstance.java |  10 +-
 .../ec2/compute/functions/PresentInstances.java |   8 +-
 .../loaders/CreateSecurityGroupIfNeeded.java    |  12 +-
 .../loaders/LoadPublicIpForInstanceOrNull.java  |   8 +-
 .../ec2/compute/loaders/RegionAndIdToImage.java |   8 +-
 .../predicates/SecurityGroupPresent.java        |   8 +-
 .../strategy/DescribeImagesParallel.java        |  42 +-
 .../EC2CreateNodesInGroupThenAddToSet.java      |  12 +-
 .../strategy/EC2DestroyNodeStrategy.java        |  12 +-
 .../compute/strategy/EC2GetImageStrategy.java   |   8 +-
 .../strategy/EC2GetNodeMetadataStrategy.java    |   8 +-
 .../compute/strategy/EC2ListNodesStrategy.java  |  10 +-
 .../compute/strategy/EC2RebootNodeStrategy.java |  10 +-
 .../compute/strategy/EC2ResumeNodeStrategy.java |  10 +-
 .../strategy/EC2SuspendNodeStrategy.java        |  10 +-
 .../ec2/config/BaseEC2HttpApiModule.java        |  78 ++
 .../jclouds/ec2/config/EC2HttpApiModule.java    |  67 ++
 .../jclouds/ec2/config/EC2RestClientModule.java | 134 ----
 .../java/org/jclouds/ec2/features/AMIApi.java   | 336 ++++++++
 .../features/AvailabilityZoneAndRegionApi.java  |  90 +++
 .../ec2/features/ElasticBlockStoreApi.java      | 545 +++++++++++++
 .../ec2/features/ElasticIPAddressApi.java       | 171 +++++
 .../org/jclouds/ec2/features/InstanceApi.java   | 765 +++++++++++++++++++
 .../org/jclouds/ec2/features/KeyPairApi.java    | 131 ++++
 .../jclouds/ec2/features/SecurityGroupApi.java  | 293 +++++++
 .../org/jclouds/ec2/features/SubnetApi.java     |  44 +-
 .../jclouds/ec2/features/SubnetAsyncApi.java    |  83 --
 .../java/org/jclouds/ec2/features/TagApi.java   |  78 +-
 .../org/jclouds/ec2/features/TagAsyncApi.java   | 138 ----
 .../org/jclouds/ec2/features/WindowsApi.java    | 159 +++-
 .../jclouds/ec2/features/WindowsAsyncApi.java   |  65 --
 .../options/BundleInstanceS3StorageOptions.java |   2 +-
 .../jclouds/ec2/options/CreateImageOptions.java |   4 +-
 .../ec2/options/CreateSnapshotOptions.java      |   4 +-
 .../DescribeAvailabilityZonesOptions.java       |   4 +-
 .../ec2/options/DescribeImagesOptions.java      |   4 +-
 .../ec2/options/DescribeRegionsOptions.java     |   2 +-
 .../ec2/options/DescribeSnapshotsOptions.java   |   4 +-
 .../ec2/options/DetachVolumeOptions.java        |   4 +-
 .../RegisterImageBackedByEbsOptions.java        |   2 +-
 .../ec2/options/RegisterImageOptions.java       |   2 +-
 .../ec2/options/RunInstancesOptions.java        |   2 +-
 .../ec2/predicates/InstanceHasIpAddress.java    |   8 +-
 .../ec2/predicates/InstanceStateRunning.java    |   8 +-
 .../ec2/predicates/InstanceStateStopped.java    |   6 +-
 .../ec2/predicates/InstanceStateTerminated.java |   8 +-
 .../ec2/predicates/SnapshotCompleted.java       |   6 +-
 .../jclouds/ec2/predicates/VolumeAttached.java  |   6 +-
 .../jclouds/ec2/predicates/VolumeAvailable.java |   6 +-
 .../jclouds/ec2/predicates/VolumeDetached.java  |   6 +-
 .../jclouds/ec2/services/AMIAsyncClient.java    | 192 -----
 .../org/jclouds/ec2/services/AMIClient.java     | 253 ------
 .../AvailabilityZoneAndRegionAsyncClient.java   |  80 --
 .../AvailabilityZoneAndRegionClient.java        |  57 --
 .../services/ElasticBlockStoreAsyncClient.java  | 239 ------
 .../ec2/services/ElasticBlockStoreClient.java   | 419 ----------
 .../services/ElasticIPAddressAsyncClient.java   | 113 ---
 .../ec2/services/ElasticIPAddressClient.java    | 117 ---
 .../ec2/services/InstanceAsyncClient.java       | 361 ---------
 .../jclouds/ec2/services/InstanceClient.java    | 587 --------------
 .../ec2/services/KeyPairAsyncClient.java        |  92 ---
 .../org/jclouds/ec2/services/KeyPairClient.java |  87 ---
 .../ec2/services/SecurityGroupAsyncClient.java  | 145 ----
 .../ec2/services/SecurityGroupClient.java       | 226 ------
 .../ec2/services/WindowsAsyncClient.java        | 112 ---
 .../org/jclouds/ec2/services/WindowsClient.java | 116 ---
 .../DescribeAvailabilityZonesInRegion.java      |  10 +-
 .../suppliers/DescribeRegionsForRegionURIs.java |  10 +-
 ...dApplicationArchitecturesEC2ApiLiveTest.java | 427 +++++++++++
 ...plicationArchitecturesEC2ClientLiveTest.java | 427 -----------
 .../org/jclouds/ec2/EBSBootEC2ApiLiveTest.java  | 607 +++++++++++++++
 .../jclouds/ec2/EBSBootEC2ClientLiveTest.java   | 607 ---------------
 .../org/jclouds/ec2/EC2AsyncClientTest.java     |  75 --
 .../BindS3UploadPolicyAndSignatureTest.java     |   6 +-
 .../ec2/compute/EC2ComputeServiceLiveTest.java  |  44 +-
 .../ec2/compute/EC2TemplateBuilderLiveTest.java |  10 +-
 .../functions/CreateUniqueKeyPairTest.java      |  21 +-
 .../compute/functions/PresentInstancesTest.java |  11 +-
 .../BaseEC2ComputeServiceContextExpectTest.java |   4 +-
 .../CreateSecurityGroupIfNeededTest.java        |   8 +-
 .../LoadPublicIpForInstanceOrNullTest.java      |  23 +-
 .../compute/loaders/RegionAndIdToImageTest.java |  23 +-
 .../EC2CreateNodesInGroupThenAddToSetTest.java  |  20 +-
 .../strategy/EC2DestroyNodeStrategyTest.java    |  39 +-
 .../ec2/config/EC2HttpApiModuleExpectTest.java  | 145 ++++
 .../config/EC2RestClientModuleExpectTest.java   | 145 ----
 .../jclouds/ec2/features/AMIApiLiveTest.java    | 202 +++++
 .../org/jclouds/ec2/features/AMIApiTest.java    | 521 +++++++++++++
 .../AvailabilityZoneAndRegionApiLiveTest.java   |  92 +++
 .../AvailabilityZoneAndRegionApiTest.java       | 116 +++
 .../jclouds/ec2/features/BaseEC2ApiTest.java    | 145 ++++
 .../EC2ElasticBlockStoreApiExpectTest.java      |  88 +++
 .../features/ElasticBlockStoreApiLiveTest.java  | 223 ++++++
 .../ec2/features/ElasticBlockStoreApiTest.java  | 401 ++++++++++
 .../features/ElasticIPAddressApiLiveTest.java   |  72 ++
 .../ec2/features/ElasticIPAddressApiTest.java   | 140 ++++
 .../ec2/features/InstanceApiLiveTest.java       |  61 ++
 .../jclouds/ec2/features/InstanceApiTest.java   | 593 ++++++++++++++
 .../ec2/features/KeyPairApiLiveTest.java        |  97 +++
 .../jclouds/ec2/features/KeyPairApiTest.java    |  88 +++
 .../ec2/features/SecurityGroupApiLiveTest.java  | 288 +++++++
 .../ec2/features/SecurityGroupApiTest.java      | 236 ++++++
 .../jclouds/ec2/features/WindowsApiTest.java    | 162 ++++
 .../ec2/internal/BaseEC2ApiExpectTest.java      |  15 +-
 .../ec2/internal/BaseEC2ClientExpectTest.java   |  64 --
 .../ec2/predicates/VolumeDetachedTest.java      |   6 +-
 .../ec2/services/AMIAsyncClientTest.java        | 521 -------------
 .../jclouds/ec2/services/AMIClientLiveTest.java | 202 -----
 ...vailabilityZoneAndRegionAsyncClientTest.java | 116 ---
 ...AvailabilityZoneAndRegionClientLiveTest.java |  92 ---
 .../ec2/services/BaseEC2AsyncClientTest.java    | 142 ----
 .../EC2ElasticBlockStoreClientExpectTest.java   |  88 ---
 .../ElasticBlockStoreAsyncClientTest.java       | 401 ----------
 .../ElasticBlockStoreClientLiveTest.java        | 223 ------
 .../ElasticIPAddressAsyncClientTest.java        | 140 ----
 .../ElasticIPAddressClientLiveTest.java         |  71 --
 .../ec2/services/InstanceAsyncClientTest.java   | 593 --------------
 .../ec2/services/InstanceClientLiveTest.java    |  61 --
 .../ec2/services/KeyPairAsyncClientTest.java    |  88 ---
 .../ec2/services/KeyPairClientLiveTest.java     |  97 ---
 .../services/SecurityGroupAsyncClientTest.java  | 236 ------
 .../services/SecurityGroupClientLiveTest.java   | 288 -------
 .../ec2/services/WindowsAsyncClientTest.java    | 162 ----
 .../DescribeAvailabilityZonesInRegionTest.java  |  23 +-
 .../jclouds/openstack/nova/ec2/NovaEC2Api.java  |  47 ++
 .../openstack/nova/ec2/NovaEC2ApiMetadata.java  |  15 +-
 .../openstack/nova/ec2/NovaEC2AsyncClient.java  |  38 -
 .../openstack/nova/ec2/NovaEC2Client.java       |  36 -
 .../nova/ec2/config/NovaEC2HttpApiModule.java   |  81 ++
 .../ec2/config/NovaEC2RestClientModule.java     | 118 ---
 .../nova/ec2/features/NovaEC2KeyPairApi.java    |  88 +++
 .../NovaCreateSecurityGroupIfNeeded.java        |   6 +-
 .../ec2/services/NovaEC2KeyPairAsyncClient.java |  61 --
 .../nova/ec2/services/NovaEC2KeyPairClient.java |  63 --
 .../ec2/features/NovaEC2AMIApiExpectTest.java   |  53 ++
 .../ec2/features/NovaEC2AMIApiLiveTest.java     |  32 +
 ...EC2AvailabilityZoneAndRegionApiLiveTest.java |  32 +
 .../NovaEC2ElasticBlockStoreApiLiveTest.java    |  32 +
 .../NovaEC2ElasticBlockStoreExpectApiTest.java  |  64 ++
 .../NovaEC2ElasticIPAddressApiLiveTest.java     |  32 +
 .../features/NovaEC2InstanceApiExpectTest.java  |  67 ++
 .../features/NovaEC2InstanceApiLiveTest.java    |  32 +
 .../features/NovaEC2KeyPairApiExpectTest.java   |  78 ++
 .../ec2/features/NovaEC2KeyPairApiLiveTest.java | 135 ++++
 .../NovaEC2SecurityGroupApiLiveTest.java        |  32 +
 .../internal/BaseNovaEC2RestApiExpectTest.java  |  71 ++
 .../BaseNovaEC2RestClientExpectTest.java        |  70 --
 .../services/NovaEC2AMIClientExpectTest.java    |  53 --
 .../ec2/services/NovaEC2AMIClientLiveTest.java  |  32 -
 ...AvailabilityZoneAndRegionClientLiveTest.java |  32 -
 .../NovaEC2ElasticBlockStoreClientLiveTest.java |  32 -
 ...ovaEC2ElasticBlockStoreExpectClientTest.java |  64 --
 .../NovaEC2ElasticIPAddressClientLiveTest.java  |  32 -
 .../NovaEC2InstanceClientExpectTest.java        |  67 --
 .../services/NovaEC2InstanceClientLiveTest.java |  32 -
 .../NovaEC2KeyPairClientExpectTest.java         |  78 --
 .../services/NovaEC2KeyPairClientLiveTest.java  | 134 ----
 .../NovaEC2SecurityGroupClientLiveTest.java     |  32 -
 .../java/org/jclouds/aws/ec2/AWSEC2Api.java     | 120 +++
 .../org/jclouds/aws/ec2/AWSEC2ApiMetadata.java  |  15 +-
 .../org/jclouds/aws/ec2/AWSEC2AsyncClient.java  |  86 ---
 .../java/org/jclouds/aws/ec2/AWSEC2Client.java  |  81 --
 .../aws/ec2/compute/AWSEC2ComputeService.java   |  10 +-
 .../AWSEC2SecurityGroupExtension.java           |  14 +-
 .../PresentSpotRequestsAndInstances.java        |   8 +-
 .../AWSEC2CreateSecurityGroupIfNeeded.java      |  20 +-
 .../AWSEC2CreateNodesInGroupThenAddToSet.java   |   8 +-
 .../strategy/AWSEC2DestroyNodeStrategy.java     |  10 +-
 .../strategy/AWSEC2GetNodeMetadataStrategy.java |   8 +-
 .../strategy/AWSEC2ListNodesStrategy.java       |  10 +-
 .../aws/ec2/config/AWSEC2HttpApiModule.java     |  98 +++
 .../aws/ec2/config/AWSEC2RestClientModule.java  | 159 ----
 .../org/jclouds/aws/ec2/features/AWSAMIApi.java | 126 +++
 .../aws/ec2/features/AWSInstanceApi.java        |  81 ++
 .../jclouds/aws/ec2/features/AWSKeyPairApi.java |  88 +++
 .../aws/ec2/features/AWSSecurityGroupApi.java   | 125 +++
 .../jclouds/aws/ec2/features/MonitoringApi.java |  97 +++
 .../aws/ec2/features/PlacementGroupApi.java     | 136 ++++
 .../aws/ec2/features/SpotInstanceApi.java       | 214 ++++++
 .../functions/CreatePlacementGroupIfNeeded.java |  10 +-
 .../ImportOrReturnExistingKeypair.java          |  12 +-
 .../aws/ec2/options/AWSRunInstancesOptions.java |   2 +-
 .../ec2/options/CreateSecurityGroupOptions.java |   2 +-
 .../DescribeSpotPriceHistoryOptions.java        |   2 +-
 .../options/RequestSpotInstancesOptions.java    |   2 +-
 .../ec2/predicates/PlacementGroupAvailable.java |   8 +-
 .../ec2/predicates/PlacementGroupDeleted.java   |   8 +-
 .../predicates/SpotInstanceRequestActive.java   |   8 +-
 .../aws/ec2/services/AWSAMIAsyncClient.java     |  91 ---
 .../jclouds/aws/ec2/services/AWSAMIClient.java  |  85 ---
 .../ec2/services/AWSInstanceAsyncClient.java    |  89 ---
 .../aws/ec2/services/AWSInstanceClient.java     |  43 --
 .../aws/ec2/services/AWSKeyPairAsyncClient.java |  61 --
 .../aws/ec2/services/AWSKeyPairClient.java      |  63 --
 .../services/AWSSecurityGroupAsyncClient.java   | 150 ----
 .../ec2/services/AWSSecurityGroupClient.java    |  51 --
 .../aws/ec2/services/MonitoringAsyncClient.java |  78 --
 .../aws/ec2/services/MonitoringClient.java      |  64 --
 .../ec2/services/PlacementGroupAsyncClient.java | 101 ---
 .../aws/ec2/services/PlacementGroupClient.java  |  89 ---
 .../ec2/services/SpotInstanceAsyncClient.java   | 128 ----
 .../aws/ec2/services/SpotInstanceClient.java    | 150 ----
 .../jclouds/aws/ec2/AWSEC2AsyncClientTest.java  |  79 --
 .../compute/AWSEC2ComputeServiceLiveTest.java   |  37 +-
 .../compute/AWSEC2TemplateBuilderLiveTest.java  |  12 +-
 .../AWSEC2ImageExtensionLiveTest.java           |   6 +-
 .../PresentSpotRequestsAndInstancesTest.java    |  31 +-
 .../BaseAWSEC2ComputeServiceExpectTest.java     |  10 +-
 .../AWSEC2CreateSecurityGroupIfNeededTest.java  |   4 +-
 .../aws/ec2/features/AWSAMIApiLiveTest.java     |  58 ++
 .../jclouds/aws/ec2/features/AWSAMIApiTest.java | 497 ++++++++++++
 .../ec2/features/AWSInstanceApiLiveTest.java    |  62 ++
 .../aws/ec2/features/AWSInstanceApiTest.java    | 539 +++++++++++++
 .../aws/ec2/features/AWSKeyPairApiLiveTest.java | 209 +++++
 .../aws/ec2/features/AWSKeyPairApiTest.java     | 134 ++++
 .../features/AWSSecurityGroupApiLiveTest.java   |  85 +++
 .../ec2/features/AWSSecurityGroupApiTest.java   | 207 +++++
 .../aws/ec2/features/BaseAWSEC2ApiTest.java     | 135 ++++
 .../aws/ec2/features/MonitoringApiLiveTest.java |  66 ++
 .../aws/ec2/features/MonitoringApiTest.java     |  73 ++
 .../ec2/features/PlacementGroupApiLiveTest.java | 184 +++++
 .../aws/ec2/features/PlacementGroupApiTest.java | 136 ++++
 .../ec2/features/SpotInstanceApiLiveTest.java   | 176 +++++
 .../aws/ec2/features/SpotInstanceApiTest.java   | 100 +++
 .../ec2/features/TagSecurityGroupLiveTest.java  |   8 +-
 .../ImportOrReturnExistingKeypairTest.java      |  49 +-
 .../aws/ec2/services/AWSAMIAsyncClientTest.java | 497 ------------
 .../aws/ec2/services/AWSAMIClientLiveTest.java  |  58 --
 .../services/AWSInstanceAsyncClientTest.java    | 539 -------------
 .../ec2/services/AWSInstanceClientLiveTest.java |  61 --
 .../ec2/services/AWSKeyPairAsyncClientTest.java | 134 ----
 .../ec2/services/AWSKeyPairClientLiveTest.java  | 209 -----
 .../AWSSecurityGroupAsyncClientTest.java        | 207 -----
 .../AWSSecurityGroupClientLiveTest.java         |  85 ---
 .../ec2/services/BaseAWSEC2AsyncClientTest.java | 135 ----
 .../ec2/services/MonitoringAsyncClientTest.java |  73 --
 .../ec2/services/MonitoringClientLiveTest.java  |  65 --
 .../services/PlacementGroupAsyncClientTest.java | 136 ----
 .../services/PlacementGroupClientLiveTest.java  | 184 -----
 .../services/SpotInstanceAsyncClientTest.java   | 100 ---
 .../services/SpotInstanceClientLiveTest.java    | 176 -----
 253 files changed, 12626 insertions(+), 14516 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/clojure/org/jclouds/ec2/ami2.clj
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/clojure/org/jclouds/ec2/ami2.clj b/apis/ec2/src/main/clojure/org/jclouds/ec2/ami2.clj
index 5d6f666..d58eb6b 100644
--- a/apis/ec2/src/main/clojure/org/jclouds/ec2/ami2.clj
+++ b/apis/ec2/src/main/clojure/org/jclouds/ec2/ami2.clj
@@ -21,12 +21,12 @@
   org.jclouds.ec2.ami2
   (:use org.jclouds.compute2)
   (:import org.jclouds.aws.domain.Region
-    org.jclouds.ec2.services.AMIClient
+    org.jclouds.ec2.features.AMIApi
     org.jclouds.ec2.options.CreateImageOptions
     org.jclouds.compute.domain.NodeMetadata
     (org.jclouds.ec2.domain Volume Volume$Status Snapshot Snapshot$Status AvailabilityZoneInfo)))
 
-(defn ^org.jclouds.ec2.services.AMIClient
+(defn ^org.jclouds.ec2.features.AMIApi
   ami-service
   ""
   [compute]
@@ -34,7 +34,7 @@
     .getContext
     .getProviderSpecificContext
     .getApi
-    .getAMIServices))
+    .getAMIApi().get))
 
 (defn get-region
   "Coerces the first parameter into a Region string; strings, keywords, and

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/clojure/org/jclouds/ec2/elastic_ip2.clj
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/clojure/org/jclouds/ec2/elastic_ip2.clj b/apis/ec2/src/main/clojure/org/jclouds/ec2/elastic_ip2.clj
index a5daf15..68c372f 100644
--- a/apis/ec2/src/main/clojure/org/jclouds/ec2/elastic_ip2.clj
+++ b/apis/ec2/src/main/clojure/org/jclouds/ec2/elastic_ip2.clj
@@ -24,12 +24,12 @@
   (:import org.jclouds.compute.domain.NodeMetadata
     (org.jclouds.ec2.domain PublicIpInstanceIdPair)))
 
-(defn ^org.jclouds.ec2.services.ElasticIPAddressClient
+(defn ^org.jclouds.ec2.features.ElasticIPAddressApi
   eip-service
-  "Returns an ElasticIPAddressClient for the given ComputeService"
+  "Returns an ElasticIPAddressApi for the given ComputeService"
   [compute]
   (-> compute
-    .getContext .getProviderSpecificContext .getApi .getElasticIPAddressServices))
+    .getContext .getProviderSpecificContext .getApi .getElasticIPAddressApi().get))
 
 (defn allocate
   "Claims a new elastic IP address within the (optionally) specified region for your account.

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/clojure/org/jclouds/ec2/security_group2.clj
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/clojure/org/jclouds/ec2/security_group2.clj b/apis/ec2/src/main/clojure/org/jclouds/ec2/security_group2.clj
index a6bc49c..a4f33cf 100644
--- a/apis/ec2/src/main/clojure/org/jclouds/ec2/security_group2.clj
+++ b/apis/ec2/src/main/clojure/org/jclouds/ec2/security_group2.clj
@@ -22,14 +22,14 @@
   (:require (org.jclouds [compute2 :as compute])
     [org.jclouds.ec2.ebs2 :as ebs])
   (:import org.jclouds.ec2.domain.SecurityGroup
-           org.jclouds.ec2.services.SecurityGroupClient
+           org.jclouds.ec2.features.SecurityGroupApi
            org.jclouds.net.domain.IpProtocol))
 
-(defn #^SecurityGroupClient
+(defn #^SecurityGroupApi
   sg-service
-  "Returns the SecurityGroup Client associated with the specified  compute service."
+  "Returns the SecurityGroup Api associated with the specified  compute service."
   [compute]
-  (-> compute .getContext .getProviderSpecificContext .getApi .getSecurityGroupServices))
+  (-> compute .getContext .getProviderSpecificContext .getApi .getSecurityGroupApi().get))
 
 (defn create-group
   "Creates a new security group.

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/EC2Api.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/EC2Api.java b/apis/ec2/src/main/java/org/jclouds/ec2/EC2Api.java
index 26cf10e..d8637e8 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/EC2Api.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/EC2Api.java
@@ -21,6 +21,13 @@ import java.util.Set;
 import org.jclouds.ec2.features.SubnetApi;
 import org.jclouds.ec2.features.TagApi;
 import org.jclouds.ec2.features.WindowsApi;
+import org.jclouds.ec2.features.AMIApi;
+import org.jclouds.ec2.features.AvailabilityZoneAndRegionApi;
+import org.jclouds.ec2.features.ElasticBlockStoreApi;
+import org.jclouds.ec2.features.ElasticIPAddressApi;
+import org.jclouds.ec2.features.InstanceApi;
+import org.jclouds.ec2.features.KeyPairApi;
+import org.jclouds.ec2.features.SecurityGroupApi;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.location.Region;
 import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
@@ -42,12 +49,11 @@ import com.google.inject.Provides;
  * Example
  * 
  * <pre>
- * Optional&lt;? extends WindowsApi&gt; windowsOption = ec2Client.getWindowsApi();
+ * Optional&lt;? extends WindowsApi&gt; windowsOption = ec2Api.getWindowsApi();
  * checkState(windowsOption.isPresent(), &quot;windows feature required, but not present&quot;);
  * </pre>
  * 
  * @author Adrian Cole
- * @see EC2AsyncApi
  */
 public interface EC2Api extends Closeable {
    /**
@@ -87,4 +93,75 @@ public interface EC2Api extends Closeable {
    @Delegate
    Optional<? extends SubnetApi> getSubnetApiForRegion(
             @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+
+   /**
+    * Provides synchronous access to AMI services.
+    */
+   @Delegate
+   Optional<? extends AMIApi> getAMIApi();
+
+   @Delegate
+   Optional<? extends AMIApi> getAMIApiForRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+
+
+   /**
+    * Provides synchronous access to Elastic IP Address services.
+    */
+   @Delegate
+   Optional<? extends ElasticIPAddressApi> getElasticIPAddressApi();
+
+   @Delegate
+   Optional<? extends ElasticIPAddressApi> getElasticIPAddressApiForRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+
+   /**
+    * Provides synchronous access to Instance services.
+    */
+   @Delegate
+   Optional<? extends InstanceApi> getInstanceApi();
+
+   @Delegate
+   Optional<? extends InstanceApi> getInstanceApiForRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+
+   /**
+    * Provides synchronous access to KeyPair services.
+    */
+   @Delegate
+   Optional<? extends KeyPairApi> getKeyPairApi();
+   
+   @Delegate
+   Optional<? extends KeyPairApi> getKeyPairApiForRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+
+   /**
+    * Provides synchronous access to SecurityGroup services.
+    */
+   @Delegate
+   Optional<? extends SecurityGroupApi> getSecurityGroupApi();
+
+   @Delegate
+   Optional<? extends SecurityGroupApi> getSecurityGroupApiForRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+
+   /**
+    * Provides synchronous access to Availability Zones and Regions services.
+    */
+   @Delegate
+   Optional<? extends AvailabilityZoneAndRegionApi> getAvailabilityZoneAndRegionApi();
+
+   @Delegate
+   Optional<? extends AvailabilityZoneAndRegionApi> getAvailabilityZoneAndRegionApiForRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+
+   /**
+    * Provides synchronous access to Elastic Block Store services.
+    */
+   @Delegate
+   Optional<? extends ElasticBlockStoreApi> getElasticBlockStoreApi();
+
+   @Delegate
+   Optional<? extends ElasticBlockStoreApi> getElasticBlockStoreApiForRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/EC2ApiMetadata.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/EC2ApiMetadata.java b/apis/ec2/src/main/java/org/jclouds/ec2/EC2ApiMetadata.java
index f380d46..47fc54b 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/EC2ApiMetadata.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/EC2ApiMetadata.java
@@ -31,8 +31,8 @@ import org.jclouds.apis.ApiMetadata;
 import org.jclouds.ec2.compute.EC2ComputeServiceContext;
 import org.jclouds.ec2.compute.config.EC2ComputeServiceContextModule;
 import org.jclouds.ec2.compute.config.EC2ResolveImagesModule;
-import org.jclouds.ec2.config.EC2RestClientModule;
-import org.jclouds.rest.internal.BaseRestApiMetadata;
+import org.jclouds.ec2.config.EC2HttpApiModule;
+import org.jclouds.rest.internal.BaseHttpApiMetadata;
 
 import com.google.common.collect.ImmutableSet;
 import com.google.common.reflect.TypeToken;
@@ -55,16 +55,8 @@ import com.google.inject.Module;
  * 
  * @author Adrian Cole
  */
-public class EC2ApiMetadata extends BaseRestApiMetadata {
+public class EC2ApiMetadata extends BaseHttpApiMetadata<EC2Api> {
 
-   /**
-    * @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(EC2Client.class)} as
-    *             {@link EC2AsyncClient} interface will be removed in jclouds 1.7.
-    */
-   @Deprecated
-   public static final TypeToken<org.jclouds.rest.RestContext<? extends EC2Client, ? extends EC2AsyncClient>> CONTEXT_TOKEN = new TypeToken<org.jclouds.rest.RestContext<? extends EC2Client, ? extends EC2AsyncClient>>() {
-      private static final long serialVersionUID = 1L;
-   };
 
    @Override
    public Builder<?> toBuilder() {
@@ -80,7 +72,7 @@ public class EC2ApiMetadata extends BaseRestApiMetadata {
    }
 
    public static Properties defaultProperties() {
-      Properties properties = BaseRestApiMetadata.defaultProperties();
+      Properties properties = BaseHttpApiMetadata.defaultProperties();
       properties.setProperty(PROPERTY_AUTH_TAG, "AWS");
       properties.setProperty(PROPERTY_HEADER_TAG, "amz");
       properties.setProperty(PROPERTY_EC2_AMI_OWNERS, "*");
@@ -91,14 +83,8 @@ public class EC2ApiMetadata extends BaseRestApiMetadata {
       return properties;
    }
 
-   public abstract static class Builder<T extends Builder<T>> extends BaseRestApiMetadata.Builder<T> {
-      @SuppressWarnings("deprecation")
+   public abstract static class Builder<T extends Builder<T>> extends BaseHttpApiMetadata.Builder<EC2Api, T> {
       protected Builder() {
-         this(EC2Client.class, EC2AsyncClient.class);
-      }
-
-      protected Builder(Class<?> syncClient, Class<?> asyncClient) {
-         super(syncClient, asyncClient);
          id("ec2")
          .name("Amazon Elastic Compute Cloud (EC2) API")
          .identityName("Access Key ID")
@@ -107,9 +93,8 @@ public class EC2ApiMetadata extends BaseRestApiMetadata {
          .documentation(URI.create("http://docs.amazonwebservices.com/AWSEC2/latest/APIReference"))
          .version("2010-06-15")
          .defaultProperties(EC2ApiMetadata.defaultProperties())
-         .context(CONTEXT_TOKEN)
          .view(EC2ComputeServiceContext.class)
-         .defaultModules(ImmutableSet.<Class<? extends Module>>of(EC2RestClientModule.class, EC2ResolveImagesModule.class, EC2ComputeServiceContextModule.class));
+         .defaultModules(ImmutableSet.<Class<? extends Module>>of(EC2HttpApiModule.class, EC2ResolveImagesModule.class, EC2ComputeServiceContextModule.class));
       }
 
       @Override

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/EC2AsyncApi.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/EC2AsyncApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/EC2AsyncApi.java
deleted file mode 100644
index e96c0a7..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/EC2AsyncApi.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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 java.io.Closeable;
-import java.util.Set;
-
-import org.jclouds.ec2.features.SubnetAsyncApi;
-import org.jclouds.ec2.features.TagAsyncApi;
-import org.jclouds.ec2.features.WindowsAsyncApi;
-import org.jclouds.javax.annotation.Nullable;
-import org.jclouds.location.Region;
-import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
-import org.jclouds.rest.annotations.Delegate;
-import org.jclouds.rest.annotations.EndpointParam;
-
-import com.google.common.base.Optional;
-import com.google.inject.Provides;
-
-/**
- * Refer to javadoc for {@link EC2Api}, as this interface is the same, except
- * features provide asynchronous return values.
- * 
- * @author Adrian Cole
- */
-public interface EC2AsyncApi extends Closeable {
-   /**
-    * 
-    * @return the Region codes configured
-    */
-   @Provides
-   @Region
-   Set<String> getConfiguredRegions();
-
-   /**
-    * Provides asynchronous access to Windows features.
-    */
-   @Delegate
-   Optional<? extends WindowsAsyncApi> getWindowsApi();
-
-   @Delegate
-   Optional<? extends WindowsAsyncApi> getWindowsApiForRegion(
-         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
-   
-   /**
-    * Provides asynchronous access to Tag features.
-    */
-   @Delegate
-   Optional<? extends TagAsyncApi> getTagApi();
-
-   @Delegate
-   Optional<? extends TagAsyncApi> getTagApiForRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
-   
-   /**
-    * Provides asynchronous access to Subnet features.
-    */
-   @Delegate
-   Optional<? extends SubnetAsyncApi> getSubnetApi();
-
-   @Delegate
-   Optional<? extends SubnetAsyncApi> getSubnetApiForRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/EC2AsyncClient.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/EC2AsyncClient.java b/apis/ec2/src/main/java/org/jclouds/ec2/EC2AsyncClient.java
deleted file mode 100644
index 9b1143e..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/EC2AsyncClient.java
+++ /dev/null
@@ -1,87 +0,0 @@
-/*
- * 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.ec2.services.AMIAsyncClient;
-import org.jclouds.ec2.services.AvailabilityZoneAndRegionAsyncClient;
-import org.jclouds.ec2.services.ElasticBlockStoreAsyncClient;
-import org.jclouds.ec2.services.ElasticIPAddressAsyncClient;
-import org.jclouds.ec2.services.InstanceAsyncClient;
-import org.jclouds.ec2.services.KeyPairAsyncClient;
-import org.jclouds.ec2.services.SecurityGroupAsyncClient;
-import org.jclouds.ec2.services.WindowsAsyncClient;
-import org.jclouds.rest.annotations.Delegate;
-
-/**
- * Provides asynchronous access to EC2 services.
- * 
- * @author Adrian Cole
- * @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(EC2Client.class)} as
- *             {@link EC2AsyncClient} interface will be removed in jclouds 1.7.
- */
-@Deprecated
-public interface EC2AsyncClient extends EC2AsyncApi {
-
-   /**
-    * Provides asynchronous access to AMI services.
-    */
-   @Delegate
-   AMIAsyncClient getAMIServices();
-
-   /**
-    * Provides asynchronous access to Elastic IP Address services.
-    */
-   @Delegate
-   ElasticIPAddressAsyncClient getElasticIPAddressServices();
-
-   /**
-    * Provides asynchronous access to Instance services.
-    */
-   @Delegate
-   InstanceAsyncClient getInstanceServices();
-
-   /**
-    * Provides asynchronous access to KeyPair services.
-    */
-   @Delegate
-   KeyPairAsyncClient getKeyPairServices();
-
-   /**
-    * Provides asynchronous access to SecurityGroup services.
-    */
-   @Delegate
-   SecurityGroupAsyncClient getSecurityGroupServices();
-
-   /**
-    * Provides asynchronous access to Windows services.
-    */
-   @Delegate
-   WindowsAsyncClient getWindowsServices();
-
-   /**
-    * Provides asynchronous access to Availability Zones and Regions services.
-    */
-   @Delegate
-   AvailabilityZoneAndRegionAsyncClient getAvailabilityZoneAndRegionServices();
-
-   /**
-    * Provides asynchronous access to Elastic Block Store services.
-    */
-   @Delegate
-   ElasticBlockStoreAsyncClient getElasticBlockStoreServices();
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/EC2Client.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/EC2Client.java b/apis/ec2/src/main/java/org/jclouds/ec2/EC2Client.java
deleted file mode 100644
index 42d1a4c..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/EC2Client.java
+++ /dev/null
@@ -1,84 +0,0 @@
-/*
- * 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.ec2.services.AMIClient;
-import org.jclouds.ec2.services.AvailabilityZoneAndRegionClient;
-import org.jclouds.ec2.services.ElasticBlockStoreClient;
-import org.jclouds.ec2.services.ElasticIPAddressClient;
-import org.jclouds.ec2.services.InstanceClient;
-import org.jclouds.ec2.services.KeyPairClient;
-import org.jclouds.ec2.services.SecurityGroupClient;
-import org.jclouds.ec2.services.WindowsClient;
-import org.jclouds.rest.annotations.Delegate;
-
-/**
- * Provides synchronous access to EC2 services.
- * 
- * @author Adrian Cole
- */
-public interface EC2Client extends EC2Api {
-   
-   /**
-    * Provides synchronous access to AMI services.
-    */
-   @Delegate
-   AMIClient getAMIServices();
-
-   /**
-    * Provides synchronous access to Elastic IP Address services.
-    */
-   @Delegate
-   ElasticIPAddressClient getElasticIPAddressServices();
-
-   /**
-    * Provides synchronous access to Instance services.
-    */
-   @Delegate
-   InstanceClient getInstanceServices();
-
-   /**
-    * Provides synchronous access to KeyPair services.
-    */
-   @Delegate
-   KeyPairClient getKeyPairServices();
-
-   /**
-    * Provides synchronous access to SecurityGroup services.
-    */
-   @Delegate
-   SecurityGroupClient getSecurityGroupServices();
-
-   /**
-    * Provides asynchronous access to Windows services.
-    */
-   @Delegate
-   WindowsClient getWindowsServices();
-
-   /**
-    * Provides synchronous access to Availability Zones and Regions services.
-    */
-   @Delegate
-   AvailabilityZoneAndRegionClient getAvailabilityZoneAndRegionServices();
-
-   /**
-    * Provides synchronous access to Elastic Block Store services.
-    */
-   @Delegate
-   ElasticBlockStoreClient getElasticBlockStoreServices();
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/EC2ComputeService.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/EC2ComputeService.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/EC2ComputeService.java
index c62a259..4c019a4 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/EC2ComputeService.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/EC2ComputeService.java
@@ -73,7 +73,7 @@ import org.jclouds.compute.strategy.ResumeNodeStrategy;
 import org.jclouds.compute.strategy.SuspendNodeStrategy;
 import org.jclouds.domain.Credentials;
 import org.jclouds.domain.Location;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
 import org.jclouds.ec2.compute.options.EC2TemplateOptions;
@@ -104,7 +104,7 @@ import com.google.inject.Inject;
  */
 @Singleton
 public class EC2ComputeService extends BaseComputeService {
-   private final EC2Client client;
+   private final EC2Api client;
    private final ConcurrentMap<RegionAndName, KeyPair> credentialsMap;
    private final LoadingCache<RegionAndName, String> securityGroupMap;
    private final Factory namingConvention;
@@ -125,7 +125,7 @@ public class EC2ComputeService extends BaseComputeService {
             InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
             RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
             PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
-            @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, EC2Client client,
+            @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, EC2Api client,
             ConcurrentMap<RegionAndName, KeyPair> credentialsMap,
             @Named("SECURITY") LoadingCache<RegionAndName, String> securityGroupMap,
             Optional<ImageExtension> imageExtension, GroupNamingConvention.Factory namingConvention,
@@ -212,9 +212,9 @@ public class EC2ComputeService extends BaseComputeService {
       checkNotNull(emptyToNull(group), "group must be defined");
       String groupName = namingConvention.create().sharedNameForGroup(group);
       
-      if (client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, groupName).size() > 0) {
+      if (client.getSecurityGroupApi().get().describeSecurityGroupsInRegion(region, groupName).size() > 0) {
          logger.debug(">> deleting securityGroup(%s)", groupName);
-         client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, groupName);
+         client.getSecurityGroupApi().get().deleteSecurityGroupInRegion(region, groupName);
          // TODO: test this clear happens
          securityGroupMap.invalidate(new RegionNameAndIngressRules(region, groupName, null, false));
          logger.debug("<< deleted securityGroup(%s)", groupName);
@@ -223,20 +223,20 @@ public class EC2ComputeService extends BaseComputeService {
 
    @VisibleForTesting
    void deleteKeyPair(String region, String group) {
-      for (KeyPair keyPair : client.getKeyPairServices().describeKeyPairsInRegion(region)) {
+      for (KeyPair keyPair : client.getKeyPairApi().get().describeKeyPairsInRegion(region)) {
          String keyName = keyPair.getKeyName();
          Predicate<String> keyNameMatcher = namingConvention.create().containsGroup(group);
          String oldKeyNameRegex = String.format("jclouds#%s#%s#%s", group, region, "[0-9a-f]+").replace('#', delimiter);
          // old keypair pattern too verbose as it has an unnecessary region qualifier
          
          if (keyNameMatcher.apply(keyName) || keyName.matches(oldKeyNameRegex)) {
-            Set<String> instancesUsingKeyPair = extractIdsFromInstances(filter(concat(client.getInstanceServices()
+            Set<String> instancesUsingKeyPair = extractIdsFromInstances(filter(concat(client.getInstanceApi().get()
                   .describeInstancesInRegion(region)), usingKeyPairAndNotDead(keyPair)));
             if (instancesUsingKeyPair.size() > 0) {
                logger.debug("<< inUse keyPair(%s), by (%s)", keyPair.getKeyName(), instancesUsingKeyPair);
             } else {
                logger.debug(">> deleting keyPair(%s)", keyPair.getKeyName());
-               client.getKeyPairServices().deleteKeyPairInRegion(region, keyPair.getKeyName());
+               client.getKeyPairApi().get().deleteKeyPairInRegion(region, keyPair.getKeyName());
                // TODO: test this clear happens
                credentialsMap.remove(new RegionAndName(region, keyPair.getKeyName()));
                credentialsMap.remove(new RegionAndName(region, group));

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/extensions/EC2ImageExtension.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/extensions/EC2ImageExtension.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/extensions/EC2ImageExtension.java
index 3969453..fe3dc9b 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/extensions/EC2ImageExtension.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/extensions/EC2ImageExtension.java
@@ -44,7 +44,7 @@ import org.jclouds.compute.domain.OperatingSystem;
 import org.jclouds.compute.extensions.ImageExtension;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.domain.Location;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.domain.Reservation;
 import org.jclouds.ec2.domain.RunningInstance;
 import org.jclouds.ec2.options.CreateImageOptions;
@@ -69,16 +69,16 @@ public class EC2ImageExtension implements ImageExtension {
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;
-   private final EC2Client ec2Client;
+   private final EC2Api ec2Api;
    private final ListeningExecutorService userExecutor;
    private final Supplier<Set<? extends Location>> locations;
    private final Predicate<AtomicReference<Image>> imageAvailablePredicate;
    
    @Inject
-   public EC2ImageExtension(EC2Client ec2Client, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
+   public EC2ImageExtension(EC2Api ec2Api, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
          @Memoized Supplier<Set<? extends Location>> locations,
          @Named(TIMEOUT_IMAGE_AVAILABLE) Predicate<AtomicReference<Image>> imageAvailablePredicate) {
-      this.ec2Client = checkNotNull(ec2Client, "ec2Client");
+      this.ec2Api = checkNotNull(ec2Api, "ec2Api");
       this.userExecutor = checkNotNull(userExecutor, "userExecutor");
       this.locations = checkNotNull(locations, "locations");
       this.imageAvailablePredicate = checkNotNull(imageAvailablePredicate, "imageAvailablePredicate");
@@ -89,7 +89,7 @@ public class EC2ImageExtension implements ImageExtension {
       String[] parts = AWSUtils.parseHandle(id);
       String region = parts[0];
       String instanceId = parts[1];
-      Reservation<? extends RunningInstance> instance = getOnlyElement(ec2Client.getInstanceServices()
+      Reservation<? extends RunningInstance> instance = getOnlyElement(ec2Api.getInstanceApi().get()
             .describeInstancesInRegion(region, instanceId));
       if (instance == null)
          throw new NoSuchElementException("Cannot find server with id: " + id);
@@ -105,7 +105,7 @@ public class EC2ImageExtension implements ImageExtension {
       String region = parts[0];
       String instanceId = parts[1];
 
-      String imageId = ec2Client.getAMIServices().createImageInRegion(region, cloneTemplate.getName(), instanceId,
+      String imageId = ec2Api.getAMIApi().get().createImageInRegion(region, cloneTemplate.getName(), instanceId,
             CreateImageOptions.NONE);
 
       final AtomicReference<Image> image = Atomics.newReference(new ImageBuilder()
@@ -133,7 +133,7 @@ public class EC2ImageExtension implements ImageExtension {
       String region = parts[0];
       String instanceId = parts[1];
       try {
-         ec2Client.getAMIServices().deregisterImageInRegion(region, instanceId);
+         ec2Api.getAMIApi().get().deregisterImageInRegion(region, instanceId);
          return true;
       } catch (Exception e) {
          return false;

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtension.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtension.java
index 4b09d56..fe0201c 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtension.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtension.java
@@ -43,7 +43,7 @@ import org.jclouds.compute.extensions.SecurityGroupExtension;
 import org.jclouds.compute.functions.GroupNamingConvention;
 import org.jclouds.compute.functions.GroupNamingConvention.Factory;
 import org.jclouds.domain.Location;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
 import org.jclouds.ec2.domain.RunningInstance;
@@ -72,7 +72,7 @@ import com.google.common.util.concurrent.UncheckedTimeoutException;
  */
 public class EC2SecurityGroupExtension implements SecurityGroupExtension {
 
-   protected final EC2Client client;
+   protected final EC2Api client;
    protected final ListeningExecutorService userExecutor;
    protected final Supplier<Set<String>> regions;
    protected final Function<org.jclouds.ec2.domain.SecurityGroup, SecurityGroup> groupConverter;
@@ -81,7 +81,7 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
    protected final Factory namingConvention;
 
    @Inject
-   public EC2SecurityGroupExtension(EC2Client client,
+   public EC2SecurityGroupExtension(EC2Api client,
                                     @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
                                     @Region Supplier<Set<String>> regions,
                                     Function<org.jclouds.ec2.domain.SecurityGroup, SecurityGroup> groupConverter,
@@ -130,7 +130,7 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
       String region = parts[0];
       String instanceId = parts[1];
       
-      RunningInstance instance = getOnlyElement(Iterables.concat(client.getInstanceServices().describeInstancesInRegion(region, instanceId)));
+      RunningInstance instance = getOnlyElement(Iterables.concat(client.getInstanceApi().get().describeInstancesInRegion(region, instanceId)));
 
       if (instance == null) {
          return ImmutableSet.of();
@@ -138,7 +138,7 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
       
       Set<String> groupNames = instance.getGroupNames();
       Set<? extends org.jclouds.ec2.domain.SecurityGroup> rawGroups =
-         client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, Iterables.toArray(groupNames, String.class));
+         client.getSecurityGroupApi().get().describeSecurityGroupsInRegion(region, Iterables.toArray(groupNames, String.class));
       
       return ImmutableSet.copyOf(transform(filter(rawGroups, notNull()), groupConverter));
    }
@@ -151,7 +151,7 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
       String groupId = parts[1];
 
       Set<? extends org.jclouds.ec2.domain.SecurityGroup> rawGroups =
-         client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, groupId);
+         client.getSecurityGroupApi().get().describeSecurityGroupsInRegion(region, groupId);
       
       return getOnlyElement(transform(filter(rawGroups, notNull()), groupConverter));
    }
@@ -183,8 +183,8 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
       String region = parts[0];
       String groupName = parts[1];
       
-      if (client.getSecurityGroupServices().describeSecurityGroupsInRegion(region, groupName).size() > 0) {
-         client.getSecurityGroupServices().deleteSecurityGroupInRegion(region, groupName);
+      if (client.getSecurityGroupApi().get().describeSecurityGroupsInRegion(region, groupName).size() > 0) {
+         client.getSecurityGroupApi().get().deleteSecurityGroupInRegion(region, groupName);
          // TODO: test this clear happens
          groupCreator.invalidate(new RegionNameAndIngressRules(region, groupName, null, false));
          return true;
@@ -201,7 +201,7 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
 
       if (ipPermission.getCidrBlocks().size() > 0) {
          for (String cidr : ipPermission.getCidrBlocks()) {
-            client.getSecurityGroupServices().
+            client.getSecurityGroupApi().get().
                authorizeSecurityGroupIngressInRegion(region,
                                                      name,
                                                      ipPermission.getIpProtocol(),
@@ -214,7 +214,7 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
       if (ipPermission.getTenantIdGroupNamePairs().size() > 0) {
          for (String userId : ipPermission.getTenantIdGroupNamePairs().keySet()) {
             for (String groupName : ipPermission.getTenantIdGroupNamePairs().get(userId)) {
-               client.getSecurityGroupServices().
+               client.getSecurityGroupApi().get().
                   authorizeSecurityGroupIngressInRegion(region,
                                                         name,
                                                         new UserIdGroupPair(userId, groupName));
@@ -235,7 +235,7 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
 
       if (Iterables.size(ipRanges) > 0) {
          for (String cidr : ipRanges) {
-            client.getSecurityGroupServices().
+            client.getSecurityGroupApi().get().
                authorizeSecurityGroupIngressInRegion(region,
                                                      name,
                                                      protocol,
@@ -248,7 +248,7 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
       if (tenantIdGroupNamePairs.size() > 0) {
          for (String userId : tenantIdGroupNamePairs.keySet()) {
             for (String groupName : tenantIdGroupNamePairs.get(userId)) {
-               client.getSecurityGroupServices().
+               client.getSecurityGroupApi().get().
                   authorizeSecurityGroupIngressInRegion(region,
                                                         name,
                                                         new UserIdGroupPair(userId, groupName));
@@ -266,7 +266,7 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
 
       if (ipPermission.getCidrBlocks().size() > 0) {
          for (String cidr : ipPermission.getCidrBlocks()) {
-            client.getSecurityGroupServices().
+            client.getSecurityGroupApi().get().
                revokeSecurityGroupIngressInRegion(region,
                                                   name,
                                                   ipPermission.getIpProtocol(),
@@ -279,7 +279,7 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
       if (ipPermission.getTenantIdGroupNamePairs().size() > 0) {
          for (String userId : ipPermission.getTenantIdGroupNamePairs().keySet()) {
             for (String groupName : ipPermission.getTenantIdGroupNamePairs().get(userId)) {
-               client.getSecurityGroupServices().
+               client.getSecurityGroupApi().get().
                   revokeSecurityGroupIngressInRegion(region,
                                                      name,
                                                      new UserIdGroupPair(userId, groupName));
@@ -300,7 +300,7 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
 
       if (Iterables.size(ipRanges) > 0) {
          for (String cidr : ipRanges) {
-            client.getSecurityGroupServices().
+            client.getSecurityGroupApi().get().
                revokeSecurityGroupIngressInRegion(region,
                                                   name,
                                                   protocol,
@@ -313,7 +313,7 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
       if (tenantIdGroupNamePairs.size() > 0) {
          for (String userId : tenantIdGroupNamePairs.keySet()) {
             for (String groupName : tenantIdGroupNamePairs.get(userId)) {
-               client.getSecurityGroupServices().
+               client.getSecurityGroupApi().get().
                   revokeSecurityGroupIngressInRegion(region,
                                                      name,
                                                      new UserIdGroupPair(userId, groupName));
@@ -356,7 +356,7 @@ public class EC2SecurityGroupExtension implements SecurityGroupExtension {
          
          @Override
          public Set<? extends org.jclouds.ec2.domain.SecurityGroup> apply(String from) {
-            return client.getSecurityGroupServices().describeSecurityGroupsInRegion(from);
+            return client.getSecurityGroupApi().get().describeSecurityGroupsInRegion(from);
          }
          
       };

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/CreateUniqueKeyPair.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/CreateUniqueKeyPair.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/CreateUniqueKeyPair.java
index 5840682..412cda2 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/CreateUniqueKeyPair.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/CreateUniqueKeyPair.java
@@ -24,7 +24,7 @@ import javax.inject.Singleton;
 
 import org.jclouds.compute.functions.GroupNamingConvention;
 import org.jclouds.compute.reference.ComputeServiceConstants;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.domain.KeyPair;
 import org.jclouds.logging.Logger;
@@ -42,12 +42,12 @@ public class CreateUniqueKeyPair implements Function<RegionAndName, KeyPair> {
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;
-   protected final EC2Client ec2Client;
+   protected final EC2Api ec2Api;
    protected final GroupNamingConvention.Factory namingConvention;
 
    @Inject
-   public CreateUniqueKeyPair(EC2Client ec2Client, GroupNamingConvention.Factory namingConvention) {
-      this.ec2Client = ec2Client;
+   public CreateUniqueKeyPair(EC2Api ec2Api, GroupNamingConvention.Factory namingConvention) {
+      this.ec2Api = ec2Api;
       this.namingConvention = checkNotNull(namingConvention, "namingConvention");
    }
 
@@ -67,7 +67,7 @@ public class CreateUniqueKeyPair implements Function<RegionAndName, KeyPair> {
       while (keyPair == null) {
          String keyName = namingConvention.create().uniqueNameForGroup(prefix);
          try {
-            keyPair = ec2Client.getKeyPairServices().createKeyPairInRegion(region, keyName);
+            keyPair = ec2Api.getKeyPairApi().get().createKeyPairInRegion(region, keyName);
          } catch (IllegalStateException e) {
             logger.trace("   invalid keyname (%s in %s); retrying", keyName, region);
          }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/PasswordCredentialsFromWindowsInstance.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/PasswordCredentialsFromWindowsInstance.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/PasswordCredentialsFromWindowsInstance.java
index 14c22d6..939daf0 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/PasswordCredentialsFromWindowsInstance.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/PasswordCredentialsFromWindowsInstance.java
@@ -31,7 +31,7 @@ import javax.inject.Singleton;
 
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.domain.LoginCredentials;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.PasswordDataAndPrivateKey;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.domain.KeyPair;
@@ -59,20 +59,20 @@ public class PasswordCredentialsFromWindowsInstance implements Function<RunningI
    protected Logger logger = Logger.NULL;
 
    private final ConcurrentMap<RegionAndName, KeyPair> credentialsMap;
-   private final EC2Client ec2Client;
+   private final EC2Api ec2Api;
    private final Function<PasswordDataAndPrivateKey, LoginCredentials> pwDataToLoginCredentials;
 
    @Inject
    protected PasswordCredentialsFromWindowsInstance(ConcurrentMap<RegionAndName, KeyPair> credentialsMap,
-            EC2Client ec2Client, Function<PasswordDataAndPrivateKey, LoginCredentials> pwDataToLoginCredentials) {
+            EC2Api ec2Api, Function<PasswordDataAndPrivateKey, LoginCredentials> pwDataToLoginCredentials) {
       this.credentialsMap = checkNotNull(credentialsMap, "credentialsMap");
-      this.ec2Client = checkNotNull(ec2Client, "ec2Client");
+      this.ec2Api = checkNotNull(ec2Api, "ec2Api");
       this.pwDataToLoginCredentials = checkNotNull(pwDataToLoginCredentials, "pwDataToLoginCredentials");
    }
 
    @Override
    public LoginCredentials apply(final RunningInstance instance) {
-      Optional<? extends WindowsApi> windowsOption = ec2Client.getWindowsApiForRegion(instance.getRegion());
+      Optional<? extends WindowsApi> windowsOption = ec2Api.getWindowsApiForRegion(instance.getRegion());
       checkState(windowsOption.isPresent(), "windows feature not present in region %s", instance.getRegion());
       
       final WindowsApi windowsApi = windowsOption.get();

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/PresentInstances.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/PresentInstances.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/PresentInstances.java
index 7ff9d3d..4f0d4f0 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/PresentInstances.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/PresentInstances.java
@@ -31,7 +31,7 @@ import java.util.Set;
 import javax.annotation.Resource;
 import javax.inject.Singleton;
 
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.domain.RunningInstance;
 import org.jclouds.logging.Logger;
@@ -53,10 +53,10 @@ public class PresentInstances implements Function<Set<RegionAndName>, Set<Runnin
    @Resource
    protected Logger logger = Logger.NULL;
 
-   private final EC2Client client;
+   private final EC2Api client;
 
    @Inject
-   public PresentInstances(EC2Client client) {
+   public PresentInstances(EC2Api client) {
       this.client = checkNotNull(client, "client");
    }
 
@@ -71,7 +71,7 @@ public class PresentInstances implements Function<Set<RegionAndName>, Set<Runnin
          String region = entry.getKey();
          Collection<String> instanceIds = entry.getValue();
          logger.trace("looking for instances %s in region %s", instanceIds, region);
-         builder.addAll(concat(client.getInstanceServices().describeInstancesInRegion(region,
+         builder.addAll(concat(client.getInstanceApi().get().describeInstancesInRegion(region,
                toArray(instanceIds, String.class))));
       }
       return builder.build();

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/loaders/CreateSecurityGroupIfNeeded.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/loaders/CreateSecurityGroupIfNeeded.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/loaders/CreateSecurityGroupIfNeeded.java
index de3b906..301f41f 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/loaders/CreateSecurityGroupIfNeeded.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/loaders/CreateSecurityGroupIfNeeded.java
@@ -24,11 +24,11 @@ import javax.inject.Named;
 import javax.inject.Singleton;
 
 import org.jclouds.compute.reference.ComputeServiceConstants;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
 import org.jclouds.ec2.domain.UserIdGroupPair;
-import org.jclouds.ec2.services.SecurityGroupClient;
+import org.jclouds.ec2.features.SecurityGroupApi;
 import org.jclouds.logging.Logger;
 import org.jclouds.net.domain.IpProtocol;
 
@@ -45,16 +45,16 @@ public class CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndName, Stri
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;
-   protected final SecurityGroupClient securityClient;
+   protected final SecurityGroupApi securityClient;
    protected final Predicate<RegionAndName> securityGroupEventualConsistencyDelay;
 
    @Inject
-   public CreateSecurityGroupIfNeeded(EC2Client ec2Client,
+   public CreateSecurityGroupIfNeeded(EC2Api ec2Api,
          @Named("SECURITY") Predicate<RegionAndName> securityGroupEventualConsistencyDelay) {
-      this(checkNotNull(ec2Client, "ec2Client").getSecurityGroupServices(), securityGroupEventualConsistencyDelay);
+      this(checkNotNull(ec2Api, "ec2Api").getSecurityGroupApi().get(), securityGroupEventualConsistencyDelay);
    }
 
-   public CreateSecurityGroupIfNeeded(SecurityGroupClient securityClient,
+   public CreateSecurityGroupIfNeeded(SecurityGroupApi securityClient,
          @Named("SECURITY") Predicate<RegionAndName> securityGroupEventualConsistencyDelay) {
       this.securityClient = checkNotNull(securityClient, "securityClient");
       this.securityGroupEventualConsistencyDelay = checkNotNull(securityGroupEventualConsistencyDelay,

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/loaders/LoadPublicIpForInstanceOrNull.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/loaders/LoadPublicIpForInstanceOrNull.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/loaders/LoadPublicIpForInstanceOrNull.java
index 1a3097e..9161c20 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/loaders/LoadPublicIpForInstanceOrNull.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/loaders/LoadPublicIpForInstanceOrNull.java
@@ -21,7 +21,7 @@ import java.util.NoSuchElementException;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.domain.PublicIpInstanceIdPair;
 
@@ -34,17 +34,17 @@ import com.google.common.collect.Iterables;
  */
 @Singleton
 public class LoadPublicIpForInstanceOrNull extends CacheLoader<RegionAndName, String> {
-   private final EC2Client client;
+   private final EC2Api client;
 
    @Inject
-   public LoadPublicIpForInstanceOrNull(EC2Client client) {
+   public LoadPublicIpForInstanceOrNull(EC2Api client) {
       this.client = client;
    }
 
    @Override
    public String load(final RegionAndName key) throws Exception {
       try {
-         return Iterables.find(client.getElasticIPAddressServices().describeAddressesInRegion(key.getRegion()),
+         return Iterables.find(client.getElasticIPAddressApi().get().describeAddressesInRegion(key.getRegion()),
                   new Predicate<PublicIpInstanceIdPair>() {
 
                      @Override

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/loaders/RegionAndIdToImage.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/loaders/RegionAndIdToImage.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/loaders/RegionAndIdToImage.java
index 5abfe9a..294c528 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/loaders/RegionAndIdToImage.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/loaders/RegionAndIdToImage.java
@@ -25,7 +25,7 @@ import javax.inject.Inject;
 import javax.inject.Singleton;
 
 import org.jclouds.compute.domain.Image;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.compute.functions.EC2ImageParser;
 import org.jclouds.logging.Logger;
@@ -43,10 +43,10 @@ public class RegionAndIdToImage extends CacheLoader<RegionAndName, Image> {
    protected Logger logger = Logger.NULL;
 
    private final EC2ImageParser parser;
-   private final EC2Client sync;
+   private final EC2Api sync;
 
    @Inject
-   public RegionAndIdToImage(EC2ImageParser parser, EC2Client sync) {
+   public RegionAndIdToImage(EC2ImageParser parser, EC2Api sync) {
       this.parser = parser;
       this.sync = sync;
    }
@@ -54,7 +54,7 @@ public class RegionAndIdToImage extends CacheLoader<RegionAndName, Image> {
    @Override
    public Image load(RegionAndName key) throws ExecutionException{
       try {
-         org.jclouds.ec2.domain.Image image = Iterables.getOnlyElement(sync.getAMIServices()
+         org.jclouds.ec2.domain.Image image = Iterables.getOnlyElement(sync.getAMIApi().get()
                .describeImagesInRegion(key.getRegion(), imageIds(key.getName())));
          return parser.apply(image);
       } catch (Exception e) {

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/predicates/SecurityGroupPresent.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/predicates/SecurityGroupPresent.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/predicates/SecurityGroupPresent.java
index aeb6044..33e492a 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/predicates/SecurityGroupPresent.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/predicates/SecurityGroupPresent.java
@@ -23,7 +23,7 @@ import java.util.NoSuchElementException;
 import javax.annotation.Resource;
 import javax.inject.Singleton;
 
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.domain.SecurityGroup;
 import org.jclouds.logging.Logger;
@@ -40,13 +40,13 @@ import com.google.inject.Inject;
 @Singleton
 public class SecurityGroupPresent implements Predicate<RegionAndName> {
 
-   private final EC2Client client;
+   private final EC2Api client;
 
    @Resource
    protected Logger logger = Logger.NULL;
 
    @Inject
-   public SecurityGroupPresent(EC2Client client) {
+   public SecurityGroupPresent(EC2Api client) {
       this.client = checkNotNull(client, "client");
    }
 
@@ -62,7 +62,7 @@ public class SecurityGroupPresent implements Predicate<RegionAndName> {
    }
 
    protected SecurityGroup refresh(RegionAndName securityGroup) {
-      return Iterables.getOnlyElement(client.getSecurityGroupServices().describeSecurityGroupsInRegion(
+      return Iterables.getOnlyElement(client.getSecurityGroupApi().get().describeSecurityGroupsInRegion(
             securityGroup.getRegion(), securityGroup.getName()));
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/DescribeImagesParallel.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/DescribeImagesParallel.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/DescribeImagesParallel.java
index 3004d89..bddbbba 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/DescribeImagesParallel.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/DescribeImagesParallel.java
@@ -17,10 +17,14 @@
 package org.jclouds.ec2.compute.strategy;
 
 import static com.google.common.collect.Iterables.concat;
-import static org.jclouds.concurrent.FutureIterables.transformParallel;
+import static com.google.common.collect.Iterables.transform;
+import static com.google.common.util.concurrent.Futures.allAsList;
+import static com.google.common.util.concurrent.Futures.getUnchecked;
 
+import java.util.List;
 import java.util.Map.Entry;
 import java.util.Set;
+import java.util.concurrent.Callable;
 
 import javax.annotation.Resource;
 import javax.inject.Inject;
@@ -29,7 +33,7 @@ import javax.inject.Singleton;
 
 import org.jclouds.Constants;
 import org.jclouds.compute.reference.ComputeServiceConstants;
-import org.jclouds.ec2.EC2AsyncClient;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.options.DescribeImagesOptions;
 import org.jclouds.logging.Logger;
 
@@ -48,25 +52,35 @@ public class DescribeImagesParallel implements
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;
 
-   protected final EC2AsyncClient async;
+   protected final EC2Api api;
    final ListeningExecutorService userExecutor;
 
    @Inject
-   public DescribeImagesParallel(EC2AsyncClient async, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
-      this.async = async;
+   public DescribeImagesParallel(EC2Api api, @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
+      this.api = api;
       this.userExecutor = userExecutor;
    }
 
    @Override
    public Iterable<? extends org.jclouds.ec2.domain.Image> apply(
-            Iterable<Entry<String, DescribeImagesOptions>> queries) {
-      return concat(transformParallel(
-               queries,
-               new Function<Entry<String, DescribeImagesOptions>, ListenableFuture<? extends Set<? extends org.jclouds.ec2.domain.Image>>>() {
-                  public ListenableFuture<Set<? extends org.jclouds.ec2.domain.Image>> apply(
-                           Entry<String, DescribeImagesOptions> from) {
-                     return async.getAMIServices().describeImagesInRegion(from.getKey(), from.getValue());
-                  }
-               }, userExecutor, null, logger, "amis"));
+            final Iterable<Entry<String, DescribeImagesOptions>> queries) {
+      ListenableFuture<List<Set<? extends org.jclouds.ec2.domain.Image>>> futures
+         = allAsList(transform(
+                            queries,
+                            new Function<Entry<String, DescribeImagesOptions>,
+                            ListenableFuture<? extends Set<? extends org.jclouds.ec2.domain.Image>>>() {
+                               public ListenableFuture<Set<? extends org.jclouds.ec2.domain.Image>> apply(
+                                                                                                          final Entry<String, DescribeImagesOptions> from) {
+                                  return userExecutor.submit(new Callable<Set<? extends org.jclouds.ec2.domain.Image>>() {
+                                        @Override
+                                        public Set<? extends org.jclouds.ec2.domain.Image> call() throws Exception {
+                                           return api.getAMIApi().get().describeImagesInRegion(from.getKey(), from.getValue());
+                                        }
+                                     });
+                               }
+                            }));
+      logger.trace("amis");
+
+      return concat(getUnchecked(futures));
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2CreateNodesInGroupThenAddToSet.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2CreateNodesInGroupThenAddToSet.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2CreateNodesInGroupThenAddToSet.java
index c385540..e40abe9 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2CreateNodesInGroupThenAddToSet.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2CreateNodesInGroupThenAddToSet.java
@@ -45,7 +45,7 @@ import org.jclouds.compute.strategy.CreateNodesInGroupThenAddToSet;
 import org.jclouds.compute.util.ComputeUtils;
 import org.jclouds.domain.Credentials;
 import org.jclouds.domain.LoginCredentials;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.compute.functions.PresentInstances;
 import org.jclouds.ec2.domain.RunningInstance;
@@ -82,7 +82,7 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
    boolean autoAllocateElasticIps = false;
 
    @VisibleForTesting
-   final EC2Client client;
+   final EC2Api client;
    @VisibleForTesting
    final Predicate<AtomicReference<NodeMetadata>> nodeRunning;
    @VisibleForTesting
@@ -99,7 +99,7 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
 
    @Inject
    protected EC2CreateNodesInGroupThenAddToSet(
-         EC2Client client,
+         EC2Api client,
          @Named("ELASTICIP") LoadingCache<RegionAndName, String> elasticIpCache,
          @Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
          CreateKeyPairAndSecurityGroupsAsNeededAndReturnRunOptions createKeyPairAndSecurityGroupsAsNeededAndReturncustomize,
@@ -191,7 +191,7 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
          RunningInstance instance = entry.getValue();
          try {
             logger.debug("<< allocating elastic IP instance(%s)", id);
-            String ip = client.getElasticIPAddressServices().allocateAddressInRegion(id.getRegion());
+            String ip = client.getElasticIPAddressApi().get().allocateAddressInRegion(id.getRegion());
             // block until instance is running
             logger.debug(">> awaiting status running instance(%s)", id);
             AtomicReference<NodeMetadata> node = newReference(runningInstanceToNodeMetadata
@@ -199,7 +199,7 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
             nodeRunning.apply(node);
             logger.trace("<< running instance(%s)", id);
             logger.debug(">> associating elastic IP %s to instance %s", ip, id);
-            client.getElasticIPAddressServices().associateAddressInRegion(id.getRegion(), ip, id.getName());
+            client.getElasticIPAddressApi().get().associateAddressInRegion(id.getRegion(), ip, id.getName());
             logger.trace("<< associated elastic IP %s to instance %s", ip, id);
             // add mapping of instance to ip into the cache
             elasticIpCache.put(id, ip);
@@ -231,7 +231,7 @@ public class EC2CreateNodesInGroupThenAddToSet implements CreateNodesInGroupThen
 
          started = ImmutableSet.copyOf(concat(
                started,
-               client.getInstanceServices().runInstancesInRegion(region, zone, template.getImage().getProviderId(), 1,
+               client.getInstanceApi().get().runInstancesInRegion(region, zone, template.getImage().getProviderId(), 1,
                      count - countStarted, instanceOptions)));
 
          countStarted = size(started);

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2DestroyNodeStrategy.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2DestroyNodeStrategy.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2DestroyNodeStrategy.java
index a3daede..2061b49 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2DestroyNodeStrategy.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2DestroyNodeStrategy.java
@@ -30,7 +30,7 @@ import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.compute.strategy.DestroyNodeStrategy;
 import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.reference.EC2Constants;
 import org.jclouds.logging.Logger;
@@ -48,7 +48,7 @@ public class EC2DestroyNodeStrategy implements DestroyNodeStrategy {
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;
-   protected final EC2Client client;
+   protected final EC2Api client;
    protected final GetNodeMetadataStrategy getNode;
    protected final LoadingCache<RegionAndName, String> elasticIpCache;
 
@@ -58,7 +58,7 @@ public class EC2DestroyNodeStrategy implements DestroyNodeStrategy {
    boolean autoAllocateElasticIps = false;
 
    @Inject
-   protected EC2DestroyNodeStrategy(EC2Client client, GetNodeMetadataStrategy getNode,
+   protected EC2DestroyNodeStrategy(EC2Api client, GetNodeMetadataStrategy getNode,
             @Named("ELASTICIP") LoadingCache<RegionAndName, String> elasticIpCache) {
       this.client = checkNotNull(client, "client");
       this.getNode = checkNotNull(getNode, "getNode");
@@ -83,11 +83,11 @@ public class EC2DestroyNodeStrategy implements DestroyNodeStrategy {
       try {
          String ip = elasticIpCache.get(new RegionAndName(region, instanceId));
          logger.debug(">> disassociating elastic IP %s", ip);
-         client.getElasticIPAddressServices().disassociateAddressInRegion(region, ip);
+         client.getElasticIPAddressApi().get().disassociateAddressInRegion(region, ip);
          logger.trace("<< disassociated elastic IP %s", ip);
          elasticIpCache.invalidate(new RegionAndName(region, instanceId));
          logger.debug(">> releasing elastic IP %s", ip);
-         client.getElasticIPAddressServices().releaseAddressInRegion(region, ip);
+         client.getElasticIPAddressApi().get().releaseAddressInRegion(region, ip);
          logger.trace("<< released elastic IP %s", ip);
       } catch (CacheLoader.InvalidCacheLoadException e) {
          // no ip was found
@@ -100,6 +100,6 @@ public class EC2DestroyNodeStrategy implements DestroyNodeStrategy {
    }
 
    protected void destroyInstanceInRegion(String instanceId, String region) {
-      client.getInstanceServices().terminateInstancesInRegion(region, instanceId);
+      client.getInstanceApi().get().terminateInstancesInRegion(region, instanceId);
    }
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2GetImageStrategy.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2GetImageStrategy.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2GetImageStrategy.java
index 4052c82..a20c48c 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2GetImageStrategy.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2GetImageStrategy.java
@@ -26,7 +26,7 @@ import javax.inject.Singleton;
 
 import org.jclouds.aws.util.AWSUtils;
 import org.jclouds.compute.strategy.GetImageStrategy;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.domain.Image;
 import org.jclouds.ec2.options.DescribeImagesOptions;
 
@@ -39,11 +39,11 @@ import com.google.common.base.Function;
 @Singleton
 public class EC2GetImageStrategy implements GetImageStrategy {
 
-   private final EC2Client client;
+   private final EC2Api client;
    private final Function<Image, org.jclouds.compute.domain.Image> imageToImage;
 
    @Inject
-   protected EC2GetImageStrategy(EC2Client client, Function<Image, org.jclouds.compute.domain.Image> imageToImage) {
+   protected EC2GetImageStrategy(EC2Api client, Function<Image, org.jclouds.compute.domain.Image> imageToImage) {
       this.client = checkNotNull(client, "client");
       this.imageToImage = checkNotNull(imageToImage, "imageToImage");
    }
@@ -63,7 +63,7 @@ public class EC2GetImageStrategy implements GetImageStrategy {
    }
 
    public Image getImageInRegion(String region, String id) {
-      return getOnlyElement(client.getAMIServices().describeImagesInRegion(region,
+      return getOnlyElement(client.getAMIApi().get().describeImagesInRegion(region,
                DescribeImagesOptions.Builder.imageIds(id)));
    }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2GetNodeMetadataStrategy.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2GetNodeMetadataStrategy.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2GetNodeMetadataStrategy.java
index 620f207..e446697 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2GetNodeMetadataStrategy.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2GetNodeMetadataStrategy.java
@@ -27,7 +27,7 @@ import javax.inject.Singleton;
 import org.jclouds.aws.util.AWSUtils;
 import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.domain.RunningInstance;
 
 import com.google.common.base.Function;
@@ -40,11 +40,11 @@ import com.google.common.collect.Iterables;
 @Singleton
 public class EC2GetNodeMetadataStrategy implements GetNodeMetadataStrategy {
 
-   private final EC2Client client;
+   private final EC2Api client;
    private final Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata;
 
    @Inject
-   protected EC2GetNodeMetadataStrategy(EC2Client client,
+   protected EC2GetNodeMetadataStrategy(EC2Api client,
             Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata) {
       this.client = checkNotNull(client, "client");
       this.runningInstanceToNodeMetadata = checkNotNull(runningInstanceToNodeMetadata, "runningInstanceToNodeMetadata");
@@ -65,7 +65,7 @@ public class EC2GetNodeMetadataStrategy implements GetNodeMetadataStrategy {
    }
 
    public RunningInstance getRunningInstanceInRegion(String region, String id) {
-      return getOnlyElement(Iterables.concat(client.getInstanceServices().describeInstancesInRegion(region, id)));
+      return getOnlyElement(Iterables.concat(client.getInstanceApi().get().describeInstancesInRegion(region, id)));
    }
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2ListNodesStrategy.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2ListNodesStrategy.java b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2ListNodesStrategy.java
index acb9df9..d550b1e 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2ListNodesStrategy.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/compute/strategy/EC2ListNodesStrategy.java
@@ -42,7 +42,7 @@ import org.jclouds.compute.domain.NodeMetadata;
 import org.jclouds.compute.predicates.NodePredicates;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.compute.strategy.ListNodesStrategy;
-import org.jclouds.ec2.EC2Client;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.domain.Reservation;
 import org.jclouds.ec2.domain.RunningInstance;
 import org.jclouds.location.Region;
@@ -73,13 +73,13 @@ public class EC2ListNodesStrategy implements ListNodesStrategy {
    @Named(Constants.PROPERTY_REQUEST_TIMEOUT)
    protected static Long maxTime;
 
-   protected final EC2Client client;
+   protected final EC2Api client;
    protected final Supplier<Set<String>> regions;
    protected final Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata;
    protected final ListeningExecutorService userExecutor;
 
    @Inject
-   protected EC2ListNodesStrategy(EC2Client client, @Region Supplier<Set<String>> regions,
+   protected EC2ListNodesStrategy(EC2Api client, @Region Supplier<Set<String>> regions,
             Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
             @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor) {
       this.client =  checkNotNull(client, "client");
@@ -146,7 +146,7 @@ public class EC2ListNodesStrategy implements ListNodesStrategy {
          
          @Override
          public Set<? extends Reservation<? extends RunningInstance>> apply(String from) {
-            return client.getInstanceServices().describeInstancesInRegion(from);
+            return client.getInstanceApi().get().describeInstancesInRegion(from);
          }
          
       };
@@ -158,7 +158,7 @@ public class EC2ListNodesStrategy implements ListNodesStrategy {
                  
          @Override
          public Set<? extends Reservation<? extends RunningInstance>> apply(String from) {
-            return client.getInstanceServices()
+            return client.getInstanceApi().get()
                .describeInstancesInRegion(from, toArray(idsByRegions.get(from), String.class));
          }
          


[18/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/features/InstanceApi.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/InstanceApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/InstanceApi.java
new file mode 100644
index 0000000..2b56324
--- /dev/null
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/InstanceApi.java
@@ -0,0 +1,765 @@
+/*
+ * 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.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import java.util.Map;
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindBlockDeviceMappingToIndexedFormParams;
+import org.jclouds.ec2.binders.BindInstanceIdsToIndexedFormParams;
+import org.jclouds.ec2.binders.IfNotNullBindAvailabilityZoneToFormParam;
+import org.jclouds.ec2.domain.BlockDevice;
+import org.jclouds.ec2.domain.InstanceStateChange;
+import org.jclouds.ec2.domain.Reservation;
+import org.jclouds.ec2.domain.RunningInstance;
+import org.jclouds.ec2.domain.Volume.InstanceInitiatedShutdownBehavior;
+import org.jclouds.ec2.functions.ConvertUnencodedBytesToBase64EncodedString;
+import org.jclouds.ec2.options.RunInstancesOptions;
+import org.jclouds.ec2.xml.BlockDeviceMappingHandler;
+import org.jclouds.ec2.xml.BooleanValueHandler;
+import org.jclouds.ec2.xml.DescribeInstancesResponseHandler;
+import org.jclouds.ec2.xml.GetConsoleOutputResponseHandler;
+import org.jclouds.ec2.xml.InstanceInitiatedShutdownBehaviorHandler;
+import org.jclouds.ec2.xml.InstanceStateChangeHandler;
+import org.jclouds.ec2.xml.InstanceTypeHandler;
+import org.jclouds.ec2.xml.RunInstancesResponseHandler;
+import org.jclouds.ec2.xml.StringValueHandler;
+import org.jclouds.ec2.xml.UnencodeStringValueHandler;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.ParamParser;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+/**
+ * Provides access to EC2 Instance Services via their REST API.
+ * <p/>
+ * 
+ * @author Adrian Cole
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+public interface InstanceApi {
+
+   /**
+    * Returns information about instances that you own.
+    * <p/>
+    * 
+    * If you specify one or more instance IDs, Amazon EC2 returns information
+    * for those instances. If you do not specify instance IDs, Amazon EC2
+    * returns information for all relevant instances. If you specify an invalid
+    * instance ID, a fault is returned. If you specify an instance that you do
+    * not own, it will not be included in the returned results.
+    * <p/>
+    * Recently terminated instances might appear in the returned results.This
+    * interval is usually less than one hour.
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * 
+    * @see #runInstancesInRegion
+    * @see #terminateInstancesInRegion
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html"
+    *      />
+    */
+   @Named("DescribeInstances")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeInstances")
+   @XMLResponseParser(DescribeInstancesResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<? extends Reservation<? extends RunningInstance>> describeInstancesInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
+
+   /**
+    * Launches a specified number of instances of an AMI for which you have
+    * permissions.
+    * <p/>
+    * 
+    * If Amazon EC2 cannot launch the minimum number AMIs you request, no
+    * instances will be launched. If there is insufficient capacity to launch
+    * the maximum number of AMIs you request, Amazon EC2 launches the minimum
+    * number specified for each AMI and allocate the remaining available
+    * instances using round robin.
+    * <p/>
+    * <h4>Security Groups</h4>
+    * <b>Note:</b> Every instance is launched in a security group (created using
+    * the CreateSecurityGroup operation.
+    * <h4>Key Pair</h4>
+    * You can provide an optional key pair ID for each image in the launch
+    * request (created using the CreateKeyPair operation). All instances that
+    * are created from images that use this key pair will have access to the
+    * associated public key at boot. You can use this key to provide secure
+    * access to an instance of an image on a per-instance basis. Amazon EC2
+    * public images use this feature to provide secure access without passwords.
+    * <p/>
+    * <b>Note:</b> Launching public images without a key pair ID will leave them
+    * inaccessible.
+    * <p/>
+    * The public key material is made available to the instance at boot time by
+    * placing it in the openssh_id.pub file on a logical device that is exposed
+    * to the instance as /dev/sda2 (the instance store). The format of this file
+    * is suitable for use as an entry within ~/.ssh/authorized_keys (the OpenSSH
+    * format). This can be done at boot (e.g., as part of rc.local) allowing for
+    * secure access without passwords.
+    * <h4>User Data</h4>
+    * Optional user data can be provided in the launch request. All instances
+    * that collectively comprise the launch request have access to this data.
+    * For more information, go the Amazon Elastic Compute Cloud Developer Guide.
+    * <h4>Product Codes</h4>
+    * 
+    * <b>Note:</b> If any of the AMIs have a product code attached for which the
+    * user has not subscribed, the RunInstances call will fail.
+    * <h4>Kernel</h4>
+    * 
+    * <b>Important:</b> We strongly recommend using the 2.6.18 Xen stock kernel
+    * with High-CPU and High-Memory instances. Although the default Amazon EC2
+    * kernels will work, the new kernels provide greater stability and
+    * performance for these instance types. For more information about kernels,
+    * go the Amazon Elastic Compute Cloud Developer Guide.
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param nullableAvailabilityZone
+    *           Specifies the placement constraints (Availability Zones) for
+    *           launching the instances. If null, Amazon will determine the best
+    *           availability zone to place the instance.
+    * @param imageId
+    *           Unique ID of a machine image, returned by a call to
+    * @param minCount
+    *           Minimum number of instances to launch. If the value is more than
+    *           Amazon EC2 can launch, no instances a re launched at all.
+    *           Constraints: Between 1 and the maximum number allowed for your
+    *           account (default: 20).
+    * @param maxCount
+    *           Maximum number of instances to launch. If the value is more than
+    *           Amazon EC2 can launch, the largest possible number above
+    *           minCount will be launched instead. Constraints: Between 1 and
+    *           the maximum number allowed for your account (default: 20).
+    * @see #describeInstancesInRegion
+    * @see #terminateInstancesInRegion
+    * @see #authorizeSecurityGroupIngressInRegion
+    * @see #revokeSecurityGroupIngressInRegion
+    * @see #describeSecurityGroupsInRegion
+    * @see #createSecurityGroupInRegion
+    * @see #createKeyPairInRegion
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RunInstances.html"
+    *      />
+    * @see RunInstancesOptions
+    */
+   @Named("RunInstances")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "RunInstances")
+   @XMLResponseParser(RunInstancesResponseHandler.class)
+   Reservation<? extends RunningInstance> runInstancesInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @Nullable @BinderParam(IfNotNullBindAvailabilityZoneToFormParam.class) String nullableAvailabilityZone,
+         @FormParam("ImageId") String imageId, @FormParam("MinCount") int minCount,
+         @FormParam("MaxCount") int maxCount, RunInstancesOptions... options);
+
+   /**
+    * Requests a reboot of one or more instances. This operation is
+    * asynchronous; it only queues a request to reboot the specified
+    * instance(s). The operation will succeed if the instances are valid and
+    * belong to you. Requests to reboot terminated instances are ignored. <h3>
+    * Note</h3> If a Linux/UNIX instance does not cleanly shut down within four
+    * minutes, Amazon EC2 will perform a hard reboot.
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * 
+    * @param instanceIds
+    *           Instance ID to reboot.
+    * 
+    * @see #startInstancesInRegion
+    * @see #runInstancesInRegion
+    * @see #describeInstancesInRegion
+    * @see #terminateInstancesInRegion
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StopInstances.html"
+    *      />
+    */
+   @Named("RebootInstances")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "RebootInstances")
+   void rebootInstancesInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
+
+   /**
+    * Shuts down one or more instances. This operation is idempotent; if you
+    * terminate an instance more than once, each call will succeed.
+    * <p/>
+    * Terminated instances will remain visible after termination (approximately
+    * one hour).
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceIds
+    *           Instance ID to terminate.
+    * @see #describeInstancesInRegion
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-TerminateInstances.html"
+    *      />
+    */
+   @Named("TerminateInstances")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "TerminateInstances")
+   @XMLResponseParser(InstanceStateChangeHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<? extends InstanceStateChange> terminateInstancesInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
+
+   /**
+    * Stops an instance that uses an Amazon EBS volume as its root device.
+    * <p/>
+    * Instances that use Amazon EBS volumes as their root devices can be quickly
+    * stopped and started. When an instance is stopped, the compute resources
+    * are released and you are not billed for hourly instance usage. However,
+    * your root partition Amazon EBS volume remains, continues to persist your
+    * data, and you are charged for Amazon EBS volume usage. You can restart
+    * your instance at any time.
+    * <h3>Note</h3>
+    * Before stopping an instance, make sure it is in a state from which it can
+    * be restarted. Stopping an instance does not preserve data stored in RAM.
+    * <p/>
+    * Performing this operation on an instance that uses an instance store as
+    * its root device returns an error.
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param force
+    *           Forces the instance to stop. The instance will not have an
+    *           opportunity to flush file system caches nor file system meta
+    *           data. If you use this option, you must perform file system check
+    *           and repair procedures. This option is not recommended for
+    *           Windows instances.
+    * @param instanceIds
+    *           Instance ID to stop.
+    * 
+    * @see #startInstancesInRegion
+    * @see #runInstancesInRegion
+    * @see #describeInstancesInRegion
+    * @see #terminateInstancesInRegion
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StopInstances.html"
+    *      />
+    */
+   @Named("StopInstances")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "StopInstances")
+   @XMLResponseParser(InstanceStateChangeHandler.class)
+   Set<? extends InstanceStateChange> stopInstancesInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("Force") boolean force,
+         @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
+
+   /**
+    * Starts an instance that uses an Amazon EBS volume as its root device.
+    * <p/>
+    * Instances that use Amazon EBS volumes as their root devices can be quickly
+    * stopped and started. When an instance is stopped, the compute resources
+    * are released and you are not billed for hourly instance usage. However,
+    * your root partition Amazon EBS volume remains, continues to persist your
+    * data, and you are charged for Amazon EBS volume usage. You can restart
+    * your instance at any time.
+    * <h3>Note</h3>
+    * Before stopping an instance, make sure it is in a state from which it can
+    * be restarted. Stopping an instance does not preserve data stored in RAM.
+    * <p/>
+    * Performing this operation on an instance that uses an instance store as
+    * its root device returns an error.
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceIds
+    *           Instance ID to start.
+    * 
+    * @see #stopInstancesInRegion
+    * @see #runInstancesInRegion
+    * @see #describeInstancesInRegion
+    * @see #terminateInstancesInRegion
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-StartInstances.html"
+    *      />
+    */
+   @Named("StartInstances")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "StartInstances")
+   @XMLResponseParser(InstanceStateChangeHandler.class)
+   Set<? extends InstanceStateChange> startInstancesInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
+
+   /**
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to describe the attribute of
+    * @return unencoded user data
+    */
+   @Named("DescribeInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "userData" })
+   @XMLResponseParser(UnencodeStringValueHandler.class)
+   String getUserDataForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId);
+
+   /**
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to describe the attribute of
+    * @return The root device name (e.g., /dev/sda1).
+    */
+   @Named("DescribeInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "rootDeviceName" })
+   @XMLResponseParser(StringValueHandler.class)
+   String getRootDeviceNameForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId);
+
+   /**
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to describe the attribute of
+    * @return the ID of the RAM disk associated with the AMI.
+    */
+   @Named("DescribeInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "ramdisk" })
+   @XMLResponseParser(StringValueHandler.class)
+   String getRamdiskForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId);
+
+   /**
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to describe the attribute of
+    * @return the ID of the kernel associated with the AMI.
+    */
+   @Named("DescribeInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "kernel" })
+   @XMLResponseParser(StringValueHandler.class)
+   String getKernelForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId);
+
+   /**
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to describe the attribute of
+    * @return Specifies whether the instance can be terminated using the APIs.
+    *         You must modify this attribute before you can terminate any
+    *         "locked" instances from the APIs.
+    */
+   @Named("DescribeInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "disableApiTermination" })
+   @XMLResponseParser(BooleanValueHandler.class)
+   boolean isApiTerminationDisabledForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId);
+
+   /**
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to describe the attribute of
+    * @return The instance type of the instance.
+    */
+   @Named("DescribeInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "instanceType" })
+   @XMLResponseParser(InstanceTypeHandler.class)
+   String getInstanceTypeForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId);
+
+   /**
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to describe the attribute of
+    * @return whether the instance's Amazon EBS volumes are stopped or
+    *         terminated when the instance is shut down.
+    */
+   @Named("DescribeInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute",
+         "instanceInitiatedShutdownBehavior" })
+   @XMLResponseParser(InstanceInitiatedShutdownBehaviorHandler.class)
+   InstanceInitiatedShutdownBehavior getInstanceInitiatedShutdownBehaviorForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId);
+
+   /**
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to describe the attribute of
+    * @return Describes the mapping that defines native device names to use when
+    *         exposing virtual devices.
+    */
+   @Named("DescribeInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeInstanceAttribute", "blockDeviceMapping" })
+   @XMLResponseParser(BlockDeviceMappingHandler.class)
+   Map<String, BlockDevice> getBlockDeviceMappingForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId);
+
+   /**
+    * Resets an attribute of an instance to its default value.
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to reset the attribute of
+    * @return the ID of the RAM disk associated with the AMI.
+    */
+   @Named("ResetInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "ResetInstanceAttribute", "ramdisk" })
+   void resetRamdiskForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId);
+
+   /**
+    * Resets an attribute of an instance to its default value.
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to reset the attribute of
+    * @return the ID of the kernel associated with the AMI.
+    */
+   @Named("ResetInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "ResetInstanceAttribute", "kernel" })
+   void resetKernelForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId);
+
+   /**
+    * Sets the userData used for starting the instance.
+    * <p/>
+    * The instance needs to be in a {@link InstanceState#STOPPED} state, which
+    * implies two things:
+    * <ol>
+    * <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
+    * <li>You have stopped and waited for the instance to transition from
+    * {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
+    * </ol>
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to change the attribute of
+    * @param unencodedData
+    *           unencoded data to set as userData
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
+    *      />
+    */
+   @Named("ModifyInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "userData" })
+   void setUserDataForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId,
+         @FormParam("Value") @ParamParser(ConvertUnencodedBytesToBase64EncodedString.class) byte[] unencodedData);
+
+   /**
+    * Sets the ramdisk used for starting the instance.
+    * <p/>
+    * The instance needs to be in a {@link InstanceState#STOPPED} state, which
+    * implies two things:
+    * <ol>
+    * <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
+    * <li>You have stopped and waited for the instance to transition from
+    * {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
+    * </ol>
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to change the attribute of
+    * @param ramdisk
+    *           ramdisk used to start the instance
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
+    *      />
+    */
+   @Named("ModifyInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "ramdisk" })
+   void setRamdiskForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId, @FormParam("Value") String ramdisk);
+
+   /**
+    * Sets the kernelId used for starting the instance.
+    * <p/>
+    * The instance needs to be in a {@link InstanceState#STOPPED} state, which
+    * implies two things:
+    * <ol>
+    * <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
+    * <li>You have stopped and waited for the instance to transition from
+    * {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
+    * </ol>
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to change the attribute of
+    * @param kernel
+    *           kernelId used to start the instance
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
+    *      />
+    */
+   @Named("ModifyInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "kernel" })
+   void setKernelForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId, @FormParam("Value") String kernel);
+
+   /**
+    * This command works while the instance is running and controls whether or
+    * not the api can be used to terminate the instance.
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to reset the attribute of
+    * @param apiTerminationDisabled
+    *           true to disable api termination
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
+    *      />
+    */
+   @Named("ModifyInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "disableApiTermination" })
+   void setApiTerminationDisabledForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId, @FormParam("Value") boolean apiTerminationDisabled);
+
+   /**
+    * Sets the instanceType used for starting the instance.
+    * <p/>
+    * The instance needs to be in a {@link InstanceState#STOPPED} state, which
+    * implies two things:
+    * <ol>
+    * <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
+    * <li>You have stopped and waited for the instance to transition from
+    * {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
+    * </ol>
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to change the attribute of
+    * @param instanceType
+    *           instanceType used to start the instance
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
+    *      />
+    */
+   @Named("ModifyInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute", "instanceType" })
+   void setInstanceTypeForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId, @FormParam("Value") String instanceType);
+
+   /**
+    * Specifies whether the instance's Amazon EBS volumes are stopped or
+    * terminated when the instance is shut down.
+    * <p/>
+    * The instance needs to be in a {@link InstanceState#STOPPED} state, which
+    * implies two things:
+    * <ol>
+    * <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
+    * <li>You have stopped and waited for the instance to transition from
+    * {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
+    * </ol>
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to change the attribute of
+    * @param instanceInitiatedShutdownBehavior
+    *           whether the instance's Amazon EBS volumes are stopped or
+    *           terminated when the instance is shut down.
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
+    *      />
+    */
+   @Named("ModifyInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "ModifyInstanceAttribute",
+         "instanceInitiatedShutdownBehavior" })
+   void setInstanceInitiatedShutdownBehaviorForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId,
+         @FormParam("Value") InstanceInitiatedShutdownBehavior instanceInitiatedShutdownBehavior);
+
+   /**
+    * Sets the blockDeviceMapping used for an instance.
+    * <p/>
+    * The instance needs to be in a {@link InstanceState#STOPPED} state, which
+    * implies two things:
+    * <ol>
+    * <li>The instance was launched from an EBS-backed AMI so that it can stop</li>
+    * <li>You have stopped and waited for the instance to transition from
+    * {@link InstanceState#STOPPING} to {@link InstanceState#STOPPED}</li>
+    * </ol>
+    * 
+    * To create the instances of {@link BlockDevice}, the
+    * constructor can be used with the following parameters:
+    * {@link BlockDevice#EbsBlockDevice(String, String, boolean)}
+    * , that are:
+    * <ol>
+    * <li>Volume id (required), for instance, "vol-blah"</li>
+    * <li>Device name (optional), for instance, "/dev/sda1". To find out more
+    * about device names, read the next paragraph.</li>
+    * <li>Delete on termination flag (optional), which defines whether the
+    * volume will be deleted upon instance's termination.</li>
+    * </ol>
+    * <p/>
+    * Note that the device names between Linux and Windows differ. For Linux,
+    * ensure that your device name is in the form /dev/sd[a-z] . For example,
+    * /dev/sda , /dev/sdb and /dev/sdh are all valid device names.
+    * <p/>
+    * For Windows, the root device is still referred to as /dev/sda1 . For other
+    * devices, ensure that they are in the form /xvd[c-p] . For example, /xvde ,
+    * /xvdf and /xvdp are all valid Windows device names.
+    * <p/>
+    * <b>NOTE</b>: As of now 02/20/2010, this command only works to change the
+    * DeleteOnTermination property of the device. The volume must be
+    * <i>attached</i> to a stopped instance.
+    * 
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to change the attribute of
+    * @param blockDeviceMapping
+    *           blockDeviceMapping used to start the instance
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyInstanceAttribute.html"
+    *      />
+    */
+   @Named("ModifyInstanceAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION }, values = { "ModifyInstanceAttribute" })
+   void setBlockDeviceMappingForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId,
+         @BinderParam(BindBlockDeviceMappingToIndexedFormParams.class) Map<String, BlockDevice> blockDeviceMapping);
+
+   /**
+    * Retrieves console output for the specified instance.
+    *
+    * Instance console output is buffered and posted shortly after instance boot, reboot, and termination. Amazon EC2 preserves
+    * the most recent 64 KB output which will be available for at least one hour after the most recent post.
+    *
+    * @param region
+    *           Instances are tied to Availability Zones. However, the instance
+    *           ID is tied to the Region.
+    * @param instanceId
+    *           which instance to retrieve console output for
+    * @return The console output
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-GetConsoleOutput.html">
+    *       ApiReference query GetConsoleOutput</a>
+    */
+   @Named("GetConsoleOutput")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION }, values = { "GetConsoleOutput" })
+   @XMLResponseParser(GetConsoleOutputResponseHandler.class)
+   String getConsoleOutputForInstanceInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId);
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/features/KeyPairApi.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/KeyPairApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/KeyPairApi.java
new file mode 100644
index 0000000..b09406e
--- /dev/null
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/KeyPairApi.java
@@ -0,0 +1,131 @@
+/*
+ * 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.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindKeyNamesToIndexedFormParams;
+import org.jclouds.ec2.domain.KeyPair;
+import org.jclouds.ec2.xml.DescribeKeyPairsResponseHandler;
+import org.jclouds.ec2.xml.KeyPairResponseHandler;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+/**
+ * Provides access to EC2 via their REST API.
+ * <p/>
+ * 
+ * @author Adrian Cole
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+public interface KeyPairApi {
+
+   /**
+    * Creates a new 2048-bit RSA key pair with the specified name. The public key is stored by
+    * Amazon EC2 and the private key is displayed on the console. The private key is returned as an
+    * unencrypted PEM encoded PKCS#8 private key. If a key with the specified name already exists,
+    * Amazon EC2 returns an error.
+    * 
+    * @param region
+    *           Key pairs (to connect to instances) are Region-specific.
+    * @param keyName
+    *           A unique name for the key pair.
+    * 
+    * @see #runInstances
+    * @see #describeKeyPairs
+    * @see #deleteKeyPair
+    * 
+    * @see <a href=
+    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateKeyPair.html"
+    *      />
+    */
+   @Named("CreateKeyPair")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "CreateKeyPair")
+   @XMLResponseParser(KeyPairResponseHandler.class)
+   KeyPair createKeyPairInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("KeyName") String keyName);
+
+   /**
+    * Returns information about key pairs available to you. If you specify key pairs, information
+    * about those key pairs is returned. Otherwise, information for all registered key pairs is
+    * returned.
+    * 
+    * @param region
+    *           Key pairs (to connect to instances) are Region-specific.
+    * @param keyPairNames
+    *           Key pairs to describe.
+    * 
+    * @see #runInstances
+    * @see #describeAvailabilityZones
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeKeyPairs.html"
+    *      />
+    */
+   @Named("DescribeKeyPairs")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeKeyPairs")
+   @XMLResponseParser(DescribeKeyPairsResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<KeyPair> describeKeyPairsInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @BinderParam(BindKeyNamesToIndexedFormParams.class) String... keyPairNames);
+
+   /**
+    * Deletes the specified key pair, by removing the public key from Amazon EC2. You must own the
+    * key pair
+    * 
+    * @param region
+    *           Key pairs (to connect to instances) are Region-specific.
+    * @param keyName
+    *           Name of the key pair to delete
+    * 
+    * @see #describeKeyPairs
+    * @see #createKeyPair
+    * 
+    * @see <a href=
+    *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteKeyPair.html"
+    *      />
+    */
+   @Named("DeleteKeyPair")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DeleteKeyPair")
+   void deleteKeyPairInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("KeyName") String keyName);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/features/SecurityGroupApi.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/SecurityGroupApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/SecurityGroupApi.java
new file mode 100644
index 0000000..70cbdac
--- /dev/null
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/SecurityGroupApi.java
@@ -0,0 +1,293 @@
+/*
+ * 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.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.VoidOnNotFoundOr404;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindGroupNamesToIndexedFormParams;
+import org.jclouds.ec2.binders.BindUserIdGroupPairToSourceSecurityGroupFormParams;
+import org.jclouds.ec2.domain.SecurityGroup;
+import org.jclouds.ec2.domain.UserIdGroupPair;
+import org.jclouds.ec2.xml.DescribeSecurityGroupsResponseHandler;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.net.domain.IpProtocol;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+/**
+ * Provides access to EC2 via their REST API.
+ * <p/>
+ * 
+ * @author Adrian Cole
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+public interface SecurityGroupApi {
+
+   /**
+    * Creates a new security group. Group names must be unique per identity.
+    * 
+    * @param region
+    *           Security groups are not copied across Regions. Instances within the Region cannot
+    *           communicate with instances outside the Region using group-based firewall rules.
+    *           Traffic from instances in another Region is seen as WAN bandwidth.
+    * @param name
+    *           Name of the security group. Accepts alphanumeric characters, spaces, dashes, and
+    *           underscores.
+    * @param description
+    *           Description of the group. This is informational only. If the description contains
+    *           spaces, you must enc lose it in single quotes (') or URL-encode it. Accepts
+    *           alphanumeric characters, spaces, dashes, and underscores.
+    * @see #runInstances
+    * @see #describeSecurityGroups
+    * @see #authorizeSecurityGroupIngress
+    * @see #revokeSecurityGroupIngress
+    * @see #deleteSecurityGroup
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateSecurityGroup.html"
+    *      />
+    */
+   @Named("CreateSecurityGroup")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "CreateSecurityGroup")
+   void createSecurityGroupInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("GroupName") String name, @FormParam("GroupDescription") String description);
+
+   /**
+    * Deletes a security group that you own.
+    * 
+    * @param region
+    *           Security groups are not copied across Regions. Instances within the Region cannot
+    *           communicate with instances outside the Region using group-based firewall rules.
+    *           Traffic from instances in another Region is seen as WAN bandwidth.
+    * @param name
+    *           Name of the security group to delete.
+    * 
+    * @see #describeSecurityGroups
+    * @see #authorizeSecurityGroupIngress
+    * @see #revokeSecurityGroupIngress
+    * @see #createSecurityGroup
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteSecurityGroup.html"
+    *      />
+    */
+   @Named("DeleteSecurityGroup")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DeleteSecurityGroup")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void deleteSecurityGroupInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region, @FormParam("GroupName") String name);
+
+   /**
+    * Returns information about security groups that you own.
+    * 
+    * @param region
+    *           Security groups are not copied across Regions. Instances within the Region cannot
+    *           communicate with instances outside the Region using group-based firewall rules.
+    *           Traffic from instances in another Region is seen as WAN bandwidth.
+    * @param securityGroupNames
+    *           Name of the security groups
+    * 
+    * @see #createSecurityGroup
+    * @see #authorizeSecurityGroupIngress
+    * @see #revokeSecurityGroupIngress
+    * @see #deleteSecurityGroup
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSecurityGroups.html"
+    *      />
+    */
+   @Named("DescribeSecurityGroups")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeSecurityGroups")
+   @XMLResponseParser(DescribeSecurityGroupsResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<SecurityGroup> describeSecurityGroupsInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @BinderParam(BindGroupNamesToIndexedFormParams.class) String... securityGroupNames);
+
+   /**
+    * 
+    * Adds permissions to a security group based on another group.
+    * 
+    * @param region
+    *           Security groups are not copied across Regions. Instances within the Region cannot
+    *           communicate with instances outside the Region using group-based firewall rules.
+    *           Traffic from instances in another Region is seen as WAN bandwidth.
+    * @param groupName
+    *           Name of the group to modify. The name must be valid and belong to the identity
+    * @param sourceSecurityGroup
+    *           group to associate with this group.
+    * 
+    * @see #createSecurityGroup
+    * @see #describeSecurityGroups
+    * @see #revokeSecurityGroupIngress
+    * @see #deleteSecurityGroup
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-AuthorizeSecurityGroupIngress.html"
+    * 
+    */
+   @Named("AuthorizeSecurityGroupIngress")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "AuthorizeSecurityGroupIngress")
+   void authorizeSecurityGroupIngressInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("GroupName") String groupName,
+            @BinderParam(BindUserIdGroupPairToSourceSecurityGroupFormParams.class) UserIdGroupPair sourceSecurityGroup);
+
+   /**
+    * 
+    * Adds permissions to a security group.
+    * <p/>
+    * Permissions are specified by the IP protocol (TCP, UDP or ICMP), the source of the request (by
+    * IP range or an Amazon EC2 user-group pair), the source and destination port ranges (for TCP
+    * and UDP), and the ICMP codes and types (for ICMP). When authorizing ICMP, -1 can be used as a
+    * wildcard in the type and code fields. Permission changes are propagated to instances within
+    * the security group as quickly as possible. However, depending on the number of instances, a
+    * small delay might occur.
+    * 
+    * @param region
+    *           Security groups are not copied across Regions. Instances within the Region cannot
+    *           communicate with instances outside the Region using group-based firewall rules.
+    *           Traffic from instances in another Region is seen as WAN bandwidth.
+    * @param groupName
+    *           Name of the group to modify. The name must be valid and belong to the identity
+    * @param ipProtocol
+    *           IP protocol.
+    * @param fromPort
+    *           Start of port range for the TCP and UDP protocols, or an ICMP type number. An ICMP
+    *           type number of -1 indicates a wildcard (i.e., any ICMP type number).
+    * @param toPort
+    *           End of port range for the TCP and UDP protocols, or an ICMP code. An ICMP code of -1
+    *           indicates a wildcard (i.e., any ICMP code).
+    * @param cidrIp
+    *           CIDR range.
+    * 
+    * @see #createSecurityGroup
+    * @see #describeSecurityGroups
+    * @see #revokeSecurityGroupIngress
+    * @see #deleteSecurityGroup
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-AuthorizeSecurityGroupIngress.html"
+    * 
+    */
+   @Named("AuthorizeSecurityGroupIngress")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "AuthorizeSecurityGroupIngress")
+   void authorizeSecurityGroupIngressInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("GroupName") String groupName, @FormParam("IpProtocol") IpProtocol ipProtocol,
+            @FormParam("FromPort") int fromPort, @FormParam("ToPort") int toPort, @FormParam("CidrIp") String cidrIp);
+
+   /**
+    * 
+    * Revokes permissions from a security group. The permissions used to revoke must be specified
+    * using the same values used to grant the permissions.
+    * 
+    * @param region
+    *           Security groups are not copied across Regions. Instances within the Region cannot
+    *           communicate with instances outside the Region using group-based firewall rules.
+    *           Traffic from instances in another Region is seen as WAN bandwidth.
+    * @param groupName
+    *           Name of the group to modify. The name must be valid and belong to the identity
+    * @param sourceSecurityGroup
+    *           group to associate with this group.
+    * 
+    * @see #createSecurityGroup
+    * @see #describeSecurityGroups
+    * @see #authorizeSecurityGroupIngress
+    * @see #deleteSecurityGroup
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RevokeSecurityGroupIngress.html"
+    * 
+    */
+   @Named("RevokeSecurityGroupIngress")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "RevokeSecurityGroupIngress")
+   void revokeSecurityGroupIngressInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("GroupName") String groupName,
+            @BinderParam(BindUserIdGroupPairToSourceSecurityGroupFormParams.class) UserIdGroupPair sourceSecurityGroup);
+
+   /**
+    * 
+    * Revokes permissions from a security group. The permissions used to revoke must be specified
+    * using the same values used to grant the permissions.
+    * <p/>
+    * Permissions are specified by IP protocol (TCP, UDP, or ICMP), the source of the request (by IP
+    * range or an Amazon EC2 user-group pair), the source and destination port ranges (for TCP and
+    * UDP), and the ICMP codes and types (for ICMP).
+    * 
+    * Permission changes are quickly propagated to instances within the security group. However,
+    * depending on the number of instances in the group, a small delay is might occur.
+    * 
+    * @param region
+    *           Security groups are not copied across Regions. Instances within the Region cannot
+    *           communicate with instances outside the Region using group-based firewall rules.
+    *           Traffic from instances in another Region is seen as WAN bandwidth.
+    * @param groupName
+    *           Name of the group to modify. The name must be valid and belong to the identity
+    * @param ipProtocol
+    *           IP protocol.
+    * @param fromPort
+    *           Start of port range for the TCP and UDP protocols, or an ICMP type number. An ICMP
+    *           type number of -1 indicates a wildcard (i.e., any ICMP type number).
+    * @param toPort
+    *           End of port range for the TCP and UDP protocols, or an ICMP code. An ICMP code of -1
+    *           indicates a wildcard (i.e., any ICMP code).
+    * @param cidrIp
+    *           CIDR range.
+    * 
+    * @see #createSecurityGroup
+    * @see #describeSecurityGroups
+    * @see #authorizeSecurityGroupIngress
+    * @see #deleteSecurityGroup
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-RevokeSecurityGroupIngress.html"
+    * 
+    */
+   @Named("RevokeSecurityGroupIngress")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "RevokeSecurityGroupIngress")
+   void revokeSecurityGroupIngressInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("GroupName") String groupName, @FormParam("IpProtocol") IpProtocol ipProtocol,
+            @FormParam("FromPort") int fromPort, @FormParam("ToPort") int toPort, @FormParam("CidrIp") String cidrIp);
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/features/SubnetApi.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/SubnetApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/SubnetApi.java
index 1d3e338..c9aa1c4 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/features/SubnetApi.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/SubnetApi.java
@@ -16,25 +16,40 @@
  */
 package org.jclouds.ec2.features;
 
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import javax.inject.Named;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams;
 import org.jclouds.ec2.domain.Subnet;
-import org.jclouds.ec2.util.SubnetFilterBuilder;
+import org.jclouds.ec2.xml.DescribeSubnetsResponseHandler;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.SinceApiVersion;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
 
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Multimap;
-
 /**
- * To help you manage your Amazon EC2 instances, images, and other Amazon EC2 resources, you can assign your own
- * metadata to each resource in the form of tags.
+ * Provides access to Amazon EC2 via the Query API
+ * <p/>
  * 
- * @see <a href="http://docs.aws.amazon.com/AmazonVPC/latest/UserGuide/VPC_Subnets.html" >doc</a>
- * @see SubnetAsyncApi
+ * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSubnets.html"
+ *      >doc</a>
  * @author Adrian Cole
  * @author Andrew Bayer
  */
 @SinceApiVersion("2011-01-01")
+@RequestFilters(FormSigner.class)
+@VirtualHost
 public interface SubnetApi {
-
    /**
     * Describes all of your subnets for your EC2 resources.
     * 
@@ -43,6 +58,12 @@ public interface SubnetApi {
     *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSubnets.html"
     *      >docs</href>
     */
+   @Named("DescribeSubnets")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeSubnets")
+   @XMLResponseParser(DescribeSubnetsResponseHandler.class)
+   @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
    FluentIterable<Subnet> list();
 
    /**
@@ -61,6 +82,13 @@ public interface SubnetApi {
     *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSubnets.html"
     *      >docs</href>
     */
-   FluentIterable<Subnet> filter(Multimap<String, String> filter);
+   @Named("DescribeSubnets")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeSubnets")
+   @XMLResponseParser(DescribeSubnetsResponseHandler.class)
+   @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
+   FluentIterable<Subnet> filter(
+         @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/features/SubnetAsyncApi.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/SubnetAsyncApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/SubnetAsyncApi.java
deleted file mode 100644
index 25454a2..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/features/SubnetAsyncApi.java
+++ /dev/null
@@ -1,83 +0,0 @@
-/*
- * 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.features;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import javax.inject.Named;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams;
-import org.jclouds.ec2.domain.Subnet;
-import org.jclouds.ec2.xml.DescribeSubnetsResponseHandler;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SinceApiVersion;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.Multimap;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to Amazon EC2 via the Query API
- * <p/>
- * 
- * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSubnets.html"
- *      >doc</a>
- * @see SubnetApi
- * @author Adrian Cole
- * @author Andrew Bayer
- */
-@SinceApiVersion("2011-01-01")
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface SubnetAsyncApi {
-   /**
-    * @see SubnetApi#list()
-    * @see <a
-    *      href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSubnets.html">docs</a>
-    */
-   @Named("DescribeSubnets")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeSubnets")
-   @XMLResponseParser(DescribeSubnetsResponseHandler.class)
-   @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
-   ListenableFuture<FluentIterable<Subnet>> list();
-
-   /**
-    * @see SubnetApi#filter
-    * @see <a
-    *      href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSubnets.html">docs</a>
-    */
-   @Named("DescribeSubnets")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeSubnets")
-   @XMLResponseParser(DescribeSubnetsResponseHandler.class)
-   @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
-   ListenableFuture<FluentIterable<Subnet>> filter(
-         @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/features/TagApi.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/TagApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/TagApi.java
index 42ac632..cdc6623 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/features/TagApi.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/TagApi.java
@@ -16,28 +16,45 @@
  */
 package org.jclouds.ec2.features;
 
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
 import java.util.Map;
+
+import javax.inject.Named;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams;
+import org.jclouds.ec2.binders.BindResourceIdsToIndexedFormParams;
+import org.jclouds.ec2.binders.BindTagKeysToIndexedFormParams;
+import org.jclouds.ec2.binders.BindTagsToIndexedFormParams;
 import org.jclouds.ec2.domain.Tag;
-import org.jclouds.ec2.util.TagFilterBuilder;
+import org.jclouds.ec2.xml.DescribeTagsResponseHandler;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.SinceApiVersion;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
 
 import com.google.common.collect.FluentIterable;
 import com.google.common.collect.Multimap;
-
 /**
- * To help you manage your Amazon EC2 instances, images, and other Amazon EC2
- * resources, you can assign your own metadata to each resource in the form of
- * tags.
+ * Provides access to Amazon EC2 via the Query API
+ * <p/>
  * 
  * @see <a
- *      href="http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/Using_Tags.html"
+ *      href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeTags.html"
  *      >doc</a>
- * @see TagAsyncApi
  * @author Adrian Cole
  */
 @SinceApiVersion("2010-08-31")
+@RequestFilters(FormSigner.class)
+@VirtualHost
 public interface TagApi {
-
    /**
     * Adds or overwrites one or more tags for the specified resource or
     * resources. Each resource can have a maximum of 10 tags. Each tag consists
@@ -58,7 +75,12 @@ public interface TagApi {
     *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateTags.html"
     *      >docs</href>
     */
-   void applyToResources(Map<String, String> tags, Iterable<String> resourceIds);
+   @Named("CreateTags")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "CreateTags")
+   void applyToResources(@BinderParam(BindTagsToIndexedFormParams.class) Iterable<String> tags,
+         @BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable<String> resourceIds);
 
    /**
     * like {@link #applyToResources(Map, Iterable)} except that the tags have no
@@ -72,7 +94,12 @@ public interface TagApi {
     * 
     * @see #applyToResources(Map, Iterable)
     */
-   void applyToResources(Iterable<String> tags, Iterable<String> resourceIds);
+   @Named("CreateTags")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "CreateTags")
+   void applyToResources(@BinderParam(BindTagsToIndexedFormParams.class) Map<String, String> tags,
+         @BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable<String> resourceIds);
 
    /**
     * Describes all of your tags for your EC2 resources.
@@ -82,6 +109,12 @@ public interface TagApi {
     *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeTags.html"
     *      >docs</href>
     */
+   @Named("DescribeTags")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeTags")
+   @XMLResponseParser(DescribeTagsResponseHandler.class)
+   @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
    FluentIterable<Tag> list();
 
    /**
@@ -100,7 +133,14 @@ public interface TagApi {
     *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeTags.html"
     *      >docs</href>
     */
-   FluentIterable<Tag> filter(Multimap<String, String> filter);
+   @Named("DescribeTags")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeTags")
+   @XMLResponseParser(DescribeTagsResponseHandler.class)
+   @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
+   FluentIterable<Tag> filter(
+         @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
 
    /**
     * Deletes a specific set of tags from a specific set of resources. This call
@@ -124,7 +164,13 @@ public interface TagApi {
     *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteTags.html"
     *      >docs</href>
     */
-   void deleteFromResources(Iterable<String> tags, Iterable<String> resourceIds);
+   @Named("DeleteTags")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DeleteTags")
+   void deleteFromResources(
+         @BinderParam(BindTagKeysToIndexedFormParams.class) Iterable<String> tags,
+         @BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable<String> resourceIds);
 
    /**
     * like {@link #deleteFromResources(Iterable, Iterable)}, except that the
@@ -144,6 +190,12 @@ public interface TagApi {
     *           {@code ami-1a2b3c4d}
     * @see #deleteFromResources(Iterable, Iterable)
     */
-   void conditionallyDeleteFromResources(Map<String, String> conditionalTagValues, Iterable<String> resourceIds);
+   @Named("DeleteTags")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DeleteTags")
+   void conditionallyDeleteFromResources(
+         @BinderParam(BindTagsToIndexedFormParams.class) Map<String, String> conditionalTagValues,
+         @BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable<String> resourceIds);
 
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/features/TagAsyncApi.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/TagAsyncApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/TagAsyncApi.java
deleted file mode 100644
index 013df70..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/features/TagAsyncApi.java
+++ /dev/null
@@ -1,138 +0,0 @@
-/*
- * 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.features;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import java.util.Map;
-
-import javax.inject.Named;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.Fallbacks.EmptyFluentIterableOnNotFoundOr404;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams;
-import org.jclouds.ec2.binders.BindResourceIdsToIndexedFormParams;
-import org.jclouds.ec2.binders.BindTagKeysToIndexedFormParams;
-import org.jclouds.ec2.binders.BindTagsToIndexedFormParams;
-import org.jclouds.ec2.domain.Tag;
-import org.jclouds.ec2.xml.DescribeTagsResponseHandler;
-import org.jclouds.rest.annotations.BinderParam;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SinceApiVersion;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.Multimap;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to Amazon EC2 via the Query API
- * <p/>
- * 
- * @see <a
- *      href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeTags.html"
- *      >doc</a>
- * @see TagApi
- * @author Adrian Cole
- */
-@SinceApiVersion("2010-08-31")
-@RequestFilters(FormSigner.class)
-@VirtualHost
-public interface TagAsyncApi {
-   /**
-    * @see TagApi#applyToResources(Iterable, Iterable)
-    * @see <a
-    *      href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateTags.html">docs</a>
-    */
-   @Named("CreateTags")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "CreateTags")
-   ListenableFuture<Void> applyToResources(@BinderParam(BindTagsToIndexedFormParams.class) Iterable<String> tags,
-         @BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable<String> resourceIds);
-
-   /**
-    * @see TagApi#applyToResources(Map, Iterable)
-    * @see <a
-    *      href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CreateTags.html">docs</a>
-    */
-   @Named("CreateTags")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "CreateTags")
-   ListenableFuture<Void> applyToResources(@BinderParam(BindTagsToIndexedFormParams.class) Map<String, String> tags,
-         @BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable<String> resourceIds);
-
-   /**
-    * @see TagApi#list()
-    * @see <a
-    *      href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeTags.html">docs</a>
-    */
-   @Named("DescribeTags")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeTags")
-   @XMLResponseParser(DescribeTagsResponseHandler.class)
-   @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
-   ListenableFuture<FluentIterable<Tag>> list();
-
-   /**
-    * @see TagApi#filter
-    * @see <a
-    *      href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeTags.html">docs</a>
-    */
-   @Named("DescribeTags")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DescribeTags")
-   @XMLResponseParser(DescribeTagsResponseHandler.class)
-   @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
-   ListenableFuture<FluentIterable<Tag>> filter(
-         @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
-
-   /**
-    * @see TagApi#deleteFromResources
-    * @see <a
-    *      href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteTags.html">docs</a>
-    */
-   @Named("DeleteTags")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DeleteTags")
-   ListenableFuture<Void> deleteFromResources(
-         @BinderParam(BindTagKeysToIndexedFormParams.class) Iterable<String> tags,
-         @BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable<String> resourceIds);
-
-   /**
-    * @see TagApi#conditionallyDeleteFromResources
-    * @see <a
-    *      href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteTags.html">docs</a>
-    */
-   @Named("DeleteTags")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "DeleteTags")
-   ListenableFuture<Void> conditionallyDeleteFromResources(
-         @BinderParam(BindTagsToIndexedFormParams.class) Map<String, String> conditionalTagValues,
-         @BinderParam(BindResourceIdsToIndexedFormParams.class) Iterable<String> resourceIds);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/features/WindowsApi.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/WindowsApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/WindowsApi.java
index c74fc20..b895d0b 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/features/WindowsApi.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/WindowsApi.java
@@ -16,24 +16,166 @@
  */
 package org.jclouds.ec2.features;
 
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.Fallbacks.NullOnNotFoundOr404;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindBundleIdsToIndexedFormParams;
+import org.jclouds.ec2.binders.BindS3UploadPolicyAndSignature;
+import org.jclouds.ec2.domain.BundleTask;
 import org.jclouds.ec2.domain.PasswordData;
+import org.jclouds.ec2.options.BundleInstanceS3StorageOptions;
+import org.jclouds.ec2.xml.BundleTaskHandler;
+import org.jclouds.ec2.xml.DescribeBundleTasksResponseHandler;
+import org.jclouds.ec2.xml.GetPasswordDataResponseHandler;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.SinceApiVersion;
-
-import com.google.common.annotations.Beta;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
 
 /**
  * Provides access to EC2 Windows Features via the Query API
  * <p/>
  * 
  * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference" >doc</a>
- * @see WindowsAsyncApi
  * @author Adrian Cole
  */
-@Beta
+@RequestFilters(FormSigner.class)
+@VirtualHost
 @SinceApiVersion("2008-08-08")
 public interface WindowsApi {
 
    /**
+    * Bundles the Windows instance. This procedure is not applicable for Linux
+    * and UNIX instances. For more information, go to the Amazon Elastic Compute
+    * Cloud Developer Guide or Amazon Elastic Compute Cloud Getting Started
+    * Guide.
+    * 
+    * @param region
+    *           Bundles are tied to the Region where its files are located
+    *           within Amazon S3.
+    * 
+    * @param instanceId
+    *           The ID of the instance to bundle.
+    * @param prefix
+    *           Specifies the beginning of the file name of the AMI.
+    * @param bucket
+    *           The bucket in which to store the AMI. You can specify a bucket
+    *           that you already own or a new bucket that Amazon EC2 creates on
+    *           your behalf. If you specify a bucket that belongs to someone
+    *           else, Amazon EC2 returns an error.
+    * @param uploadPolicy
+    *           An Amazon S3 upload policy that gives Amazon EC2 permission to
+    *           upload items into Amazon S3 on the user's behalf.
+    *           <p/>
+    *           ex.
+    * 
+    *           <pre>
+    * {"expiration": "2008-08-30T08:49:09Z","conditions": ["bucket": "my-bucket"},["starts-with", "$key", "my-new-image"]]}
+    * </pre>
+    * 
+    * @param options
+    *           if the bucket isn't owned by you, use this to set the bucket's
+    *           accesskeyid
+    * @return status of the work
+    * 
+    * @see #cancelBundleTaskInRegion
+    * @see #describeBundleTasksInRegion
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-BundleInstance.html"
+    *      />
+    */
+   @Named("BundleInstance")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "BundleInstance")
+   @XMLResponseParser(BundleTaskHandler.class)
+   BundleTask bundleInstanceInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("InstanceId") String instanceId, @FormParam("Storage.S3.Prefix") String prefix,
+            @FormParam("Storage.S3.Bucket") String bucket,
+            @BinderParam(BindS3UploadPolicyAndSignature.class) String uploadPolicy,
+            BundleInstanceS3StorageOptions... options);
+
+   /**
+    * Cancels an Amazon EC2 bundling operation.
+    * 
+    * @param region
+    *           The bundleTask ID is tied to the Region.
+    * @param bundleId
+    *           The ID of the bundle task to cancel.
+    * @return task for the cancel.
+    * 
+    * @see #bundleInstanceInRegion
+    * @see #describeBundleTasksInRegion
+    * 
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-CancelBundleTask.html"
+    *      />
+    */
+   @Named("CancelBundleTask")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "CancelBundleTask")
+   @XMLResponseParser(BundleTaskHandler.class)
+   BundleTask cancelBundleTaskInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("BundleId") String bundleId);
+
+   /**
+    * 
+    * Describes current bundling tasks.
+    * 
+    * @param region
+    *           The bundleTask ID is tied to the Region.
+    * 
+    * @see #cancelBundleTaskInRegion
+    * @see #bundleInstanceInRegion
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeBundleTasks.html"
+    *      />
+    */
+   @Named("DescribeBundleTasks")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeBundleTasks")
+   @XMLResponseParser(DescribeBundleTasksResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<BundleTask> describeBundleTasksInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @BinderParam(BindBundleIdsToIndexedFormParams.class) String... bundleTaskIds);
+
+   /**
+    *
+    * Retrieves the encrypted administrator password for the instances running Windows.
+    *
+    * @param region The region where the instance is based
+    * @param instanceId The ID of the instance to query
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-GetPasswordData.html" />
+    */
+   @Named("GetPasswordData")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "GetPasswordData")
+   @XMLResponseParser(GetPasswordDataResponseHandler.class)
+   PasswordData getPasswordDataInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("InstanceId") String instanceId);
+
+
+   /**
     * 
     * Retrieves the encrypted administrator password for the instances running Windows. <h4>Note</h4>
     * 
@@ -49,5 +191,12 @@ public interface WindowsApi {
     *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-GetPasswordData.html"
     *      />
     */
-   PasswordData getPasswordDataForInstance(String instanceId);
+   @Named("GetPasswordData")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "GetPasswordData")
+   @XMLResponseParser(GetPasswordDataResponseHandler.class)
+   @Fallback(NullOnNotFoundOr404.class)
+   PasswordData getPasswordDataForInstance(@FormParam("InstanceId") String instanceId);
+
 }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/features/WindowsAsyncApi.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/features/WindowsAsyncApi.java b/apis/ec2/src/main/java/org/jclouds/ec2/features/WindowsAsyncApi.java
deleted file mode 100644
index 3f8f02d..0000000
--- a/apis/ec2/src/main/java/org/jclouds/ec2/features/WindowsAsyncApi.java
+++ /dev/null
@@ -1,65 +0,0 @@
-/*
- * 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.features;
-
-import static org.jclouds.aws.reference.FormParameters.ACTION;
-
-import javax.inject.Named;
-import javax.ws.rs.FormParam;
-import javax.ws.rs.POST;
-import javax.ws.rs.Path;
-
-import org.jclouds.Fallbacks.NullOnNotFoundOr404;
-import org.jclouds.aws.filters.FormSigner;
-import org.jclouds.ec2.domain.PasswordData;
-import org.jclouds.ec2.xml.GetPasswordDataResponseHandler;
-import org.jclouds.rest.annotations.Fallback;
-import org.jclouds.rest.annotations.FormParams;
-import org.jclouds.rest.annotations.RequestFilters;
-import org.jclouds.rest.annotations.SinceApiVersion;
-import org.jclouds.rest.annotations.VirtualHost;
-import org.jclouds.rest.annotations.XMLResponseParser;
-
-import com.google.common.annotations.Beta;
-import com.google.common.util.concurrent.ListenableFuture;
-
-/**
- * Provides access to EC2 Windows Features via the Query API
- * <p/>
- * 
- * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference" >doc</a>
- * @see WindowsAsyncApi
- * @author Adrian Cole
- */
-@RequestFilters(FormSigner.class)
-@VirtualHost
-@Beta
-@SinceApiVersion("2008-08-08")
-public interface WindowsAsyncApi {
-
-   /**
-    * @see WindowsApi#getPasswordDataForInstance
-    */
-   @Named("GetPasswordData")
-   @POST
-   @Path("/")
-   @FormParams(keys = ACTION, values = "GetPasswordData")
-   @XMLResponseParser(GetPasswordDataResponseHandler.class)
-   @Fallback(NullOnNotFoundOr404.class)
-   ListenableFuture<PasswordData> getPasswordDataForInstance(@FormParam("InstanceId") String instanceId);
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/options/BundleInstanceS3StorageOptions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/options/BundleInstanceS3StorageOptions.java b/apis/ec2/src/main/java/org/jclouds/ec2/options/BundleInstanceS3StorageOptions.java
index 91e6618..ec655ae 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/options/BundleInstanceS3StorageOptions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/options/BundleInstanceS3StorageOptions.java
@@ -39,7 +39,7 @@ import com.google.inject.Inject;
  * <code>
  * import static org.jclouds.ec2.options.BundleInstanceS3StorageOptions.Builder.*
  * <p/>
- * EC2Client connection = // get connection
+ * EC2Api connection = // get connection
  * String imageId = connection.getWindowsServices().bundleInstanceInRegion(...bucketOwnedBy(anotherAccessKey));
  * <code>
  * 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/options/CreateImageOptions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/options/CreateImageOptions.java b/apis/ec2/src/main/java/org/jclouds/ec2/options/CreateImageOptions.java
index e6665cc..8c604d5 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/options/CreateImageOptions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/options/CreateImageOptions.java
@@ -29,8 +29,8 @@ import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
  * <code>
  * import static org.jclouds.ec2.options.CreateImageOptions.Builder.*
  * <p/>
- * EC2Client connection = // get connection
- * Future<Set<ImageMetadata>> images = connection.getAMIServices().createImage(withDescription("123125").noReboot());
+ * EC2Api connection = // get connection
+ * Future<Set<ImageMetadata>> images = connection.getAMIApi().get().createImage(withDescription("123125").noReboot());
  * <code>
  * 
  * @author Adrian Cole

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/ec2/src/main/java/org/jclouds/ec2/options/CreateSnapshotOptions.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/options/CreateSnapshotOptions.java b/apis/ec2/src/main/java/org/jclouds/ec2/options/CreateSnapshotOptions.java
index 83dcd19..2c05a27 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/options/CreateSnapshotOptions.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/options/CreateSnapshotOptions.java
@@ -29,8 +29,8 @@ import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
  * <code>
  * import static org.jclouds.ec2.options.CreateSnapshotOptions.Builder.*
  * <p/>
- * EC2Client connection = // get connection
- * Snapshot snapshot = connection.getElasticBlockStoreServices().createSnapshotInRegion(volumeId, withDescription("123125"));
+ * EC2Api connection = // get connection
+ * Snapshot snapshot = connection.getElasticBlockStoreApi().get().createSnapshotInRegion(volumeId, withDescription("123125"));
  * <code>
  * 
  * @author Adrian Cole


[07/20] JCLOUDS-150 - Removal of async from AWS - specifically EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2ElasticBlockStoreExpectClientTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2ElasticBlockStoreExpectClientTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2ElasticBlockStoreExpectClientTest.java
deleted file mode 100644
index e4a83a2..0000000
--- a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2ElasticBlockStoreExpectClientTest.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/*
- * 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.openstack.nova.ec2.services;
-
-import static org.testng.Assert.assertEquals;
-
-import java.util.Set;
-
-import org.jclouds.ec2.domain.Attachment;
-import org.jclouds.ec2.domain.Volume;
-import org.jclouds.ec2.services.ElasticBlockStoreClient;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.openstack.nova.ec2.internal.BaseNovaEC2RestClientExpectTest;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableSet;
-
-/**
- * @author Adam Lowe
- */
-@Test(groups = "unit", testName = "NovaEC2ElasticBlockStoreClientTest")
-public class NovaEC2ElasticBlockStoreExpectClientTest extends BaseNovaEC2RestClientExpectTest {
-
-   public void testDescribeVolumesWithNovaEC2Status() {
-      ElasticBlockStoreClient client = requestsSendResponses(
-            describeAvailabilityZonesRequest,
-            describeAvailabilityZonesResponse,
-            HttpRequest.builder().method("POST")
-                  .endpoint("http://localhost:8773/services/Cloud/")
-                  .addHeader("Host", "localhost:8773")
-                  .payload(payloadFromStringWithContentType("Action=DescribeVolumes&Signature=AvRznSzGExM%2Buaj2JJj66wq4v4f%2BakicyLooRDtC0t0%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
-            HttpResponse.builder().statusCode(200).payload(payloadFromResource("/nova_ec2_describe_volumes.xml")).build()
-      ).getElasticBlockStoreServices();
-
-      Set<Volume> expected = ImmutableSet.of(Volume
-            .builder()
-            .status(Volume.Status.AVAILABLE)
-            .availabilityZone("nova")
-            .region("nova")
-            .id("vol-00000007")
-            .size(1)
-            .attachments(Attachment.builder().region("nova").build())
-            .createTime(dateService.iso8601SecondsDateParse("2012-04-10T10:39:52Z"))
-            .build());
-
-      assertEquals(client.describeVolumesInRegion("nova"), expected);
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2ElasticIPAddressClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2ElasticIPAddressClientLiveTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2ElasticIPAddressClientLiveTest.java
deleted file mode 100644
index fcf8c1b..0000000
--- a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2ElasticIPAddressClientLiveTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.openstack.nova.ec2.services;
-
-import org.jclouds.ec2.services.ElasticIPAddressClientLiveTest;
-import org.testng.annotations.Test;
-
-/**
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true, testName = "NovaEC2ElasticIPAddressClientLiveTest")
-public class NovaEC2ElasticIPAddressClientLiveTest extends ElasticIPAddressClientLiveTest {
-   public NovaEC2ElasticIPAddressClientLiveTest() {
-      provider = "openstack-nova-ec2";
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2InstanceClientExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2InstanceClientExpectTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2InstanceClientExpectTest.java
deleted file mode 100644
index 3c412f3..0000000
--- a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2InstanceClientExpectTest.java
+++ /dev/null
@@ -1,67 +0,0 @@
-/*
- * 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.openstack.nova.ec2.services;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertFalse;
-import static org.testng.Assert.assertNull;
-
-import java.util.Set;
-
-import org.jclouds.ec2.domain.BlockDevice;
-import org.jclouds.ec2.domain.Reservation;
-import org.jclouds.ec2.domain.RunningInstance;
-import org.jclouds.ec2.services.InstanceClient;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.openstack.nova.ec2.internal.BaseNovaEC2RestClientExpectTest;
-
-import com.google.common.collect.Iterables;
-
-/**
- * @author Adam Lowe
- */
-public class NovaEC2InstanceClientExpectTest extends BaseNovaEC2RestClientExpectTest {
-
-   public void testDescribeInstancesWithDashesInPlaceOfNullDates() {
-      InstanceClient client = requestsSendResponses(
-            describeAvailabilityZonesRequest,
-            describeAvailabilityZonesResponse,
-            HttpRequest.builder().method("POST")
-                  .endpoint("http://localhost:8773/services/Cloud/")
-                  .addHeader("Host", "localhost:8773")
-                  .payload(payloadFromStringWithContentType("Action=DescribeInstances&Signature=kkCE1HzyntmkICEidOizw50B9yjLdNZvAWUXVse1c8o%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
-            HttpResponse.builder().statusCode(200).payload(payloadFromResource("/nova_ec2_describe_instances.xml")).build()
-      ).getInstanceServices();
-
-      Set<? extends Reservation<? extends RunningInstance>> response = client.describeInstancesInRegion("nova");
-      
-      assertEquals(response.size(), 3);
-
-      Reservation<? extends RunningInstance> target = Iterables.get(response, 2);
-      RunningInstance runningInstance = Iterables.getOnlyElement(target);
-      BlockDevice bd = Iterables.getOnlyElement(runningInstance.getEbsBlockDevices().values());
-      
-      // this is a '-' in the nova_ec2_describe_instances.xml
-      assertNull(bd.getAttachTime());
-
-      // double-check the other fields
-      assertFalse(bd.isDeleteOnTermination());
-      assertEquals(bd.getVolumeId(), "1");
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2InstanceClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2InstanceClientLiveTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2InstanceClientLiveTest.java
deleted file mode 100644
index 4244688..0000000
--- a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2InstanceClientLiveTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.openstack.nova.ec2.services;
-
-import org.jclouds.ec2.services.InstanceClientLiveTest;
-import org.testng.annotations.Test;
-
-/**
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true, testName = "NovaEC2InstanceClientLiveTest")
-public class NovaEC2InstanceClientLiveTest extends InstanceClientLiveTest {
-   public NovaEC2InstanceClientLiveTest() {
-      provider = "openstack-nova-ec2";
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairClientExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairClientExpectTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairClientExpectTest.java
deleted file mode 100644
index 9c3903d..0000000
--- a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairClientExpectTest.java
+++ /dev/null
@@ -1,78 +0,0 @@
-/*
- * 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.openstack.nova.ec2.services;
-
-import static org.testng.Assert.assertEquals;
-
-import org.jclouds.ec2.domain.KeyPair;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.openstack.nova.ec2.internal.BaseNovaEC2RestClientExpectTest;
-import org.jclouds.rest.ResourceNotFoundException;
-import org.testng.annotations.Test;
-
-/**
- * @author Adam Lowe
- */
-public class NovaEC2KeyPairClientExpectTest extends BaseNovaEC2RestClientExpectTest {
-
-   public void testImportKeyPair() {
-      NovaEC2KeyPairClient client = requestsSendResponses(
-            describeAvailabilityZonesRequest,
-            describeAvailabilityZonesResponse,
-            HttpRequest.builder().method("POST")
-                  .endpoint("http://localhost:8773/services/Cloud/")
-                  .addHeader("Host", "localhost:8773")
-                  .payload(payloadFromStringWithContentType("Action=ImportKeyPair&KeyName=mykey&PublicKeyMaterial=c3NoLXJzYSBBQQ%3D%3D&Signature=wOOKOlDfJezRkx7NKcyOyaBQuY7PoVE3HFa9495RL7s%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
-            HttpResponse.builder().statusCode(200).payload(payloadFromResource("/nova_ec2_import_keypair_response.xml")).build()
-      ).getKeyPairServices();
-
-      KeyPair result = client.importKeyPairInRegion(null, "mykey", "ssh-rsa AA");
-      assertEquals(result.getKeyName(), "aplowe-nova-ec22");
-      assertEquals(result.getSha1OfPrivateKey(), "e3:fd:de:f6:4c:36:7d:9b:8f:2f:4c:20:f8:ae:b0:ea");
-   }
-
-   @Test(expectedExceptions = ResourceNotFoundException.class)
-   public void testImportKeyPairFailsNotFound() {
-      NovaEC2KeyPairClient client = requestsSendResponses(
-            describeAvailabilityZonesRequest,
-            describeAvailabilityZonesResponse,
-            HttpRequest.builder().method("POST")
-                  .endpoint("http://localhost:8773/services/Cloud/")
-                  .addHeader("Host", "localhost:8773")
-                  .payload(payloadFromStringWithContentType("Action=ImportKeyPair&KeyName=mykey&PublicKeyMaterial=c3NoLXJzYSBBQQ%3D%3D&Signature=wOOKOlDfJezRkx7NKcyOyaBQuY7PoVE3HFa9495RL7s%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
-            HttpResponse.builder().statusCode(404).build()
-      ).getKeyPairServices();
-
-      client.importKeyPairInRegion(null, "mykey", "ssh-rsa AA");
-   }
-
-   @Test(expectedExceptions = IllegalStateException.class)
-   public void testImportKeyPairFailsAlreadyExists() {
-      NovaEC2KeyPairClient client = requestsSendResponses(
-            describeAvailabilityZonesRequest,
-            describeAvailabilityZonesResponse,
-            HttpRequest.builder().method("POST")
-                  .endpoint("http://localhost:8773/services/Cloud/")
-                  .addHeader("Host", "localhost:8773")
-                  .payload(payloadFromStringWithContentType("Action=ImportKeyPair&KeyName=mykey&PublicKeyMaterial=c3NoLXJzYSBBQQ%3D%3D&Signature=wOOKOlDfJezRkx7NKcyOyaBQuY7PoVE3HFa9495RL7s%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2009-04-04&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
-            HttpResponse.builder().statusCode(409).build()
-      ).getKeyPairServices();
-
-      client.importKeyPairInRegion(null, "mykey", "ssh-rsa AA");
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairClientLiveTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairClientLiveTest.java
deleted file mode 100644
index 85aa0c5..0000000
--- a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2KeyPairClientLiveTest.java
+++ /dev/null
@@ -1,134 +0,0 @@
-/*
- * 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.openstack.nova.ec2.services;
-
-import static com.google.common.collect.Sets.newTreeSet;
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.fail;
-
-import java.io.IOException;
-import java.util.Map;
-import java.util.Set;
-import java.util.SortedSet;
-
-import org.jclouds.compute.ComputeTestUtils;
-import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
-import org.jclouds.ec2.domain.KeyPair;
-import org.jclouds.openstack.nova.ec2.NovaEC2ApiMetadata;
-import org.jclouds.ssh.SshKeys;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-/**
- * Tests behavior of {@code NovaKeyPairClient}
- * 
- * @author Adam Lowe
- */
-@Test(groups = "live", singleThreaded = true)
-public class NovaEC2KeyPairClientLiveTest extends BaseComputeServiceContextLiveTest {
-
-   public static final String PREFIX = System.getProperty("user.name") + "-nova-ec2";
-
-   public NovaEC2KeyPairClientLiveTest() {
-      provider = "openstack-nova-ec2";
-   }
-
-   private NovaEC2KeyPairClient client;
-   private Set<String> regions;
-   
-   @Override
-   @BeforeClass(groups = { "integration", "live" })
-   public void setupContext() {
-      super.setupContext();
-      client = view.unwrap(NovaEC2ApiMetadata.CONTEXT_TOKEN).getApi().getKeyPairServices();
-      regions = view.unwrap(NovaEC2ApiMetadata.CONTEXT_TOKEN).getApi().getAvailabilityZoneAndRegionServices().describeRegions().keySet();
-   }
-
-   @Test
-   void testDescribeKeyPairs() {
-      for (String region : regions) {
-         SortedSet<KeyPair> allResults = newTreeSet(client.describeKeyPairsInRegion(region));
-         assertNotNull(allResults);
-         if (allResults.size() >= 1) {
-            KeyPair pair = allResults.last();
-            SortedSet<KeyPair> result = newTreeSet(client.describeKeyPairsInRegion(region, pair.getKeyName()));
-            assertNotNull(result);
-            KeyPair compare = result.last();
-            assertEquals(compare, pair);
-         }
-      }
-   }
-
-   @Test
-   void testCreateKeyPair() {
-      String keyName = PREFIX + "1";
-      cleanupKeyPair(keyName);
-      try {
-         KeyPair keyPair = client.createKeyPairInRegion(null, keyName);
-         checkKeyPair(keyName, keyPair);
-         assertNotNull(keyPair.getKeyMaterial());
-      } finally {
-         cleanupKeyPair(keyName);
-      }
-   }
-
-   protected void cleanupKeyPair(String keyName) {
-      try {
-         client.deleteKeyPairInRegion(null, keyName);
-      } catch (Exception e) {
-
-      }
-      client.deleteKeyPairInRegion(null, keyName);
-   }
-
-   @Test
-   void testImportKeyPair() throws IOException {
-      String keyName = PREFIX + "2";
-      cleanupKeyPair(keyName);
-      Map<String, String> myKey = ComputeTestUtils.setupKeyPair();
-      try {
-         KeyPair keyPair = client.importKeyPairInRegion(null, keyName, myKey.get("public"));
-         checkKeyPair(keyName, keyPair);
-
-         // check the fingerprint of public key (in the sha10OfPrivateKey field)
-         assertEquals(keyPair.getSha1OfPrivateKey(), SshKeys.fingerprintPublicKey(myKey.get("public")));
-
-         // try again to see if there's an error
-         try {
-            client.importKeyPairInRegion(null, keyName, myKey.get("public"));
-            fail("Duplicate call importKeyPairInRegion should have failed!");
-         } catch (IllegalStateException e) {
-         }
-      } finally {
-         cleanupKeyPair(keyName);
-      }
-   }
-
-   protected void checkKeyPair(String keyName, KeyPair keyPair) {
-      assertNotNull(keyPair);
-      assertNotNull(keyPair.getSha1OfPrivateKey());
-      assertEquals(keyPair.getKeyName(), keyName);
-
-      Set<KeyPair> twoResults = client.describeKeyPairsInRegion(null, keyName);
-      assertNotNull(twoResults);
-      assertEquals(twoResults.size(), 1);
-      KeyPair listPair = twoResults.iterator().next();
-      assertEquals(listPair.getKeyName(), keyPair.getKeyName());
-      assertEquals(listPair.getSha1OfPrivateKey(), keyPair.getSha1OfPrivateKey());
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2SecurityGroupClientLiveTest.java
----------------------------------------------------------------------
diff --git a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2SecurityGroupClientLiveTest.java b/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2SecurityGroupClientLiveTest.java
deleted file mode 100644
index 4c3dced..0000000
--- a/apis/openstack-nova-ec2/src/test/java/org/jclouds/openstack/nova/ec2/services/NovaEC2SecurityGroupClientLiveTest.java
+++ /dev/null
@@ -1,32 +0,0 @@
-/*
- * 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.openstack.nova.ec2.services;
-
-import org.jclouds.ec2.services.SecurityGroupClientLiveTest;
-import org.testng.annotations.Test;
-
-/**
- * 
- * @author Adrian Cole
- */
-@Test(groups = "live", singleThreaded = true, testName = "NovaEC2SecurityGroupClientLiveTest")
-public class NovaEC2SecurityGroupClientLiveTest extends SecurityGroupClientLiveTest {
-   public NovaEC2SecurityGroupClientLiveTest() {
-      provider = "openstack-nova-ec2";
-   }
-
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2Api.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2Api.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2Api.java
new file mode 100644
index 0000000..ad6e536
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2Api.java
@@ -0,0 +1,120 @@
+/*
+ * 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.aws.ec2;
+
+import org.jclouds.aws.ec2.features.AWSAMIApi;
+import org.jclouds.aws.ec2.features.AWSInstanceApi;
+import org.jclouds.aws.ec2.features.AWSKeyPairApi;
+import org.jclouds.aws.ec2.features.AWSSecurityGroupApi;
+import org.jclouds.aws.ec2.features.MonitoringApi;
+import org.jclouds.aws.ec2.features.PlacementGroupApi;
+import org.jclouds.aws.ec2.features.SpotInstanceApi;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.Region;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.Delegate;
+import org.jclouds.rest.annotations.EndpointParam;
+
+import com.google.common.base.Optional;
+
+/**
+ * Provides synchronous access to EC2 services.
+ * 
+ * @author Adrian Cole
+ */
+public interface AWSEC2Api extends EC2Api {
+
+   /**
+    * {@inheritDoc}
+    */
+   @Delegate
+   @Override
+   Optional<? extends AWSInstanceApi> getInstanceApi();
+
+   @Delegate
+   @Override
+   Optional<? extends AWSInstanceApi> getInstanceApiForRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+
+   /**
+    * {@inheritDoc}
+    */
+   @Delegate
+   @Override
+   Optional<? extends AWSSecurityGroupApi> getSecurityGroupApi();
+
+   @Delegate
+   @Override
+   Optional<? extends AWSSecurityGroupApi> getSecurityGroupApiForRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+   
+   /**
+    * {@inheritDoc}
+    */
+   @Delegate
+   @Override
+   Optional<? extends AWSAMIApi> getAMIApi();
+
+   @Delegate
+   @Override
+   Optional<? extends AWSAMIApi> getAMIApiForRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+
+
+   /**
+    * Provides synchronous access to PlacementGroup services.
+    */
+   @Delegate
+   Optional<? extends PlacementGroupApi> getPlacementGroupApi();
+   
+   @Delegate
+   Optional<? extends PlacementGroupApi> getPlacementGroupApiForRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+
+   /**
+    * Provides synchronous access to Monitoring services.
+    */
+   @Delegate
+   Optional<? extends MonitoringApi> getMonitoringApi();
+   
+   @Delegate
+   Optional<? extends MonitoringApi> getMonitoringApiForRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+
+   /**
+    * {@inheritDoc}
+    */
+   @Delegate
+   @Override
+   Optional<? extends AWSKeyPairApi> getKeyPairApi();
+   
+   @Delegate
+   @Override
+   Optional<? extends AWSKeyPairApi> getKeyPairApiForRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+   
+   /**
+    * Provides synchronous access to SpotInstance services.
+    */
+   @Delegate
+   Optional<? extends SpotInstanceApi> getSpotInstanceApi();
+   
+   @Delegate
+   Optional<? extends SpotInstanceApi> getSpotInstanceApiForRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2ApiMetadata.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2ApiMetadata.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2ApiMetadata.java
index 4427fdd..1724331 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2ApiMetadata.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2ApiMetadata.java
@@ -23,7 +23,7 @@ import java.util.Properties;
 import org.jclouds.apis.ApiMetadata;
 import org.jclouds.aws.ec2.compute.AWSEC2ComputeServiceContext;
 import org.jclouds.aws.ec2.compute.config.AWSEC2ComputeServiceContextModule;
-import org.jclouds.aws.ec2.config.AWSEC2RestClientModule;
+import org.jclouds.aws.ec2.config.AWSEC2HttpApiModule;
 import org.jclouds.ec2.EC2ApiMetadata;
 import org.jclouds.ec2.compute.config.EC2ResolveImagesModule;
 
@@ -38,15 +38,6 @@ import com.google.inject.Module;
  */
 public class AWSEC2ApiMetadata extends EC2ApiMetadata {
 
-   /**
-    * @deprecated please use {@code org.jclouds.ContextBuilder#buildApi(AWSEC2Client.class)} as
-    *             {@link AWSEC2AsyncClient} interface will be removed in jclouds 1.7.
-    */
-   @Deprecated
-   public static final TypeToken<org.jclouds.rest.RestContext<AWSEC2Client, AWSEC2AsyncClient>> CONTEXT_TOKEN = new TypeToken<org.jclouds.rest.RestContext<AWSEC2Client, AWSEC2AsyncClient>>() {
-      private static final long serialVersionUID = 1L;
-   };
-
    @Override
    public Builder toBuilder() {
       return new Builder().fromApiMetadata(this);
@@ -73,14 +64,12 @@ public class AWSEC2ApiMetadata extends EC2ApiMetadata {
    public static class Builder extends EC2ApiMetadata.Builder<Builder> {
       @SuppressWarnings("deprecation")
       protected Builder(){
-         super(AWSEC2Client.class, AWSEC2AsyncClient.class);
          id("aws-ec2")
          .version("2012-06-01")
          .name("Amazon-specific EC2 API")
          .view(AWSEC2ComputeServiceContext.class)
-         .context(CONTEXT_TOKEN)
          .defaultProperties(AWSEC2ApiMetadata.defaultProperties())
-         .defaultModules(ImmutableSet.<Class<? extends Module>>of(AWSEC2RestClientModule.class, EC2ResolveImagesModule.class, AWSEC2ComputeServiceContextModule.class));
+         .defaultModules(ImmutableSet.<Class<? extends Module>>of(AWSEC2HttpApiModule.class, EC2ResolveImagesModule.class, AWSEC2ComputeServiceContextModule.class));
       }
       
       @Override

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2AsyncClient.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2AsyncClient.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2AsyncClient.java
deleted file mode 100644
index 2d638b0..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2AsyncClient.java
+++ /dev/null
@@ -1,86 +0,0 @@
-/*
- * 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.aws.ec2;
-
-import org.jclouds.aws.ec2.services.AWSAMIAsyncClient;
-import org.jclouds.aws.ec2.services.AWSInstanceAsyncClient;
-import org.jclouds.aws.ec2.services.AWSKeyPairAsyncClient;
-import org.jclouds.aws.ec2.services.AWSSecurityGroupAsyncClient;
-import org.jclouds.aws.ec2.services.MonitoringAsyncClient;
-import org.jclouds.aws.ec2.services.PlacementGroupAsyncClient;
-import org.jclouds.aws.ec2.services.SpotInstanceAsyncClient;
-import org.jclouds.ec2.EC2AsyncClient;
-import org.jclouds.rest.annotations.Delegate;
-
-/**
- * Provides asynchronous access to EC2 services.
- * 
- * @author Adrian Cole
- * 
- * @deprecated please use
- *             {@code org.jclouds.ContextBuilder#buildApi(AWSEC2Client.class)}
- *             as {@link AWSEC2AsyncClient} interface will be removed in jclouds 1.7.
- */
-@Deprecated
-public interface AWSEC2AsyncClient extends EC2AsyncClient {
-
-   /**
-    * {@inheritDoc}
-    */
-   @Delegate
-   @Override
-   AWSInstanceAsyncClient getInstanceServices();
-
-   /**
-    * {@inheritDoc}
-    */
-   @Delegate
-   @Override
-   AWSAMIAsyncClient getAMIServices();
-
-   /**
-    * {@inheritDoc}
-    */
-   @Delegate
-   @Override
-   AWSSecurityGroupAsyncClient getSecurityGroupServices();
-
-   /**
-    * Provides asynchronous access to PlacementGroup services.
-    */
-   @Delegate
-   PlacementGroupAsyncClient getPlacementGroupServices();
-
-   /**
-    * Provides asynchronous access to Monitoring services.
-    */
-   @Delegate
-   MonitoringAsyncClient getMonitoringServices();
-
-   /**
-    * {@inheritDoc}
-    */
-   @Delegate
-   @Override
-   AWSKeyPairAsyncClient getKeyPairServices();
-
-   /**
-    * Provides asynchronous access to SpotInstance services.
-    */
-   @Delegate
-   SpotInstanceAsyncClient getSpotInstanceServices();
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2Client.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2Client.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2Client.java
deleted file mode 100644
index a605e3c..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2Client.java
+++ /dev/null
@@ -1,81 +0,0 @@
-/*
- * 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.aws.ec2;
-
-import org.jclouds.aws.ec2.services.AWSAMIClient;
-import org.jclouds.aws.ec2.services.AWSInstanceClient;
-import org.jclouds.aws.ec2.services.AWSKeyPairClient;
-import org.jclouds.aws.ec2.services.AWSSecurityGroupClient;
-import org.jclouds.aws.ec2.services.MonitoringClient;
-import org.jclouds.aws.ec2.services.PlacementGroupClient;
-import org.jclouds.aws.ec2.services.SpotInstanceClient;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.rest.annotations.Delegate;
-
-/**
- * Provides synchronous access to EC2 services.
- * 
- * @author Adrian Cole
- */
-public interface AWSEC2Client extends EC2Client {
-
-   /**
-    * {@inheritDoc}
-    */
-   @Delegate
-   @Override
-   AWSInstanceClient getInstanceServices();
-
-   /**
-    * {@inheritDoc}
-    */
-   @Delegate
-   @Override
-   AWSSecurityGroupClient getSecurityGroupServices();
-   
-   /**
-    * {@inheritDoc}
-    */
-   @Delegate
-   @Override
-   AWSAMIClient getAMIServices();
-
-   /**
-    * Provides synchronous access to PlacementGroup services.
-    */
-   @Delegate
-   PlacementGroupClient getPlacementGroupServices();
-
-   /**
-    * Provides synchronous access to Monitoring services.
-    */
-   @Delegate
-   MonitoringClient getMonitoringServices();
-
-   /**
-    * {@inheritDoc}
-    */
-   @Delegate
-   @Override
-   AWSKeyPairClient getKeyPairServices();
-   
-   /**
-    * Provides synchronous access to SpotInstance services.
-    */
-   @Delegate
-   SpotInstanceClient getSpotInstanceServices();
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeService.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeService.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeService.java
index 8bcc4d5..f512074 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeService.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeService.java
@@ -35,7 +35,7 @@ import javax.inject.Provider;
 import javax.inject.Singleton;
 
 import org.jclouds.Constants;
-import org.jclouds.aws.ec2.AWSEC2Client;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.domain.PlacementGroup;
 import org.jclouds.aws.ec2.domain.PlacementGroup.State;
 import org.jclouds.collect.Memoized;
@@ -82,7 +82,7 @@ public class AWSEC2ComputeService extends EC2ComputeService {
 
    private final LoadingCache<RegionAndName, String> placementGroupMap;
    private final Predicate<PlacementGroup> placementGroupDeleted;
-   private final AWSEC2Client client;
+   private final AWSEC2Api client;
 
    @Inject
    protected AWSEC2ComputeService(ComputeServiceContext context, Map<String, Credentials> credentialStore,
@@ -99,7 +99,7 @@ public class AWSEC2ComputeService extends EC2ComputeService {
          InitializeRunScriptOnNodeOrPlaceInBadMap.Factory initScriptRunnerFactory,
          RunScriptOnNode.Factory runScriptOnNodeFactory, InitAdminAccess initAdminAccess,
          PersistNodeCredentials persistNodeCredentials, Timeouts timeouts,
-         @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, AWSEC2Client client,
+         @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor, AWSEC2Api client,
          ConcurrentMap<RegionAndName, KeyPair> credentialsMap,
          @Named("SECURITY") LoadingCache<RegionAndName, String> securityGroupMap,
          @Named("PLACEMENT") LoadingCache<RegionAndName, String> placementGroupMap,
@@ -125,10 +125,10 @@ public class AWSEC2ComputeService extends EC2ComputeService {
       // http://docs.amazonwebservices.com/AWSEC2/latest/UserGuide/index.html?using_cluster_computing.html
       String placementGroup = String.format("jclouds#%s#%s", group, region);
       try {
-         if (client.getPlacementGroupServices().describePlacementGroupsInRegion(region, placementGroup).size() > 0) {
+         if (client.getPlacementGroupApi().get().describePlacementGroupsInRegion(region, placementGroup).size() > 0) {
             logger.debug(">> deleting placementGroup(%s)", placementGroup);
             try {
-               client.getPlacementGroupServices().deletePlacementGroupInRegion(region, placementGroup);
+               client.getPlacementGroupApi().get().deletePlacementGroupInRegion(region, placementGroup);
                checkState(placementGroupDeleted.apply(new PlacementGroup(region, placementGroup, "cluster",
                         State.PENDING)), String.format("placementGroup region(%s) name(%s) failed to delete", region,
                         placementGroup));

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtension.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtension.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtension.java
index c0e21f0..ef12576 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtension.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtension.java
@@ -35,7 +35,7 @@ import javax.inject.Named;
 import javax.inject.Provider;
 
 import org.jclouds.Constants;
-import org.jclouds.aws.ec2.AWSEC2Client;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.util.AWSUtils;
 import org.jclouds.collect.Memoized;
 import org.jclouds.compute.domain.SecurityGroup;
@@ -72,10 +72,10 @@ import com.google.common.util.concurrent.UncheckedTimeoutException;
  * @author Andrew Bayer
  */
 public class AWSEC2SecurityGroupExtension extends EC2SecurityGroupExtension {
-   protected final AWSEC2Client client;
+   protected final AWSEC2Api client;
 
    @Inject
-   public AWSEC2SecurityGroupExtension(AWSEC2Client client,
+   public AWSEC2SecurityGroupExtension(AWSEC2Api client,
                                        @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
                                        @Region Supplier<Set<String>> regions,
                                        Function<org.jclouds.ec2.domain.SecurityGroup, SecurityGroup> groupConverter,
@@ -93,7 +93,7 @@ public class AWSEC2SecurityGroupExtension extends EC2SecurityGroupExtension {
       String region = AWSUtils.getRegionFromLocationOrNull(group.getLocation());
       String name = group.getName();
 
-      client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(region, name, ipPermission);
+      client.getSecurityGroupApi().get().authorizeSecurityGroupIngressInRegion(region, name, ipPermission);
 
       return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
    }
@@ -126,7 +126,7 @@ public class AWSEC2SecurityGroupExtension extends EC2SecurityGroupExtension {
          }
       }
 
-      client.getSecurityGroupServices().authorizeSecurityGroupIngressInRegion(region, name, builder.build());
+      client.getSecurityGroupApi().get().authorizeSecurityGroupIngressInRegion(region, name, builder.build());
 
       return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
    }
@@ -136,7 +136,7 @@ public class AWSEC2SecurityGroupExtension extends EC2SecurityGroupExtension {
       String region = AWSUtils.getRegionFromLocationOrNull(group.getLocation());
       String name = group.getName();
 
-      client.getSecurityGroupServices().revokeSecurityGroupIngressInRegion(region, name, ipPermission);
+      client.getSecurityGroupApi().get().revokeSecurityGroupIngressInRegion(region, name, ipPermission);
 
       return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
    }
@@ -170,7 +170,7 @@ public class AWSEC2SecurityGroupExtension extends EC2SecurityGroupExtension {
          }
       }
 
-      client.getSecurityGroupServices().revokeSecurityGroupIngressInRegion(region, name, builder.build());
+      client.getSecurityGroupApi().get().revokeSecurityGroupIngressInRegion(region, name, builder.build());
 
       return getSecurityGroupById(new RegionAndName(region, group.getName()).slashEncode());
    }

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/functions/PresentSpotRequestsAndInstances.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/functions/PresentSpotRequestsAndInstances.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/functions/PresentSpotRequestsAndInstances.java
index ee04c14..24b3a8a 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/functions/PresentSpotRequestsAndInstances.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/functions/PresentSpotRequestsAndInstances.java
@@ -33,7 +33,7 @@ import java.util.Set;
 
 import javax.inject.Singleton;
 
-import org.jclouds.aws.ec2.AWSEC2Client;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.domain.AWSRunningInstance;
 import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
 import org.jclouds.aws.ec2.functions.SpotInstanceRequestToAWSRunningInstance;
@@ -56,11 +56,11 @@ import com.google.inject.Inject;
 @Singleton
 public class PresentSpotRequestsAndInstances extends PresentInstances {
 
-   private final AWSEC2Client client;
+   private final AWSEC2Api client;
    private final Function<SpotInstanceRequest, AWSRunningInstance> spotConverter;
 
    @Inject
-   public PresentSpotRequestsAndInstances(AWSEC2Client client, Function<SpotInstanceRequest, AWSRunningInstance> spotConverter) {
+   public PresentSpotRequestsAndInstances(AWSEC2Api client, Function<SpotInstanceRequest, AWSRunningInstance> spotConverter) {
       super(client);
       this.client = checkNotNull(client, "client");
       this.spotConverter = checkNotNull(spotConverter, "spotConverter");
@@ -83,7 +83,7 @@ public class PresentSpotRequestsAndInstances extends PresentInstances {
          Collection<String> spotIds = entry.getValue();
          logger.trace("looking for spots %s in region %s", spotIds, region);
          builder.addAll(transform(
-               client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(region,
+                                  client.getSpotInstanceApi().get().describeSpotInstanceRequestsInRegion(region,
                      toArray(spotIds, String.class)), spotConverter));
       }
       return builder.build();

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeeded.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeeded.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeeded.java
index 6676ef6..c794fdb 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeeded.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeeded.java
@@ -27,8 +27,8 @@ import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
-import org.jclouds.aws.ec2.AWSEC2Client;
-import org.jclouds.aws.ec2.services.AWSSecurityGroupClient;
+import org.jclouds.aws.ec2.AWSEC2Api;
+import org.jclouds.aws.ec2.features.AWSSecurityGroupApi;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
@@ -52,18 +52,18 @@ public class AWSEC2CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndName
    @Resource
    @Named(ComputeServiceConstants.COMPUTE_LOGGER)
    protected Logger logger = Logger.NULL;
-   protected final AWSSecurityGroupClient securityClient;
+   protected final AWSSecurityGroupApi securityApi;
    protected final Predicate<RegionAndName> securityGroupEventualConsistencyDelay;
 
    @Inject
-   public AWSEC2CreateSecurityGroupIfNeeded(AWSEC2Client ec2Client,
+   public AWSEC2CreateSecurityGroupIfNeeded(AWSEC2Api ec2Api,
          @Named("SECURITY") Predicate<RegionAndName> securityGroupEventualConsistencyDelay) {
-      this(checkNotNull(ec2Client, "ec2Client").getSecurityGroupServices(), securityGroupEventualConsistencyDelay);
+      this(checkNotNull(ec2Api, "ec2Api").getSecurityGroupApi().get(), securityGroupEventualConsistencyDelay);
    }
 
-   public AWSEC2CreateSecurityGroupIfNeeded(AWSSecurityGroupClient securityClient,
+   public AWSEC2CreateSecurityGroupIfNeeded(AWSSecurityGroupApi securityApi,
          @Named("SECURITY") Predicate<RegionAndName> securityGroupEventualConsistencyDelay) {
-      this.securityClient = checkNotNull(securityClient, "securityClient");
+      this.securityApi = checkNotNull(securityApi, "securityApi");
       this.securityGroupEventualConsistencyDelay = checkNotNull(securityGroupEventualConsistencyDelay,
             "securityGroupEventualConsistencyDelay");
    }
@@ -80,7 +80,7 @@ public class AWSEC2CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndName
       checkNotNull(name, "name");
       logger.debug(">> creating securityGroup region(%s) name(%s)", region, name);
       try {
-         securityClient.createSecurityGroupInRegion(region, name, name);
+         securityApi.createSecurityGroupInRegion(region, name, name);
          boolean created = securityGroupEventualConsistencyDelay.apply(new RegionAndName(region, name));
          if (!created)
             throw new RuntimeException(String.format("security group %s/%s is not available after creating", region,
@@ -99,7 +99,7 @@ public class AWSEC2CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndName
                                .build());
             }
 
-            String myOwnerId = Iterables.get(securityClient.describeSecurityGroupsInRegion(region, name), 0).getOwnerId();
+            String myOwnerId = Iterables.get(securityApi.describeSecurityGroupsInRegion(region, name), 0).getOwnerId();
             permissions.add(IpPermission.builder()
                             .fromPort(0)
                             .toPort(65535)
@@ -118,7 +118,7 @@ public class AWSEC2CreateSecurityGroupIfNeeded extends CacheLoader<RegionAndName
 
          if (perms.size() > 0) {
             logger.debug(">> authorizing securityGroup region(%s) name(%s) IpPermissions(%s)", region, name, perms);
-            securityClient.authorizeSecurityGroupIngressInRegion(region, name, perms);
+            securityApi.authorizeSecurityGroupIngressInRegion(region, name, perms);
             logger.debug("<< authorized securityGroup(%s)", name);
          }            
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2CreateNodesInGroupThenAddToSet.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2CreateNodesInGroupThenAddToSet.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2CreateNodesInGroupThenAddToSet.java
index b9c205f..5faaba6 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2CreateNodesInGroupThenAddToSet.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2CreateNodesInGroupThenAddToSet.java
@@ -29,7 +29,7 @@ import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
-import org.jclouds.aws.ec2.AWSEC2Client;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
 import org.jclouds.aws.ec2.compute.functions.PresentSpotRequestsAndInstances;
 import org.jclouds.aws.ec2.domain.LaunchSpecification;
@@ -68,12 +68,12 @@ public class AWSEC2CreateNodesInGroupThenAddToSet extends EC2CreateNodesInGroupT
    private Logger logger = Logger.NULL;
 
    @VisibleForTesting
-   private final AWSEC2Client client;
+   private final AWSEC2Api client;
    private final SpotInstanceRequestToAWSRunningInstance spotConverter;
 
    @Inject
    protected AWSEC2CreateNodesInGroupThenAddToSet(
-         AWSEC2Client client,
+         AWSEC2Api client,
          @Named("ELASTICIP") LoadingCache<RegionAndName, String> elasticIpCache,
          @Named(TIMEOUT_NODE_RUNNING) Predicate<AtomicReference<NodeMetadata>> nodeRunning,
          @Named(PROPERTY_EC2_GENERATE_INSTANCE_NAMES) boolean generateInstanceNames,
@@ -103,7 +103,7 @@ public class AWSEC2CreateNodesInGroupThenAddToSet extends EC2CreateNodesInGroupT
          if (logger.isDebugEnabled())
             logger.debug(">> requesting %d spot instances region(%s) price(%f) spec(%s) options(%s)", count, region,
                      spotPrice, spec, options);
-         return ImmutableSet.<RunningInstance> copyOf(transform(client.getSpotInstanceServices()
+         return ImmutableSet.<RunningInstance> copyOf(transform(client.getSpotInstanceApi().get()
                .requestSpotInstancesInRegion(region, spotPrice, count, spec, options), spotConverter));
       }
       return super.createNodesInRegionAndZone(region, zone, group, count, template, instanceOptions);

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2DestroyNodeStrategy.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2DestroyNodeStrategy.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2DestroyNodeStrategy.java
index 84efca0..ee7b03b 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2DestroyNodeStrategy.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2DestroyNodeStrategy.java
@@ -26,7 +26,7 @@ import javax.inject.Inject;
 import javax.inject.Named;
 import javax.inject.Singleton;
 
-import org.jclouds.aws.ec2.AWSEC2Client;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.compute.strategy.GetNodeMetadataStrategy;
 import org.jclouds.domain.Credentials;
 import org.jclouds.ec2.compute.domain.RegionAndName;
@@ -42,11 +42,11 @@ import com.google.common.collect.Iterables;
 @Singleton
 public class AWSEC2DestroyNodeStrategy extends EC2DestroyNodeStrategy {
 
-   protected final AWSEC2Client client;
+   protected final AWSEC2Api client;
    protected final Map<String, Credentials> credentialStore;
 
    @Inject
-   protected AWSEC2DestroyNodeStrategy(AWSEC2Client client, GetNodeMetadataStrategy getNode,
+   protected AWSEC2DestroyNodeStrategy(AWSEC2Api client, GetNodeMetadataStrategy getNode,
             @Named("ELASTICIP") LoadingCache<RegionAndName, String> elasticIpCache,
             Map<String, Credentials> credentialStore) {
       super(client, getNode, elasticIpCache);
@@ -60,14 +60,14 @@ public class AWSEC2DestroyNodeStrategy extends EC2DestroyNodeStrategy {
       if (id.indexOf("sir-") != 0) {
          try {
             spotId = getOnlyElement(
-                     Iterables.concat(client.getInstanceServices().describeInstancesInRegion(region, id)))
+                                    Iterables.concat(client.getInstanceApi().get().describeInstancesInRegion(region, id)))
                      .getSpotInstanceRequestId();
             credentialStore.remove("node#" + region + "/" + spotId);
          } catch (NoSuchElementException e) {
          }
          super.destroyInstanceInRegion(id, region);
       } else {
-         client.getSpotInstanceServices().cancelSpotInstanceRequestsInRegion(region, spotId);
+         client.getSpotInstanceApi().get().cancelSpotInstanceRequestsInRegion(region, spotId);
          credentialStore.remove("node#" + region + "/" + id);
       }
 

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2GetNodeMetadataStrategy.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2GetNodeMetadataStrategy.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2GetNodeMetadataStrategy.java
index b442576..ffc2e0b 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2GetNodeMetadataStrategy.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2GetNodeMetadataStrategy.java
@@ -22,7 +22,7 @@ import static com.google.common.collect.Iterables.getOnlyElement;
 import javax.inject.Inject;
 import javax.inject.Singleton;
 
-import org.jclouds.aws.ec2.AWSEC2Client;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
 import org.jclouds.aws.ec2.functions.SpotInstanceRequestToAWSRunningInstance;
 import org.jclouds.compute.domain.NodeMetadata;
@@ -38,11 +38,11 @@ import com.google.common.base.Function;
 @Singleton
 public class AWSEC2GetNodeMetadataStrategy extends EC2GetNodeMetadataStrategy {
 
-   private final AWSEC2Client client;
+   private final AWSEC2Api client;
    private final SpotInstanceRequestToAWSRunningInstance spotConverter;
 
    @Inject
-   protected AWSEC2GetNodeMetadataStrategy(AWSEC2Client client,
+   protected AWSEC2GetNodeMetadataStrategy(AWSEC2Api client,
             Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
             SpotInstanceRequestToAWSRunningInstance spotConverter) {
       super(client, runningInstanceToNodeMetadata);
@@ -54,7 +54,7 @@ public class AWSEC2GetNodeMetadataStrategy extends EC2GetNodeMetadataStrategy {
    public RunningInstance getRunningInstanceInRegion(String region, String id) {
       if (id.indexOf("sir-") != 0)
          return super.getRunningInstanceInRegion(region, id);
-      SpotInstanceRequest spot = getOnlyElement(client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(
+      SpotInstanceRequest spot = getOnlyElement(client.getSpotInstanceApi().get().describeSpotInstanceRequestsInRegion(
                region, id));
       if (spot.getState() == SpotInstanceRequest.State.ACTIVE)
          return super.getRunningInstanceInRegion(region, spot.getInstanceId());

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2ListNodesStrategy.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2ListNodesStrategy.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2ListNodesStrategy.java
index 35d193e..0d3b034 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2ListNodesStrategy.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/AWSEC2ListNodesStrategy.java
@@ -31,7 +31,7 @@ import javax.inject.Named;
 import javax.inject.Singleton;
 
 import org.jclouds.Constants;
-import org.jclouds.aws.ec2.AWSEC2Client;
+import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.domain.AWSRunningInstance;
 import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
 import org.jclouds.aws.ec2.functions.SpotInstanceRequestToAWSRunningInstance;
@@ -55,11 +55,11 @@ import com.google.inject.Inject;
 @Singleton
 public class AWSEC2ListNodesStrategy extends EC2ListNodesStrategy {
 
-   protected final AWSEC2Client client;
+   protected final AWSEC2Api client;
    protected final SpotInstanceRequestToAWSRunningInstance spotConverter;
 
    @Inject
-   protected AWSEC2ListNodesStrategy(AWSEC2Client client, @Region Supplier<Set<String>> regions,
+   protected AWSEC2ListNodesStrategy(AWSEC2Api client, @Region Supplier<Set<String>> regions,
             Function<RunningInstance, NodeMetadata> runningInstanceToNodeMetadata,
             @Named(Constants.PROPERTY_USER_THREADS) ListeningExecutorService userExecutor,
             SpotInstanceRequestToAWSRunningInstance spotConverter) {
@@ -92,7 +92,7 @@ public class AWSEC2ListNodesStrategy extends EC2ListNodesStrategy {
 
          @Override
          public Set<SpotInstanceRequest> apply(String from) {
-            return client.getSpotInstanceServices().describeSpotInstanceRequestsInRegion(from);
+            return client.getSpotInstanceApi().get().describeSpotInstanceRequestsInRegion(from);
          }
       };
    }
@@ -102,7 +102,7 @@ public class AWSEC2ListNodesStrategy extends EC2ListNodesStrategy {
 
          @Override
          public Set<SpotInstanceRequest> apply(String from) {
-            return client.getSpotInstanceServices()
+            return client.getSpotInstanceApi().get()
                .describeSpotInstanceRequestsInRegion(from, toArray(idsByRegions.get(from), String.class));
          }
       };

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/config/AWSEC2HttpApiModule.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/config/AWSEC2HttpApiModule.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/config/AWSEC2HttpApiModule.java
new file mode 100644
index 0000000..db1f8d2
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/config/AWSEC2HttpApiModule.java
@@ -0,0 +1,98 @@
+/*
+ * 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.aws.ec2.config;
+import static org.jclouds.reflect.Reflection2.typeToken;
+
+import java.util.Map;
+
+import javax.inject.Singleton;
+
+import org.jclouds.aws.ec2.AWSEC2Api;
+import org.jclouds.aws.ec2.domain.AWSRunningInstance;
+import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
+import org.jclouds.aws.ec2.functions.SpotInstanceRequestToAWSRunningInstance;
+import org.jclouds.aws.ec2.options.AWSRunInstancesOptions;
+import org.jclouds.aws.ec2.features.AWSAMIApi;
+import org.jclouds.aws.ec2.features.AWSInstanceApi;
+import org.jclouds.aws.ec2.features.AWSKeyPairApi;
+import org.jclouds.aws.ec2.features.AWSSecurityGroupApi;
+import org.jclouds.aws.ec2.features.MonitoringApi;
+import org.jclouds.aws.ec2.features.PlacementGroupApi;
+import org.jclouds.aws.ec2.features.SpotInstanceApi;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.config.BaseEC2HttpApiModule;
+import org.jclouds.ec2.features.SubnetApi;
+import org.jclouds.ec2.features.TagApi;
+import org.jclouds.ec2.features.WindowsApi;
+import org.jclouds.ec2.options.RunInstancesOptions;
+import org.jclouds.ec2.features.AMIApi;
+import org.jclouds.ec2.features.AvailabilityZoneAndRegionApi;
+import org.jclouds.ec2.features.ElasticBlockStoreApi;
+import org.jclouds.ec2.features.ElasticIPAddressApi;
+import org.jclouds.ec2.features.InstanceApi;
+import org.jclouds.ec2.features.SecurityGroupApi;
+import org.jclouds.rest.ConfiguresHttpApi;
+
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableMap;
+import com.google.inject.Provides;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Configures the EC2 connection.
+ * 
+ * @author Adrian Cole
+ */
+@ConfiguresHttpApi
+public class AWSEC2HttpApiModule extends BaseEC2HttpApiModule<AWSEC2Api> {
+
+   public AWSEC2HttpApiModule() {
+      super(AWSEC2Api.class);
+   }
+
+   @Singleton
+   @Provides
+   EC2Api provide(AWSEC2Api in) {
+      return in;
+   }
+
+   @Singleton
+   @Provides
+   InstanceApi getInstanceApi(AWSEC2Api in) {
+      return in.getInstanceApi().get();
+   }
+
+   @Singleton
+   @Provides
+   SecurityGroupApi getSecurityGroupApi(AWSEC2Api in) {
+      return in.getSecurityGroupApi().get();
+   }
+
+   @Singleton
+   @Provides
+   AMIApi getAMIApi(AWSEC2Api in) {
+      return in.getAMIApi().get();
+   }
+
+   @Override
+   protected void configure() {
+      bind(RunInstancesOptions.class).to(AWSRunInstancesOptions.class);
+      bind(new TypeLiteral<Function<SpotInstanceRequest, AWSRunningInstance>>() {
+      }).to(SpotInstanceRequestToAWSRunningInstance.class);
+      super.configure();
+   }
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/config/AWSEC2RestClientModule.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/config/AWSEC2RestClientModule.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/config/AWSEC2RestClientModule.java
deleted file mode 100644
index 0ebba84..0000000
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/config/AWSEC2RestClientModule.java
+++ /dev/null
@@ -1,159 +0,0 @@
-/*
- * 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.aws.ec2.config;
-import static org.jclouds.reflect.Reflection2.typeToken;
-
-import java.util.Map;
-
-import javax.inject.Singleton;
-
-import org.jclouds.aws.ec2.AWSEC2AsyncClient;
-import org.jclouds.aws.ec2.AWSEC2Client;
-import org.jclouds.aws.ec2.domain.AWSRunningInstance;
-import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
-import org.jclouds.aws.ec2.functions.SpotInstanceRequestToAWSRunningInstance;
-import org.jclouds.aws.ec2.options.AWSRunInstancesOptions;
-import org.jclouds.aws.ec2.services.AWSAMIAsyncClient;
-import org.jclouds.aws.ec2.services.AWSAMIClient;
-import org.jclouds.aws.ec2.services.AWSInstanceAsyncClient;
-import org.jclouds.aws.ec2.services.AWSInstanceClient;
-import org.jclouds.aws.ec2.services.AWSKeyPairAsyncClient;
-import org.jclouds.aws.ec2.services.AWSKeyPairClient;
-import org.jclouds.aws.ec2.services.AWSSecurityGroupAsyncClient;
-import org.jclouds.aws.ec2.services.AWSSecurityGroupClient;
-import org.jclouds.aws.ec2.services.MonitoringAsyncClient;
-import org.jclouds.aws.ec2.services.MonitoringClient;
-import org.jclouds.aws.ec2.services.PlacementGroupAsyncClient;
-import org.jclouds.aws.ec2.services.PlacementGroupClient;
-import org.jclouds.aws.ec2.services.SpotInstanceAsyncClient;
-import org.jclouds.aws.ec2.services.SpotInstanceClient;
-import org.jclouds.ec2.EC2AsyncClient;
-import org.jclouds.ec2.EC2Client;
-import org.jclouds.ec2.config.EC2RestClientModule;
-import org.jclouds.ec2.features.SubnetApi;
-import org.jclouds.ec2.features.SubnetAsyncApi;
-import org.jclouds.ec2.features.TagApi;
-import org.jclouds.ec2.features.TagAsyncApi;
-import org.jclouds.ec2.features.WindowsApi;
-import org.jclouds.ec2.features.WindowsAsyncApi;
-import org.jclouds.ec2.options.RunInstancesOptions;
-import org.jclouds.ec2.services.AMIAsyncClient;
-import org.jclouds.ec2.services.AMIClient;
-import org.jclouds.ec2.services.AvailabilityZoneAndRegionAsyncClient;
-import org.jclouds.ec2.services.AvailabilityZoneAndRegionClient;
-import org.jclouds.ec2.services.ElasticBlockStoreAsyncClient;
-import org.jclouds.ec2.services.ElasticBlockStoreClient;
-import org.jclouds.ec2.services.ElasticIPAddressAsyncClient;
-import org.jclouds.ec2.services.ElasticIPAddressClient;
-import org.jclouds.ec2.services.InstanceAsyncClient;
-import org.jclouds.ec2.services.InstanceClient;
-import org.jclouds.ec2.services.SecurityGroupAsyncClient;
-import org.jclouds.ec2.services.SecurityGroupClient;
-import org.jclouds.ec2.services.WindowsAsyncClient;
-import org.jclouds.ec2.services.WindowsClient;
-import org.jclouds.rest.ConfiguresRestClient;
-
-import com.google.common.base.Function;
-import com.google.common.collect.ImmutableMap;
-import com.google.inject.Provides;
-import com.google.inject.TypeLiteral;
-
-/**
- * Configures the EC2 connection.
- * 
- * @author Adrian Cole
- */
-@ConfiguresRestClient
-public class AWSEC2RestClientModule extends EC2RestClientModule<AWSEC2Client, AWSEC2AsyncClient> {
-
-   public static final Map<Class<?>, Class<?>> DELEGATE_MAP = ImmutableMap.<Class<?>, Class<?>> builder()//
-         .put(AWSAMIClient.class, AWSAMIAsyncClient.class)//
-         .put(ElasticIPAddressClient.class, ElasticIPAddressAsyncClient.class)//
-         .put(AWSInstanceClient.class, AWSInstanceAsyncClient.class)//
-         .put(AWSKeyPairClient.class, AWSKeyPairAsyncClient.class)//
-         .put(AWSSecurityGroupClient.class, AWSSecurityGroupAsyncClient.class)//
-         .put(PlacementGroupClient.class, PlacementGroupAsyncClient.class)//
-         .put(MonitoringClient.class, MonitoringAsyncClient.class)//
-         .put(WindowsClient.class, WindowsAsyncClient.class)//
-         .put(AvailabilityZoneAndRegionClient.class, AvailabilityZoneAndRegionAsyncClient.class)//
-         .put(ElasticBlockStoreClient.class, ElasticBlockStoreAsyncClient.class)//
-         .put(SpotInstanceClient.class, SpotInstanceAsyncClient.class)//
-         .put(WindowsApi.class, WindowsAsyncApi.class)//
-         .put(TagApi.class, TagAsyncApi.class)//
-         .put(SubnetApi.class, SubnetAsyncApi.class)//
-         .build();
-
-   public AWSEC2RestClientModule() {
-      super(typeToken(AWSEC2Client.class), typeToken(AWSEC2AsyncClient.class), DELEGATE_MAP);
-   }
-
-   @Singleton
-   @Provides
-   EC2Client provide(AWSEC2Client in) {
-      return in;
-   }
-
-   @Singleton
-   @Provides
-   EC2AsyncClient provide(AWSEC2AsyncClient in) {
-      return in;
-   }
-
-   @Singleton
-   @Provides
-   InstanceClient getInstanceServices(AWSEC2Client in) {
-      return in.getInstanceServices();
-   }
-
-   @Singleton
-   @Provides
-   InstanceAsyncClient getInstanceServices(AWSEC2AsyncClient in) {
-      return in.getInstanceServices();
-   }
-
-   @Singleton
-   @Provides
-   SecurityGroupClient getSecurityGroupServices(AWSEC2Client in) {
-      return in.getSecurityGroupServices();
-   }
-
-   @Singleton
-   @Provides
-   SecurityGroupAsyncClient getSecurityGroupServices(AWSEC2AsyncClient in) {
-      return in.getSecurityGroupServices();
-   }
-
-   @Singleton
-   @Provides
-   AMIClient getAMIServices(AWSEC2Client in) {
-      return in.getAMIServices();
-   }
-
-   @Singleton
-   @Provides
-   AMIAsyncClient getAMIServices(AWSEC2AsyncClient in) {
-      return in.getAMIServices();
-   }
-
-   @Override
-   protected void configure() {
-      bind(RunInstancesOptions.class).to(AWSRunInstancesOptions.class);
-      bind(new TypeLiteral<Function<SpotInstanceRequest, AWSRunningInstance>>() {
-      }).to(SpotInstanceRequestToAWSRunningInstance.class);
-      super.configure();
-   }
-}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSAMIApi.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSAMIApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSAMIApi.java
new file mode 100644
index 0000000..92eb3b0
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSAMIApi.java
@@ -0,0 +1,126 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.aws.ec2.xml.ProductCodesHandler;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindProductCodesToIndexedFormParams;
+import org.jclouds.ec2.features.AMIApi;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+/**
+ * Provides access to AMI Services.
+ * <p/>
+ * 
+ * @author Adrian Cole
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+public interface AWSAMIApi extends AMIApi {
+   // TODO make AWSImage as it has product codes...
+
+   /**
+    * Returns the Product Codes of an image.
+    * 
+    * @param region
+    *           AMIs are tied to the Region where its files are located within Amazon S3.
+    * @param imageId
+    *           The ID of the AMI for which an attribute will be described
+    * @see #describeImages
+    * @see #modifyImageAttribute
+    * @see #resetImageAttribute
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeImageAttribute.html"
+    *      />
+    * @see DescribeImagesOptions
+    */
+   @Named("DescribeImageAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "Attribute" }, values = { "DescribeImageAttribute", "productCodes" })
+   @XMLResponseParser(ProductCodesHandler.class)
+   Set<String> getProductCodesForImageInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @FormParam("ImageId") String imageId);
+
+   /**
+    * Adds {@code productCode}s to an AMI.
+    * 
+    * @param region
+    *           AMIs are tied to the Region where its files are located within Amazon S3.
+    * @param productCodes
+    *           Product Codes
+    * @param imageId
+    *           The AMI ID.
+    * 
+    * @see #removeProductCodesFromImage
+    * @see #describeImageAttribute
+    * @see #resetImageAttribute
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyImageAttribute.html"
+    *      />
+    */
+   @Named("ModifyImageAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "OperationType", "Attribute" }, values = { "ModifyImageAttribute", "add",
+            "productCodes" })
+   void addProductCodesToImageInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @BinderParam(BindProductCodesToIndexedFormParams.class) Iterable<String> productCodes,
+            @FormParam("ImageId") String imageId);
+
+   /**
+    * Removes {@code productCode}s from an AMI.
+    * 
+    * @param region
+    *           AMIs are tied to the Region where its files are located within Amazon S3.
+    * @param productCodes
+    *           Product Codes
+    * @param imageId
+    *           The AMI ID.
+    * 
+    * @see #addProductCodesToImage
+    * @see #describeImageAttribute
+    * @see #resetImageAttribute
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-ModifyImageAttribute.html"
+    *      />
+    */
+   @Named("ModifyImageAttribute")
+   @POST
+   @Path("/")
+   @FormParams(keys = { ACTION, "OperationType", "Attribute" }, values = { "ModifyImageAttribute", "remove",
+            "productCodes" })
+   void removeProductCodesFromImageInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @BinderParam(BindProductCodesToIndexedFormParams.class) Iterable<String> productCodes,
+            @FormParam("ImageId") String imageId);
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSInstanceApi.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSInstanceApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSInstanceApi.java
new file mode 100644
index 0000000..5a26707
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSInstanceApi.java
@@ -0,0 +1,81 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import java.util.Set;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
+import org.jclouds.aws.ec2.domain.AWSRunningInstance;
+import org.jclouds.aws.ec2.xml.AWSDescribeInstancesResponseHandler;
+import org.jclouds.aws.ec2.xml.AWSRunInstancesResponseHandler;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindInstanceIdsToIndexedFormParams;
+import org.jclouds.ec2.binders.IfNotNullBindAvailabilityZoneToFormParam;
+import org.jclouds.ec2.domain.Reservation;
+import org.jclouds.ec2.options.RunInstancesOptions;
+import org.jclouds.ec2.features.InstanceApi;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+/**
+ * Provides access to EC2 Instance Services via their REST API.
+ * <p/>
+ * 
+ * @author Adrian Cole
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+public interface AWSInstanceApi extends InstanceApi {
+
+   @Named("DescribeInstances")
+   @Override
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeInstances")
+   @XMLResponseParser(AWSDescribeInstancesResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<? extends Reservation<? extends AWSRunningInstance>> describeInstancesInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
+
+   @Named("RunInstances")
+   @Override
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "RunInstances")
+   @XMLResponseParser(AWSRunInstancesResponseHandler.class)
+   Reservation<? extends AWSRunningInstance> runInstancesInRegion(
+            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+            @Nullable @BinderParam(IfNotNullBindAvailabilityZoneToFormParam.class) String nullableAvailabilityZone,
+            @FormParam("ImageId") String imageId, @FormParam("MinCount") int minCount,
+            @FormParam("MaxCount") int maxCount, RunInstancesOptions... options);
+
+}

http://git-wip-us.apache.org/repos/asf/incubator-jclouds/blob/5f3b8d3f/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSKeyPairApi.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSKeyPairApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSKeyPairApi.java
new file mode 100644
index 0000000..5813dce
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSKeyPairApi.java
@@ -0,0 +1,88 @@
+/*
+ * 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.aws.ec2.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.domain.KeyPair;
+import org.jclouds.ec2.functions.EncodedRSAPublicKeyToBase64;
+import org.jclouds.ec2.features.KeyPairApi;
+import org.jclouds.ec2.xml.KeyPairResponseHandler;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.ParamParser;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+/**
+ * @author Adrian Cole
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+public interface AWSKeyPairApi extends KeyPairApi {
+
+   /**
+    * Imports the public key from an RSA key pair that you created with a third-party tool. Compare
+    * this with CreateKeyPair, in which AWS creates the key pair and gives the keys to you (AWS
+    * keeps a copy of the public key). With ImportKeyPair, you create the key pair and give AWS just
+    * the public key. The private key is never transferred between you and AWS.
+    * 
+    * <p/>
+    * You can easily create an RSA key pair on Windows and Linux using the ssh-keygen command line
+    * tool (provided with the standard OpenSSH installation). Standard library support for RSA key
+    * pair creation is also available in Java, Ruby, Python, and many other programming languages.
+    * 
+    * <p/>
+    * <h4>Supported Formats</h4>
+    * <ul>
+    * <li>OpenSSH public key format (e.g., the format in ~/.ssh/authorized_keys)</li>
+    * <li>Base64 encoded DER format</li>
+    * <li>SSH public key file format as specified in RFC4716</li>
+    * </ul>
+    * DSA keys are not supported. Make sure your key generator is set up to create RSA keys.
+    * <p/>
+    * Supported lengths: 1024, 2048, and 4096.
+    * <p/>
+    * 
+    * @param region
+    *           region to import the key into
+    * @param keyName
+    *           A unique name for the key pair. Accepts alphanumeric characters, spaces, dashes, and
+    *           underscores.
+    * @param publicKeyMaterial
+    *           The public key
+    * @return imported key including fingerprint
+    */
+   @Named("ImportKeyPair")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "ImportKeyPair")
+   @XMLResponseParser(KeyPairResponseHandler.class)
+   KeyPair importKeyPairInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+         @FormParam("KeyName") String keyName,
+         @FormParam("PublicKeyMaterial") @ParamParser(EncodedRSAPublicKeyToBase64.class) String publicKeyMaterial);
+}