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/11/14 20:54:17 UTC

[1/3] JCLOUDS-361. Add support for filtering Describe* methods in EC2

Updated Branches:
  refs/heads/master 55b21b644 -> 2077da287


http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 2d728e4..aee2c9d 100644
--- 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
@@ -38,6 +38,7 @@ 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.ec2.binders.BindFiltersToIndexedFormParams;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
 import org.jclouds.rest.annotations.BinderParam;
@@ -48,6 +49,8 @@ import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.VirtualHost;
 import org.jclouds.rest.annotations.XMLResponseParser;
 
+import com.google.common.collect.Multimap;
+
 /**
  * Provides access to EC2 Spot Instances via their REST API.
  * <p/>
@@ -89,6 +92,36 @@ public interface SpotInstanceApi {
          @BinderParam(BindSpotInstanceRequestIdsToIndexedFormParams.class) String... requestIds);
 
    /**
+    * 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 filter
+    *           Mulitmap of filter key/values.
+    *
+    * @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> describeSpotInstanceRequestsInRegionWithFilter(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
+
+   /**
     * request a single spot instance
     * 
     * @param region

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 468de54..c617439 100644
--- 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
@@ -21,7 +21,6 @@ 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;
@@ -58,5 +57,4 @@ public class AWSInstanceApiLiveTest extends BaseComputeServiceContextLiveTest {
          assert allResults.size() >= 0 : allResults.size();
       }
    }
-
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiExpectTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiExpectTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiExpectTest.java
new file mode 100644
index 0000000..32502b7
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/PlacementGroupApiExpectTest.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.aws.ec2.features;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.aws.ec2.AWSEC2Api;
+import org.jclouds.aws.ec2.compute.internal.BaseAWSEC2ComputeServiceExpectTest;
+import org.jclouds.aws.ec2.domain.PlacementGroup;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Andrew Bayer
+ */
+@Test(groups = "unit", testName = "PlacementGroupApiExpectTest")
+public class PlacementGroupApiExpectTest extends BaseAWSEC2ComputeServiceExpectTest {
+
+   HttpRequest filter = HttpRequest.builder().method("POST")
+           .endpoint("https://ec2.us-east-1.amazonaws.com/")
+           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+           .addFormParam("Action", "DescribePlacementGroups")
+           .addFormParam("Filter.1.Name", "strategy")
+           .addFormParam("Filter.1.Value.1", "cluster")
+           .addFormParam("Signature", "SaA7Un1BE3m9jIEKyjXNdQPzFh/QAJSCebvKXiwUEK0%3D")
+           .addFormParam("SignatureMethod", "HmacSHA256")
+           .addFormParam("SignatureVersion", "2")
+           .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z")
+           .addFormParam("Version", "2012-06-01")
+           .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testFilterWhenResponseIs2xx() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResourceWithContentType("/describe_placement_groups.xml", "text/xml")).build();
+
+      AWSEC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse)
+              .getContext().unwrapApi(AWSEC2Api.class);
+
+      PlacementGroup group = getOnlyElement(apiWhenExist.getPlacementGroupApi().get().describePlacementGroupsInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("strategy", "cluster")
+                      .build()));
+
+      assertEquals(group.getName(), "XYZ-cluster");
+   }
+
+   public void testFilterWhenResponseIs404() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build();
+
+      AWSEC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse)
+              .getContext().unwrapApi(AWSEC2Api.class);
+
+      assertEquals(apiWhenNotExist.getPlacementGroupApi().get().describePlacementGroupsInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("strategy", "cluster")
+                      .build()),
+              ImmutableSet.of());
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 9c699e9..ae4d842 100644
--- 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
@@ -29,6 +29,7 @@ import java.util.ArrayList;
 import java.util.Set;
 import java.util.SortedSet;
 
+import org.jclouds.aws.AWSResponseException;
 import org.jclouds.aws.domain.Region;
 import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.domain.PlacementGroup;
@@ -53,6 +54,7 @@ import org.testng.annotations.Test;
 
 import com.google.common.base.Predicate;
 import com.google.common.base.Throwables;
+import com.google.common.collect.ImmutableMultimap;
 import com.google.inject.Module;
 
 /**
@@ -84,7 +86,7 @@ public class PlacementGroupApiLiveTest extends BaseComputeServiceContextLiveTest
    }
 
    @Test
-   void testDescribe() {
+   public void testDescribe() {
       for (String region : supportedRegions) {
          SortedSet<PlacementGroup> allResults = newTreeSet(client.getPlacementGroupApi().get()
                   .describePlacementGroupsInRegion(region));
@@ -110,7 +112,42 @@ public class PlacementGroupApiLiveTest extends BaseComputeServiceContextLiveTest
    }
 
    @Test
-   void testCreatePlacementGroup() {
+   public void testFilter() {
+      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()
+                    .describePlacementGroupsInRegionWithFilter(region,
+                            ImmutableMultimap.<String, String>builder()
+                            .put("group-name", group.getName()).build()));
+            assertNotNull(result);
+            PlacementGroup compare = result.last();
+            assertEquals(compare, group);
+         }
+      }
+   }
+
+   @Test(expectedExceptions = AWSResponseException.class)
+   public void testFilterInvalid() {
+      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()
+                    .describePlacementGroupsInRegionWithFilter(region,
+                            ImmutableMultimap.<String, String>builder()
+                                    .put("invalid-filter", group.getName()).build()));
+         }
+      }
+   }
+
+   @Test
+   public void testCreatePlacementGroup() {
       String groupName = PREFIX + "1";
       for (String region : supportedRegions) {
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiExpectTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiExpectTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiExpectTest.java
new file mode 100644
index 0000000..08c852b
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/SpotInstanceApiExpectTest.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.aws.ec2.features;
+
+import static com.google.common.collect.Iterables.getOnlyElement;
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.aws.ec2.AWSEC2Api;
+import org.jclouds.aws.ec2.compute.internal.BaseAWSEC2ComputeServiceExpectTest;
+import org.jclouds.aws.ec2.domain.SpotInstanceRequest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Andrew Bayer
+ */
+@Test(groups = "unit", testName = "SpotInstanceApiExpectTest")
+public class SpotInstanceApiExpectTest extends BaseAWSEC2ComputeServiceExpectTest {
+
+   HttpRequest filter = HttpRequest.builder().method("POST")
+           .endpoint("https://ec2.us-east-1.amazonaws.com/")
+           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+           .addFormParam("Action", "DescribeSpotInstanceRequests")
+           .addFormParam("Filter.1.Name", "instance-id")
+           .addFormParam("Filter.1.Value.1", "i-ef308e8e")
+           .addFormParam("Signature", "wQtGpumMCDEzvlldKepCKeEjD9iE7eAyiRBlQztcJMA%3D")
+           .addFormParam("SignatureMethod", "HmacSHA256")
+           .addFormParam("SignatureVersion", "2")
+           .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z")
+           .addFormParam("Version", "2012-06-01")
+           .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testFilterWhenResponseIs2xx() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResourceWithContentType("/describe_spot_instance.xml", "text/xml")).build();
+
+      AWSEC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse)
+              .getContext().unwrapApi(AWSEC2Api.class);
+
+      SpotInstanceRequest request = getOnlyElement(apiWhenExist.getSpotInstanceApi().get().describeSpotInstanceRequestsInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("instance-id", "i-ef308e8e")
+                      .build()));
+
+      assertEquals(request.getId(), "sir-1ede0012");
+   }
+
+   public void testFilterWhenResponseIs404() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build();
+
+      AWSEC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse)
+              .getContext().unwrapApi(AWSEC2Api.class);
+
+      assertEquals(apiWhenNotExist.getSpotInstanceApi().get().describeSpotInstanceRequestsInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("instance-id", "i-ef308e8e")
+                      .build()),
+              ImmutableSet.of());
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 88257cd..ca6ee0a 100644
--- 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
@@ -30,6 +30,7 @@ import java.util.Set;
 import java.util.SortedSet;
 import java.util.concurrent.TimeUnit;
 
+import org.jclouds.aws.AWSResponseException;
 import org.jclouds.aws.domain.Region;
 import org.jclouds.aws.ec2.AWSEC2Api;
 import org.jclouds.aws.ec2.domain.AWSRunningInstance;
@@ -44,6 +45,7 @@ import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.ImmutableSortedSet;
 
@@ -74,7 +76,7 @@ public class SpotInstanceApiLiveTest  extends BaseComputeServiceContextLiveTest
    }
 
    @Test
