JCLOUDS-1269; JCLOUDS-1120: ec2 subnet/securityGroups fixes

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

Branch: refs/heads/2.0.x
Commit: a9cc10c490e4695d0385e228a9aba60a0e151fff
Parents: df5427f
Author: Andrea Turli <[email protected]>
Authored: Sat Oct 29 15:06:51 2016 +0200
Committer: Andrea Turli <[email protected]>
Committed: Thu May 4 17:42:26 2017 +0200

----------------------------------------------------------------------
 .../BindSubnetIdsToIndexedFormParams.java       |  35 +++
 .../jclouds/ec2/compute/EC2ComputeService.java  |  51 ++--
 .../functions/EC2SecurityGroupIdFromName.java   |   5 +-
 .../predicates/SecurityGroupPresent.java        |   7 +-
 .../jclouds/ec2/features/SecurityGroupApi.java  |  34 +++
 .../ec2/xml/DescribeSubnetsResponseHandler.java |   8 +-
 .../java/org/jclouds/ec2/xml/SubnetHandler.java |  10 +
 .../compute/EC2ComputeServiceExpectTest.java    |   5 +
 .../extensions/EC2ImageExtensionExpectTest.java |   5 -
 .../EC2SecurityGroupExtensionExpectTest.java    |  20 ++
 .../BaseEC2ComputeServiceExpectTest.java        |  16 ++
 .../features/SecurityGroupApiExpectTest.java    |  66 +++++
 .../ec2/features/SecurityGroupApiLiveTest.java  |   2 +-
 .../java/org/jclouds/aws/ec2/AWSEC2Api.java     |  25 +-
 .../AWSEC2CreateSecurityGroupIfNeeded.java      |  14 +-
 ...curityGroupsAsNeededAndReturnRunOptions.java |   9 +-
 .../aws/ec2/features/AWSSecurityGroupApi.java   |   9 +
 .../jclouds/aws/ec2/features/AWSSubnetApi.java  | 133 +++++++++
 .../ec2/options/CreateSecurityGroupOptions.java |   2 +-
 .../aws/ec2/options/CreateSubnetOptions.java    |  85 ++++++
 .../AWSEC2ComputeServiceApiMockTest.java        |  34 +--
 ...AWSEC2SecurityGroupExtensionApiMockTest.java |   4 +-
 .../AWSEC2CreateSecurityGroupIfNeededTest.java  |   3 +-
 ...tyGroupsAsNeededAndReturnRunOptionsTest.java |   2 +-
 .../features/AWSSecurityGroupApiLiveTest.java   |  44 +++
 .../features/AWSSecurityGroupApiMockTest.java   | 270 +++++++++++++++++++
 .../aws/ec2/features/AWSSubnetApiLiveTest.java  | 109 +++++++-
 .../aws/ec2/features/AWSSubnetApiMockTest.java  | 213 +++++++++++++++
 .../aws/ec2/features/VPCApiLiveTest.java        |  17 +-
 .../aws/ec2/internal/BaseAWSEC2ApiMockTest.java |   2 +-
 30 files changed, 1166 insertions(+), 73 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/apis/ec2/src/main/java/org/jclouds/ec2/binders/BindSubnetIdsToIndexedFormParams.java
----------------------------------------------------------------------
diff --git 
a/apis/ec2/src/main/java/org/jclouds/ec2/binders/BindSubnetIdsToIndexedFormParams.java
 