-   void testDescribeSpotRequestsInRegion() {
+   public void testDescribeSpotRequestsInRegion() {
       for (String region : Region.DEFAULT_REGIONS) {
          SortedSet<SpotInstanceRequest> allResults = ImmutableSortedSet.copyOf(client.getSpotInstanceApi().get()
                   .describeSpotInstanceRequestsInRegion(region));
@@ -92,7 +94,45 @@ public class SpotInstanceApiLiveTest  extends BaseComputeServiceContextLiveTest
    }
 
    @Test
-   void testDescribeSpotPriceHistoryInRegion() {
+   public void testDescribeSpotRequestsInRegionFilter() {
+      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()
+                    .describeSpotInstanceRequestsInRegionWithFilter(region,
+                            ImmutableMultimap.<String, String>builder()
+                                    .put("spot-instance-request-id", request.getId()).build()));
+
+            assertNotNull(result);
+            SpotInstanceRequest compare = result.last();
+            assertEquals(compare, request);
+         }
+      }
+
+   }
+
+   @Test(expectedExceptions = AWSResponseException.class)
+   public void testDescribeSpotRequestsInRegionFilterInvalid() {
+      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()
+                    .describeSpotInstanceRequestsInRegionWithFilter(region,
+                            ImmutableMultimap.<String, String>builder()
+                                    .put("invalid-filter", request.getId()).build()));
+         }
+      }
+
+   }
+
+   @Test
+   public void testDescribeSpotPriceHistoryInRegion() {
       for (String region : Region.DEFAULT_REGIONS) {
          Set<Spot> spots = client.getSpotInstanceApi().get().describeSpotPriceHistoryInRegion(region, from(new Date()));
          assertNotNull(spots);
@@ -115,7 +155,7 @@ public class SpotInstanceApiLiveTest  extends BaseComputeServiceContextLiveTest
    }
 
    @Test(enabled = true)
-   void testCreateSpotInstance() {
+   public void testCreateSpotInstance() {
       String launchGroup = PREFIX + "1";
       for (String region : Region.DEFAULT_REGIONS)
          for (SpotInstanceRequest request : client.getSpotInstanceApi().get().describeSpotInstanceRequestsInRegion(


[2/3] JCLOUDS-361. Add support for filtering Describe* methods in EC2

Posted by ab...@apache.org.
http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 858cf20..bc080a7 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiLiveTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiLiveTest.java
@@ -20,11 +20,13 @@ 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.assertFalse;
 import static org.testng.Assert.assertNotNull;
 
 import java.util.Set;
 import java.util.SortedSet;
 
+import org.jclouds.aws.AWSResponseException;
 import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
 import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.domain.AvailabilityZoneInfo;
@@ -38,6 +40,7 @@ import org.testng.annotations.Test;
 
 import com.google.common.base.Predicate;
 import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.Iterables;
 import com.google.common.collect.Sets;
 
@@ -75,17 +78,42 @@ public class ElasticBlockStoreApiLiveTest extends BaseComputeServiceContextLiveT
 
    @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);
-         }
-      }
+      String region = defaultRegion;
+      SortedSet<Volume> allResults = Sets.newTreeSet(client.describeVolumesInRegion(region));
+      assertNotNull(allResults);
+      assertFalse(allResults.isEmpty());
+      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 testDescribeVolumesWithFilter() {
+      String region = defaultRegion;
+      SortedSet<Volume> allResults = Sets.newTreeSet(client.describeVolumesInRegion(region));
+      assertNotNull(allResults);
+      assertFalse(allResults.isEmpty());
+      Volume volume = allResults.last();
+      SortedSet<Volume> result = Sets.newTreeSet(client.describeVolumesInRegionWithFilter(region,
+              ImmutableMultimap.<String, String>builder()
+                      .put("volume-id", volume.getId()).build()));
+      assertNotNull(result);
+      Volume compare = result.last();
+      assertEquals(compare, volume);
+   }
+
+   @Test(expectedExceptions = AWSResponseException.class)
+   void testDescribeVolumesWithInvalidFilter() {
+      String region = defaultRegion;
+      SortedSet<Volume> allResults = Sets.newTreeSet(client.describeVolumesInRegion(region));
+      assertNotNull(allResults);
+      assertFalse(allResults.isEmpty());
+      Volume volume = allResults.last();
+      SortedSet<Volume> result = Sets.newTreeSet(client.describeVolumesInRegionWithFilter(region,
+              ImmutableMultimap.<String, String>builder()
+                      .put("invalid-filter", volume.getId()).build()));
    }
 
    @Test
@@ -163,16 +191,43 @@ public class ElasticBlockStoreApiLiveTest extends BaseComputeServiceContextLiveT
 
    @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);
-         }
+      String region = defaultRegion;
+      SortedSet<Snapshot> allResults = Sets.newTreeSet(client.describeSnapshotsInRegion(region));
+      assertNotNull(allResults);
+      if (!allResults.isEmpty()) {
+         Snapshot snapshot = allResults.last();
+         Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegion(region,
+                 snapshotIds(snapshot.getId())));
+         assertNotNull(result);
+         assertEquals(result, snapshot);
+      }
+   }
+
+   @Test
+   void testDescribeSnapshotsWithFilter() {
+      String region = defaultRegion;
+      SortedSet<Snapshot> allResults = Sets.newTreeSet(client.describeSnapshotsInRegion(region));
+      assertNotNull(allResults);
+      if (!allResults.isEmpty()) {
+         Snapshot snapshot = allResults.last();
+         Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegionWithFilter(region,
+                 ImmutableMultimap.<String, String>builder()
+                         .put("snapshot-id", snapshot.getId()).build()));
+         assertNotNull(result);
+         assertEquals(result, snapshot);
+      }
+   }
+
+   @Test(expectedExceptions = AWSResponseException.class)
+   void testDescribeSnapshotsWithFilterInvalid() {
+      String region = defaultRegion;
+      SortedSet<Snapshot> allResults = Sets.newTreeSet(client.describeSnapshotsInRegion(region));
+      assertNotNull(allResults);
+      if (!allResults.isEmpty()) {
+         Snapshot snapshot = allResults.last();
+         Snapshot result = Iterables.getOnlyElement(client.describeSnapshotsInRegionWithFilter(region,
+                 ImmutableMultimap.<String, String>builder()
+                         .put("invalid-filter", snapshot.getId()).build()));
       }
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index b0b4fba..fefd2a7 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticBlockStoreApiTest.java
@@ -70,11 +70,11 @@ public class ElasticBlockStoreApiTest extends BaseEC2ApiTest<ElasticBlockStoreAp
                                             .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("Signature", "nNxWg5dwYZEQu1QCzCtNp7iDmPR8wXXdKhWmLEKFLGI%3D")
                                             .addFormParam("SignatureMethod", "HmacSHA256")
                                             .addFormParam("SignatureVersion", "2")
                                             .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                            .addFormParam("Version", "2010-06-15")
+                                            .addFormParam("Version", "2010-08-31")
                                             .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testDescribeVolumes() throws SecurityException, NoSuchMethodException, IOException {
@@ -119,11 +119,11 @@ public class ElasticBlockStoreApiTest extends BaseEC2ApiTest<ElasticBlockStoreAp
                                          .addFormParam("Action", "AttachVolume")
                                          .addFormParam("Device", "/device")
                                          .addFormParam("InstanceId", "instanceId")
-                                         .addFormParam("Signature", "LaOppR61eWpdNgMYJ3ccfo9vzbmUyJf9Ars%2Bbcu4OGI%3D")
+                                         .addFormParam("Signature", "0%2BUY5oCQzoJapEHq4Dl2R/0nAA8uXEHqvHbnnNI5NcA%3D")
                                          .addFormParam("SignatureMethod", "HmacSHA256")
                                          .addFormParam("SignatureVersion", "2")
                                          .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                         .addFormParam("Version", "2010-06-15")
+                                         .addFormParam("Version", "2010-08-31")
                                          .addFormParam("VolumeId", "id")
                                          .addFormParam("AWSAccessKeyId", "identity").build();
 
@@ -151,11 +151,11 @@ public class ElasticBlockStoreApiTest extends BaseEC2ApiTest<ElasticBlockStoreAp
                                          .addHeader("Host", "ec2.us-east-1.amazonaws.com")
                                          .addFormParam("Action", "DetachVolume")
                                          .addFormParam("Force", "false")
-                                         .addFormParam("Signature", "4c6EmHwCYbe%2BifuUV0PNXpKfReoZvJXyme37mKtnLk8%3D")
+                                         .addFormParam("Signature", "tfNB1g2WVqb3EwvBJlk4duU1H1fDOa1SBstsm1elpbg%3D")
                                          .addFormParam("SignatureMethod", "HmacSHA256")
                                          .addFormParam("SignatureVersion", "2")
                                          .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                         .addFormParam("Version", "2010-06-15")
+                                         .addFormParam("Version", "2010-08-31")
                                          .addFormParam("VolumeId", "id")
                                          .addFormParam("AWSAccessKeyId", "identity").build();
 
@@ -185,11 +185,11 @@ public class ElasticBlockStoreApiTest extends BaseEC2ApiTest<ElasticBlockStoreAp
                                                 .addFormParam("Device", "/device")
                                                 .addFormParam("Force", "true")
                                                 .addFormParam("InstanceId", "instanceId")
-                                                .addFormParam("Signature", "GrUGXc6H5W%2BNF8zcXU8gSRbt1ELt%2BTcCDEvbY1a88NE%3D")
+                                                .addFormParam("Signature", "VFhgwdkKBKXr/dEn2gvk6Vqq3JIunw4zZgM2Tt/ouME%3D")
                                                 .addFormParam("SignatureMethod", "HmacSHA256")
                                                 .addFormParam("SignatureVersion", "2")
                                                 .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                .addFormParam("Version", "2010-06-15")
+                                                .addFormParam("Version", "2010-08-31")
                                                 .addFormParam("VolumeId", "id")
                                                 .addFormParam("AWSAccessKeyId", "identity").build();
 
@@ -311,7 +311,7 @@ public class ElasticBlockStoreApiTest extends BaseEC2ApiTest<ElasticBlockStoreAp
                                                                  .addFormParam("Action", "ModifySnapshotAttribute")
                                                                  .addFormParam("Attribute", "createVolumePermission")
                                                                  .addFormParam("OperationType", "add")
-                                                                 .addFormParam("Signature", "AizV1N1rCCXi%2BbzXX/Vz7shFq9yAJAwcmAGyRQMH%2Bjs%3D")
+                                                                 .addFormParam("Signature", "s8m8DqQRXmecWguuRjxfl3Ibd%2B1AjjktGzTlJLUTcPc%3D")
                                                                  .addFormParam("SignatureMethod", "HmacSHA256")
                                                                  .addFormParam("SignatureVersion", "2")
                                                                  .addFormParam("SnapshotId", "snapshotId")
@@ -319,7 +319,7 @@ public class ElasticBlockStoreApiTest extends BaseEC2ApiTest<ElasticBlockStoreAp
                                                                  .addFormParam("UserGroup.1", "all")
                                                                  .addFormParam("UserId.1", "bob")
                                                                  .addFormParam("UserId.2", "sue")
-                                                                 .addFormParam("Version", "2010-06-15")
+                                                                 .addFormParam("Version", "2010-08-31")
                                                                  .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testAddCreateVolumePermissionsToSnapshot() throws SecurityException, NoSuchMethodException, IOException {
@@ -348,7 +348,7 @@ public class ElasticBlockStoreApiTest extends BaseEC2ApiTest<ElasticBlockStoreAp
                                                                       .addFormParam("Action", "ModifySnapshotAttribute")
                                                                       .addFormParam("Attribute", "createVolumePermission")
                                                                       .addFormParam("OperationType", "remove")
-                                                                      .addFormParam("Signature", "Lmlt2daM%2BJ4kIoU9HmCempwVGZP1fC6V%2Br9o8MQjYy8%3D")
+                                                                      .addFormParam("Signature", "RzxHUIWV80cyhQDtrMiHDWUosS1g8cn1%2B7ONLJCe1dg%3D")
                                                                       .addFormParam("SignatureMethod", "HmacSHA256")
                                                                       .addFormParam("SignatureVersion", "2")
                                                                       .addFormParam("SnapshotId", "snapshotId")
@@ -356,7 +356,7 @@ public class ElasticBlockStoreApiTest extends BaseEC2ApiTest<ElasticBlockStoreAp
                                                                       .addFormParam("UserGroup.1", "all")
                                                                       .addFormParam("UserId.1", "bob")
                                                                       .addFormParam("UserId.2", "sue")
-                                                                      .addFormParam("Version", "2010-06-15")
+                                                                      .addFormParam("Version", "2010-08-31")
                                                                       .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testRemoveCreateVolumePermissionsFromSnapshot() throws SecurityException, NoSuchMethodException,

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiExpectTest.java
new file mode 100644
index 0000000..824a4ff
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiExpectTest.java
@@ -0,0 +1,102 @@
+/*
+ * 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.Iterables.getOnlyElement;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.Properties;
+
+import org.jclouds.Constants;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.domain.PublicIpInstanceIdPair;
+import org.jclouds.ec2.internal.BaseEC2ApiExpectTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.rest.internal.BaseRestApiExpectTest;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Andrew Bayer
+ *
+ * @see org.jclouds.ec2.features.ElasticIPAddressApi
+ */
+@Test(groups = "unit")
+public class ElasticIPAddressApiExpectTest extends BaseEC2ApiExpectTest<EC2Api> {
+
+   protected Properties setupProperties() {
+      Properties props = super.setupProperties();
+      props.put(Constants.PROPERTY_API_VERSION, "2010-08-31");
+      return props;
+   }
+
+   HttpRequest filter =
+           HttpRequest.builder()
+                   .method("POST")
+                   .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                   .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                   .payload(BaseRestApiExpectTest.payloadFromStringWithContentType(
+                           "Action=DescribeAddresses" +
+                                   "&Filter.1.Name=instance-id" +
+                                   "&Filter.1.Value.1=i-f15ebb98" +
+                                   "&Signature=dJbTUsBGHSrarQQAwmLm8LLI255R/lzdE7ZcYJucOzI%3D" +
+                                   "&SignatureMethod=HmacSHA256" +
+                                   "&SignatureVersion=2" +
+                                   "&Timestamp=2012-04-16T15%3A54%3A08.897Z" +
+                                   "&Version=2010-08-31" +
+                                   "&AWSAccessKeyId=identity",
+                           "application/x-www-form-urlencoded"))
+                   .build();
+
+   public void testFilterWhenResponseIs2xx() throws Exception {
+
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResourceWithContentType("/describe_addresses_single.xml", "text/xml")).build();
+
+
+      EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse,
+              filter, filterResponse);
+
+      PublicIpInstanceIdPair address = getOnlyElement(apiWhenExist.getElasticIPAddressApi()
+              .get().describeAddressesInRegionWithFilter("us-east-1",
+                      ImmutableMultimap.<String, String>builder()
+                              .put("instance-id", "i-f15ebb98")
+                              .build()));
+      assertNotNull(address, "address should not be null");
+
+      assertEquals(address.getPublicIp(), "67.202.55.255");
+   }
+
+   public void testFilterWhenResponseIs404() throws Exception {
+
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build();
+
+      EC2Api apiWhenDontExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse,
+              filter, filterResponse);
+
+      assertEquals(apiWhenDontExist.getElasticIPAddressApi()
+              .get().describeAddressesInRegionWithFilter("us-east-1",
+                      ImmutableMultimap.<String, String>builder()
+                              .put("instance-id", "i-f15ebb98")
+                              .build()), ImmutableSet.of());
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 119c2de..f435404 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiLiveTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiLiveTest.java
@@ -23,12 +23,11 @@ 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.ImmutableMultimap;
 import com.google.common.collect.Sets;
 
 /**
@@ -58,13 +57,19 @@ public class ElasticIPAddressApiLiveTest extends BaseComputeServiceContextLiveTe
       for (String region : ec2Api.getConfiguredRegions()) {
          SortedSet<PublicIpInstanceIdPair> allResults = Sets.newTreeSet(client.describeAddressesInRegion(region));
          assertNotNull(allResults);
-         if (allResults.size() >= 1) {
+         if (!allResults.isEmpty()) {
             PublicIpInstanceIdPair pair = allResults.last();
             SortedSet<PublicIpInstanceIdPair> result = Sets.newTreeSet(client.describeAddressesInRegion(region, pair
                      .getPublicIp()));
             assertNotNull(result);
             PublicIpInstanceIdPair compare = result.last();
             assertEquals(compare, pair);
+
+            SortedSet<PublicIpInstanceIdPair> filterResult = Sets.newTreeSet(client.describeAddressesInRegionWithFilter(
+                    region, ImmutableMultimap.<String, String>builder().put("public-ip", pair.getPublicIp()).build()));
+            assertNotNull(filterResult);
+            PublicIpInstanceIdPair filterCompare = filterResult.last();
+            assertEquals(filterCompare, pair);
          }
       }
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index d230ca4..abdfae6 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/ElasticIPAddressApiTest.java
@@ -63,11 +63,11 @@ public class ElasticIPAddressApiTest extends BaseEC2ApiTest<ElasticIPAddressApi>
                                              .addFormParam("Action", "AssociateAddress")
                                              .addFormParam("InstanceId", "me")
                                              .addFormParam("PublicIp", "127.0.0.1")
-                                             .addFormParam("Signature", "YmPyvEljuFw0INSUbQx5xAhC/1GQ4a1Ht6TdoXeMc9Y%3D")
+                                             .addFormParam("Signature", "nLU6xGLqXtT/dmyAvkN4BdL/3CxQlDWJYeskikhl54k%3D")
                                              .addFormParam("SignatureMethod", "HmacSHA256")
                                              .addFormParam("SignatureVersion", "2")
                                              .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                             .addFormParam("Version", "2010-06-15")
+                                             .addFormParam("Version", "2010-08-31")
                                              .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testAssociateAddress() throws SecurityException, NoSuchMethodException, IOException {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiExpectTest.java
new file mode 100644
index 0000000..0c19bd7
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiExpectTest.java
@@ -0,0 +1,101 @@
+/*
+ * 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.Iterables.getOnlyElement;
+import static org.testng.Assert.assertNotNull;
+
+import java.util.Properties;
+
+import org.jclouds.Constants;
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.domain.RunningInstance;
+import org.jclouds.ec2.internal.BaseEC2ApiExpectTest;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.http.HttpResponse;
+import org.jclouds.rest.internal.BaseRestApiExpectTest;
+import org.jclouds.util.Strings2;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Andrew Bayer
+ *
+ * @see InstanceApi
+ */
+@Test(groups = "unit")
+public class InstanceApiExpectTest extends BaseEC2ApiExpectTest<EC2Api> {
+
+   protected Properties setupProperties() {
+      Properties props = super.setupProperties();
+      props.put(Constants.PROPERTY_API_VERSION, "2010-08-31");
+      return props;
+   }
+
+   HttpRequest filter =
+           HttpRequest.builder()
+                   .method("POST")
+                   .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                   .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                   .payload(BaseRestApiExpectTest.payloadFromStringWithContentType(
+                           "Action=DescribeInstances" +
+                                   "&Filter.1.Name=key-name" +
+                                   "&Filter.1.Value.1=" + Strings2.urlEncode("adriancole.ec21") +
+                                   "&Signature=%2B2ktAljlAPNUMAJUFh3poQrTvwcwWytuQFBg/ktKdTc%3D" +
+                                   "&SignatureMethod=HmacSHA256" +
+                                   "&SignatureVersion=2" +
+                                   "&Timestamp=2012-04-16T15%3A54%3A08.897Z" +
+                                   "&Version=2010-08-31" +
+                                   "&AWSAccessKeyId=identity",
+                           "application/x-www-form-urlencoded"))
+                   .build();
+
+   public void testFilterWhenResponseIs2xx() throws Exception {
+
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResourceWithContentType("/describe_instances_running.xml", "text/xml")).build();
+
+
+      EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse,
+              filter, filterResponse);
+
+      RunningInstance instance = getOnlyElement(getOnlyElement(apiWhenExist.getInstanceApi().get().describeInstancesInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("key-name", "adriancole.ec21")
+                      .build())));
+      assertNotNull(instance, "Instance should not be null");
+
+      Assert.assertEquals(instance.getId(), "i-0799056f");
+   }
+
+   public void testFilterWhenResponseIs404() throws Exception {
+
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build();
+
+      EC2Api apiWhenDontExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse,
+              filter, filterResponse);
+
+      Assert.assertEquals(apiWhenDontExist.getInstanceApi().get().describeInstancesInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("key-name", "adriancole.ec21")
+                      .build()), ImmutableSet.of());
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 57f9441..6b7818a 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiLiveTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiLiveTest.java
@@ -16,22 +16,26 @@
  */
 package org.jclouds.ec2.features;
 