b/apis/ec2/src/main/java/org/jclouds/ec2/binders/BindSubnetIdsToIndexedFormParams.java
new file mode 100644
index 0000000..f71d8d0
--- /dev/null
+++ 
b/apis/ec2/src/main/java/org/jclouds/ec2/binders/BindSubnetIdsToIndexedFormParams.java
@@ -0,0 +1,35 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.ec2.binders;
+
+import javax.inject.Singleton;
+
+import org.jclouds.aws.util.AWSUtils;
+import org.jclouds.http.HttpRequest;
+import org.jclouds.rest.Binder;
+
+/**
+ * Binds the String [] to query parameters named with SubnetId.index
+ */
+@Singleton
+public class BindSubnetIdsToIndexedFormParams implements Binder {
+   @Override
+   public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+      return AWSUtils.indexStringArrayToFormValuesWithPrefix(request, 
"SubnetId", input);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/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 e84b65e..37d7553 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
@@ -32,9 +32,6 @@ import static 
org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_GENERATE_INSTA
 import static org.jclouds.ec2.util.Tags.resourceToTagsAsMap;
 import static org.jclouds.util.Predicates2.retry;
 
-import javax.inject.Named;
-import javax.inject.Provider;
-import javax.inject.Singleton;
 import java.util.List;
 import java.util.Map;
 import java.util.Map.Entry;
@@ -42,21 +39,10 @@ import java.util.Set;
 import java.util.concurrent.ConcurrentMap;
 import java.util.concurrent.atomic.AtomicReference;
 
-import com.google.common.annotations.VisibleForTesting;
-import com.google.common.base.Function;
-import com.google.common.base.Optional;
-import com.google.common.base.Predicate;
-import com.google.common.base.Supplier;
-import com.google.common.cache.LoadingCache;
-import com.google.common.collect.FluentIterable;
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMultimap;
-import com.google.common.collect.ImmutableMultimap.Builder;
-import com.google.common.collect.ImmutableSet;
-import com.google.common.collect.Maps;
-import com.google.common.collect.Multimap;
-import com.google.common.util.concurrent.ListeningExecutorService;
-import com.google.inject.Inject;
+import javax.inject.Named;
+import javax.inject.Provider;
+import javax.inject.Singleton;
+
 import org.jclouds.Constants;
 import org.jclouds.aws.util.AWSUtils;
 import org.jclouds.collect.Memoized;
@@ -95,10 +81,27 @@ 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.SecurityGroup;
 import org.jclouds.ec2.domain.Tag;
 import org.jclouds.ec2.util.TagFilterBuilder;
 import org.jclouds.scriptbuilder.functions.InitAdminAccess;
 
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Function;
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.base.Supplier;
+import com.google.common.cache.LoadingCache;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.ImmutableMultimap.Builder;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.Maps;
+import com.google.common.collect.Multimap;
+import com.google.common.util.concurrent.ListeningExecutorService;
+import com.google.inject.Inject;
+
 @Singleton
 public class EC2ComputeService extends BaseComputeService {
    private final EC2Api client;
@@ -220,10 +223,16 @@ public class EC2ComputeService extends BaseComputeService 
{
       checkNotNull(emptyToNull(group), "group must be defined");
       String groupName = namingConvention.create().sharedNameForGroup(group);
 
-      if 
(!client.getSecurityGroupApi().get().describeSecurityGroupsInRegion(region, 
groupName).isEmpty()) {
+      Multimap<String, String> securityGroupFilterByName = 
ImmutableMultimap.of("group-name", groupName);
+      Set<SecurityGroup> securityGroupsToDelete = 
client.getSecurityGroupApi().get()
+              .describeSecurityGroupsInRegionWithFilter(region, 
securityGroupFilterByName);
+      if (securityGroupsToDelete.size() > 1) {
+         logger.warn("When trying to delete security group %s found more than 
one matching the name. Will delete all - %s.",
+                 group, securityGroupsToDelete);
+      }
+      for (SecurityGroup securityGroup : securityGroupsToDelete) {
          logger.debug(">> deleting securityGroup(%s)", groupName);
-         
client.getSecurityGroupApi().get().deleteSecurityGroupInRegion(region, 
groupName);
-         // TODO: test this clear happens
+         
client.getSecurityGroupApi().get().deleteSecurityGroupInRegionById(region, 
securityGroup.getId());
          securityGroupMap.invalidate(new RegionNameAndIngressRules(region, 
groupName, null, false, null));
          logger.debug("<< deleted securityGroup(%s)", groupName);
       }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/EC2SecurityGroupIdFromName.java
----------------------------------------------------------------------
diff --git 
a/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/EC2SecurityGroupIdFromName.java
 
b/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/EC2SecurityGroupIdFromName.java
index 640a967..56a7f80 100644
--- 
a/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/EC2SecurityGroupIdFromName.java
+++ 
b/apis/ec2/src/main/java/org/jclouds/ec2/compute/functions/EC2SecurityGroupIdFromName.java
@@ -17,6 +17,7 @@
 package org.jclouds.ec2.compute.functions;
 
 import static com.google.common.base.Preconditions.checkNotNull;
+import static com.google.common.collect.ImmutableMultimap.of;
 
 import javax.inject.Inject;
 import javax.inject.Singleton;
@@ -42,7 +43,7 @@ public class EC2SecurityGroupIdFromName implements 
Function<String, String> {
       String[] parts = AWSUtils.parseHandle(input);
       String region = parts[0];
       String name = parts[1];
-
-      return  
Iterables.getOnlyElement(api.getSecurityGroupApi().get().describeSecurityGroupsInRegion(region,
 name), null).getId();
+      return Iterables.getOnlyElement(api.getSecurityGroupApi().get()
+               .describeSecurityGroupsInRegionWithFilter(region, 
of("group-name", name))).getId();
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/apis/ec2/src/main/java/org/jclouds/ec2/compute/predicates/SecurityGroupPresent.java
----------------------------------------------------------------------
diff --git 
a/apis/ec2/src/main/java/org/jclouds/ec2/compute/predicates/SecurityGroupPresent.java
 
b/apis/ec2/src/main/java/org/jclouds/ec2/compute/predicates/SecurityGroupPresent.java
index 7899478..788ce01 100644
--- 
a/apis/ec2/src/main/java/org/jclouds/ec2/compute/predicates/SecurityGroupPresent.java
+++ 
b/apis/ec2/src/main/java/org/jclouds/ec2/compute/predicates/SecurityGroupPresent.java
@@ -30,6 +30,7 @@ import org.jclouds.logging.Logger;
 import org.jclouds.rest.ResourceNotFoundException;
 
 import com.google.common.base.Predicate;
+import com.google.common.collect.ImmutableMultimap;
 import com.google.common.collect.Iterables;
 import com.google.inject.Inject;
 
@@ -57,8 +58,8 @@ public class SecurityGroupPresent implements 
Predicate<RegionAndName> {
       }
    }
 
-   protected SecurityGroup refresh(RegionAndName securityGroup) {
-      return 
Iterables.getOnlyElement(client.getSecurityGroupApi().get().describeSecurityGroupsInRegion(
-            securityGroup.getRegion(), securityGroup.getName()));
+   protected SecurityGroup refresh(final RegionAndName securityGroup) {
+      return 
Iterables.getOnlyElement(client.getSecurityGroupApi().get().describeSecurityGroupsInRegionWithFilter(securityGroup.getRegion(),
+              ImmutableMultimap.of("group-name", securityGroup.getName())));
    }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/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 28fd497..b44290f 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
@@ -86,6 +86,39 @@ public interface SecurityGroupApi {
             @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region,
             @FormParam("GroupName") String name, 
@FormParam("GroupDescription") String description);
 
+
+   // Supported by
+   //  * AWS
+   //  * Openstack - 
https://github.com/openstack/ec2-api/blob/61daf6a80fd6cc9ab800e6b6a2cd3d1d827e2527/ec2api/api/security_group.py#L130
+   //  * Eucalyptus - 
https://docs.eucalyptus.com/eucalyptus/4.4.0/#euca2ools-guide/euca-delete-group.html
+   //                 
https://github.com/eucalyptus/euca2ools/blob/096d97ef2729da976759657d6d6f645a6e959e05/euca2ools/commands/ec2/deletesecuritygroup.py#L37
+   /**
+    * Deletes a security group by ID.
+    *
+    * @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 id
+    *           ID of the security group to delete.
+    *
+    * @see #describeSecurityGroups
+    * @see #authorizeSecurityGroupIngress
+    * @see #revokeSecurityGroupIngress
+    * @see #createSecurityGroup
+    *
+    * @see <a 
href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DeleteSecurityGroup.html";
+    *      />
+    */
+   @Named("DeleteSecurityGroup")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DeleteSecurityGroup")
+   @Fallback(VoidOnNotFoundOr404.class)
+   void deleteSecurityGroupInRegionById(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region,
+           @FormParam("GroupId") String id);
+   
    /**
     * Deletes a security group that you own.
     * 
@@ -114,6 +147,7 @@ public interface SecurityGroupApi {
 
    /**
     * Returns information about security groups that you own.
+    * <p><em>NOTE</em> Works with groups in default VPC only</p>
     *
     * @param region
     *           Security groups are not copied across Regions. Instances 
within the Region cannot

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeSubnetsResponseHandler.java
----------------------------------------------------------------------
diff --git 
a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeSubnetsResponseHandler.java
 
b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeSubnetsResponseHandler.java
index 1f25d4b..dbcc968 100644
--- 
a/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeSubnetsResponseHandler.java
+++ 
b/apis/ec2/src/main/java/org/jclouds/ec2/xml/DescribeSubnetsResponseHandler.java
@@ -37,6 +37,7 @@ public class DescribeSubnetsResponseHandler extends
    private StringBuilder currentText = new StringBuilder();
    private boolean inSubnetSet;
    private boolean inTagSet;
+   private boolean inIpv6CidrBlockAssociationSet;
    private Builder<Subnet> subnets = ImmutableSet.<Subnet> builder();
 
    @Inject
@@ -56,6 +57,8 @@ public class DescribeSubnetsResponseHandler extends
       } else if (inSubnetSet) {
          if (equalsOrSuffix(qName, "tagSet")) {
             inTagSet = true;
+         } else if (equalsOrSuffix(qName, "ipv6CidrBlockAssociationSet")) {
+            inIpv6CidrBlockAssociationSet = true;
          }
          subnetHandler.startElement(url, name, qName, attributes);
       }
@@ -68,7 +71,10 @@ public class DescribeSubnetsResponseHandler extends
       } else if (equalsOrSuffix(qName, "tagSet")) {
          inTagSet = false;
          subnetHandler.endElement(uri, name, qName);
-      } else if (equalsOrSuffix(qName, "item") && !inTagSet) {
+      } else if (equalsOrSuffix(qName, "ipv6CidrBlockAssociationSet")) {
+         inIpv6CidrBlockAssociationSet = false;
+         subnetHandler.endElement(uri, name, qName);
+      } else if (equalsOrSuffix(qName, "item") && !inTagSet && 
!inIpv6CidrBlockAssociationSet) {
          subnets.add(subnetHandler.getResult());
       } else if (inSubnetSet) {
          subnetHandler.endElement(uri, name, qName);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/apis/ec2/src/main/java/org/jclouds/ec2/xml/SubnetHandler.java
----------------------------------------------------------------------
diff --git a/apis/ec2/src/main/java/org/jclouds/ec2/xml/SubnetHandler.java 
b/apis/ec2/src/main/java/org/jclouds/ec2/xml/SubnetHandler.java
index e055425..1dd21e1 100644
--- a/apis/ec2/src/main/java/org/jclouds/ec2/xml/SubnetHandler.java
+++ b/apis/ec2/src/main/java/org/jclouds/ec2/xml/SubnetHandler.java
@@ -33,6 +33,7 @@ public class SubnetHandler extends 
ParseSax.HandlerForGeneratedRequestWithResult
    private Subnet.Builder builder = Subnet.builder();
    private final TagSetHandler tagSetHandler;
    private boolean inTagSet;
+   private boolean inIpv6CidrBlockAssociationSet;
 
    @Inject
    public SubnetHandler(TagSetHandler tagSetHandler) {
@@ -52,6 +53,8 @@ public class SubnetHandler extends 
ParseSax.HandlerForGeneratedRequestWithResult
    public void startElement(String uri, String name, String qName, Attributes 
attrs) {
       if (equalsOrSuffix(qName, "tagSet")) {
          inTagSet = true;
+      } else if (equalsOrSuffix(qName, "ipv6CidrBlockAssociationSet")) {
+         inIpv6CidrBlockAssociationSet = true;
       }
       if (inTagSet) {
          tagSetHandler.startElement(uri, name, qName, attrs);
@@ -60,6 +63,13 @@ public class SubnetHandler extends 
ParseSax.HandlerForGeneratedRequestWithResult
 
    @Override
    public void endElement(String uri, String name, String qName) {
+      if (equalsOrSuffix(qName, "ipv6CidrBlockAssociationSet")) {
+         inIpv6CidrBlockAssociationSet = false;
+      }
+      if (inIpv6CidrBlockAssociationSet) {
+         return; // ignore contents (otherwise "item" and "state" will confuse 
us!
+      }
+      
       if (equalsOrSuffix(qName, "tagSet")) {
          inTagSet = false;
          builder.tags(tagSetHandler.getResult());

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/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 4ffad1f..6de7d27 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
@@ -118,6 +118,7 @@ public class EC2ComputeServiceExpectTest extends 
BaseEC2ComputeServiceExpectTest
       requestResponseMap.put(describeImagesRequest, describeImagesResponse);
       requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
       requestResponseMap.put(createSecurityGroupRequest, 
createSecurityGroupResponse);
+      requestResponseMap.put(describeSecurityGroupFilteredRequest, 
describeSecurityGroupFilteredResponse);
       requestResponseMap.put(describeSecurityGroupRequest, 
describeSecurityGroupResponse);
       requestResponseMap.put(authorizeSecurityGroupIngressRequest22, 
authorizeSecurityGroupIngressResponse);
       requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, 
authorizeSecurityGroupIngressResponse);
@@ -144,6 +145,7 @@ public class EC2ComputeServiceExpectTest extends 
BaseEC2ComputeServiceExpectTest
       requestResponseMap.put(describeImagesRequest, describeImagesResponse);
       requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
       requestResponseMap.put(createSecurityGroupRequest, 
createSecurityGroupResponse);
+      requestResponseMap.put(describeSecurityGroupFilteredRequest, 
describeSecurityGroupFilteredResponse);
       requestResponseMap.put(describeSecurityGroupRequest, 
describeSecurityGroupResponse);
       requestResponseMap.put(authorizeSecurityGroupIngressRequest22, 
authorizeSecurityGroupIngressResponse);
       requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, 
authorizeSecurityGroupIngressResponse);
@@ -171,6 +173,7 @@ public class EC2ComputeServiceExpectTest extends 
BaseEC2ComputeServiceExpectTest
       requestResponseMap.put(describeImagesRequest, describeImagesResponse);
       requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
       requestResponseMap.put(createSecurityGroupRequest, 
createSecurityGroupResponse);
+      requestResponseMap.put(describeSecurityGroupFilteredRequest, 
describeSecurityGroupFilteredResponse);
       requestResponseMap.put(describeSecurityGroupRequest, 
describeSecurityGroupResponse);
       requestResponseMap.put(authorizeSecurityGroupIngressRequest22, 
authorizeSecurityGroupIngressResponse);
       requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, 
authorizeSecurityGroupIngressResponse);
@@ -263,6 +266,7 @@ public class EC2ComputeServiceExpectTest extends 
BaseEC2ComputeServiceExpectTest
       requestResponseMap.put(describeImagesRequest, describeImagesResponse);
       requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
       requestResponseMap.put(createSecurityGroupRequest, 
createSecurityGroupResponse);
+      requestResponseMap.put(describeSecurityGroupFilteredRequest, 
describeSecurityGroupFilteredResponse);
       requestResponseMap.put(describeSecurityGroupRequest, 
describeSecurityGroupResponse);
       requestResponseMap.put(authorizeSecurityGroupIngressRequest22, 
authorizeSecurityGroupIngressResponse);
       requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, 
authorizeSecurityGroupIngressResponse);
@@ -298,6 +302,7 @@ public class EC2ComputeServiceExpectTest extends 
BaseEC2ComputeServiceExpectTest
       requestResponseMap.put(describeImagesRequest, describeImagesResponse);
       requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
       requestResponseMap.put(createSecurityGroupRequest, 
createSecurityGroupResponse);
+      requestResponseMap.put(describeSecurityGroupFilteredRequest, 
describeSecurityGroupFilteredResponse);
       requestResponseMap.put(describeSecurityGroupRequest, 
describeSecurityGroupResponse);
       requestResponseMap.put(authorizeSecurityGroupIngressRequest22, 
authorizeSecurityGroupIngressResponse);
       requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, 
authorizeSecurityGroupIngressResponse);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/apis/ec2/src/test/java/org/jclouds/ec2/compute/extensions/EC2ImageExtensionExpectTest.java
----------------------------------------------------------------------
diff --git 
a/apis/ec2/src/test/java/org/jclouds/ec2/compute/extensions/EC2ImageExtensionExpectTest.java
 
b/apis/ec2/src/test/java/org/jclouds/ec2/compute/extensions/EC2ImageExtensionExpectTest.java
index 4ca6c62..11c968a 100644
--- 
a/apis/ec2/src/test/java/org/jclouds/ec2/compute/extensions/EC2ImageExtensionExpectTest.java
+++ 
b/apis/ec2/src/test/java/org/jclouds/ec2/compute/extensions/EC2ImageExtensionExpectTest.java
@@ -40,11 +40,6 @@ public class EC2ImageExtensionExpectTest extends 
BaseEC2ComputeServiceExpectTest
       requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
       requestResponseMap.put(describeAvailabilityZonesRequest, 
describeAvailabilityZonesResponse);
       requestResponseMap.put(describeImagesRequest, describeImagesResponse);
-      requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
-      requestResponseMap.put(createSecurityGroupRequest, 
createSecurityGroupResponse);
-      requestResponseMap.put(describeSecurityGroupRequest, 
describeSecurityGroupResponse);
-      requestResponseMap.put(authorizeSecurityGroupIngressRequest22, 
authorizeSecurityGroupIngressResponse);
-      requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, 
authorizeSecurityGroupIngressResponse);
       requestResponseMap.put(describeInstanceRequest, 
describeInstanceResponse);
       
       HttpRequest createImageRequest = 
formSigner.filter(HttpRequest.builder().method("POST")

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/apis/ec2/src/test/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtensionExpectTest.java
----------------------------------------------------------------------
diff --git 
a/apis/ec2/src/test/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtensionExpectTest.java
 
b/apis/ec2/src/test/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtensionExpectTest.java
index 5bb73bb..733edbf 100644
--- 
a/apis/ec2/src/test/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtensionExpectTest.java
+++ 
b/apis/ec2/src/test/java/org/jclouds/ec2/compute/extensions/EC2SecurityGroupExtensionExpectTest.java
@@ -49,6 +49,12 @@ import com.google.common.collect.Sets;
 @Test(groups = "unit", testName = "EC2SecurityGroupExtensionExpectTest")
 public class EC2SecurityGroupExtensionExpectTest extends 
BaseEC2ComputeServiceExpectTest {
    
+   public EC2SecurityGroupExtensionExpectTest() {
+      // Don't use the default (us-east-1) region. Better to ensure we always 
pass through the
+      // desired region, rather than it falling back to the default!
+      region = "eu-west-1";
+   }
+   
    public void testListSecurityGroups() {
       HttpRequest describeSecurityGroupsAllRequest = 
          formSigner.filter(HttpRequest.builder()
@@ -209,10 +215,24 @@ public class EC2SecurityGroupExtensionExpectTest extends 
BaseEC2ComputeServiceEx
          .payload(payloadFromResourceWithContentType(
                                                      
"/describe_securitygroups_extension_single.xml", 
MediaType.APPLICATION_XML)).build();
       
+      HttpRequest describeSecurityGroupsSingleFilteredRequest = 
+            formSigner.filter(HttpRequest.builder()
+                              .method("POST")
+                              .endpoint("https://ec2."; + region + 
".amazonaws.com/")
+                              .addHeader("Host", "ec2." + region + 
".amazonaws.com")
+                              .addFormParam("Action", "DescribeSecurityGroups")
+                              .addFormParam("Filter.1.Name", "group-name")
+                              .addFormParam("Filter.1.Value.1", 
"jclouds#some-group").build());
+
+         HttpResponse describeSecurityGroupsSingleFilteredResponse = 
+            HttpResponse.builder().statusCode(200)
+            .payload(payloadFromResourceWithContentType(
+                                                        
"/describe_securitygroups_extension_single.xml", 
MediaType.APPLICATION_XML)).build();
 
       Builder<HttpRequest, HttpResponse> requestResponseMap = 
ImmutableMap.<HttpRequest, HttpResponse> builder();
       requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
       requestResponseMap.put(describeAvailabilityZonesRequest, 
describeAvailabilityZonesResponse);
+      requestResponseMap.put(describeSecurityGroupsSingleFilteredRequest, 
describeSecurityGroupsSingleFilteredResponse);
       requestResponseMap.put(describeSecurityGroupsSingleRequest, 
describeSecurityGroupsSingleResponse);
       requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
       requestResponseMap.put(createSecurityGroupExtRequest, 
createSecurityGroupResponse);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/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 4178e74..eb7e397 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
@@ -46,6 +46,8 @@ public abstract class BaseEC2ComputeServiceExpectTest extends 
BaseEC2ComputeServ
    protected HttpResponse createKeyPairResponse;
    protected HttpRequest createSecurityGroupRequest;
    protected HttpResponse createSecurityGroupResponse;
+   protected HttpRequest describeSecurityGroupFilteredRequest;
+   protected HttpResponse describeSecurityGroupFilteredResponse;
    protected HttpRequest describeSecurityGroupRequest;
    protected HttpResponse describeSecurityGroupResponse;
    protected HttpRequest authorizeSecurityGroupIngressRequest22;
@@ -124,6 +126,20 @@ public abstract class BaseEC2ComputeServiceExpectTest 
extends BaseEC2ComputeServ
                            .payload(payloadFromResourceWithContentType(
                                  "/created_securitygroup.xml", 
MediaType.APPLICATION_XML)).build();
 
+      describeSecurityGroupFilteredRequest = 
+            formSigner.filter(HttpRequest.builder()
+                       .method("POST")
+                       .endpoint("https://ec2."; + region + ".amazonaws.com/")
+                       .addHeader("Host", "ec2." + region + ".amazonaws.com")
+                       .addFormParam("Action", "DescribeSecurityGroups")
+                       .addFormParam("Filter.1.Name", "group-name")
+                       .addFormParam("Filter.1.Value.1", 
"jclouds#test").build());
+   
+      describeSecurityGroupFilteredResponse = 
+            HttpResponse.builder().statusCode(200)
+                        .payload(payloadFromResourceWithContentType(
+                              "/new_securitygroup.xml", 
MediaType.APPLICATION_XML)).build();
+   
       describeSecurityGroupRequest = 
                formSigner.filter(HttpRequest.builder()
                           .method("POST")

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/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
index 811711a..0e5d593 100644
--- 
a/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiExpectTest.java
+++ 
b/apis/ec2/src/test/java/org/jclouds/ec2/features/SecurityGroupApiExpectTest.java
@@ -45,6 +45,30 @@ public class SecurityGroupApiExpectTest extends 
BaseEC2ApiExpectTest<EC2Api> {
            .addFormParam("Version", "2010-08-31")
            .addFormParam("AWSAccessKeyId", "identity").build();
 
+   HttpRequest deleteById = HttpRequest.builder().method("POST")
+         .endpoint("https://ec2.us-east-1.amazonaws.com/";)
+         .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+         .addFormParam("Action", "DeleteSecurityGroup")
+         .addFormParam("GroupId", "sg-3c6ef654")
+         .addFormParam("Signature", 
"FhFx9Uv587s+86KuCOngA2x3DiLRuRrkyd0ZTrXAYbc=")
+         .addFormParam("SignatureMethod", "HmacSHA256")
+         .addFormParam("SignatureVersion", "2")
+         .addFormParam("Timestamp", "2012-04-16T15:54:08.897Z")
+         .addFormParam("Version", "2010-08-31")
+         .addFormParam("AWSAccessKeyId", "identity").build();
+
+   HttpRequest deleteByName = HttpRequest.builder().method("POST")
+         .endpoint("https://ec2.us-east-1.amazonaws.com/";)
+         .addHeader("Host", "ec2.us-east-1.amazonaws.com")
+         .addFormParam("Action", "DeleteSecurityGroup")
+         .addFormParam("GroupName", "jclouds#some-group")
+         .addFormParam("Signature", 
"Jw9ZpWcnAEPaNtZNZBsMyOUUFP1qGETKUzvHiAOz5C8=")
+         .addFormParam("SignatureMethod", "HmacSHA256")
+         .addFormParam("SignatureVersion", "2")
+         .addFormParam("Timestamp", "2012-04-16T15:54:08.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();
@@ -70,4 +94,46 @@ public class SecurityGroupApiExpectTest extends 
BaseEC2ApiExpectTest<EC2Api> {
                       .build()),
               ImmutableSet.of());
    }
+   
+   public void testDeleteSecurityGroupById() {
+      HttpResponse deleteResponse = HttpResponse.builder().statusCode(200)
+            
.payload(payloadFromResourceWithContentType("/delete_securitygroup.xml", 
"text/xml")).build();
+
+      EC2Api apiWhenNotExist = requestsSendResponses(
+            describeRegionsRequest, describeRegionsResponse, 
+            deleteById, deleteResponse);
+
+      
apiWhenNotExist.getSecurityGroupApi().get().deleteSecurityGroupInRegionById("us-east-1",
 "sg-3c6ef654");
+   }
+   
+   public void testDeleteSecurityGroupByIdWhen404() {
+      HttpResponse deleteResponse = 
HttpResponse.builder().statusCode(404).build();
+
+      EC2Api apiWhenNotExist = requestsSendResponses(
+            describeRegionsRequest, describeRegionsResponse, 
+            deleteById, deleteResponse);
+
+      
apiWhenNotExist.getSecurityGroupApi().get().deleteSecurityGroupInRegionById("us-east-1",
 "sg-3c6ef654");
+   }
+   
+   public void testDeleteSecurityGroupByName() {
+      HttpResponse deleteResponse = HttpResponse.builder().statusCode(200)
+            
.payload(payloadFromResourceWithContentType("/delete_securitygroup.xml", 
"text/xml")).build();
+
+      EC2Api apiWhenNotExist = requestsSendResponses(
+            describeRegionsRequest, describeRegionsResponse, 
+            deleteByName, deleteResponse);
+
+      
apiWhenNotExist.getSecurityGroupApi().get().deleteSecurityGroupInRegion("us-east-1",
 "jclouds#some-group");
+   }
+   
+   public void testDeleteSecurityGroupByNameWhen404() {
+      HttpResponse deleteResponse = 
HttpResponse.builder().statusCode(404).build();
+
+      EC2Api apiWhenNotExist = requestsSendResponses(
+            describeRegionsRequest, describeRegionsResponse, 
+            deleteByName, deleteResponse);
+
+      
apiWhenNotExist.getSecurityGroupApi().get().deleteSecurityGroupInRegion("us-east-1",
 "jclouds#some-group");
+   }
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/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 d2c1238..c37e7e7 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
@@ -52,7 +52,7 @@ public class SecurityGroupApiLiveTest extends 
BaseComputeServiceContextLiveTest
       provider = "ec2";
    }
 
-   private EC2Api ec2Api;
+   protected EC2Api ec2Api;
    protected SecurityGroupApi client;
 
    @Override

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2Api.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2Api.java 
b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2Api.java
index 37ca0e9..851597f 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2Api.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/AWSEC2Api.java
@@ -20,6 +20,7 @@ import org.jclouds.aws.ec2.features.AWSAMIApi;
 import org.jclouds.aws.ec2.features.AWSInstanceApi;
 import org.jclouds.aws.ec2.features.AWSKeyPairApi;
 import org.jclouds.aws.ec2.features.AWSSecurityGroupApi;
+import org.jclouds.aws.ec2.features.AWSSubnetApi;
 import org.jclouds.aws.ec2.features.MonitoringApi;
 import org.jclouds.aws.ec2.features.PlacementGroupApi;
 import org.jclouds.aws.ec2.features.SpotInstanceApi;
@@ -47,7 +48,7 @@ public interface AWSEC2Api extends EC2Api {
    @Delegate
    @Override
    Optional<? extends AWSInstanceApi> getInstanceApiForRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
 
    /**
     * {@inheritDoc}
@@ -59,7 +60,7 @@ public interface AWSEC2Api extends EC2Api {
    @Delegate
    @Override
    Optional<? extends AWSSecurityGroupApi> getSecurityGroupApiForRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
 
    /**
     * {@inheritDoc}
@@ -71,7 +72,7 @@ public interface AWSEC2Api extends EC2Api {
    @Delegate
    @Override
    Optional<? extends AWSAMIApi> getAMIApiForRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
 
 
    /**
@@ -82,7 +83,7 @@ public interface AWSEC2Api extends EC2Api {
 
    @Delegate
    Optional<? extends PlacementGroupApi> getPlacementGroupApiForRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
 
    /**
     * Provides synchronous access to Monitoring services.
@@ -92,7 +93,7 @@ public interface AWSEC2Api extends EC2Api {
 
    @Delegate
    Optional<? extends MonitoringApi> getMonitoringApiForRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
 
    /**
     * {@inheritDoc}
@@ -104,7 +105,7 @@ public interface AWSEC2Api extends EC2Api {
    @Delegate
    @Override
    Optional<? extends AWSKeyPairApi> getKeyPairApiForRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
 
    /**
     * Provides synchronous access to SpotInstance services.
@@ -114,11 +115,21 @@ public interface AWSEC2Api extends EC2Api {
 
    @Delegate
    Optional<? extends SpotInstanceApi> getSpotInstanceApiForRegion(
-            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
 
    /**
     * Provides synchronous access to VPC services.
     */
    @Delegate
    Optional<? extends VPCApi> getVPCApi();
+
+   /**
+    * Provides access to Subnet services.
+    */
+   @Delegate
+   Optional<? extends AWSSubnetApi> getAWSSubnetApi();
+
+   @Delegate
+   Optional<? extends AWSSubnetApi> getAWSSubnetApiForRegion(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
 }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeeded.java
----------------------------------------------------------------------
diff --git 
a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeeded.java
 
b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeeded.java
index 9e17354..1b2b033 100644
--- 
a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeeded.java
+++ 
b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeeded.java
@@ -33,6 +33,7 @@ import org.jclouds.aws.ec2.options.CreateSecurityGroupOptions;
 import org.jclouds.compute.reference.ComputeServiceConstants;
 import org.jclouds.ec2.compute.domain.RegionAndName;
 import org.jclouds.ec2.compute.domain.RegionNameAndIngressRules;
+import org.jclouds.ec2.domain.SecurityGroup;
 import org.jclouds.logging.Logger;
 import org.jclouds.net.domain.IpPermission;
 import org.jclouds.net.domain.IpProtocol;
@@ -73,7 +74,7 @@ public class AWSEC2CreateSecurityGroupIfNeeded extends 
CacheLoader<RegionAndName
       return createSecurityGroupInRegion(from.getRegion(), from.getName(), 
realFrom.getVpcId(), realFrom.getPorts());
    }
 
-   private String createSecurityGroupInRegion(String region, String name, 
String vpcId, int... ports) {
+   private String createSecurityGroupInRegion(String region, final String 
name, String vpcId, int... ports) {
       checkNotNull(region, "region");
       checkNotNull(name, "name");
       logger.debug(">> creating securityGroup region(%s) name(%s)", region, 
name);
@@ -102,7 +103,16 @@ public class AWSEC2CreateSecurityGroupIfNeeded extends 
CacheLoader<RegionAndName
                                .build());
             }
 
-            String myOwnerId = 
Iterables.get(securityApi.describeSecurityGroupsInRegion(region, name), 
0).getOwnerId();
+            // Use filter (as per `SecurityGroupPresent`, in 
securityGroupEventualConsistencyDelay)
+            Set<SecurityGroup> securityGroups = 
securityApi.describeSecurityGroupsInRegionById(region, id);
+            if (securityGroups.isEmpty()) {
+               throw new IllegalStateException(String.format("security group 
%s/%s not found after creating", region, name));
+            } else if (securityGroups.size() > 1) {
+               throw new IllegalStateException(String.format("multiple 
security groups matching %s/%s found after creating: %s", 
+                     region, name, securityGroups));
+            }
+            SecurityGroup securityGroup = 
Iterables.getOnlyElement(securityGroups);
+            String myOwnerId = securityGroup.getOwnerId();
             permissions.add(IpPermission.builder()
                             .fromPort(0)
                             .toPort(65535)

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java
----------------------------------------------------------------------
diff --git 
a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java
 
b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java
index 782e376..694e1db 100644
--- 
a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java
+++ 
b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions.java
@@ -43,14 +43,15 @@ import 
org.jclouds.ec2.compute.strategy.CreateKeyPairAndSecurityGroupsAsNeededAn
 import org.jclouds.ec2.domain.KeyPair;
 import org.jclouds.ec2.domain.Subnet;
 import org.jclouds.ec2.options.RunInstancesOptions;
-import org.jclouds.ec2.util.SubnetFilterBuilder;
 import org.jclouds.logging.Logger;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Function;
 import com.google.common.base.Optional;
 import com.google.common.base.Predicate;
+import com.google.common.base.Predicates;
 import com.google.common.cache.LoadingCache;
+import com.google.common.collect.Iterables;
 
 @Singleton
 public class 
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions extends
@@ -192,7 +193,7 @@ public class 
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions
          
awsInstanceOptions.withSecurityGroupIds(awsTemplateOptions.getGroupIds());
       String subnetId = awsTemplateOptions.getSubnetId();
       if (subnetId != null) {
-         Set<String> groups = getSecurityGroupsForTagAndOptions(region, group, 
vpcIdForSubnet(subnetId), template.getOptions());
+         Set<String> groups = getSecurityGroupsForTagAndOptions(region, group, 
vpcIdForSubnet(region, subnetId), template.getOptions());
          awsInstanceOptions.withSubnetId(subnetId);
          awsInstanceOptions.withSecurityGroupIds(groups);
       } else {
@@ -202,8 +203,8 @@ public class 
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions
    }
    
    @VisibleForTesting
-   String vpcIdForSubnet(String subnetId) {
-      Optional<Subnet> subnet = awsEC2Api.getSubnetApi().get().filter(new 
SubnetFilterBuilder().subnetId(subnetId).build()).first();
+   String vpcIdForSubnet(String region, String subnetId) {
+      Optional<Subnet> subnet = 
Iterables.tryFind(awsEC2Api.getAWSSubnetApi().get().describeSubnetsInRegion(region,
 subnetId), Predicates.<Subnet>notNull());
       if (!subnet.isPresent()) {
          throw new IllegalArgumentException("Subnet " + subnetId + " not 
found");
       }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/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 f4e06f6..ef998e8 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
@@ -139,6 +139,15 @@ public interface AWSSecurityGroupApi extends 
SecurityGroupApi {
    @FormParams(keys = ACTION, values = "DescribeSecurityGroups")
    @XMLResponseParser(AWSEC2DescribeSecurityGroupsResponseHandler.class)
    @Fallback(EmptySetOnNotFoundOr404.class)
+   Set<SecurityGroup> describeSecurityGroupsInRegion(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region);
+   
+   @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/a9cc10c4/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSubnetApi.java
----------------------------------------------------------------------
diff --git 
a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSubnetApi.java
 
b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSubnetApi.java
new file mode 100644
index 0000000..ccafebe
--- /dev/null
+++ 
b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSubnetApi.java
@@ -0,0 +1,133 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks;
+import org.jclouds.aws.ec2.options.CreateSubnetOptions;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams;
+import org.jclouds.ec2.binders.BindSubnetIdsToIndexedFormParams;
+import org.jclouds.ec2.domain.Subnet;
+import org.jclouds.ec2.features.SubnetApi;
+import org.jclouds.ec2.xml.DescribeSubnetsResponseHandler;
+import org.jclouds.ec2.xml.SubnetHandler;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.SinceApiVersion;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Multimap;
+
+/**
+ * Provides access to Amazon EC2 via the Query API
+ * <p/>
+ *
+ * @see <a 
href="http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/ApiReference-query-DescribeSubnets.html";
+ * >doc</a>
+ */
+@SinceApiVersion("2011-01-01")
+@RequestFilters(FormSigner.class)
+@VirtualHost
+public interface AWSSubnetApi extends SubnetApi {
+
+   /**
+    * Creates a subnet in an existing VPC.
+    *
+    * @param region
+    * @param vpcId     The ID of the VPC.
+    * @param cidrBlock The network range for the subnet, in CIDR notation. For 
example, 10.0.0.0/24.
+    * @param options
+    * @return AWS Subnet
+    */
+   @Named("CreateSubnet")
+   @POST
+   @Path("/")
+   @XMLResponseParser(SubnetHandler.class)
+   @FormParams(keys = ACTION, values = "CreateSubnet")
+   Subnet createSubnetInRegion(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region,
+           @FormParam("VpcId") String vpcId, @FormParam("CidrBlock") String 
cidrBlock,
+           CreateSubnetOptions... options);
+
+   /**
+    * Deletes a subnet.
+    *
+    * @param region
+    * @param subnetId
+    * @see <a 
href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DeleteSubnet.html";
+    * >doc</a>
+    */
+   @Named("DeleteSubnet")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DeleteSubnet")
+   void deleteSubnetInRegion(
+         @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region,
+           @FormParam("SubnetId") String subnetId);
+
+   /**
+    * Describes one or more of your subnets.
+    *
+    * @param region       Subnet are Region-specific.
+    * @param subnetIds    Subnet to describe.
+    * @see <a 
href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSubnets.html";
+    * >doc</a>
+    */
+   @Named("DescribeSubnets")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeSubnets")
+   @XMLResponseParser(DescribeSubnetsResponseHandler.class)
+   @Fallback(Fallbacks.EmptyFluentIterableOnNotFoundOr404.class)
+   FluentIterable<Subnet> describeSubnetsInRegion(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region,
+           @BinderParam(BindSubnetIdsToIndexedFormParams.class) String... 
subnetIds);
+
+   /**
+    * Returns information about subnets available to you. If you specify 
filters,
+    * information about subnets matching those filters is returned. Otherwise, 
all
+    * subnets you have access to are returned.
+    *
+    * @param region Subnets are Region-specific.
+    * @param filter Multimap of filter key/values.
+    * @see <a 
href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeSubnets.html";
+    * >doc</a>
+    */
+   @Named("DescribeSubnets")
+   @POST
+   @Path("/")
+   @FormParams(keys = ACTION, values = "DescribeSubnets")
+   @XMLResponseParser(DescribeSubnetsResponseHandler.class)
+   @Fallback(Fallbacks.EmptyFluentIterableOnNotFoundOr404.class)
+   FluentIterable<Subnet> describeSubnetsInRegionWithFilter(
+           @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) 
@Nullable String region,
+           @BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, 
String> filter);
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/CreateSecurityGroupOptions.java
----------------------------------------------------------------------
diff --git 
a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/CreateSecurityGroupOptions.java
 
b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/CreateSecurityGroupOptions.java
index 8e1ec94..604a8c0 100644
--- 
a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/CreateSecurityGroupOptions.java
+++ 
b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/CreateSecurityGroupOptions.java
@@ -31,7 +31,7 @@ import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
  * import static 
org.jclouds.aws.ec2.options.CreateSecurityGroupOptions.Builder.*
  * <p/>
  * AWSEC2Api connection = // get connection
- * group = 
connection.getAMIServices().createSecurityGroup(vpcId("123125").noReboot());
+ * group = connection.getAMIServices().createSecurityGroup(vpcId("123125"));
  * <code>
  * 
  * @see <a href=

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/CreateSubnetOptions.java
----------------------------------------------------------------------
diff --git 
a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/CreateSubnetOptions.java
 
b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/CreateSubnetOptions.java
new file mode 100644
index 0000000..0490a76
--- /dev/null
+++ 
b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/CreateSubnetOptions.java
@@ -0,0 +1,85 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.options;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
+
+/**
+ * Contains options supported in the Form API for the CreateSubnet
+ * operation. <h2>
+ * Usage</h2> The recommended way to instantiate a CreateSubnetOptions
+ * object is to statically import CreateSubnetOptions.Builder.* and
+ * invoke a static creation method followed by an instance mutator (if needed):
+ * <p/>
+ * <code>
+ * import static org.jclouds.aws.ec2.options.CreateSubnetOptions.Builder.*
+ * <p/>
+ * AWSEC2Api connection = // get connection
+ * String vpcId = "vpc-1a2b3c4d";
+ * String cidrBlock = "10.0.1.0/24";
+ * group = connection.getAWSSubnetApi().createSubnetInRegion(vpcId, cirdBlock, 
availabilityZone("us-east-1a"));
+ * <code>
+ * 
+ * @see <a href=
+ *      
"http://docs.amazonwebservices.com/AWSEC2/latest/APIReference/index.html?ApiReference-form-CreateSubnet.html";
+ *      />
+ */
+public class CreateSubnetOptions extends BaseEC2RequestOptions {
+
+   /**
+    * The Availability Zone for the subnet.
+    */
+   public CreateSubnetOptions availabilityZone(String availabilityZone) {
+      formParameters.put("AvailabilityZone", checkNotNull(availabilityZone, 
"availabilityZone"));
+      return this;
+   }
+
+   public String getAvailabilityZone() {
+      return getFirstFormOrNull("AvailabilityZone");
+   }
+
+   public CreateSubnetOptions dryRun() {
+      formParameters.put("DryRun", "true");
+      return this;
+   }
+
+   public boolean isDryRun() {
+      return Boolean.parseBoolean(getFirstFormOrNull("DryRun"));
+   }
+
+   public static class Builder {
+
+      /**
+       * @see CreateSubnetOptions#availabilityZone(String )
+       */
+      public static CreateSubnetOptions availabilityZone(String 
availabilityZone) {
+         CreateSubnetOptions options = new CreateSubnetOptions();
+         return options.availabilityZone(availabilityZone);
+      }
+
+      /**
+       * @see CreateSubnetOptions#dryRun()
+       */
+      public static CreateSubnetOptions dryRun() {
+         CreateSubnetOptions options = new CreateSubnetOptions();
+         return options.dryRun();
+      }
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceApiMockTest.java
----------------------------------------------------------------------
diff --git 
a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceApiMockTest.java
 
b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceApiMockTest.java
index 09f1d10..cc81219 100644
--- 
a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceApiMockTest.java
+++ 
b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceApiMockTest.java
@@ -76,10 +76,10 @@ public class AWSEC2ComputeServiceApiMockTest extends 
BaseAWSEC2ApiMockTest {
       assertPosted(DEFAULT_REGION, "Action=DescribeAvailabilityZones");
       assertPosted(DEFAULT_REGION, 
"Action=DescribeImages&Filter.1.Name=owner-id&Filter.1.Value.1=137112412989&Filter.1.Value.2=801119661308&Filter.1.Value.3=063491364108&Filter.1.Value.4=099720109477&Filter.1.Value.5=411009282317&Filter.2.Name=state&Filter.2.Value.1=available&Filter.3.Name=image-type&Filter.3.Value.1=machine");
       assertPosted(DEFAULT_REGION, 
"Action=DescribeImages&Filter.1.Name=virtualization-type&Filter.1.Value.1=hvm&Filter.2.Name=architecture&Filter.2.Value.1=x86_64&Filter.3.Name=owner-id&Filter.3.Value.1=137112412989&Filter.3.Value.2=099720109477&Filter.4.Name=hypervisor&Filter.4.Value.1=xen&Filter.5.Name=state&Filter.5.Value.1=available&Filter.6.Name=image-type&Filter.6.Value.1=machine&Filter.7.Name=root-device-type&Filter.7.Value.1=ebs");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSubnets&Filter.1.Name=subnet-id&Filter.1.Value.1=subnet-9d4a7b6c");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSubnets&SubnetId.1=subnet-9d4a7b6c");
       assertPosted(DEFAULT_REGION, 
"Action=CreateSecurityGroup&GroupName=jclouds%23test&GroupDescription=jclouds%23test&VpcId=vpc-1a2b3c4d");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23test");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23test");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&Filter.1.Name=group-name&Filter.1.Value.1=jclouds%23test");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupId.1=sg-3c6ef654");
       assertPosted(DEFAULT_REGION, 
"Action=AuthorizeSecurityGroupIngress&GroupId=sg-3c6ef654&IpPermissions.0.IpProtocol=tcp&IpPermissions.0.FromPort=22&IpPermissions.0.ToPort=22&IpPermissions.0.IpRanges.0.CidrIp=0.0.0.0/0&IpPermissions.1.IpProtocol=tcp&IpPermissions.1.FromPort=0&IpPermissions.1.ToPort=65535&IpPermissions.1.Groups.0.UserId=993194456877&IpPermissions.1.Groups.0.GroupId=sg-3c6ef654&IpPermissions.2.IpProtocol=udp&IpPermissions.2.FromPort=0&IpPermissions.2.ToPort=65535&IpPermissions.2.Groups.0.UserId=993194456877&IpPermissions.2.Groups.0.GroupId=sg-3c6ef654");
       assertPosted(DEFAULT_REGION, 
"Action=RequestSpotInstances&SpotPrice=1.0&InstanceCount=1&LaunchSpecification.ImageId=ami-"
 + getDefaultImageId() + 
"&LaunchSpecification.Placement.AvailabilityZone=us-east-1a&LaunchSpecification.SecurityGroupId.1=sg-3c6ef654&LaunchSpecification.InstanceType="
 + getDefaultSmallestInstanceType() + 
"&LaunchSpecification.SubnetId=subnet-9d4a7b6c&LaunchSpecification.KeyName=Demo&LaunchSpecification.UserData=I2Nsb3VkLWNvbmZpZwpyZXBvX3VwZ3JhZGU6IG5vbmUK");
       assertPosted(DEFAULT_REGION, 
"Action=DescribeSpotInstanceRequests&SpotInstanceRequestId.1=sir-228e6406");
@@ -118,8 +118,8 @@ public class AWSEC2ComputeServiceApiMockTest extends 
BaseAWSEC2ApiMockTest {
       assertPosted(DEFAULT_REGION, 
"Action=DescribeImages&Filter.1.Name=owner-id&Filter.1.Value.1=137112412989&Filter.1.Value.2=801119661308&Filter.1.Value.3=063491364108&Filter.1.Value.4=099720109477&Filter.1.Value.5=411009282317&Filter.2.Name=state&Filter.2.Value.1=available&Filter.3.Name=image-type&Filter.3.Value.1=machine");
       assertPosted(DEFAULT_REGION, 
"Action=DescribeImages&Filter.1.Name=virtualization-type&Filter.1.Value.1=hvm&Filter.2.Name=architecture&Filter.2.Value.1=x86_64&Filter.3.Name=owner-id&Filter.3.Value.1=137112412989&Filter.3.Value.2=099720109477&Filter.4.Name=hypervisor&Filter.4.Value.1=xen&Filter.5.Name=state&Filter.5.Value.1=available&Filter.6.Name=image-type&Filter.6.Value.1=machine&Filter.7.Name=root-device-type&Filter.7.Value.1=ebs");
       assertPosted(DEFAULT_REGION, 
"Action=CreateSecurityGroup&GroupName=jclouds%23test&GroupDescription=jclouds%23test");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23test");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23test");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&Filter.1.Name=group-name&Filter.1.Value.1=jclouds%23test");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupId.1=sg-3c6ef654");
       assertPosted(DEFAULT_REGION, 
"Action=AuthorizeSecurityGroupIngress&GroupId=sg-3c6ef654&IpPermissions.0.IpProtocol=tcp&IpPermissions.0.FromPort=22&IpPermissions.0.ToPort=22&IpPermissions.0.IpRanges.0.CidrIp=0.0.0.0/0&IpPermissions.1.IpProtocol=tcp&IpPermissions.1.FromPort=0&IpPermissions.1.ToPort=65535&IpPermissions.1.Groups.0.UserId=993194456877&IpPermissions.1.Groups.0.GroupId=sg-3c6ef654&IpPermissions.2.IpProtocol=udp&IpPermissions.2.FromPort=0&IpPermissions.2.ToPort=65535&IpPermissions.2.Groups.0.UserId=993194456877&IpPermissions.2.Groups.0.GroupId=sg-3c6ef654");
       assertPosted(DEFAULT_REGION, 
"Action=RequestSpotInstances&SpotPrice=1.0&InstanceCount=1&LaunchSpecification.ImageId=ami-"
 + getDefaultImageId() + 
"&LaunchSpecification.Placement.AvailabilityZone=us-east-1a&LaunchSpecification.SecurityGroupId.1=sg-3c6ef654&LaunchSpecification.InstanceType="
 + getDefaultSmallestInstanceType() + 
"&LaunchSpecification.UserData=I2Nsb3VkLWNvbmZpZwpyZXBvX3VwZ3JhZGU6IG5vbmUK&LaunchSpecification.IamInstanceProfile.Arn=arn%3Aaws%3Aiam%3A%3A123456789012%3Ainstance-profile/application_abc/component_xyz/Webserver");
       assertPosted(DEFAULT_REGION, 
"Action=DescribeSpotInstanceRequests&SpotInstanceRequestId.1=sir-228e6406");
@@ -156,8 +156,8 @@ public class AWSEC2ComputeServiceApiMockTest extends 
BaseAWSEC2ApiMockTest {
       assertPosted(DEFAULT_REGION, 
"Action=DescribeImages&Filter.1.Name=owner-id&Filter.1.Value.1=137112412989&Filter.1.Value.2=801119661308&Filter.1.Value.3=063491364108&Filter.1.Value.4=099720109477&Filter.1.Value.5=411009282317&Filter.2.Name=state&Filter.2.Value.1=available&Filter.3.Name=image-type&Filter.3.Value.1=machine");
       assertPosted(DEFAULT_REGION, 
"Action=DescribeImages&Filter.1.Name=virtualization-type&Filter.1.Value.1=hvm&Filter.2.Name=architecture&Filter.2.Value.1=x86_64&Filter.3.Name=owner-id&Filter.3.Value.1=137112412989&Filter.3.Value.2=099720109477&Filter.4.Name=hypervisor&Filter.4.Value.1=xen&Filter.5.Name=state&Filter.5.Value.1=available&Filter.6.Name=image-type&Filter.6.Value.1=machine&Filter.7.Name=root-device-type&Filter.7.Value.1=ebs");
       assertPosted(DEFAULT_REGION, 
"Action=CreateSecurityGroup&GroupName=jclouds%23test&GroupDescription=jclouds%23test");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23test");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23test");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&Filter.1.Name=group-name&Filter.1.Value.1=jclouds%23test");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupId.1=sg-3c6ef654");
       assertPosted(DEFAULT_REGION, 
"Action=AuthorizeSecurityGroupIngress&GroupId=sg-3c6ef654&IpPermissions.0.IpProtocol=tcp&IpPermissions.0.FromPort=22&IpPermissions.0.ToPort=22&IpPermissions.0.IpRanges.0.CidrIp=0.0.0.0/0&IpPermissions.1.IpProtocol=tcp&IpPermissions.1.FromPort=0&IpPermissions.1.ToPort=65535&IpPermissions.1.Groups.0.UserId=993194456877&IpPermissions.1.Groups.0.GroupId=sg-3c6ef654&IpPermissions.2.IpProtocol=udp&IpPermissions.2.FromPort=0&IpPermissions.2.ToPort=65535&IpPermissions.2.Groups.0.UserId=993194456877&IpPermissions.2.Groups.0.GroupId=sg-3c6ef654");
       assertPosted(DEFAULT_REGION, 
"Action=RequestSpotInstances&SpotPrice=1.0&InstanceCount=1&LaunchSpecification.ImageId=ami-"
 + getDefaultImageId() + 
"&LaunchSpecification.Placement.AvailabilityZone=us-east-1a&LaunchSpecification.SecurityGroupId.1=sg-3c6ef654&LaunchSpecification.InstanceType="
 + getDefaultSmallestInstanceType() + 
"&LaunchSpecification.UserData=I2Nsb3VkLWNvbmZpZwpyZXBvX3VwZ3JhZGU6IG5vbmUK&LaunchSpecification.IamInstanceProfile.Name=Webserver");
       assertPosted(DEFAULT_REGION, 
"Action=DescribeSpotInstanceRequests&SpotInstanceRequestId.1=sir-228e6406");
@@ -190,8 +190,8 @@ public class AWSEC2ComputeServiceApiMockTest extends 
BaseAWSEC2ApiMockTest {
       assertPosted(DEFAULT_REGION, 
"Action=DescribeImages&Filter.1.Name=virtualization-type&Filter.1.Value.1=hvm&Filter.2.Name=architecture&Filter.2.Value.1=x86_64&Filter.3.Name=owner-id&Filter.3.Value.1=137112412989&Filter.3.Value.2=099720109477&Filter.4.Name=hypervisor&Filter.4.Value.1=xen&Filter.5.Name=state&Filter.5.Value.1=available&Filter.6.Name=image-type&Filter.6.Value.1=machine&Filter.7.Name=root-device-type&Filter.7.Value.1=ebs");
       assertPosted(DEFAULT_REGION, "Action=DescribeAvailabilityZones");
       assertPosted(DEFAULT_REGION, 
"Action=CreateSecurityGroup&GroupName=jclouds%23test&GroupDescription=jclouds%23test");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23test");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23test");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&Filter.1.Name=group-name&Filter.1.Value.1=jclouds%23test");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupId.1=sg-3c6ef654");
       assertPosted(DEFAULT_REGION, 
"Action=AuthorizeSecurityGroupIngress&GroupId=sg-3c6ef654&IpPermissions.0.IpProtocol=tcp&IpPermissions.0.FromPort=22&IpPermissions.0.ToPort=22&IpPermissions.0.IpRanges.0.CidrIp=0.0.0.0/0&IpPermissions.1.IpProtocol=tcp&IpPermissions.1.FromPort=0&IpPermissions.1.ToPort=65535&IpPermissions.1.Groups.0.UserId=993194456877&IpPermissions.1.Groups.0.GroupId=sg-3c6ef654&IpPermissions.2.IpProtocol=udp&IpPermissions.2.FromPort=0&IpPermissions.2.ToPort=65535&IpPermissions.2.Groups.0.UserId=993194456877&IpPermissions.2.Groups.0.GroupId=sg-3c6ef654");
       assertPosted(DEFAULT_REGION, 
"Action=RunInstances&ImageId=ami-8ce4b5c9&MinCount=1&MaxCount=1&InstanceType=" 
+ getDefaultParavirtualInstanceType() + 
"&SecurityGroupId.1=sg-3c6ef654&UserData=I2Nsb3VkLWNvbmZpZwpyZXBvX3VwZ3JhZGU6IG5vbmUK&IamInstanceProfile.Arn=arn%3Aaws%3Aiam%3A%3A123456789012%3Ainstance-profile/application_abc/component_xyz/Webserver");
       assertPosted(DEFAULT_REGION, 
"Action=DescribeInstances&InstanceId.1=i-2baa5550");
@@ -224,8 +224,8 @@ public class AWSEC2ComputeServiceApiMockTest extends 
BaseAWSEC2ApiMockTest {
       assertPosted(DEFAULT_REGION, 
"Action=DescribeImages&Filter.1.Name=virtualization-type&Filter.1.Value.1=hvm&Filter.2.Name=architecture&Filter.2.Value.1=x86_64&Filter.3.Name=owner-id&Filter.3.Value.1=137112412989&Filter.3.Value.2=099720109477&Filter.4.Name=hypervisor&Filter.4.Value.1=xen&Filter.5.Name=state&Filter.5.Value.1=available&Filter.6.Name=image-type&Filter.6.Value.1=machine&Filter.7.Name=root-device-type&Filter.7.Value.1=ebs");
       assertPosted(DEFAULT_REGION, "Action=DescribeAvailabilityZones");
       assertPosted(DEFAULT_REGION, 
"Action=CreateSecurityGroup&GroupName=jclouds%23test&GroupDescription=jclouds%23test");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23test");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23test");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&Filter.1.Name=group-name&Filter.1.Value.1=jclouds%23test");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupId.1=sg-3c6ef654");
       assertPosted(DEFAULT_REGION, 
"Action=AuthorizeSecurityGroupIngress&GroupId=sg-3c6ef654&IpPermissions.0.IpProtocol=tcp&IpPermissions.0.FromPort=22&IpPermissions.0.ToPort=22&IpPermissions.0.IpRanges.0.CidrIp=0.0.0.0/0&IpPermissions.1.IpProtocol=tcp&IpPermissions.1.FromPort=0&IpPermissions.1.ToPort=65535&IpPermissions.1.Groups.0.UserId=993194456877&IpPermissions.1.Groups.0.GroupId=sg-3c6ef654&IpPermissions.2.IpProtocol=udp&IpPermissions.2.FromPort=0&IpPermissions.2.ToPort=65535&IpPermissions.2.Groups.0.UserId=993194456877&IpPermissions.2.Groups.0.GroupId=sg-3c6ef654");
       assertPosted(DEFAULT_REGION, 
"Action=RunInstances&ImageId=ami-8ce4b5c9&MinCount=1&MaxCount=1&InstanceType=" 
+ getDefaultParavirtualInstanceType() + 
"&SecurityGroupId.1=sg-3c6ef654&UserData=I2Nsb3VkLWNvbmZpZwpyZXBvX3VwZ3JhZGU6IG5vbmUK&IamInstanceProfile.Name=Webserver");
       assertPosted(DEFAULT_REGION, 
"Action=DescribeInstances&InstanceId.1=i-2baa5550");
@@ -258,8 +258,8 @@ public class AWSEC2ComputeServiceApiMockTest extends 
BaseAWSEC2ApiMockTest {
       assertPosted(DEFAULT_REGION, 
"Action=DescribeImages&Filter.1.Name=virtualization-type&Filter.1.Value.1=hvm&Filter.2.Name=architecture&Filter.2.Value.1=x86_64&Filter.3.Name=owner-id&Filter.3.Value.1=137112412989&Filter.3.Value.2=099720109477&Filter.4.Name=hypervisor&Filter.4.Value.1=xen&Filter.5.Name=state&Filter.5.Value.1=available&Filter.6.Name=image-type&Filter.6.Value.1=machine&Filter.7.Name=root-device-type&Filter.7.Value.1=ebs");
       assertPosted(DEFAULT_REGION, "Action=DescribeAvailabilityZones");
       assertPosted(DEFAULT_REGION, 
"Action=CreateSecurityGroup&GroupName=jclouds%23test&GroupDescription=jclouds%23test");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23test");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23test");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&Filter.1.Name=group-name&Filter.1.Value.1=jclouds%23test");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupId.1=sg-3c6ef654");
       assertPosted(DEFAULT_REGION, 
"Action=AuthorizeSecurityGroupIngress&GroupId=sg-3c6ef654&IpPermissions.0.IpProtocol=tcp&IpPermissions.0.FromPort=22&IpPermissions.0.ToPort=22&IpPermissions.0.IpRanges.0.CidrIp=0.0.0.0/0&IpPermissions.1.IpProtocol=tcp&IpPermissions.1.FromPort=0&IpPermissions.1.ToPort=65535&IpPermissions.1.Groups.0.UserId=993194456877&IpPermissions.1.Groups.0.GroupId=sg-3c6ef654&IpPermissions.2.IpProtocol=udp&IpPermissions.2.FromPort=0&IpPermissions.2.ToPort=65535&IpPermissions.2.Groups.0.UserId=993194456877&IpPermissions.2.Groups.0.GroupId=sg-3c6ef654");
       assertPosted(DEFAULT_REGION, 
"Action=RunInstances&ImageId=ami-8ce4b5c9&MinCount=1&MaxCount=1&InstanceType=" 
+ getDefaultParavirtualInstanceType() + 
"&SecurityGroupId.1=sg-3c6ef654&UserData=I2Nsb3VkLWNvbmZpZwpyZXBvX3VwZ3JhZGU6IG5vbmUK&Placement.Tenancy=host&Placement.HostId=TestHostId");
       assertPosted(DEFAULT_REGION, 
"Action=DescribeInstances&InstanceId.1=i-2baa5550");
@@ -302,8 +302,8 @@ public class AWSEC2ComputeServiceApiMockTest extends 
BaseAWSEC2ApiMockTest {
       computeService.cleanUpIncidentalResources(DEFAULT_REGION, "sg-3c6ef654");
 
       assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23sg-3c6ef654");
-      assertPosted(DEFAULT_REGION, 
"Action=DeleteSecurityGroup&GroupName=jclouds%23sg-3c6ef654");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&Filter.1.Name=group-name&Filter.1.Value.1=jclouds%23sg-3c6ef654");
+      assertPosted(DEFAULT_REGION, 
"Action=DeleteSecurityGroup&GroupId=sg-3c6ef654");
       assertPosted(DEFAULT_REGION, 
"Action=DescribeKeyPairs&Filter.1.Name=key-name&Filter.1.Value.1=jclouds%23sg-3c6ef654%23%2A");
       assertPosted(DEFAULT_REGION, 
"Action=DescribeInstances&Filter.1.Name=instance-state-name&Filter.1.Value.1=terminated&Filter.1.Value.2=shutting-down&Filter.2.Name=key-name&Filter.2.Value.1=jclouds%23sg-3c6ef654");
       assertPosted(DEFAULT_REGION, 
"Action=DeleteKeyPair&KeyName=jclouds%23sg-3c6ef654");
@@ -336,8 +336,8 @@ public class AWSEC2ComputeServiceApiMockTest extends 
BaseAWSEC2ApiMockTest {
       computeService.cleanUpIncidentalResources(DEFAULT_REGION, "sg-3c6ef654");
 
       assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23sg-3c6ef654");
-      assertPosted(DEFAULT_REGION, 
"Action=DeleteSecurityGroup&GroupName=jclouds%23sg-3c6ef654");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&Filter.1.Name=group-name&Filter.1.Value.1=jclouds%23sg-3c6ef654");
+      assertPosted(DEFAULT_REGION, 
"Action=DeleteSecurityGroup&GroupId=sg-3c6ef654");
       assertPosted(DEFAULT_REGION, 
"Action=DescribePlacementGroups&GroupName.1=jclouds%23sg-3c6ef654%23us-east-1");
       assertPosted(DEFAULT_REGION, 
"Action=DeletePlacementGroup&GroupName=jclouds%23sg-3c6ef654%23us-east-1");
       assertPosted(DEFAULT_REGION, 
"Action=DescribePlacementGroups&GroupName.1=jclouds%23sg-3c6ef654%23us-east-1");

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtensionApiMockTest.java
----------------------------------------------------------------------
diff --git 
a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtensionApiMockTest.java
 
b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtensionApiMockTest.java
index 24c91e2..d5f0220 100644
--- 
a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtensionApiMockTest.java
+++ 
b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtensionApiMockTest.java
@@ -153,8 +153,8 @@ public class AWSEC2SecurityGroupExtensionApiMockTest 
extends BaseAWSEC2ApiMockTe
       assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
       assertPosted(DEFAULT_REGION,
             
"Action=CreateSecurityGroup&GroupName=jclouds%23some-group&GroupDescription=jclouds%23some-group");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23some-group");
-      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupName.1=jclouds%23some-group");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&Filter.1.Name=group-name&Filter.1.Value.1=jclouds%23some-group");
+      assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&Filter.1.Name=group-name&Filter.1.Value.1=jclouds%23some-group");
       assertPosted(DEFAULT_REGION, 
"Action=DescribeSecurityGroups&GroupId.1=sg-3c6ef654");
       assertPosted(DEFAULT_REGION, "Action=DescribeAvailabilityZones");
    }

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeededTest.java
----------------------------------------------------------------------
diff --git 
a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeededTest.java
 
b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeededTest.java
index bf87309..1880a23 100644
--- 
a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeededTest.java
+++ 
b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/loaders/AWSEC2CreateSecurityGroupIfNeededTest.java
@@ -82,7 +82,8 @@ public class AWSEC2CreateSecurityGroupIfNeededTest {
                   new 
CreateSecurityGroupOptions().vpcId("vpc"))).andReturn("sg-123456");
       expect(group.getOwnerId()).andReturn("ownerId");
       client.authorizeSecurityGroupIngressInRegion("region", "sg-123456", 
permissions.build());
-      expect(client.describeSecurityGroupsInRegion("region", 
"group")).andReturn(Set.class.cast(groups));
+      expect(client.describeSecurityGroupsInRegionById("region", "sg-123456"))
+               .andReturn(Set.class.cast(groups));
 
 
       replay(client);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsTest.java
----------------------------------------------------------------------
diff --git 
a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsTest.java
 
b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsTest.java
index f73ebc1..3c738a6 100644
--- 
a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsTest.java
+++ 
b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/strategy/CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsTest.java
@@ -308,7 +308,7 @@ public class 
CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptionsT
       expect(options.getSubnetId()).andReturn("1");
       expect(options.getUserData()).andReturn(null);
       expect(options.isMonitoringEnabled()).andReturn(false);
-      expect(strategy.vpcIdForSubnet("1")).andReturn("vpc1");
+      expect(strategy.vpcIdForSubnet("", "1")).andReturn("vpc1");
 
       // replay mocks
       replay(options);

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a9cc10c4/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiLiveTest.java
----------------------------------------------------------------------
diff --git 
a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiLiveTest.java
 
b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiLiveTest.java
index 9100a5b..dcc2b89 100644
--- 
a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiLiveTest.java
+++ 
b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSecurityGroupApiLiveTest.java
@@ -19,18 +19,26 @@ package org.jclouds.aws.ec2.features;
 import static org.testng.Assert.assertEquals;
 import static org.testng.Assert.assertNotNull;
 
+import java.util.Random;
 import java.util.Set;
 
+import org.jclouds.aws.ec2.AWSEC2Api;
+import org.jclouds.aws.ec2.domain.VPC;
+import org.jclouds.aws.ec2.options.CreateSecurityGroupOptions;
+import org.jclouds.aws.ec2.options.CreateVpcOptions;
+import org.jclouds.ec2.EC2Api;
 import org.jclouds.ec2.domain.SecurityGroup;
 import org.jclouds.ec2.domain.UserIdGroupPair;
 import org.jclouds.ec2.features.SecurityGroupApiLiveTest;
 import org.jclouds.ec2.util.IpPermissions;
 import org.jclouds.net.domain.IpPermission;
 import org.jclouds.net.domain.IpProtocol;
+import org.testng.annotations.BeforeClass;
 import org.testng.annotations.Test;
 
 import com.google.common.base.Predicate;
 import com.google.common.collect.ImmutableMultimap;
+import com.google.common.collect.Iterables;
 
 @Test(groups = "live", singleThreaded = true)
 public class AWSSecurityGroupApiLiveTest extends SecurityGroupApiLiveTest {
@@ -116,4 +124,40 @@ public class AWSSecurityGroupApiLiveTest extends 
SecurityGroupApiLiveTest {
          client.deleteSecurityGroupInRegion(null, group1Name);
       }
    }
+
+   @Override
+   @BeforeClass(groups = { "integration", "live" })
+   public void setupContext() {
+      super.setupContext();
+      ec2Api = view.unwrapApi(EC2Api.class);
+      client = ec2Api.getSecurityGroupApi().get();
+   }
+
+   @Test
+   void testCreateSecurityGroupInVpc() {
+      String region = "us-west-2";
+      String groupName = PREFIX + "1" + new Random().nextInt(10000);
+      String description = "jclouds testCreateSecurityGroupInVpc";
+      
+      VPCApi vpcClient = AWSEC2Api.class.cast(ec2Api).getVPCApi().get();
+      AWSSecurityGroupApi sgClient = AWSSecurityGroupApi.class.cast(client);
+
+      VPC vpc = vpcClient.createVpc(region, "10.0.0.0/16", 
CreateVpcOptions.NONE);
+      try {
+         String sgId = sgClient.createSecurityGroupInRegionAndReturnId(
+               region, groupName, description, 
CreateSecurityGroupOptions.Builder.vpcId(vpc.id()));
+
+         try {
+            Set<SecurityGroup> securityGroups = 
sgClient.describeSecurityGroupsInRegionWithFilter(
+                  region, ImmutableMultimap.of("vpc-id", vpc.id(), "group-id", 
sgId));
+            SecurityGroup sg = Iterables.getOnlyElement(securityGroups);
+            assertEquals(sg.getId(), sgId);
+            assertEquals(sg.getId(), sgId);
+         } finally {
+            sgClient.deleteSecurityGroupInRegionById(region, sgId);
+         }
+      } finally {
+         vpcClient.deleteVpc(region, vpc.id());
+      }
+   }
 }

Reply via email to