+import static com.google.common.collect.Iterables.getFirst;
 import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
 
 import java.util.Set;
 
+import org.jclouds.aws.AWSResponseException;
 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;
 
+import com.google.common.collect.ImmutableMultimap;
+
 /**
  * Tests behavior of {@code EC2Api}
  * 
- * @author Adrian Cole
+ * @author Adrian Cole, Andrew Bayer
  */
 @Test(groups = "live", singleThreaded = true, testName = "InstanceApiLiveTest")
 public class InstanceApiLiveTest extends BaseComputeServiceContextLiveTest {
@@ -55,7 +59,39 @@ public class InstanceApiLiveTest extends BaseComputeServiceContextLiveTest {
       for (String region : ec2Api.getConfiguredRegions()) {
          Set<? extends Reservation<? extends RunningInstance>> allResults = client.describeInstancesInRegion(region);
          assertNotNull(allResults);
-         assert allResults.size() >= 0 : allResults.size();
       }
    }
-}
+
+   @Test
+   void testFilterInstances() {
+      for (String region : view.unwrapApi(EC2Api.class).getAvailabilityZoneAndRegionApi().get().describeRegions().keySet()) {
+         Set<? extends Reservation<? extends RunningInstance>> allResults = client.describeInstancesInRegion(region);
+         assertNotNull(allResults);
+
+         if (!allResults.isEmpty())  {
+            RunningInstance instance = getFirst(getFirst(allResults, null), null);
+
+            assertNotNull(instance);
+
+            Set<? extends Reservation<? extends RunningInstance>> filterResults = client.describeInstancesInRegionWithFilter(region,
+                    ImmutableMultimap.<String, String>builder()
+                            .put("key-name", instance.getKeyName())
+                            .build());
+
+            assertNotNull(filterResults);
+            assertTrue(!filterResults.isEmpty(), "No results found for filter, but there should be.");
+
+         }
+      }
+   }
+
+   @Test(expectedExceptions = AWSResponseException.class)
+   void testInvalidFilterInstances() {
+      for (String region : view.unwrapApi(EC2Api.class).getAvailabilityZoneAndRegionApi().get().describeRegions().keySet()) {
+         Set<? extends Reservation<? extends RunningInstance>> filterResults = client.describeInstancesInRegionWithFilter(region,
+                 ImmutableMultimap.<String, String>builder()
+                         .put("invalid-key", "some-value")
+                         .build());
+
+      }
+   }}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 2f17735..fbeb57a 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/InstanceApiTest.java
@@ -351,12 +351,12 @@ public class InstanceApiTest extends BaseEC2ApiTest<InstanceApi> {
                                                    .addFormParam("Action", "ModifyInstanceAttribute")
                                                    .addFormParam("Attribute", "userData")
                                                    .addFormParam("InstanceId", "1")
-                                                   .addFormParam("Signature", "LfUmzLM5DsACR5nQcEfGF5FPdznOwwhJ7tjhBWfHtGs%3D")
+                                                   .addFormParam("Signature", "SfxT/1i/WokibleyEHo0zHizHisLzbDzzRxfOdnr1vY%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("Version", "2010-08-31")
                                                    .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testSetUserDataForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
@@ -384,12 +384,12 @@ public class InstanceApiTest extends BaseEC2ApiTest<InstanceApi> {
                                                   .addFormParam("Action", "ModifyInstanceAttribute")
                                                   .addFormParam("Attribute", "ramdisk")
                                                   .addFormParam("InstanceId", "1")
-                                                  .addFormParam("Signature", "qx6NeVbihiYrKvi5Oe5LzMsGHTjS7%2BqoNhh2abt275g%3D")
+                                                  .addFormParam("Signature", "aMQzFsknmQt1OA8Rb8aIzZoFXGK23UvrMIy8imNVUeQ%3D")
                                                   .addFormParam("SignatureMethod", "HmacSHA256")
                                                   .addFormParam("SignatureVersion", "2")
                                                   .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
                                                   .addFormParam("Value", "test")
-                                                  .addFormParam("Version", "2010-06-15")
+                                                  .addFormParam("Version", "2010-08-31")
                                                   .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testSetRamdiskForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
@@ -417,12 +417,12 @@ public class InstanceApiTest extends BaseEC2ApiTest<InstanceApi> {
                                                  .addFormParam("Action", "ModifyInstanceAttribute")
                                                  .addFormParam("Attribute", "kernel")
                                                  .addFormParam("InstanceId", "1")
-                                                 .addFormParam("Signature", "juSiuoiXJzTxj3q0LUW2528HzDyP4JAcKin%2BI4AuIT0%3D")
+                                                 .addFormParam("Signature", "GaQ9sC0uXHlN5JAMWQpYx%2Bc3XaF38qZgJex/kyqdR1E%3D")
                                                  .addFormParam("SignatureMethod", "HmacSHA256")
                                                  .addFormParam("SignatureVersion", "2")
                                                  .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
                                                  .addFormParam("Value", "test")
-                                                 .addFormParam("Version", "2010-06-15")
+                                                 .addFormParam("Version", "2010-08-31")
                                                  .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testSetKernelForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
@@ -450,12 +450,12 @@ public class InstanceApiTest extends BaseEC2ApiTest<InstanceApi> {
                                                       .addFormParam("Action", "ModifyInstanceAttribute")
                                                       .addFormParam("Attribute", "disableApiTermination")
                                                       .addFormParam("InstanceId", "1")
-                                                      .addFormParam("Signature", "tiBMWWTi22BWeAjsRfuzVom0tQgsOBeYTkatMuWRrbg%3D")
+                                                      .addFormParam("Signature", "hErzi%2Bf4jBADviJ%2BLVTTGhlHWhMR/pyPUSBZgaHC79I%3D")
                                                       .addFormParam("SignatureMethod", "HmacSHA256")
                                                       .addFormParam("SignatureVersion", "2")
                                                       .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
                                                       .addFormParam("Value", "true")
-                                                      .addFormParam("Version", "2010-06-15")
+                                                      .addFormParam("Version", "2010-08-31")
                                                       .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testSetApiTerminationDisabledForInstanceInRegion() throws SecurityException, NoSuchMethodException,
@@ -484,12 +484,12 @@ public class InstanceApiTest extends BaseEC2ApiTest<InstanceApi> {
                                                     .addFormParam("Action", "ModifyInstanceAttribute")
                                                     .addFormParam("Attribute", "instanceType")
                                                     .addFormParam("InstanceId", "1")
-                                                    .addFormParam("Signature", "XK%2BzQmQ0S57gXIgVRMqUkKunURN9TaCJD1YWiYMAOHo%3D")
+                                                    .addFormParam("Signature", "OYJQ1w79NoxkcrawNK6U71k3Wl78kqz2ikzTXmQCX2E%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("Version", "2010-08-31")
                                                     .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testSetInstanceTypeForInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
@@ -517,12 +517,12 @@ public class InstanceApiTest extends BaseEC2ApiTest<InstanceApi> {
                                                                  .addFormParam("Action", "ModifyInstanceAttribute")
                                                                  .addFormParam("Attribute", "instanceInitiatedShutdownBehavior")
                                                                  .addFormParam("InstanceId", "1")
-                                                                 .addFormParam("Signature", "s5xBMLd%2BXNVp44x7C6qVE58qBov//f6yvxoM757KcZU%3D")
+                                                                 .addFormParam("Signature", "2Tgi9M9AcCv5Y%2BEXwq0SD6g8bBGtPPEgjdTtfdGZQlI%3D")
                                                                  .addFormParam("SignatureMethod", "HmacSHA256")
                                                                  .addFormParam("SignatureVersion", "2")
                                                                  .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
                                                                  .addFormParam("Value", "terminate")
-                                                                 .addFormParam("Version", "2010-06-15")
+                                                                 .addFormParam("Version", "2010-08-31")
                                                                  .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testSetInstanceInitiatedShutdownBehaviorForInstanceInRegion() throws SecurityException,

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiExpectTest.java
new file mode 100644
index 0000000..4b08ba7
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiExpectTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.Iterables.getOnlyElement;
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.domain.KeyPair;
+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.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Andrew Bayer
+ */
+@Test(groups = "unit", testName = "KeyPairApiExpectTest")
+public class KeyPairApiExpectTest extends BaseEC2ApiExpectTest<EC2Api> {
+
+   HttpRequest filter = HttpRequest.builder().method("POST")
+           .endpoint("https://ec2.us-east-1.amazonaws.com/")
+           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+           .addFormParam("Action", "DescribeKeyPairs")
+           .addFormParam("Filter.1.Name", "key-name")
+           .addFormParam("Filter.1.Value.1", "gsg-keypair")
+           .addFormParam("Signature", "xg8vGx%2Bv9UEG0%2BFGy%2BhincdI2ziWLbwPJvW85l%2Bvqwg%3D")
+           .addFormParam("SignatureMethod", "HmacSHA256")
+           .addFormParam("SignatureVersion", "2")
+           .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z")
+           .addFormParam("Version", "2010-08-31")
+           .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testFilterWhenResponseIs2xx() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResourceWithContentType("/describe_keypairs.xml", "text/xml")).build();
+
+      EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse);
+
+      KeyPair keyPair = getOnlyElement(apiWhenExist.getKeyPairApi().get().describeKeyPairsInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("key-name", "gsg-keypair")
+                      .build()));
+
+      assertEquals(keyPair.getKeyName(), "gsg-keypair");
+   }
+
+   public void testFilterWhenResponseIs404() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build();
+
+      EC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse);
+
+      assertEquals(apiWhenNotExist.getKeyPairApi().get().describeKeyPairsInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("key-name", "gsg-keypair")
+                      .build()),
+              ImmutableSet.of());
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index ad693ac..b9219a5 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiLiveTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/KeyPairApiLiveTest.java
@@ -22,6 +22,7 @@ import static org.testng.Assert.assertNotNull;
 import java.util.Set;
 import java.util.SortedSet;
 
+import org.jclouds.aws.AWSResponseException;
 import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
 import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.domain.KeyPair;
@@ -29,6 +30,7 @@ import org.testng.annotations.AfterClass;
 import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
+import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.Sets;
 
 /**
@@ -58,7 +60,7 @@ public class KeyPairApiLiveTest extends BaseComputeServiceContextLiveTest {
       for (String region : ec2Api.getConfiguredRegions()) {
          SortedSet<KeyPair> allResults = Sets.newTreeSet(client.describeKeyPairsInRegion(region));
          assertNotNull(allResults);
-         if (allResults.size() >= 1) {
+         if (!allResults.isEmpty()) {
             KeyPair pair = allResults.last();
             SortedSet<KeyPair> result = Sets.newTreeSet(client.describeKeyPairsInRegion(region, pair.getKeyName()));
             assertNotNull(result);
@@ -68,6 +70,37 @@ public class KeyPairApiLiveTest extends BaseComputeServiceContextLiveTest {
       }
    }
 
+   @Test
+   void testDescribeKeyPairsWithFilter() {
+      for (String region : ec2Api.getConfiguredRegions()) {
+         SortedSet<KeyPair> allResults = Sets.newTreeSet(client.describeKeyPairsInRegion(region));
+         assertNotNull(allResults);
+         if (!allResults.isEmpty()) {
+            KeyPair pair = allResults.last();
+            SortedSet<KeyPair> result = Sets.newTreeSet(client.describeKeyPairsInRegionWithFilter(region,
+                    ImmutableMultimap.<String, String>builder()
+                            .put("key-name", pair.getKeyName()).build()));
+            assertNotNull(result);
+            KeyPair compare = result.last();
+            assertEquals(compare, pair);
+         }
+      }
+   }
+
+   @Test(expectedExceptions = AWSResponseException.class)
+   void testDescribeKeyPairsWithInvalidFilter() {
+      for (String region : ec2Api.getConfiguredRegions()) {
+         SortedSet<KeyPair> allResults = Sets.newTreeSet(client.describeKeyPairsInRegion(region));
+         assertNotNull(allResults);
+         if (!allResults.isEmpty()) {
+            KeyPair pair = allResults.last();
+            SortedSet<KeyPair> result = Sets.newTreeSet(client.describeKeyPairsInRegionWithFilter(region,
+                    ImmutableMultimap.<String, String>builder()
+                            .put("invalid-filter", pair.getKeyName()).build()));
+         }
+      }
+   }
+
    public static final String PREFIX = System.getProperty("user.name") + "-ec2";
 
    @Test

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiExpectTest.java
new file mode 100644
index 0000000..9e5491e
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiExpectTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.Iterables.getOnlyElement;
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.domain.SecurityGroup;
+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.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Andrew Bayer
+ */
+@Test(groups = "unit", testName = "SecurityGroupApiExpectTest")
+public class SecurityGroupApiExpectTest extends BaseEC2ApiExpectTest<EC2Api> {
+
+   HttpRequest filter = HttpRequest.builder().method("POST")
+           .endpoint("https://ec2.us-east-1.amazonaws.com/")
+           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+           .addFormParam("Action", "DescribeSecurityGroups")
+           .addFormParam("Filter.1.Name", "owner-id")
+           .addFormParam("Filter.1.Value.1", "993194456877")
+           .addFormParam("Signature", "zk8EEWkG9Hi0bBLPueF9WdTUKapxQqUXgyJTxeZHXBc%3D")
+           .addFormParam("SignatureMethod", "HmacSHA256")
+           .addFormParam("SignatureVersion", "2")
+           .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z")
+           .addFormParam("Version", "2010-08-31")
+           .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testFilterWhenResponseIs2xx() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResourceWithContentType("/describe_securitygroups_extension_single.xml", "text/xml")).build();
+
+      EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse);
+
+      SecurityGroup group = getOnlyElement(apiWhenExist.getSecurityGroupApi().get().describeSecurityGroupsInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("owner-id", "993194456877")
+                      .build()));
+
+      assertEquals(group.getId(), "sg-3c6ef654");
+   }
+
+   public void testFilterWhenResponseIs404() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build();
+
+      EC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse);
+
+      assertEquals(apiWhenNotExist.getSecurityGroupApi().get().describeSecurityGroupsInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("owner-id", "993194456877")
+                      .build()),
+              ImmutableSet.of());
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 220e14f..edfc3ca 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiLiveTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiLiveTest.java
@@ -27,9 +27,9 @@ import static org.testng.Assert.assertTrue;
 
 import java.util.Set;
 
+import org.jclouds.aws.AWSResponseException;
 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;
@@ -70,20 +70,66 @@ public class SecurityGroupApiLiveTest extends BaseComputeServiceContextLiveTest
       for (String region : ec2Api.getConfiguredRegions()) {
          Set<SecurityGroup> allResults = client.describeSecurityGroupsInRegion(region);
          assertNotNull(allResults);
-         if (allResults.size() >= 1) {
+         if (!allResults.isEmpty()) {
             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();
+                    .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()));
+                    group.getName()));
             // the above command has a chance of returning less groups than the original
-            assertTrue(expected.containsAll(result));
+            assertTrue(expected.containsAll(result), "group(s) for name not found");
+         }
+      }
+   }
+
+   @Test
+   void testFilter() {
+      for (String region : ec2Api.getConfiguredRegions()) {
+         Set<SecurityGroup> allResults = client.describeSecurityGroupsInRegion(region);
+         assertNotNull(allResults);
+         if (!allResults.isEmpty()) {
+            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.describeSecurityGroupsInRegionWithFilter(region,
+                    ImmutableMultimap.<String, String>builder()
+                            .put("group-name", group.getName()).build()));
+            // the above command has a chance of returning less groups than the original
+            assertTrue(expected.containsAll(result), "group(s) for name not found");
+         }
+      }
+   }
+
+   @Test(expectedExceptions = AWSResponseException.class)
+   void testFilterInvalid() {
+      for (String region : ec2Api.getConfiguredRegions()) {
+         Set<SecurityGroup> allResults = client.describeSecurityGroupsInRegion(region);
+         assertNotNull(allResults);
+         if (!allResults.isEmpty()) {
+            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.describeSecurityGroupsInRegionWithFilter(region,
+                    ImmutableMultimap.<String, String>builder()
+                            .put("invalid-filter", group.getName()).build()));
          }
       }
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 85b7374..b5d2d17 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiTest.java
@@ -65,11 +65,11 @@ public class SecurityGroupApiTest extends BaseEC2ApiTest<SecurityGroupApi> {
                                                 .addFormParam("Action", "CreateSecurityGroup")
                                                 .addFormParam("GroupDescription", "description")
                                                 .addFormParam("GroupName", "name")
-                                                .addFormParam("Signature", "F3o0gnZcX9sWrtDUhVwi3k5GY2JKLP0Dhi6CcEqK2vE%3D")
+                                                .addFormParam("Signature", "msp9zFJLrRXYsVu/vbSZE8tQVS/TEvF0Cu/ldYVFdcA%3D")
                                                 .addFormParam("SignatureMethod", "HmacSHA256")
                                                 .addFormParam("SignatureVersion", "2")
                                                 .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                .addFormParam("Version", "2010-06-15")
+                                                .addFormParam("Version", "2010-08-31")
                                                 .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testCreateSecurityGroup() throws SecurityException, NoSuchMethodException, IOException {
@@ -153,12 +153,12 @@ public class SecurityGroupApiTest extends BaseEC2ApiTest<SecurityGroupApi> {
                                                               .addFormParam("FromPort", "6000")
                                                               .addFormParam("GroupName", "group")
                                                               .addFormParam("IpProtocol", "tcp")
-                                                              .addFormParam("Signature", "6NQega9YUGDxdwk3Y0Hv71u/lHi%2B0D6qMCJLpJVD/aI%3D")
+                                                              .addFormParam("Signature", "xeaZpQ1Lvhp%2BqETpEzOPGHW6isAWYwgtBdCnTqWzkAw%3D")
                                                               .addFormParam("SignatureMethod", "HmacSHA256")
                                                               .addFormParam("SignatureVersion", "2")
                                                               .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
                                                               .addFormParam("ToPort", "7000")
-                                                              .addFormParam("Version", "2010-06-15")
+                                                              .addFormParam("Version", "2010-08-31")
                                                               .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testAuthorizeSecurityGroupIngressCidr() throws SecurityException, NoSuchMethodException, IOException {
@@ -207,12 +207,12 @@ public class SecurityGroupApiTest extends BaseEC2ApiTest<SecurityGroupApi> {
                                                            .addFormParam("FromPort", "6000")
                                                            .addFormParam("GroupName", "group")
                                                            .addFormParam("IpProtocol", "tcp")
-                                                           .addFormParam("Signature", "WPlDYXI8P6Ip4F2JIEP3lWrVlP/7gxbZvlshKYlrvxk%3D")
+                                                           .addFormParam("Signature", "P5lxCXMwz6FE8Wo79nEMh8clgLDK3rZxCPRTOKssKKQ%3D")
                                                            .addFormParam("SignatureMethod", "HmacSHA256")
                                                            .addFormParam("SignatureVersion", "2")
                                                            .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
                                                            .addFormParam("ToPort", "7000")
-                                                           .addFormParam("Version", "2010-06-15")
+                                                           .addFormParam("Version", "2010-08-31")
                                                            .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testRevokeSecurityGroupIngressCidr() throws SecurityException, NoSuchMethodException, IOException {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiExpectTest.java
index 87dfb87..457b08d 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiExpectTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiExpectTest.java
@@ -16,16 +16,21 @@
  */
 package org.jclouds.ec2.features;
 
+import static com.google.common.collect.Iterables.getOnlyElement;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNull;
 
 import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.domain.BundleTask;
 import org.jclouds.ec2.internal.BaseEC2ApiExpectTest;
 import org.jclouds.ec2.parse.GetPasswordDataResponseTest;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
 import org.testng.annotations.Test;
 
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+
 /**
  * @author Adrian Cole
  */
@@ -40,16 +45,28 @@ public class WindowsApiExpectTest extends BaseEC2ApiExpectTest<EC2Api> {
                                    payloadFromStringWithContentType(
                                          "Action=GetPasswordData" +
                                                "&InstanceId=i-2574e22a" +
-                                               "&Signature=vX1Tskc4VuBUWPqsJ%2BzcjEj6/2iMCKzqjWnKFXRkDdA%3D" +
+                                               "&Signature=PMr4kU4p%2BSF2ISHXAFUme1kNh%2BCqftIUQchuw3vhKCw%3D" +
                                                "&SignatureMethod=HmacSHA256" +
                                                "&SignatureVersion=2" +
                                                "&Timestamp=2012-04-16T15%3A54%3A08.897Z" +
-                                               "&Version=2010-06-15" +
+                                               "&Version=2010-08-31" +
                                                "&AWSAccessKeyId=identity",
                                          "application/x-www-form-urlencoded"))
                                 .build();
-  
-   
+
+   HttpRequest filter = HttpRequest.builder().method("POST")
+           .endpoint("https://ec2.us-east-1.amazonaws.com/")
+           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+           .addFormParam("Action", "DescribeBundleTasks")
+           .addFormParam("Filter.1.Name", "instance-id")
+           .addFormParam("Filter.1.Value.1", "i-12345678")
+           .addFormParam("Signature", "y0y3UBUKU/uYwbWPTCbkXzprU%2B8fMhg5LfF%2B5hWU2F4%3D")
+           .addFormParam("SignatureMethod", "HmacSHA256")
+           .addFormParam("SignatureVersion", "2")
+           .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z")
+           .addFormParam("Version", "2010-08-31")
+           .addFormParam("AWSAccessKeyId", "identity").build();
+
    public void testGetPasswordDataWhenResponseIs2xx() throws Exception {
 
       HttpResponse getResponse = HttpResponse.builder().statusCode(200)
@@ -68,4 +85,31 @@ public class WindowsApiExpectTest extends BaseEC2ApiExpectTest<EC2Api> {
 
       assertNull(apiWhenDontExist.getWindowsApi().get().getPasswordDataForInstance("i-2574e22a"));
    }
+
+   public void testFilterBundleTasksWhenResponseIs2xx() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResourceWithContentType("/describe_bundle_tasks.xml", "text/xml")).build();
+
+      EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse);
+
+      BundleTask task = getOnlyElement(apiWhenExist.getWindowsApi().get().describeBundleTasksInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("instance-id", "i-12345678")
+                      .build()));
+
+      assertEquals(task.getBundleId(), "bun-c1a540a8");
+   }
+
+   public void testFilterBundleTasksWhenResponseIs404() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build();
+
+      EC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse);
+
+      assertEquals(apiWhenNotExist.getWindowsApi().get().describeBundleTasksInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("instance-id", "i-12345678")
+                      .build()),
+              ImmutableSet.of());
+   }
+
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 572b247..d6b44e7 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/WindowsApiTest.java
@@ -45,7 +45,7 @@ public class WindowsApiTest extends BaseEC2ApiTest<WindowsApi> {
                                                    .addHeader("Host", "ec2.us-east-1.amazonaws.com")
                                                    .addFormParam("Action", "BundleInstance")
                                                    .addFormParam("InstanceId", "i-e468cd8d")
-                                                   .addFormParam("Signature", "Uw5gH4eN3H8KXeFfIVLDDt88ApYn8L4pkf31hpojpcM%3D")
+                                                   .addFormParam("Signature", "78A6SjliGJg%2BKzaICB9I4bqEXFoNa4FKonuIwAj9hik%3D")
                                                    .addFormParam("SignatureMethod", "HmacSHA256")
                                                    .addFormParam("SignatureVersion", "2")
                                                    .addFormParam("Storage.S3.Bucket", "my-bucket")
@@ -53,7 +53,7 @@ public class WindowsApiTest extends BaseEC2ApiTest<WindowsApi> {
                                                    .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("Version", "2010-08-31")
                                                    .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testBundleInstanceInRegion() throws SecurityException, NoSuchMethodException, IOException {
@@ -88,7 +88,7 @@ public class WindowsApiTest extends BaseEC2ApiTest<WindowsApi> {
                                                           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
                                                           .addFormParam("Action", "BundleInstance")
                                                           .addFormParam("InstanceId","i-e468cd8d")
-                                                          .addFormParam("Signature", "ahFjX9Tv/DGMFq9EFdF1mWSAnTKyQyyIj7dWJxBOhaE%3D")
+                                                          .addFormParam("Signature", "9UbWwb%2BnO2vHn2O59K9FpmaK445RwX7vXsruHRznwik%3D")
                                                           .addFormParam("SignatureMethod", "HmacSHA256")
                                                           .addFormParam("SignatureVersion", "2")
                                                           .addFormParam("Storage.S3.AWSAccessKeyId", "10QMXFEV71ZS32XQFTR2")
@@ -97,7 +97,7 @@ public class WindowsApiTest extends BaseEC2ApiTest<WindowsApi> {
                                                           .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("Version", "2010-08-31")
                                                           .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testBundleInstanceInRegionOptions() throws SecurityException, NoSuchMethodException, IOException {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ExpectTest.java
index 993bc34..29808b7 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ExpectTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/internal/BaseEC2ExpectTest.java
@@ -72,7 +72,7 @@ public abstract class BaseEC2ExpectTest<T> extends BaseRestClientExpectTest<T> {
                           .endpoint("https://ec2." + region + ".amazonaws.com/")
                           .addHeader("Host", "ec2." + region + ".amazonaws.com")
                           .payload(payloadFromStringWithContentType(
-                                 "Action=DescribeAvailabilityZones&Version=2010-06-15",
+                                 "Action=DescribeAvailabilityZones&Version=2010-08-31",
                                  MediaType.APPLICATION_FORM_URLENCODED)).build()),
                HttpResponse.builder().statusCode(200)
                            .payload(payloadFromResourceWithContentType(

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeRegionsResponseHandlerTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeRegionsResponseHandlerTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeRegionsResponseHandlerTest.java
index 6d8bc58..1e444e3 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeRegionsResponseHandlerTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/xml/DescribeRegionsResponseHandlerTest.java
@@ -85,7 +85,7 @@ public class DescribeRegionsResponseHandlerTest extends BaseHandlerTest {
    public void testEuc() {
 
       InputStream is = Strings2
-            .toInputStream("<DescribeRegionsResponse xmlns=\"http://ec2.amazonaws.com/doc/2010-06-15/\"><requestId>6a3b36f9-9ff4-47cf-87e3-285b08fbe5e5</requestId><regionInfo><item><regionName>Eucalyptus</regionName><regionEndpoint>http://173.205.188.130:8773/services/Eucalyptus</regionEndpoint></item><item><regionName>Walrus</regionName><regionEndpoint>http://173.205.188.130:8773/services/Walrus</regionEndpoint></item></regionInfo></DescribeRegionsResponse>");
+            .toInputStream("<DescribeRegionsResponse xmlns=\"http://ec2.amazonaws.com/doc/2010-08-31/\"><requestId>6a3b36f9-9ff4-47cf-87e3-285b08fbe5e5</requestId><regionInfo><item><regionName>Eucalyptus</regionName><regionEndpoint>http://173.205.188.130:8773/services/Eucalyptus</regionEndpoint></item><item><regionName>Walrus</regionName><regionEndpoint>http://173.205.188.130:8773/services/Walrus</regionEndpoint></item></regionInfo></DescribeRegionsResponse>");
 
       Map<String, URI> expected = ImmutableMap.<String, URI> of("Eucalyptus",
             URI.create("http://173.205.188.130:8773/services/Eucalyptus"));

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/test/resources/describe_addresses_single.xml
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/resources/describe_addresses_single.xml b/apis/ec2/src/test/resources/describe_addresses_single.xml
new file mode 100644
index 0000000..d9179bd
--- /dev/null
+++ b/apis/ec2/src/test/resources/describe_addresses_single.xml
@@ -0,0 +1,8 @@
+<DescribeAddressesResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
+    <addressesSet>
+        <item>
+            <instanceId>i-f15ebb98</instanceId>
+            <publicIp>67.202.55.255</publicIp>
+        </item>
+    </addressesSet>
+</DescribeAddressesResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/test/resources/describe_securitygroups_empty.xml
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/resources/describe_securitygroups_empty.xml b/apis/ec2/src/test/resources/describe_securitygroups_empty.xml
index ca89f4e..e3336a7 100644
--- a/apis/ec2/src/test/resources/describe_securitygroups_empty.xml
+++ b/apis/ec2/src/test/resources/describe_securitygroups_empty.xml
@@ -1,6 +1,6 @@
 <?xml version="1.0" ?>
 <DescribeSecurityGroupsResponse
-	xmlns="http://ec2.amazonaws.com/doc/2010-06-15/">
+	xmlns="http://ec2.amazonaws.com/doc/2010-08-31/">
 	<requestId>L6EFIZVPJS76T3K5-0UV</requestId>
 	<securityGroupInfo>
 		<item>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/test/resources/describe_volumes_single.xml
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/resources/describe_volumes_single.xml b/apis/ec2/src/test/resources/describe_volumes_single.xml
new file mode 100644
index 0000000..fcc10a5
--- /dev/null
+++ b/apis/ec2/src/test/resources/describe_volumes_single.xml
@@ -0,0 +1,15 @@
+<?xml version="1.0"?>
+<DescribeVolumesResponse xmlns="http://ec2.amazonaws.com/doc/2009-11-30/">
+    <requestId>31ab5542-e479-44cb-aa94-c340c2481e0b</requestId>
+    <volumeSet>
+        <item>
+            <volumeId>vol-4282672b</volumeId>
+            <size>800</size>
+            <snapshotId>snap-536d1b3a</snapshotId>
+            <availabilityZone>us-east-1a</availabilityZone>
+            <status>in-use</status>
+            <createTime>2008-05-07T11:51:50.000Z</createTime>
+            <attachmentSet />
+        </item>
+    </volumeSet>
+</DescribeVolumesResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/test/resources/run_instances_cloudbridge.xml
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/resources/run_instances_cloudbridge.xml b/apis/ec2/src/test/resources/run_instances_cloudbridge.xml
index 37d5ae8..7dc31f0 100644
--- a/apis/ec2/src/test/resources/run_instances_cloudbridge.xml
+++ b/apis/ec2/src/test/resources/run_instances_cloudbridge.xml
@@ -1,5 +1,5 @@
 <?xml version="1.0"?>
-<RunInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-06-15/">
+<RunInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-08-31/">
   <requestId>56eeacd9-c790-45c3-85f3-e4380b55e1d8</requestId>
   <reservationId>r-f847a6ca</reservationId>
   <ownerId>55ed6530-9b32-48f1-acb7-6ec0d3255a65</ownerId>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 5a26707..4ccb4a2 100644
--- 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
@@ -30,11 +30,12 @@ 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.BindFiltersToIndexedFormParams;
 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.ec2.options.RunInstancesOptions;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
 import org.jclouds.rest.annotations.BinderParam;
@@ -45,6 +46,8 @@ import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.VirtualHost;
 import org.jclouds.rest.annotations.XMLResponseParser;
 
+import com.google.common.collect.Multimap;
+
 /**
  * Provides access to EC2 Instance Services via their REST API.
  * <p/>
@@ -66,6 +69,16 @@ public interface AWSInstanceApi extends InstanceApi {
             @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
             @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
 
+   @Named("DescribeInstances")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeInstances")
+   @XMLResponseParser(AWSDescribeInstancesResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<? extends Reservation<? extends AWSRunningInstance>> describeInstancesInRegionWithFilter(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
+
    @Named("RunInstances")
    @Override
    @POST

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 6f0f761..161afba 100644
--- 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
@@ -31,6 +31,7 @@ import org.jclouds.aws.ec2.options.CreateSecurityGroupOptions;
 import org.jclouds.aws.ec2.xml.AWSEC2DescribeSecurityGroupsResponseHandler;
 import org.jclouds.aws.ec2.xml.CreateSecurityGroupResponseHandler;
 import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams;
 import org.jclouds.ec2.binders.BindGroupIdsToIndexedFormParams;
 import org.jclouds.ec2.binders.BindGroupNamesToIndexedFormParams;
 import org.jclouds.ec2.binders.BindIpPermissionToIndexedFormParams;
@@ -49,6 +50,7 @@ import org.jclouds.rest.annotations.VirtualHost;
 import org.jclouds.rest.annotations.XMLResponseParser;
 
 import com.google.common.annotations.Beta;
+import com.google.common.collect.Multimap;
 
 /**
  * Provides access to EC2 SecurityGroup Services via their REST API.
@@ -132,4 +134,14 @@ public interface AWSSecurityGroupApi extends SecurityGroupApi {
    Set<SecurityGroup> describeSecurityGroupsInRegion(
            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
            @BinderParam(BindGroupNamesToIndexedFormParams.class) String... securityGroupNames);
+
+   @Named("DescribeSecurityGroups")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeSecurityGroups")
+   @XMLResponseParser(AWSEC2DescribeSecurityGroupsResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<SecurityGroup> describeSecurityGroupsInRegionWithFilter(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 1acc121..ec6f986 100644
--- 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
@@ -30,6 +30,7 @@ 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.BindFiltersToIndexedFormParams;
 import org.jclouds.ec2.binders.BindGroupNamesToIndexedFormParams;
 import org.jclouds.javax.annotation.Nullable;
 import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
@@ -41,6 +42,8 @@ import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.VirtualHost;
 import org.jclouds.rest.annotations.XMLResponseParser;
 
+import com.google.common.collect.Multimap;
+
 /**
  * Provides access to EC2 Placement Groups via their REST API.
  * <p/>
@@ -133,4 +136,27 @@ public interface PlacementGroupApi {
             @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
             @BinderParam(BindGroupNamesToIndexedFormParams.class) String... placementGroupIds);
 
+   /**
+    *
+    * Returns information about one or more placement groups in your account.
+    *
+    * @param region
+    *           The bundleTask ID is tied to the Region.
+    * @param filter
+    *           Multimap of filter key/values
+    *
+    * @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> describePlacementGroupsInRegionWithFilter(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
 }


[3/3] git commit: JCLOUDS-361. Add support for filtering Describe* methods in EC2

Posted by ab...@apache.org.
JCLOUDS-361. Add support for filtering Describe* methods in EC2


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

Branch: refs/heads/master
Commit: 2077da2879efab6d03f9ef9549587afbb250e66b
Parents: 55b21b6
Author: Andrew Bayer <an...@gmail.com>
Authored: Thu Nov 14 10:31:10 2013 -0800
Committer: Andrew Bayer <an...@gmail.com>
Committed: Thu Nov 14 11:53:31 2013 -0800

----------------------------------------------------------------------
 apis/ec2/pom.xml                                |   2 +-
 .../java/org/jclouds/ec2/EC2ApiMetadata.java    |   2 +-
 .../jclouds/ec2/compute/EC2ComputeService.java  |  32 +++---
 .../org/jclouds/ec2/domain/RunningInstance.java |   2 +-
 .../java/org/jclouds/ec2/features/AMIApi.java   |  30 ++++++
 .../ec2/features/ElasticBlockStoreApi.java      |  67 +++++++++++-
 .../ec2/features/ElasticIPAddressApi.java       |  29 ++++++
 .../org/jclouds/ec2/features/InstanceApi.java   |  38 +++++++
 .../org/jclouds/ec2/features/KeyPairApi.java    |  28 +++++
 .../jclouds/ec2/features/SecurityGroupApi.java  |  41 +++++++-
 .../org/jclouds/ec2/features/WindowsApi.java    |  37 ++++++-
 .../ec2/xml/DescribeImagesResponseHandler.java  |   2 +-
 .../xml/DescribeKeyPairsResponseHandler.java    |   2 +-
 .../DescribeSecurityGroupsResponseHandler.java  |   2 +-
 .../ec2/xml/InstanceStateChangeHandler.java     |   6 +-
 .../compute/EC2ComputeServiceExpectTest.java    |   2 +
 .../BaseEC2ComputeServiceExpectTest.java        |  25 +++++
 .../jclouds/ec2/features/AMIApiExpectTest.java  |  76 ++++++++++++++
 .../jclouds/ec2/features/AMIApiLiveTest.java    |  83 +++++++++++----
 .../org/jclouds/ec2/features/AMIApiTest.java    |  56 +++++-----
 .../AvailabilityZoneAndRegionApiLiveTest.java   |   4 +-
 .../EC2ElasticBlockStoreApiExpectTest.java      |  86 +++++++++++++++-
 .../features/ElasticBlockStoreApiLiveTest.java  |  97 ++++++++++++++----
 .../ec2/features/ElasticBlockStoreApiTest.java  |  24 ++---
 .../features/ElasticIPAddressApiExpectTest.java | 102 +++++++++++++++++++
 .../features/ElasticIPAddressApiLiveTest.java   |  11 +-
 .../ec2/features/ElasticIPAddressApiTest.java   |   4 +-
 .../ec2/features/InstanceApiExpectTest.java     | 101 ++++++++++++++++++
 .../ec2/features/InstanceApiLiveTest.java       |  44 +++++++-
 .../jclouds/ec2/features/InstanceApiTest.java   |  24 ++---
 .../ec2/features/KeyPairApiExpectTest.java      |  76 ++++++++++++++
 .../ec2/features/KeyPairApiLiveTest.java        |  35 ++++++-
 .../features/SecurityGroupApiExpectTest.java    |  76 ++++++++++++++
 .../ec2/features/SecurityGroupApiLiveTest.java  |  66 ++++++++++--
 .../ec2/features/SecurityGroupApiTest.java      |  12 +--
 .../ec2/features/WindowsApiExpectTest.java      |  52 +++++++++-
 .../jclouds/ec2/features/WindowsApiTest.java    |   8 +-
 .../jclouds/ec2/internal/BaseEC2ExpectTest.java |   2 +-
 .../xml/DescribeRegionsResponseHandlerTest.java |   2 +-
 .../resources/describe_addresses_single.xml     |   8 ++
 .../resources/describe_securitygroups_empty.xml |   2 +-
 .../test/resources/describe_volumes_single.xml  |  15 +++
 .../resources/run_instances_cloudbridge.xml     |   2 +-
 .../aws/ec2/features/AWSInstanceApi.java        |  15 ++-
 .../aws/ec2/features/AWSSecurityGroupApi.java   |  12 +++
 .../aws/ec2/features/PlacementGroupApi.java     |  26 +++++
 .../aws/ec2/features/SpotInstanceApi.java       |  33 ++++++
 .../ec2/features/AWSInstanceApiLiveTest.java    |   2 -
 .../features/PlacementGroupApiExpectTest.java   |  78 ++++++++++++++
 .../ec2/features/PlacementGroupApiLiveTest.java |  41 +++++++-
 .../ec2/features/SpotInstanceApiExpectTest.java |  78 ++++++++++++++
 .../ec2/features/SpotInstanceApiLiveTest.java   |  46 ++++++++-
 52 files changed, 1564 insertions(+), 182 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/pom.xml
----------------------------------------------------------------------
diff --git a/apis/ec2/pom.xml b/apis/ec2/pom.xml
index 4818c57..fafde83 100644
--- a/apis/ec2/pom.xml
+++ b/apis/ec2/pom.xml
@@ -33,7 +33,7 @@
 
   <properties>
     <test.ec2.endpoint>https://ec2.us-east-1.amazonaws.com</test.ec2.endpoint>
-    <test.ec2.api-version>2010-06-15</test.ec2.api-version>
+    <test.ec2.api-version>2010-08-31</test.ec2.api-version>
     <test.ec2.build-version />
     <test.ec2.identity>${test.aws.identity}</test.ec2.identity>
     <test.ec2.credential>${test.aws.credential}</test.ec2.credential>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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 8d544a3..2b081c5 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/EC2ApiMetadata.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/EC2ApiMetadata.java
@@ -72,7 +72,7 @@ public final class EC2ApiMetadata extends BaseHttpApiMetadata<EC2Api> {
          .credentialName("Secret Access Key")
          .defaultEndpoint("https://ec2.us-east-1.amazonaws.com")
          .documentation(URI.create("http://docs.amazonwebservices.com/AWSEC2/latest/APIReference"))
-         .version("2010-06-15")
+         .version("2010-08-31")
          .defaultProperties(EC2ApiMetadata.defaultProperties())
          .view(EC2ComputeServiceContext.class)
          .defaultModules(ImmutableSet.<Class<? extends Module>>of(EC2HttpApiModule.class, EC2ResolveImagesModule.class, EC2ComputeServiceContextModule.class));

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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 7bfa4bd..248102e 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
@@ -15,10 +15,10 @@
  * limitations under the License.
  */
 package org.jclouds.ec2.compute;
+
 import static com.google.common.base.Preconditions.checkNotNull;
 import static com.google.common.base.Strings.emptyToNull;
 import static com.google.common.collect.Iterables.concat;
-import static com.google.common.collect.Iterables.filter;
 import static com.google.common.collect.Iterables.transform;
 import static java.util.concurrent.TimeUnit.MILLISECONDS;
 import static java.util.concurrent.TimeUnit.SECONDS;
@@ -77,11 +77,13 @@ 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;
+import org.jclouds.ec2.domain.InstanceState;
 import org.jclouds.ec2.domain.KeyPair;
 import org.jclouds.ec2.domain.RunningInstance;
 import org.jclouds.ec2.domain.Tag;
 import org.jclouds.ec2.util.TagFilterBuilder;
 import org.jclouds.scriptbuilder.functions.InitAdminAccess;
+import org.jclouds.util.Strings2;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
@@ -224,15 +226,23 @@ public class EC2ComputeService extends BaseComputeService {
 
    @VisibleForTesting
    void deleteKeyPair(String region, String group) {
-      for (KeyPair keyPair : client.getKeyPairApi().get().describeKeyPairsInRegion(region)) {
+      for (KeyPair keyPair : client.getKeyPairApi().get().describeKeyPairsInRegionWithFilter(region,
+              ImmutableMultimap.<String, String>builder()
+                      .put("key-name", Strings2.urlEncode(
+                              String.format("jclouds#%s#%s*", group, region).replace('#', delimiter)))
+                      .build())) {
          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.getInstanceApi().get()
-                  .describeInstancesInRegion(region)), usingKeyPairAndNotDead(keyPair)));
+            Set<String> instancesUsingKeyPair = extractIdsFromInstances(concat(client.getInstanceApi().get()
+                  .describeInstancesInRegionWithFilter(region, ImmutableMultimap.<String, String>builder()
+                          .put("instance-state-name", InstanceState.TERMINATED.toString())
+                          .put("instance-state-name", InstanceState.SHUTTING_DOWN.toString())
+                          .put("key-name", keyPair.getKeyName()).build())));
+
             if (instancesUsingKeyPair.size() > 0) {
                logger.debug("<< inUse keyPair(%s), by (%s)", keyPair.getKeyName(), instancesUsingKeyPair);
             } else {
@@ -258,20 +268,6 @@ public class EC2ComputeService extends BaseComputeService {
       }));
    }
 
-   protected Predicate<RunningInstance> usingKeyPairAndNotDead(final KeyPair keyPair) {
-      return new Predicate<RunningInstance>() {
-         @Override
-         public boolean apply(RunningInstance input) {
-            switch (input.getInstanceState()) {
-            case TERMINATED:
-            case SHUTTING_DOWN:
-               return false;
-            }
-            return keyPair.getKeyName().equals(input.getKeyName());
-         }
-      };
-   }
-
    /**
     * Cleans implicit keypairs and security groups.
     */

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/main/java/org/jclouds/ec2/domain/RunningInstance.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/domain/RunningInstance.java b/apis/ec2/src/main/java/org/jclouds/ec2/domain/RunningInstance.java
index 9b502d6..725165a 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/domain/RunningInstance.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/domain/RunningInstance.java
@@ -330,7 +330,7 @@ public class RunningInstance implements Comparable<RunningInstance> {
     * more information, go to the Metadata section of the Amazon Elastic Compute Cloud Developer
     * Guide.
     * 
-    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/2010-06-15/DeveloperGuide/" />
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/2010-08-31/DeveloperGuide/" />
     */
    public String getAmiLaunchIndex() {
       return amiLaunchIndex;

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 40540aa..bdc7756 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/features/AMIApi.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/AMIApi.java
@@ -28,6 +28,7 @@ import javax.ws.rs.Path;
 
 import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
 import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams;
 import org.jclouds.ec2.binders.BindUserGroupsToIndexedFormParams;
 import org.jclouds.ec2.binders.BindUserIdsToIndexedFormParams;
 import org.jclouds.ec2.domain.Image;
@@ -51,6 +52,8 @@ import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.VirtualHost;
 import org.jclouds.rest.annotations.XMLResponseParser;
 
+import com.google.common.collect.Multimap;
+
 /**
  * Provides access to AMI Services.
  * <p/>
@@ -86,6 +89,33 @@ public interface AMIApi {
             DescribeImagesOptions... options);
 
    /**
+    * 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.
+    * @param filter
+    *           Multimap of filter key/values.
+    * @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> describeImagesInRegionWithFilter(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter,
+           DescribeImagesOptions... options);
+
+   /**
     * Creates an AMI that uses an Amazon EBS root device from a "running" or "stopped" instance.
     * 
     * @param region

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 8e56f77..69c92bf 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticBlockStoreApi.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticBlockStoreApi.java
@@ -28,6 +28,7 @@ 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.BindFiltersToIndexedFormParams;
 import org.jclouds.ec2.binders.BindUserGroupsToIndexedFormParams;
 import org.jclouds.ec2.binders.BindUserIdsToIndexedFormParams;
 import org.jclouds.ec2.binders.BindVolumeIdsToIndexedFormParams;
@@ -55,6 +56,8 @@ import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.VirtualHost;
 import org.jclouds.rest.annotations.XMLResponseParser;
 
+import com.google.common.collect.Multimap;
+
 /**
  * Provides access to EC2 Elastic Block Store services via their REST API.
  * <p/>
@@ -168,25 +171,50 @@ public interface ElasticBlockStoreApi {
     * 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")   
+   @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);
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindVolumeIdsToIndexedFormParams.class) String... volumeIds);
+
+   /**
+    * Describes the specified Amazon EBS volumes that you own and match the given filters. If you
+    * do not specify any filters, 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 filter
+    *           Multimap of filter key/values
+    *
+    * @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> describeVolumesInRegionWithFilter(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
 
    /**
     * Deletes an Amazon EBS volume that you own. For more information about Amazon EBS, go to the
@@ -414,6 +442,35 @@ public interface ElasticBlockStoreApi {
             DescribeSnapshotsOptions... options);
 
    /**
+    * Returns information about EBS snapshots matching the given filters.
+    *
+    * @param region
+    *           Snapshots are tied to Regions and can only be used for volumes within the same
+    *           Region.
+    * @param filter
+    *           Multimap of filter key/values.
+    * @param options
+    *           specify the snapshot ids or other parameters to clarify the list.
+    * @return matching snapshots.
+    *
+    * @see #describeSnapshotsInRegion
+    * @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> describeSnapshotsInRegionWithFilter(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter,
+           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.
     * 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 47d93a7..3401cde 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticIPAddressApi.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/ElasticIPAddressApi.java
@@ -27,6 +27,7 @@ import javax.ws.rs.Path;
 
 import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
 import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams;
 import org.jclouds.ec2.binders.BindPublicIpsToIndexedFormParams;
 import org.jclouds.ec2.domain.PublicIpInstanceIdPair;
 import org.jclouds.ec2.xml.AllocateAddressResponseHandler;
@@ -38,9 +39,12 @@ 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 org.jclouds.rest.annotations.VirtualHost;
 import org.jclouds.rest.annotations.XMLResponseParser;
 
+import com.google.common.collect.Multimap;
+
 /**
  * Provides access to EC2 Elastic IP Addresses via REST API.
  * <p/>
@@ -168,4 +172,29 @@ public interface ElasticIPAddressApi {
             @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
             @BinderParam(BindPublicIpsToIndexedFormParams.class) String... publicIps);
 
+   /**
+    * Lists elastic IP addresses assigned to your identity or provides information on addresses
+    * matching a given filter.
+    *
+    * @param region
+    *           Elastic IP addresses are tied to a Region and cannot be mapped across Regions.
+    * @param filter
+    *
+    * @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"
+    *      />
+    */
+   @SinceApiVersion("2010-08-31")
+   @Named("DescribeAddresses")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeAddresses")
+   @XMLResponseParser(DescribeAddressesResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<PublicIpInstanceIdPair> describeAddressesInRegionWithFilter(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 2b56324..5d7a591 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/features/InstanceApi.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/InstanceApi.java
@@ -29,6 +29,7 @@ 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.BindFiltersToIndexedFormParams;
 import org.jclouds.ec2.binders.BindInstanceIdsToIndexedFormParams;
 import org.jclouds.ec2.binders.IfNotNullBindAvailabilityZoneToFormParam;
 import org.jclouds.ec2.domain.BlockDevice;
@@ -56,9 +57,12 @@ 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.SinceApiVersion;
 import org.jclouds.rest.annotations.VirtualHost;
 import org.jclouds.rest.annotations.XMLResponseParser;
 
+import com.google.common.collect.Multimap;
+
 /**
  * Provides access to EC2 Instance Services via their REST API.
  * <p/>
@@ -102,6 +106,40 @@ public interface InstanceApi {
          @BinderParam(BindInstanceIdsToIndexedFormParams.class) String... instanceIds);
 
    /**
+    * Returns information about instances that you own.
+    * <p/>
+    *
+    * If you specify one or filters, Amazon EC2 returns information for instances
+    * matching those filters. If you do not specify any filters, Amazon EC2
+    * returns information for all relevant instances. If you specify an invalid
+    * filter, a fault is returned. Only instances you own will be included in the
+    * 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.
+    * @param filter
+    *
+    * @see #runInstancesInRegion
+    * @see #terminateInstancesInRegion
+    * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeInstances.html"
+    *      />
+    */
+   @SinceApiVersion("2010-08-31")
+   @Named("DescribeInstances")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeInstances")
+   @XMLResponseParser(DescribeInstancesResponseHandler.class)
+   @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<? extends Reservation<? extends RunningInstance>> describeInstancesInRegionWithFilter(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
+
+   /**
     * Launches a specified number of instances of an AMI for which you have
     * permissions.
     * <p/>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index b09406e..c10f3eb 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/features/KeyPairApi.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/KeyPairApi.java
@@ -27,6 +27,7 @@ import javax.ws.rs.Path;
 
 import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
 import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams;
 import org.jclouds.ec2.binders.BindKeyNamesToIndexedFormParams;
 import org.jclouds.ec2.domain.KeyPair;
 import org.jclouds.ec2.xml.DescribeKeyPairsResponseHandler;
@@ -41,6 +42,8 @@ import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.VirtualHost;
 import org.jclouds.rest.annotations.XMLResponseParser;
 
+import com.google.common.collect.Multimap;
+
 /**
  * Provides access to EC2 via their REST API.
  * <p/>
@@ -105,6 +108,31 @@ public interface KeyPairApi {
             @BinderParam(BindKeyNamesToIndexedFormParams.class) String... keyPairNames);
 
    /**
+    * Returns information about key pairs available to you. If you specify filters,
+    * information about keypairs matching those filters is returned. Otherwise, all
+    * keypairs you have access to are returned.
+    *
+    * @param region
+    *           Key pairs (to connect to instances) are Region-specific.
+    * @param filter
+    *           Multimap of filter key/values.
+    *
+    * @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> describeKeyPairsInRegionWithFilter(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
+
+   /**
     * Deletes the specified key pair, by removing the public key from Amazon EC2. You must own the
     * key pair
     * 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 70cbdac..c082bd0 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/features/SecurityGroupApi.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/features/SecurityGroupApi.java
@@ -28,6 +28,7 @@ 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.BindFiltersToIndexedFormParams;
 import org.jclouds.ec2.binders.BindGroupNamesToIndexedFormParams;
 import org.jclouds.ec2.binders.BindUserIdGroupPairToSourceSecurityGroupFormParams;
 import org.jclouds.ec2.domain.SecurityGroup;
@@ -44,6 +45,8 @@ import org.jclouds.rest.annotations.RequestFilters;
 import org.jclouds.rest.annotations.VirtualHost;
 import org.jclouds.rest.annotations.XMLResponseParser;
 
+import com.google.common.collect.Multimap;
+
 /**
  * Provides access to EC2 via their REST API.
  * <p/>
@@ -113,19 +116,19 @@ public interface SecurityGroupApi {
 
    /**
     * 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"
     *      />
     */
@@ -136,8 +139,36 @@ public interface SecurityGroupApi {
    @XMLResponseParser(DescribeSecurityGroupsResponseHandler.class)
    @Fallback(EmptySetOnNotFoundOr404.class)
    Set<SecurityGroup> describeSecurityGroupsInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindGroupNamesToIndexedFormParams.class) String... securityGroupNames);
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindGroupNamesToIndexedFormParams.class) String... securityGroupNames);
+
+   /**
+    * 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 filter
+    *           Multimap of filter key/values.
+    *
+    * @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> describeSecurityGroupsInRegionWithFilter(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
 
    /**
     * 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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 b895d0b..5461b23 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
@@ -29,6 +29,7 @@ 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.BindFiltersToIndexedFormParams;
 import org.jclouds.ec2.binders.BindS3UploadPolicyAndSignature;
 import org.jclouds.ec2.domain.BundleTask;
 import org.jclouds.ec2.domain.PasswordData;
@@ -47,6 +48,8 @@ import org.jclouds.rest.annotations.SinceApiVersion;
 import org.jclouds.rest.annotations.VirtualHost;
 import org.jclouds.rest.annotations.XMLResponseParser;
 
+import com.google.common.collect.Multimap;
+
 /**
  * Provides access to EC2 Windows Features via the Query API
  * <p/>
@@ -136,12 +139,12 @@ public interface WindowsApi {
             @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"
@@ -154,8 +157,32 @@ public interface WindowsApi {
    @XMLResponseParser(DescribeBundleTasksResponseHandler.class)
    @Fallback(EmptySetOnNotFoundOr404.class)
    Set<BundleTask> describeBundleTasksInRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
-            @BinderParam(BindBundleIdsToIndexedFormParams.class) String... bundleTaskIds);
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindBundleIdsToIndexedFormParams.class) String... bundleTaskIds);
+
+   /**
+    *
+    * Describes current bundling tasks.
+    *
+    * @param region
+    *           The bundleTask ID is tied to the Region.
+    * @param filter
+    *           Filter multimap
+    *
+    * @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> describeBundleTasksInRegionWithFilter(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+           @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
 
    /**
     *

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java
index 8e9a656..b55875a 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeImagesResponseHandler.java
@@ -46,7 +46,7 @@ import com.google.common.collect.Sets;
 /**
  * Parses the following XML document:
  * <p/>
- * DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/2010-06-15/"
+ * DescribeImagesResponse xmlns="http://ec2.amazonaws.com/doc/2010-08-31/"
  * 
  * @author Adrian Cole
  * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeImages.html"

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeKeyPairsResponseHandler.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeKeyPairsResponseHandler.java b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeKeyPairsResponseHandler.java
index 1b23f82..aca734f 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeKeyPairsResponseHandler.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeKeyPairsResponseHandler.java
@@ -32,7 +32,7 @@ import com.google.common.base.Supplier;
 import com.google.common.collect.Sets;
 
 /**
- * Parses: DescribeKeyPairsResponse xmlns="http://ec2.amazonaws.com/doc/2010-06-15/"
+ * Parses: DescribeKeyPairsResponse xmlns="http://ec2.amazonaws.com/doc/2010-08-31/"
  * 
  * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeKeyPairs.html"
  *      />

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeSecurityGroupsResponseHandler.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeSecurityGroupsResponseHandler.java b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeSecurityGroupsResponseHandler.java
index aed7ee0..8a00ac4 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeSecurityGroupsResponseHandler.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeSecurityGroupsResponseHandler.java
@@ -34,7 +34,7 @@ import com.google.common.collect.ImmutableSet.Builder;
 
 /**
  * Parses: DescribeSecurityGroupsResponse
- * xmlns="http://ec2.amazonaws.com/doc/2010-06-15/"
+ * xmlns="http://ec2.amazonaws.com/doc/2010-08-31/"
  *
  * @see <a href=
  *      "http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-query-DescribesecurityGroupInfo.html"

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/main/java/org/jclouds/ec2/xml/InstanceStateChangeHandler.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/xml/InstanceStateChangeHandler.java b/apis/ec2/src/main/java/org/jclouds/ec2/xml/InstanceStateChangeHandler.java
index 4541ab6..9c8933f 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/xml/InstanceStateChangeHandler.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/xml/InstanceStateChangeHandler.java
@@ -33,9 +33,9 @@ import com.google.common.collect.Sets;
 /**
  * Parses the following XML document:
  * <p/>
- * TerminateInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-06-15/"
- * StartInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-06-15/" StopInstancesResponse
- * xmlns="http://ec2.amazonaws.com/doc/2010-06-15/"
+ * TerminateInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-08-31/"
+ * StartInstancesResponse xmlns="http://ec2.amazonaws.com/doc/2010-08-31/" StopInstancesResponse
+ * xmlns="http://ec2.amazonaws.com/doc/2010-08-31/"
  * 
  * @author Adrian Cole
  * @see <a href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-ItemType-TerminateInstancesResponseInfoType.html"

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceExpectTest.java
index f95a398..61f3c50 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceExpectTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/EC2ComputeServiceExpectTest.java
@@ -52,6 +52,7 @@ public class EC2ComputeServiceExpectTest extends BaseEC2ComputeServiceExpectTest
       requestResponseMap.put(describeInstanceRequest, describeInstanceResponse);
       requestResponseMap.put(describeInstanceMultiIdsRequest, describeInstanceMultiIdsResponse);
       requestResponseMap.put(describeImageRequest, describeImagesResponse);
+      requestResponseMap.put(createTagsRequest, createTagsResponse);
 
       ComputeService apiThatCreatesNode = requestsSendResponses(requestResponseMap.build());
 
@@ -78,6 +79,7 @@ public class EC2ComputeServiceExpectTest extends BaseEC2ComputeServiceExpectTest
       requestResponseMap.put(describeInstanceRequest, describeInstanceResponse);
       requestResponseMap.put(describeInstanceMultiIdsRequest, describeInstanceMultiIdsResponse);
       requestResponseMap.put(describeImageRequest, describeImagesResponse);
+      requestResponseMap.put(createTagsRequest, createTagsResponse);
 
       ComputeService apiThatCreatesNode = requestsSendResponses(requestResponseMap.build());
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/test/java/org/jclouds/ec2/compute/internal/BaseEC2ComputeServiceExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/compute/internal/BaseEC2ComputeServiceExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/compute/internal/BaseEC2ComputeServiceExpectTest.java
index 5d37fc4..610cfb7 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/compute/internal/BaseEC2ComputeServiceExpectTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/compute/internal/BaseEC2ComputeServiceExpectTest.java
@@ -59,6 +59,8 @@ public abstract class BaseEC2ComputeServiceExpectTest extends BaseEC2ComputeServ
    protected HttpRequest describeInstanceMultiIdsRequest;
    protected HttpResponse describeInstanceMultiIdsResponse;
    protected HttpRequest describeImageRequest;
+   protected HttpRequest createTagsRequest;
+   protected HttpResponse createTagsResponse;
 
    public BaseEC2ComputeServiceExpectTest() {
       region = "us-east-1";
@@ -211,6 +213,29 @@ public abstract class BaseEC2ComputeServiceExpectTest extends BaseEC2ComputeServ
                           .addHeader("Host", "ec2." + region + ".amazonaws.com")
                           .addFormParam("ImageId.1", "ami-aecd60c7")
                           .addFormParam("Action", "DescribeImages").build());
+
+      createTagsRequest =
+              formSigner.filter(HttpRequest.builder()
+                      .method("POST")
+                      .endpoint("https://ec2.us-east-1.amazonaws.com/")
+                      .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+                      .payload(
+                              payloadFromStringWithContentType(
+                                      "Action=CreateTags" +
+                                              "&ResourceId.1=i-2baa5550" +
+                                              "&Signature=Trp5e5%2BMqeBeBZbLYa9s9gxahQ9nkx6ETfsGl82IV8Y%3D" +
+                                              "&SignatureMethod=HmacSHA256" +
+                                              "&SignatureVersion=2" +
+                                              "&Tag.1.Key=Name" +
+                                              "&Tag.1.Value=test-2baa5550" +
+                                              "&Timestamp=2012-04-16T15%3A54%3A08.897Z" +
+                                              "&Version=2010-08-31" +
+                                              "&AWSAccessKeyId=identity",
+                                      "application/x-www-form-urlencoded"))
+                      .build());
+
+      createTagsResponse = HttpResponse.builder().statusCode(200).build();
+
    }
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiExpectTest.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiExpectTest.java b/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiExpectTest.java
new file mode 100644
index 0000000..d3ba9a5
--- /dev/null
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiExpectTest.java
@@ -0,0 +1,76 @@
+/*
+ * 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.Iterables.getOnlyElement;
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.domain.Image;
+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.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
+
+/**
+ * @author Andrew Bayer
+ */
+@Test(groups = "unit", testName = "AMIApiExpectTest")
+public class AMIApiExpectTest extends BaseEC2ApiExpectTest<EC2Api> {
+
+   HttpRequest filter = HttpRequest.builder().method("POST")
+           .endpoint("https://ec2.us-east-1.amazonaws.com/")
+           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+           .addFormParam("Action", "DescribeImages")
+           .addFormParam("Filter.1.Name", "owner-id")
+           .addFormParam("Filter.1.Value.1", "206029621532")
+           .addFormParam("Signature", "BxOCrCYJujtaUqSPagRvv1ki76veVBiKK3yWHvRWgR0%3D")
+           .addFormParam("SignatureMethod", "HmacSHA256")
+           .addFormParam("SignatureVersion", "2")
+           .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z")
+           .addFormParam("Version", "2010-08-31")
+           .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testFilterWhenResponseIs2xx() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResourceWithContentType("/describe_images.xml", "text/xml")).build();
+
+      EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse);
+
+      Image image = getOnlyElement(apiWhenExist.getAMIApi().get().describeImagesInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("owner-id", "206029621532")
+                      .build()));
+
+      assertEquals(image.getId(), "ami-be3adfd7");
+   }
+
+   public void testFilterWhenResponseIs404() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build();
+
+      EC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filter, filterResponse);
+
+      assertEquals(apiWhenNotExist.getAMIApi().get().describeImagesInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("owner-id", "206029621532")
+                      .build()),
+              ImmutableSet.of());
+   }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 3eee397..2b56e0a 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiLiveTest.java
@@ -18,6 +18,7 @@ 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.getFirst;
 import static com.google.common.collect.Iterables.getOnlyElement;
 import static com.google.common.collect.Sets.newHashSet;
 import static java.util.concurrent.TimeUnit.SECONDS;
@@ -32,12 +33,12 @@ import java.util.Iterator;
 import java.util.Properties;
 import java.util.Set;
 
+import org.jclouds.aws.AWSResponseException;
 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;
@@ -51,6 +52,7 @@ import org.testng.annotations.Test;
 
 import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
 
 /**
  * Tests behavior of {@code AMIApi}
@@ -98,7 +100,9 @@ public class AMIApiLiveTest extends BaseComputeServiceContextLiveTest {
          Template template = view.getComputeService().templateBuilder().from(ebsTemplate).build();
          regionId = template.getLocation().getId();
          imageId = template.getImage().getProviderId();
-         for (Image image : client.describeImagesInRegion(regionId)) {
+         for (Image image : client.describeImagesInRegionWithFilter(regionId,
+                 ImmutableMultimap.<String, String>builder()
+                         .put("name", ebsBackedImageName).build())) {
             if (ebsBackedImageName.equals(image.getName()))
                client.deregisterImageInRegion(regionId, image.getId());
          }
@@ -115,20 +119,58 @@ public class AMIApiLiveTest extends BaseComputeServiceContextLiveTest {
    }
 
    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);
-      }
+      // Just run in the first region - no need to take the time on all of them.
+      String region = getFirst(ec2Api.getConfiguredRegions(), null);
+      assertNotNull(region, "region should not be null");
+      Set<? extends Image> allResults = client.describeImagesInRegion(region);
+      assertNotNull(allResults);
+      assertTrue(allResults.size() >= 2);
+      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 testDescribeImagesWithFilter() {
+      // Just run in the first region - no need to take the time on all of them.
+      String region = getFirst(ec2Api.getConfiguredRegions(), null);
+      assertNotNull(region, "region should not be null");
+      Set<? extends Image> allResults = client.describeImagesInRegion(region);
+      assertNotNull(allResults);
+      assertTrue(allResults.size() >= 2);
+      String id1 = allResults.iterator().next().getId();
+      Set<? extends Image> filterResult = client.describeImagesInRegionWithFilter(region,
+              ImmutableMultimap.<String, String>builder()
+                      .put("image-id", id1)
+                      .build());
+      assertNotNull(filterResult);
+      assertEquals(filterResult.size(), 1);
+      assertEquals(filterResult.iterator().next().getId(), id1);
+   }
+
+   @Test(expectedExceptions = AWSResponseException.class)
+   public void testDescribeImagesWithInvalidFilter() {
+      // Just run in the first region - no need to take the time on all of them.
+      String region = getFirst(ec2Api.getConfiguredRegions(), null);
+      assertNotNull(region, "region should not be null");
+
+      Set<? extends Image> allResults = client.describeImagesInRegion(region);
+      assertNotNull(allResults);
+      assertTrue(allResults.size() >= 2);
+      String id1 = allResults.iterator().next().getId();
+      Set<? extends Image> filterResult = client.describeImagesInRegionWithFilter(region,
+              ImmutableMultimap.<String, String>builder()
+                      .put("invalid-filter-id", id1)
+                      .build());
+      assertNotNull(filterResult);
+      assertEquals(filterResult.size(), 1);
+      assertEquals(filterResult.iterator().next().getId(), id1);
    }
 
    @Test
@@ -136,7 +178,9 @@ public class AMIApiLiveTest extends BaseComputeServiceContextLiveTest {
       Snapshot snapshot = createSnapshot();
 
       // List of images before...
-      int sizeBefore = client.describeImagesInRegion(regionId).size();
+      int sizeBefore = client.describeImagesInRegionWithFilter(regionId,
+              ImmutableMultimap.<String, String>builder()
+                      .put("name", ebsBackedImageName).build()).size();
 
       // Register a new image...
       ebsBackedImageId = client.registerUnixImageBackedByEbsInRegion(regionId, ebsBackedImageName, snapshot.getId(),
@@ -154,7 +198,10 @@ public class AMIApiLiveTest extends BaseComputeServiceContextLiveTest {
                   "/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();
+      int after = client.describeImagesInRegionWithFilter(regionId,
+              ImmutableMultimap.<String, String>builder()
+                      .put("name", ebsBackedImageName).build()).size();
+
       assertEquals(after, sizeBefore + 1);
    }
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index c3907ab..b4b7f85 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/AMIApiTest.java
@@ -54,11 +54,11 @@ public class AMIApiTest extends BaseEC2ApiTest<AMIApi> {
                                         .addFormParam("Action", "CreateImage")
                                         .addFormParam("InstanceId", "instanceId")
                                         .addFormParam("Name", "name")
-                                        .addFormParam("Signature", "hBIUf4IUOiCKGQKehaNwwbZUjRN4NC4RSNfJ%2B8kvJdY%3D")
+                                        .addFormParam("Signature", "MuMtOMs697BLVks2RUZUNeLdVCo6NXPHuDhh0nmNtvc%3D")
                                         .addFormParam("SignatureMethod", "HmacSHA256")
                                         .addFormParam("SignatureVersion", "2")
                                         .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                        .addFormParam("Version", "2010-06-15")
+                                        .addFormParam("Version", "2010-08-31")
                                         .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testCreateImage() throws SecurityException, NoSuchMethodException, IOException {
@@ -87,11 +87,11 @@ public class AMIApiTest extends BaseEC2ApiTest<AMIApi> {
                                                .addFormParam("InstanceId", "instanceId")
                                                .addFormParam("Name", "name")
                                                .addFormParam("NoReboot", "true")
-                                               .addFormParam("Signature", "fz3KW27JxlSq9ivmVOl4IujcHXXw1cOhdig80I7wR6o%3D")
+                                               .addFormParam("Signature", "8SgbaWihxOICMXDLvwk3ahy/99nhZvTvbno%2B8dMyvJg%3D")
                                                .addFormParam("SignatureMethod", "HmacSHA256")
                                                .addFormParam("SignatureVersion", "2")
                                                .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                               .addFormParam("Version", "2010-06-15")
+                                               .addFormParam("Version", "2010-08-31")
                                                .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testCreateImageOptions() throws SecurityException, NoSuchMethodException, IOException {
@@ -118,11 +118,11 @@ public class AMIApiTest extends BaseEC2ApiTest<AMIApi> {
                                            .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("Signature", "hQxNAaRVX6OvXV0IKgx1vV0FoNbRyuHQ2fhRhaPJnS8%3D")
                                            .addFormParam("SignatureMethod", "HmacSHA256")
                                            .addFormParam("SignatureVersion", "2")
                                            .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                           .addFormParam("Version", "2010-06-15")
+                                           .addFormParam("Version", "2010-08-31")
                                            .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testDescribeImages() throws SecurityException, NoSuchMethodException, IOException {
@@ -153,11 +153,11 @@ public class AMIApiTest extends BaseEC2ApiTest<AMIApi> {
                                                   .addFormParam("ImageId.2", "2")
                                                   .addFormParam("Owner.1", "fred")
                                                   .addFormParam("Owner.2", "nancy")
-                                                  .addFormParam("Signature", "%2BE9wji7oFnNUaGmOBggYNNp6v%2BL8OzSGjuI4nx1l2Jw%3D")
+                                                  .addFormParam("Signature", "cIft3g1fwMu52NgB0En9NtHyXjVhmeSx7TBP7YR%2BTvI%3D")
                                                   .addFormParam("SignatureMethod", "HmacSHA256")
                                                   .addFormParam("SignatureVersion", "2")
                                                   .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                  .addFormParam("Version", "2010-06-15")
+                                                  .addFormParam("Version", "2010-08-31")
                                                   .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testDescribeImagesOptions() throws SecurityException, NoSuchMethodException, IOException {
@@ -185,11 +185,11 @@ public class AMIApiTest extends BaseEC2ApiTest<AMIApi> {
                                             .addHeader("Host", "ec2.us-east-1.amazonaws.com")
                                             .addFormParam("Action", "DeregisterImage")
                                             .addFormParam("ImageId", "imageId")
-                                            .addFormParam("Signature", "3sk9LAJAIr2lG04OMuI0qtzCoBtCU1Ac9I6TTmAWjyA%3D")
+                                            .addFormParam("Signature", "tm6nGoPPJh7xt5TSdV5Ov0DJvcGTAW%2BYSfXL7j%2BTkOA%3D")
                                             .addFormParam("SignatureMethod", "HmacSHA256")
                                             .addFormParam("SignatureVersion", "2")
                                             .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                            .addFormParam("Version", "2010-06-15")
+                                            .addFormParam("Version", "2010-08-31")
                                             .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testDeregisterImage() throws SecurityException, NoSuchMethodException, IOException {
@@ -216,11 +216,11 @@ public class AMIApiTest extends BaseEC2ApiTest<AMIApi> {
                                                       .addFormParam("Action", "RegisterImage")
                                                       .addFormParam("ImageLocation", "pathToManifest")
                                                       .addFormParam("Name", "name")
-                                                      .addFormParam("Signature", "alGqfUiV/bpmpCAj/YzG9VxdTeCwOYyoPjNfwYhm7os%3D")
+                                                      .addFormParam("Signature", "Ie7k7w4Bdki3uCGeSFGdJ5EKrp/ohkHvWwivbIaVLEM%3D")
                                                       .addFormParam("SignatureMethod", "HmacSHA256")
                                                       .addFormParam("SignatureVersion", "2")
                                                       .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                      .addFormParam("Version", "2010-06-15")
+                                                      .addFormParam("Version", "2010-08-31")
                                                       .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testRegisterImageFromManifest() throws SecurityException, NoSuchMethodException, IOException {
@@ -248,11 +248,11 @@ public class AMIApiTest extends BaseEC2ApiTest<AMIApi> {
                                                              .addFormParam("Description", "description")
                                                              .addFormParam("ImageLocation", "pathToManifest")
                                                              .addFormParam("Name", "name")
-                                                             .addFormParam("Signature", "p77vQLVlPoak6cP/8eoM%2Bz6zkSXx9e2iSlGgLvIwP7I%3D")
+                                                             .addFormParam("Signature", "ilWV1eAWW6kTK/jHliQ%2BIkzJR4DRNy4ye%2BSKtnUjjDs%3D")
                                                              .addFormParam("SignatureMethod", "HmacSHA256")
                                                              .addFormParam("SignatureVersion", "2")
                                                              .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                             .addFormParam("Version", "2010-06-15")
+                                                             .addFormParam("Version", "2010-08-31")
                                                              .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testRegisterImageFromManifestOptions() throws SecurityException, NoSuchMethodException, IOException {
@@ -283,11 +283,11 @@ public class AMIApiTest extends BaseEC2ApiTest<AMIApi> {
                                                      .addFormParam("BlockDeviceMapping.0.Ebs.SnapshotId", "snapshotId")
                                                      .addFormParam("Name", "imageName")
                                                      .addFormParam("RootDeviceName", "/dev/sda1")
-                                                     .addFormParam("Signature", "KGqYXGpJ/UQVTM172Y2TwU4tlG21JXd3Qrx5nSLBVuA%3D")
+                                                     .addFormParam("Signature", "ZbZcY6uwxPbD65jFmiNZXoWeHY/2zqRuGuDmTfkt84A%3D")
                                                      .addFormParam("SignatureMethod", "HmacSHA256")
                                                      .addFormParam("SignatureVersion", "2")
                                                      .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                     .addFormParam("Version", "2010-06-15")
+                                                     .addFormParam("Version", "2010-08-31")
                                                      .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testRegisterImageBackedByEBS() throws SecurityException, NoSuchMethodException, IOException {
@@ -324,11 +324,11 @@ public class AMIApiTest extends BaseEC2ApiTest<AMIApi> {
                                                             .addFormParam("Description", "description")
                                                             .addFormParam("Name", "imageName")
                                                             .addFormParam("RootDeviceName", "/dev/sda1")
-                                                            .addFormParam("Signature", "xuWi0w8iODQrg4E0azwqNm2lz/Rf4hBa7m%2BunDTZvVI%3D")
+                                                            .addFormParam("Signature", "DrNujyZMGrKvuw73A7ObFTThXvc/MRfNqjvIy8gey5g%3D")
                                                             .addFormParam("SignatureMethod", "HmacSHA256")
                                                             .addFormParam("SignatureVersion", "2")
                                                             .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                            .addFormParam("Version", "2010-06-15")
+                                                            .addFormParam("Version", "2010-08-31")
                                                             .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testRegisterImageBackedByEBSOptions() throws SecurityException, NoSuchMethodException, IOException {
@@ -358,11 +358,11 @@ public class AMIApiTest extends BaseEC2ApiTest<AMIApi> {
                                                            .addFormParam("Action", "DescribeImageAttribute")
                                                            .addFormParam("Attribute", "blockDeviceMapping")
                                                            .addFormParam("ImageId", "imageId")
-                                                           .addFormParam("Signature", "puwfzm8BlfeKiEZ9CNn5ax86weZ6SQ2xyZhN6etu4gA%3D")
+                                                           .addFormParam("Signature", "MJCIc1roG%2BnIWxRSUqV9KP9Wc4AWuuiNkxeDSih5/mI%3D")
                                                            .addFormParam("SignatureMethod", "HmacSHA256")
                                                            .addFormParam("SignatureVersion", "2")
                                                            .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                           .addFormParam("Version", "2010-06-15")
+                                                           .addFormParam("Version", "2010-08-31")
                                                            .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testGetBlockDeviceMappingsForImage() throws SecurityException, NoSuchMethodException, IOException {
@@ -390,11 +390,11 @@ public class AMIApiTest extends BaseEC2ApiTest<AMIApi> {
                                                         .addFormParam("Action", "DescribeImageAttribute")
                                                         .addFormParam("Attribute", "launchPermission")
                                                         .addFormParam("ImageId", "imageId")
-                                                        .addFormParam("Signature", "ocCMlLh3Kpg6HwIcPKlrwoPPg9C5rt5nD0dl717mOq8%3D")
+                                                        .addFormParam("Signature", "iN7JbsAhM1NAES3o%2BOw8BaaFJ%2B1g9imBjcU4mFCyrxM%3D")
                                                         .addFormParam("SignatureMethod", "HmacSHA256")
                                                         .addFormParam("SignatureVersion", "2")
                                                         .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                        .addFormParam("Version", "2010-06-15")
+                                                        .addFormParam("Version", "2010-08-31")
                                                         .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testGetLaunchPermissionForImage() throws SecurityException, NoSuchMethodException, IOException {
@@ -422,14 +422,14 @@ public class AMIApiTest extends BaseEC2ApiTest<AMIApi> {
                                                           .addFormParam("Attribute", "launchPermission")
                                                           .addFormParam("ImageId", "imageId")
                                                           .addFormParam("OperationType", "add")
-                                                          .addFormParam("Signature", "WZzNWOC1KHbuySvXEuLTiBA%2BVUfKpSBN2Lud6MrhlCQ%3D")
+                                                          .addFormParam("Signature", "ZuMuzW/iQDRURhUJaBzvoAdNJrE454y6X0jM24lcxxk%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("Version", "2010-08-31")
                                                           .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testAddLaunchPermissionsToImage() throws SecurityException, NoSuchMethodException, IOException {
@@ -459,14 +459,14 @@ public class AMIApiTest extends BaseEC2ApiTest<AMIApi> {
                                                    .addFormParam("Attribute", "launchPermission")
                                                    .addFormParam("ImageId", "imageId")
                                                    .addFormParam("OperationType", "remove")
-                                                   .addFormParam("Signature", "z8OYGQBAwu4HwXV6VF/vuOZlBtptxLxtCQiLXY7UvMU%3D")
+                                                   .addFormParam("Signature", "HreSEawbVaUp/UMicCJbhrx%2BmoX01f2pEphJCPz8/5g%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("Version", "2010-08-31")
                                                    .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testRemoveLaunchPermissionsFromImage() throws SecurityException, NoSuchMethodException, IOException {
@@ -494,11 +494,11 @@ public class AMIApiTest extends BaseEC2ApiTest<AMIApi> {
                                                           .addFormParam("Action", "ResetImageAttribute")
                                                           .addFormParam("Attribute", "launchPermission")
                                                           .addFormParam("ImageId", "imageId")
-                                                          .addFormParam("Signature", "mOVwrqAzidhz%2B4E1dqOJAzG9G9ZX7eDpi8BobN4dA%2BE%3D")
+                                                          .addFormParam("Signature", "fVCR9aGYvNX/Jt1/uqBGcUQRLrHwxtcvmNYKzpul1P4%3D")
                                                           .addFormParam("SignatureMethod", "HmacSHA256")
                                                           .addFormParam("SignatureVersion", "2")
                                                           .addFormParam("Timestamp", "2009-11-08T15%3A54%3A08.897Z")
-                                                          .addFormParam("Version", "2010-06-15")
+                                                          .addFormParam("Version", "2010-08-31")
                                                           .addFormParam("AWSAccessKeyId", "identity").build();
 
    public void testResetLaunchPermissionsOnImage() throws SecurityException, NoSuchMethodException, IOException {

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index 2867e69..3ba8332 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApiLiveTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/AvailabilityZoneAndRegionApiLiveTest.java
@@ -62,7 +62,7 @@ public class AvailabilityZoneAndRegionApiLiveTest extends BaseComputeServiceCont
       for (String region : ec2Api.getConfiguredRegions()) {
          Set<AvailabilityZoneInfo> allResults = client.describeAvailabilityZonesInRegion(region);
          assertNotNull(allResults);
-         assert allResults.size() >= 1 : allResults.size();
+         assert !allResults.isEmpty() : allResults.size();
          Iterator<AvailabilityZoneInfo> iterator = allResults.iterator();
          String id1 = iterator.next().getZone();
          Set<AvailabilityZoneInfo> oneResult = client.describeAvailabilityZonesInRegion(region,
@@ -78,7 +78,7 @@ public class AvailabilityZoneAndRegionApiLiveTest extends BaseComputeServiceCont
       SortedMap<String, URI> allResults = Maps.newTreeMap();
       allResults.putAll(client.describeRegions());
       assertNotNull(allResults);
-      assert allResults.size() >= 1 : allResults.size();
+      assert !allResults.isEmpty() : allResults.size();
       Iterator<Entry<String, URI>> iterator = allResults.entrySet().iterator();
       String r1 = iterator.next().getKey();
       SortedMap<String, URI> oneResult = Maps.newTreeMap();

http://git-wip-us.apache.org/repos/asf/jclouds/blob/2077da28/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
index a72486f..9fc2338 100644
--- a/apis/ec2/src/test/java/org/jclouds/ec2/features/EC2ElasticBlockStoreApiExpectTest.java
+++ b/apis/ec2/src/test/java/org/jclouds/ec2/features/EC2ElasticBlockStoreApiExpectTest.java
@@ -16,17 +16,22 @@
  */
 package org.jclouds.ec2.features;
 
+import static com.google.common.collect.Iterables.getOnlyElement;
 import static org.testng.Assert.assertEquals;
 
 import org.jclouds.ec2.EC2Api;
+import org.jclouds.ec2.domain.Snapshot;
 import org.jclouds.ec2.domain.Volume;
 import org.jclouds.ec2.internal.BaseEC2ApiExpectTest;
 import org.jclouds.http.HttpRequest;
 import org.jclouds.http.HttpResponse;
+import org.jclouds.rest.ResourceNotFoundException;
 import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableMap.Builder;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableSet;
 
 /**
  * @author Adrian Cole
@@ -52,7 +57,7 @@ public class EC2ElasticBlockStoreApiExpectTest extends BaseEC2ApiExpectTest<EC2A
                        .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(),
+                       .payload(payloadFromStringWithContentType("Action=CreateVolume&AvailabilityZone=us-east-1a&Signature=NCu8HU8u0A385rTgj%2BN5lq606jkc1eu88jof9yAxb6s%3D&SignatureMethod=HmacSHA256&SignatureVersion=2&Size=4&Timestamp=2012-04-16T15%3A54%3A08.897Z&Version=2010-08-31&AWSAccessKeyId=identity", "application/x-www-form-urlencoded")).build(),
             HttpResponse.builder()
                         .statusCode(200)
                         .payload(payloadFromResource("/created_volume.xml")).build());
@@ -85,4 +90,83 @@ public class EC2ElasticBlockStoreApiExpectTest extends BaseEC2ApiExpectTest<EC2A
 
       assertEquals(client.createVolumeFromSnapshotInAvailabilityZone(region + "a", 1, "snap-8b7ffbdd"), creating.toBuilder().region(region).build());
    }
+
+   HttpRequest filterVolumes = HttpRequest.builder().method("POST")
+           .endpoint("https://ec2.us-east-1.amazonaws.com/")
+           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+           .addFormParam("Action", "DescribeVolumes")
+           .addFormParam("Filter.1.Name", "snapshot-id")
+           .addFormParam("Filter.1.Value.1", "snap-536d1b3a")
+           .addFormParam("Signature", "7g2ySW39nIVfxtIbuVttUBom7sssmQknxX/9SThkm2Y%3D")
+           .addFormParam("SignatureMethod", "HmacSHA256")
+           .addFormParam("SignatureVersion", "2")
+           .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z")
+           .addFormParam("Version", "2010-08-31")
+           .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testFilterVolumesWhenResponseIs2xx() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResourceWithContentType("/describe_volumes_single.xml", "text/xml")).build();
+
+      EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filterVolumes, filterResponse);
+
+      Volume volume = getOnlyElement(apiWhenExist.getElasticBlockStoreApi().get().describeVolumesInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("snapshot-id", "snap-536d1b3a")
+                      .build()));
+
+      assertEquals(volume.getId(), "vol-4282672b");
+   }
+
+   @Test(expectedExceptions = ResourceNotFoundException.class)
+   public void testFilterVolumesWhenResponseIs404() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build();
+
+      EC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filterVolumes, filterResponse);
+
+      assertEquals(apiWhenNotExist.getElasticBlockStoreApi().get().describeVolumesInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("snapshot-id", "snap-536d1b3a")
+                      .build()),
+              ImmutableSet.of());
+   }
+
+   HttpRequest filterSnapshots = HttpRequest.builder().method("POST")
+           .endpoint("https://ec2.us-east-1.amazonaws.com/")
+           .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+           .addFormParam("Action", "DescribeSnapshots")
+           .addFormParam("Filter.1.Name", "volume-id")
+           .addFormParam("Filter.1.Value.1", "4d826724")
+           .addFormParam("Signature", "vT7R4YmfQJPNLSojXEMY1qcErMh0OzrOTYxbGYSZ4Uw%3D")
+           .addFormParam("SignatureMethod", "HmacSHA256")
+           .addFormParam("SignatureVersion", "2")
+           .addFormParam("Timestamp", "2012-04-16T15%3A54%3A08.897Z")
+           .addFormParam("Version", "2010-08-31")
+           .addFormParam("AWSAccessKeyId", "identity").build();
+
+   public void testFilterSnapshotsWhenResponseIs2xx() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(200)
+              .payload(payloadFromResourceWithContentType("/describe_snapshots.xml", "text/xml")).build();
+
+      EC2Api apiWhenExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filterSnapshots, filterResponse);
+
+      Snapshot snapshot = getOnlyElement(apiWhenExist.getElasticBlockStoreApi().get().describeSnapshotsInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("volume-id", "4d826724")
+                      .build()));
+
+      assertEquals(snapshot.getId(), "snap-78a54011");
+   }
+
+   public void testFilterSnapshotsWhenResponseIs404() {
+      HttpResponse filterResponse = HttpResponse.builder().statusCode(404).build();
+
+      EC2Api apiWhenNotExist = requestsSendResponses(describeRegionsRequest, describeRegionsResponse, filterSnapshots, filterResponse);
+
+      assertEquals(apiWhenNotExist.getElasticBlockStoreApi().get().describeSnapshotsInRegionWithFilter("us-east-1",
+              ImmutableMultimap.<String, String>builder()
+                      .put("volume-id", "4d826724")
+                      .build()),
+              ImmutableSet.of());
+   }
 }