You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by ad...@apache.org on 2014/11/22 17:09:48 UTC

[2/3] jclouds git commit: JCLOUDS-480 support version 4 signatures for aws-ec2.

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a449b24e/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceExpectTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceExpectTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceExpectTest.java
deleted file mode 100644
index da2f898..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2ComputeServiceExpectTest.java
+++ /dev/null
@@ -1,278 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.aws.ec2.compute;
-
-import static org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions.Builder.blockUntilRunning;
-import static org.testng.Assert.assertEquals;
-
-import javax.ws.rs.core.MediaType;
-
-import org.jclouds.aws.ec2.compute.internal.BaseAWSEC2ComputeServiceExpectTest;
-import org.jclouds.compute.ComputeService;
-import org.jclouds.compute.domain.NodeMetadata;
-import org.jclouds.compute.domain.Template;
-import org.jclouds.compute.predicates.NodePredicates;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.testng.annotations.BeforeClass;
-import org.testng.annotations.Test;
-
-import com.google.common.collect.ImmutableMap;
-import com.google.common.collect.ImmutableMap.Builder;
-import com.google.common.collect.Iterables;
-
-/**
- * Tests the compute service abstraction of the EC2 api.
- */
-@Test(groups = "unit", testName = "AWSEC2ComputeServiceExpectTest")
-public class AWSEC2ComputeServiceExpectTest extends BaseAWSEC2ComputeServiceExpectTest {
-
-   private HttpResponse requestSpotInstancesResponse;
-   private HttpRequest describeSpotInstanceRequest;
-   private HttpResponse describeSpotInstanceResponse;
-
-   @BeforeClass
-   @Override
-   protected void setupDefaultRequests() {
-      super.setupDefaultRequests();
-      requestSpotInstancesResponse = HttpResponse.builder().statusCode(200)
-                       .payload(payloadFromResourceWithContentType(
-                             "/request_spot_instances-ebs.xml", MediaType.APPLICATION_XML)).build();
-   
-      describeSpotInstanceRequest = formSigner.filter(HttpRequest.builder().method("POST")
-                       .endpoint("https://ec2." + region + ".amazonaws.com/")
-                       .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                       .addFormParam("Action", "DescribeSpotInstanceRequests")
-                       .addFormParam("SpotInstanceRequestId.1", "sir-228e6406").build());
-
-      describeSpotInstanceResponse = HttpResponse.builder().statusCode(200)
-                       .payload(payloadFromResourceWithContentType(
-                             "/request_spot_instances-ebs.xml", MediaType.APPLICATION_XML)).build();
-   }
-
-   public void testLaunchVPCSpotInstanceSubnetId() throws Exception {
-      HttpRequest requestSpotInstancesRequest = formSigner.filter(HttpRequest.builder().method("POST")
-                          .endpoint("https://ec2." + region + ".amazonaws.com/")
-                          .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                          .addFormParam("Action", "RequestSpotInstances")
-                          .addFormParam("InstanceCount", "1")
-                          .addFormParam("LaunchSpecification.ImageId", "ami-be3adfd7")
-                          .addFormParam("LaunchSpecification.InstanceType", "m1.small")
-                          .addFormParam("LaunchSpecification.KeyName", "Demo")
-                          .addFormParam("LaunchSpecification.Placement.AvailabilityZone", "us-east-1a")
-                          .addFormParam("LaunchSpecification.SubnetId", "subnet-xyz")
-                          .addFormParam("LaunchSpecification.UserData", "I2Nsb3VkLWNvbmZpZwpyZXBvX3VwZ3JhZGU6IG5vbmUK")
-                          .addFormParam("SpotPrice", "1.0").build());
-
-      Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
-      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(requestSpotInstancesRequest, requestSpotInstancesResponse);
-      requestResponseMap.put(describeSpotInstanceRequest, describeSpotInstanceResponse);
-
-      ComputeService createsVPCSpotInstance = requestsSendResponses(requestResponseMap.build());
-
-      Template template = createsVPCSpotInstance.templateBuilder().locationId("us-east-1a").build();
-
-      template.getOptions().as(AWSEC2TemplateOptions.class).spotPrice(1f).subnetId("subnet-xyz").keyPair("Demo").blockUntilRunning(false);
-
-      NodeMetadata node = Iterables.getOnlyElement(createsVPCSpotInstance.createNodesInGroup("test", 1, template));
-      assertEquals(node.getId(), "us-east-1/sir-228e6406");
-   }
-
-   String iamInstanceProfileArn = "arn:aws:iam::123456789012:instance-profile/application_abc/component_xyz/Webserver";
-
-   public void testLaunchSpotInstanceIAMInstanceProfileArn() throws Exception {
-      HttpRequest requestSpotInstancesRequest = formSigner.filter(HttpRequest.builder().method("POST")
-                          .endpoint("https://ec2." + region + ".amazonaws.com/")
-                          .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                          .addFormParam("Action", "RequestSpotInstances")
-                          .addFormParam("InstanceCount", "1")
-                          .addFormParam("LaunchSpecification.IamInstanceProfile.Arn", iamInstanceProfileArn)
-                          .addFormParam("LaunchSpecification.ImageId", "ami-be3adfd7")
-                          .addFormParam("LaunchSpecification.InstanceType", "m1.small")
-                          .addFormParam("LaunchSpecification.Placement.AvailabilityZone", "us-east-1a")
-                          .addFormParam("LaunchSpecification.SecurityGroup.1", "jclouds#test")
-                          .addFormParam("LaunchSpecification.UserData", "I2Nsb3VkLWNvbmZpZwpyZXBvX3VwZ3JhZGU6IG5vbmUK")
-                          .addFormParam("SpotPrice", "1.0").build());
-
-      Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
-      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(requestSpotInstancesRequest, requestSpotInstancesResponse);
-      requestResponseMap.put(describeSpotInstanceRequest, describeSpotInstanceResponse);
-
-      ComputeService createsSpotInstance = requestsSendResponses(requestResponseMap.build());
-
-      Template template = createsSpotInstance.templateBuilder().locationId("us-east-1a").build();
-
-      template.getOptions().as(AWSEC2TemplateOptions.class).spotPrice(1f).iamInstanceProfileArn(iamInstanceProfileArn)
-            .noKeyPair().blockUntilRunning(false);
-
-      NodeMetadata node = Iterables.getOnlyElement(createsSpotInstance.createNodesInGroup("test", 1, template));
-      assertEquals(node.getId(), "us-east-1/sir-228e6406");
-   }
-
-   public void testLaunchSpotInstanceIAMInstanceProfileName() throws Exception {
-      HttpRequest requestSpotInstancesRequest = formSigner.filter(HttpRequest.builder().method("POST")
-                          .endpoint("https://ec2." + region + ".amazonaws.com/")
-                          .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                          .addFormParam("Action", "RequestSpotInstances")
-                          .addFormParam("InstanceCount", "1")
-                          .addFormParam("LaunchSpecification.IamInstanceProfile.Name", "Webserver")
-                          .addFormParam("LaunchSpecification.ImageId", "ami-be3adfd7")
-                          .addFormParam("LaunchSpecification.InstanceType", "m1.small")
-                          .addFormParam("LaunchSpecification.Placement.AvailabilityZone", "us-east-1a")
-                          .addFormParam("LaunchSpecification.SecurityGroup.1", "jclouds#test")
-                          .addFormParam("LaunchSpecification.UserData", "I2Nsb3VkLWNvbmZpZwpyZXBvX3VwZ3JhZGU6IG5vbmUK")
-                          .addFormParam("SpotPrice", "1.0").build());
-
-      Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
-      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(requestSpotInstancesRequest, requestSpotInstancesResponse);
-      requestResponseMap.put(describeSpotInstanceRequest, describeSpotInstanceResponse);
-
-      ComputeService createsSpotInstance = requestsSendResponses(requestResponseMap.build());
-
-      Template template = createsSpotInstance.templateBuilder().locationId("us-east-1a").build();
-
-      template.getOptions().as(AWSEC2TemplateOptions.class).spotPrice(1f).iamInstanceProfileName("Webserver")
-            .noKeyPair().blockUntilRunning(false);
-
-      NodeMetadata node = Iterables.getOnlyElement(createsSpotInstance.createNodesInGroup("test", 1, template));
-      assertEquals(node.getId(), "us-east-1/sir-228e6406");
-   }
-
-   public void testCreateNodeWithIAMInstanceProfileArn() throws Exception {
-      HttpRequest runInstancesRequest = formSigner.filter(HttpRequest.builder().method("POST")
-            .endpoint("https://ec2." + region + ".amazonaws.com/")
-            .addHeader("Host", "ec2." + region + ".amazonaws.com")
-            .addFormParam("Action", "RunInstances")
-            .addFormParam("IamInstanceProfile.Arn", iamInstanceProfileArn)
-            .addFormParam("ImageId", "ami-be3adfd7")
-            .addFormParam("InstanceType", "m1.small")
-            .addFormParam("MaxCount", "1")
-            .addFormParam("MinCount", "1")
-            .addFormParam("SecurityGroup.1", "jclouds#test")
-            .addFormParam("UserData", "I2Nsb3VkLWNvbmZpZwpyZXBvX3VwZ3JhZGU6IG5vbmUK").build());
-
-      Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
-      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(runInstancesRequest, runInstancesResponse);
-      requestResponseMap.put(describeInstanceRequest, describeInstanceResponse);
-      requestResponseMap.put(describeImageRequest, describeImagesResponse);
-
-      ComputeService apiThatCreatesNode = requestsSendResponses(requestResponseMap.build());
-
-      NodeMetadata node = Iterables.getOnlyElement(apiThatCreatesNode.createNodesInGroup("test", 1,
-            blockUntilRunning(false).iamInstanceProfileArn(iamInstanceProfileArn).noKeyPair()));
-      assertEquals(node.getId(), "us-east-1/i-2baa5550");
-   }
-
-   public void testCreateNodeWithIAMInstanceProfileName() throws Exception {
-      HttpRequest runInstancesRequest = formSigner.filter(HttpRequest.builder().method("POST")
-            .endpoint("https://ec2." + region + ".amazonaws.com/")
-            .addHeader("Host", "ec2." + region + ".amazonaws.com")
-            .addFormParam("Action", "RunInstances")
-            .addFormParam("IamInstanceProfile.Name", "Webserver")
-            .addFormParam("ImageId", "ami-be3adfd7")
-            .addFormParam("InstanceType", "m1.small")
-            .addFormParam("MaxCount", "1")
-            .addFormParam("MinCount", "1")
-            .addFormParam("SecurityGroup.1", "jclouds#test")
-            .addFormParam("UserData", "I2Nsb3VkLWNvbmZpZwpyZXBvX3VwZ3JhZGU6IG5vbmUK").build());
-
-      Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
-      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(runInstancesRequest, runInstancesResponse);
-      requestResponseMap.put(describeInstanceRequest, describeInstanceResponse);
-      requestResponseMap.put(describeImageRequest, describeImagesResponse);
-
-      ComputeService apiThatCreatesNode = requestsSendResponses(requestResponseMap.build());
-
-      NodeMetadata node = Iterables.getOnlyElement(apiThatCreatesNode.createNodesInGroup("test", 1,
-            blockUntilRunning(false).iamInstanceProfileName("Webserver").noKeyPair()));
-      assertEquals(node.getId(), "us-east-1/i-2baa5550");
-   }
-
-   public void testListNodesWhereImageDoesntExist() throws Exception {
-      HttpRequest describeInstancesRequest = formSigner.filter(HttpRequest.builder().method("POST")
-                           .endpoint("https://ec2." + region + ".amazonaws.com/")
-                           .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                           .addFormParam("Action", "DescribeInstances").build());
-
-      HttpRequest describeSpotInstancesRequest = formSigner.filter(HttpRequest.builder().method("POST")
-                          .endpoint("https://ec2." + region + ".amazonaws.com/")
-                          .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                          .addFormParam("Action", "DescribeSpotInstanceRequests").build());
-
-      HttpResponse noSpotInstancesResponse = HttpResponse.builder().statusCode(200)
-            .payload(payloadFromStringWithContentType(
-                  "<DescribeSpotInstanceRequestsResponse><spotInstanceRequestSet></spotInstanceRequestSet></DescribeSpotInstanceRequestsResponse>",
-                  MediaType.APPLICATION_XML)).build();
-      
-      HttpResponse noImagesResponse = HttpResponse.builder().statusCode(200)
-                          .payload(payloadFromStringWithContentType(
-                                 "<DescribeImagesResponse><imagesSet></imagesSet></DescribeImagesResponse>",
-                                 MediaType.APPLICATION_XML)).build();
-      
-      Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
-      requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
-      requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
-      requestResponseMap.put(describeImagesRequest, noImagesResponse);
-      requestResponseMap.put(describeInstancesRequest, describeInstanceResponse);
-      requestResponseMap.put(describeSpotInstancesRequest, noSpotInstancesResponse);
-
-      ComputeService listsWithoutImages = requestsSendResponses(requestResponseMap.build());
-
-      NodeMetadata node = Iterables.getOnlyElement(listsWithoutImages.listNodesDetailsMatching(NodePredicates.all()));
-      assertEquals(node.getId(), "us-east-1/i-2baa5550");
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a449b24e/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateBuilderLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateBuilderLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateBuilderLiveTest.java
index 65cbd60..050b9aa 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateBuilderLiveTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/AWSEC2TemplateBuilderLiveTest.java
@@ -29,6 +29,7 @@ import java.util.Set;
 
 import org.jclouds.aws.domain.Region;
 import org.jclouds.aws.ec2.AWSEC2Api;
+import org.jclouds.aws.ec2.AWSEC2ProviderMetadata;
 import org.jclouds.aws.ec2.reference.AWSEC2Constants;
 import org.jclouds.compute.ComputeServiceContext;
 import org.jclouds.compute.domain.OsFamily;
@@ -46,6 +47,7 @@ import org.jclouds.http.HttpCommand;
 import org.jclouds.http.internal.TrackingJavaUrlHttpCommandExecutorService;
 import org.jclouds.location.reference.LocationConstants;
 import org.jclouds.logging.log4j.config.Log4JLoggingModule;
+import org.jclouds.providers.ProviderMetadata;
 import org.testng.annotations.Test;
 
 import com.google.common.collect.ImmutableSet;
@@ -59,6 +61,10 @@ public class AWSEC2TemplateBuilderLiveTest extends EC2TemplateBuilderLiveTest {
       provider = "aws-ec2";
    }
 
+   @Override public ProviderMetadata createProviderMetadata() {
+      return new AWSEC2ProviderMetadata();
+   }
+
    @Test
    public void testTemplateBuilderM1MEDIUMWithNegativeLookaroundDoesntMatchTestImages() {
 

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a449b24e/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
new file mode 100644
index 0000000..1bee5d5
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtensionApiMockTest.java
@@ -0,0 +1,167 @@
+/*
+ * 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.compute.extensions;
+
+import static org.jclouds.domain.LocationScope.REGION;
+import static org.testng.Assert.assertEquals;
+
+import org.jclouds.aws.ec2.internal.BaseAWSEC2ApiMockTest;
+import org.jclouds.compute.domain.SecurityGroup;
+import org.jclouds.compute.domain.SecurityGroupBuilder;
+import org.jclouds.compute.extensions.SecurityGroupExtension;
+import org.jclouds.domain.LocationBuilder;
+import org.jclouds.net.domain.IpPermission;
+import org.jclouds.net.domain.IpProtocol;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.Iterables;
+
+@Test(groups = "unit", testName = "AWSEC2SecurityGroupExtensionMockTest", singleThreaded = true)
+public class AWSEC2SecurityGroupExtensionApiMockTest extends BaseAWSEC2ApiMockTest {
+
+   SecurityGroup group = new SecurityGroupBuilder() //
+         .id(DEFAULT_REGION + "/sg-3c6ef654") //
+         .providerId("sg-3c6ef654") //
+         .name("jclouds#some-group") //
+         .ownerId("993194456877")
+         .location(new LocationBuilder().scope(REGION).id(DEFAULT_REGION).description("").build()).build();
+
+   IpPermission permByCidrBlock = IpPermission.builder() //
+         .ipProtocol(IpProtocol.TCP) //
+         .fromPort(22) //
+         .toPort(40) //
+         .cidrBlock("0.0.0.0/0").build();
+
+   public void addIpPermissionCidrFromIpPermission() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/authorize_securitygroup_ingress_response.xml");
+      enqueueXml(DEFAULT_REGION, "/describe_securitygroups_extension_cidr.xml");
+      enqueueXml(DEFAULT_REGION, "/availabilityZones.xml");
+
+      SecurityGroup newGroup = extension().addIpPermission(permByCidrBlock, group);
+
+      assertEquals(1, newGroup.getIpPermissions().size());
+
+      IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
+      assertEquals(newPerm, permByCidrBlock);
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION,
+            "Action=AuthorizeSecurityGroupIngress&GroupId=sg-3c6ef654&IpPermissions.0.IpProtocol=tcp&IpPermissions.0.FromPort=22&IpPermissions.0.ToPort=40&IpPermissions.0.IpRanges.0.CidrIp=0.0.0.0/0");
+      assertPosted(DEFAULT_REGION, "Action=DescribeSecurityGroups&GroupId.1=sg-3c6ef654");
+      assertPosted(DEFAULT_REGION, "Action=DescribeAvailabilityZones");
+   }
+
+   public void addIpPermissionCidrFromParams() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/authorize_securitygroup_ingress_response.xml");
+      enqueueXml(DEFAULT_REGION, "/describe_securitygroups_extension_cidr.xml");
+      enqueueXml(DEFAULT_REGION, "/availabilityZones.xml");
+
+      SecurityGroup newGroup = extension()
+            .addIpPermission(permByCidrBlock.getIpProtocol(), permByCidrBlock.getFromPort(),
+                  permByCidrBlock.getToPort(), permByCidrBlock.getTenantIdGroupNamePairs(),
+                  permByCidrBlock.getCidrBlocks(), permByCidrBlock.getGroupIds(), group);
+
+      IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
+      assertEquals(newPerm, permByCidrBlock);
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION,
+            "Action=AuthorizeSecurityGroupIngress&GroupId=sg-3c6ef654&IpPermissions.0.IpProtocol=tcp&IpPermissions.0.FromPort=22&IpPermissions.0.ToPort=40&IpPermissions.0.IpRanges.0.CidrIp=0.0.0.0/0");
+      assertPosted(DEFAULT_REGION, "Action=DescribeSecurityGroups&GroupId.1=sg-3c6ef654");
+      assertPosted(DEFAULT_REGION, "Action=DescribeAvailabilityZones");
+   }
+
+   IpPermission permByGroup = IpPermission.builder() //
+         .ipProtocol(IpProtocol.TCP) //
+         .fromPort(22) //
+         .toPort(40) //
+         .tenantIdGroupNamePair(group.getOwnerId(), group.getProviderId()).build();
+
+   public void addIpPermissionGroupFromIpPermission() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/authorize_securitygroup_ingress_response.xml");
+      enqueueXml(DEFAULT_REGION, "/describe_securitygroups_extension_group.xml");
+      enqueueXml(DEFAULT_REGION, "/availabilityZones.xml");
+
+      SecurityGroup newGroup = extension().addIpPermission(permByGroup, group);
+
+      assertEquals(1, newGroup.getIpPermissions().size());
+
+      IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
+      assertEquals(newPerm, permByGroup);
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION,
+            "Action=AuthorizeSecurityGroupIngress&GroupId=sg-3c6ef654&IpPermissions.0.IpProtocol=tcp&IpPermissions.0.FromPort=22&IpPermissions.0.ToPort=40&IpPermissions.0.Groups.0.UserId=993194456877&IpPermissions.0.Groups.0.GroupId=sg-3c6ef654");
+      assertPosted(DEFAULT_REGION, "Action=DescribeSecurityGroups&GroupId.1=sg-3c6ef654");
+      assertPosted(DEFAULT_REGION, "Action=DescribeAvailabilityZones");
+   }
+
+   public void addIpPermissionGroupFromParams() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/authorize_securitygroup_ingress_response.xml");
+      enqueueXml(DEFAULT_REGION, "/describe_securitygroups_extension_group.xml");
+      enqueueXml(DEFAULT_REGION, "/availabilityZones.xml");
+
+      SecurityGroup newGroup = extension()
+            .addIpPermission(permByGroup.getIpProtocol(), permByGroup.getFromPort(), permByGroup.getToPort(),
+                  permByGroup.getTenantIdGroupNamePairs(), permByGroup.getCidrBlocks(), permByGroup.getGroupIds(),
+                  group);
+
+      IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
+      assertEquals(newPerm, permByGroup);
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION,
+            "Action=AuthorizeSecurityGroupIngress&GroupId=sg-3c6ef654&IpPermissions.0.IpProtocol=tcp&IpPermissions.0.FromPort=22&IpPermissions.0.ToPort=40&IpPermissions.0.Groups.0.UserId=993194456877&IpPermissions.0.Groups.0.GroupId=sg-3c6ef654");
+      assertPosted(DEFAULT_REGION, "Action=DescribeSecurityGroups&GroupId.1=sg-3c6ef654");
+      assertPosted(DEFAULT_REGION, "Action=DescribeAvailabilityZones");
+   }
+
+   public void createSecurityGroup() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/created_securitygroup.xml");
+      // TODO: ridiculously chatty
+      enqueueXml(DEFAULT_REGION, "/describe_securitygroups_extension_single.xml");
+      enqueueXml(DEFAULT_REGION, "/describe_securitygroups_extension_single.xml");
+      enqueueXml(DEFAULT_REGION, "/describe_securitygroups_extension_single.xml");
+      enqueueXml(DEFAULT_REGION, "/describe_securitygroups_extension_single.xml");
+      enqueueXml(DEFAULT_REGION, "/availabilityZones.xml");
+
+      SecurityGroup newGroup = extension()
+            .createSecurityGroup(group.getName().replace("jclouds#", ""), group.getLocation());
+      assertEquals(newGroup.getId(), group.getId());
+      assertEquals(newGroup.getProviderId(), group.getProviderId());
+      assertEquals(newGroup.getName(), group.getName());
+      assertEquals(newGroup.getLocation().getId(), group.getLocation().getId()); // One from response has a parent
+
+      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&GroupName.1=jclouds%23some-group");
+      assertPosted(DEFAULT_REGION, "Action=DescribeSecurityGroups&GroupId.1=sg-3c6ef654");
+      assertPosted(DEFAULT_REGION, "Action=DescribeAvailabilityZones");
+   }
+
+   private SecurityGroupExtension extension() {
+      return computeService().getSecurityGroupExtension().get();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a449b24e/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtensionExpectTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtensionExpectTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtensionExpectTest.java
deleted file mode 100644
index 3e59794..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/extensions/AWSEC2SecurityGroupExtensionExpectTest.java
+++ /dev/null
@@ -1,414 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.aws.ec2.compute.extensions;
-
-import static org.testng.Assert.assertEquals;
-import static org.testng.Assert.assertNotNull;
-import static org.testng.Assert.assertTrue;
-
-import javax.ws.rs.core.MediaType;
-import java.util.Set;
-
-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;
-import com.google.common.collect.Iterables;
-import com.google.common.collect.LinkedHashMultimap;
-import com.google.common.collect.Multimap;
-import com.google.common.collect.Sets;
-import org.jclouds.aws.ec2.compute.internal.BaseAWSEC2ComputeServiceExpectTest;
-import org.jclouds.compute.domain.SecurityGroup;
-import org.jclouds.compute.domain.SecurityGroupBuilder;
-import org.jclouds.compute.extensions.SecurityGroupExtension;
-import org.jclouds.domain.LocationBuilder;
-import org.jclouds.domain.LocationScope;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.http.HttpResponse;
-import org.jclouds.net.domain.IpPermission;
-import org.jclouds.net.domain.IpProtocol;
-import org.testng.annotations.Test;
-
-@Test(groups = "unit", testName = "AWSEC2SecurityGroupExtensionExpectTest")
-public class AWSEC2SecurityGroupExtensionExpectTest extends BaseAWSEC2ComputeServiceExpectTest {
-
-   public void testAddIpPermissionCidrFromIpPermission() {
-      HttpRequest describeSecurityGroupsSingleRequest = 
-         formSigner.filter(HttpRequest.builder()
-                           .method("POST")
-                           .endpoint("https://ec2." + region + ".amazonaws.com/")
-                           .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                           .addFormParam("Action", "DescribeSecurityGroups")
-                           .addFormParam("GroupId.1", "sg-3c6ef654").build());
-      
-      HttpResponse describeSecurityGroupsSingleResponse = 
-         HttpResponse.builder().statusCode(200)
-         .payload(payloadFromResourceWithContentType(
-                                                     "/describe_securitygroups_extension_cidr.xml", MediaType.APPLICATION_XML)).build();
-      
-
-      HttpRequest authorizeSecurityGroupIngressRequestRange = 
-               formSigner.filter(HttpRequest.builder()
-                                 .method("POST")
-                                 .endpoint("https://ec2." + region + ".amazonaws.com/")
-                                 .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                                 .addFormParam("Action", "AuthorizeSecurityGroupIngress")
-                                 .addFormParam("GroupId", "sg-3c6ef654")
-                                 .addFormParam("IpPermissions.0.FromPort", "22")
-                                 .addFormParam("IpPermissions.0.IpProtocol", "tcp")
-                                 .addFormParam("IpPermissions.0.IpRanges.0.CidrIp", "0.0.0.0/0")
-                                 .addFormParam("IpPermissions.0.ToPort", "40")
-                                 .build());
-                                 
-      Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
-      requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
-      requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
-      requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
-      requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
-      requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
-
-      requestResponseMap.put(authorizeSecurityGroupIngressRequestRange, authorizeSecurityGroupIngressResponse);
-
-      IpPermission.Builder builder = IpPermission.builder();
-
-      builder.ipProtocol(IpProtocol.TCP);
-      builder.fromPort(22);
-      builder.toPort(40);
-      builder.cidrBlock("0.0.0.0/0");
-
-      IpPermission perm = builder.build();
-
-      SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
-
-      SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
-      groupBuilder.id("us-east-1/sg-3c6ef654");
-      groupBuilder.providerId("sg-3c6ef654");
-      groupBuilder.name("jclouds#some-group");
-      groupBuilder.location(new LocationBuilder()
-                            .scope(LocationScope.REGION)
-                            .id(region)
-                            .description("region")
-                            .build());
-      
-      SecurityGroup origGroup = groupBuilder.build();
-
-      SecurityGroup newGroup = extension.addIpPermission(perm, origGroup);
-
-      assertEquals(1, newGroup.getIpPermissions().size());
-
-      IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
-
-      assertNotNull(newPerm);
-      assertEquals(IpProtocol.TCP, newPerm.getIpProtocol());
-      assertEquals(22, newPerm.getFromPort());
-      assertEquals(40, newPerm.getToPort());
-      assertEquals(1, newPerm.getCidrBlocks().size());
-      assertTrue(newPerm.getCidrBlocks().contains("0.0.0.0/0"));
-   }
-
-   public void testAddIpPermissionCidrFromParams() {
-      HttpRequest describeSecurityGroupsSingleRequest = 
-         formSigner.filter(HttpRequest.builder()
-                           .method("POST")
-                           .endpoint("https://ec2." + region + ".amazonaws.com/")
-                           .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                           .addFormParam("Action", "DescribeSecurityGroups")
-                           .addFormParam("GroupId.1", "sg-3c6ef654").build());
-      
-      HttpResponse describeSecurityGroupsSingleResponse = 
-         HttpResponse.builder().statusCode(200)
-         .payload(payloadFromResourceWithContentType(
-                                                     "/describe_securitygroups_extension_cidr.xml", MediaType.APPLICATION_XML)).build();
-      
-
-      HttpRequest authorizeSecurityGroupIngressRequestRange = 
-               formSigner.filter(HttpRequest.builder()
-                                 .method("POST")
-                                 .endpoint("https://ec2." + region + ".amazonaws.com/")
-                                 .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                                 .addFormParam("Action", "AuthorizeSecurityGroupIngress")
-                                 .addFormParam("GroupId", "sg-3c6ef654")
-                                 .addFormParam("IpPermissions.0.FromPort", "22")
-                                 .addFormParam("IpPermissions.0.IpProtocol", "tcp")
-                                 .addFormParam("IpPermissions.0.IpRanges.0.CidrIp", "0.0.0.0/0")
-                                 .addFormParam("IpPermissions.0.ToPort", "40")
-                                 .build());
-      
-      Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
-      requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
-      requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
-      requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
-      requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
-      requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
-
-      requestResponseMap.put(authorizeSecurityGroupIngressRequestRange, authorizeSecurityGroupIngressResponse);
-
-      SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
-
-      SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
-      groupBuilder.id("us-east-1/sg-3c6ef654");
-      groupBuilder.providerId("sg-3c6ef654");
-      groupBuilder.name("jclouds#some-group");
-      groupBuilder.location(new LocationBuilder()
-                            .scope(LocationScope.REGION)
-                            .id(region)
-                            .description("region")
-                            .build());
-      
-      SecurityGroup origGroup = groupBuilder.build();
-
-      SecurityGroup newGroup = extension.addIpPermission(IpProtocol.TCP,
-                                                         22,
-                                                         40,
-                                                         emptyMultimap(),
-                                                         ImmutableSet.of("0.0.0.0/0"),
-                                                         emptyStringSet(),
-                                                         origGroup);
-
-      assertEquals(1, newGroup.getIpPermissions().size());
-
-      IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
-
-      assertNotNull(newPerm);
-      assertEquals(IpProtocol.TCP, newPerm.getIpProtocol());
-      assertEquals(22, newPerm.getFromPort());
-      assertEquals(40, newPerm.getToPort());
-      assertEquals(1, newPerm.getCidrBlocks().size());
-      assertTrue(newPerm.getCidrBlocks().contains("0.0.0.0/0"));
-   }
-
-   public void testAddIpPermissionGroupFromIpPermission() {
-      HttpRequest describeSecurityGroupsSingleRequest = 
-         formSigner.filter(HttpRequest.builder()
-                           .method("POST")
-                           .endpoint("https://ec2." + region + ".amazonaws.com/")
-                           .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                           .addFormParam("Action", "DescribeSecurityGroups")
-                           .addFormParam("GroupId.1", "sg-3c6ef654").build());
-      
-      HttpResponse describeSecurityGroupsSingleResponse = 
-         HttpResponse.builder().statusCode(200)
-         .payload(payloadFromResourceWithContentType(
-                                                     "/describe_securitygroups_extension_group.xml", MediaType.APPLICATION_XML)).build();
-      
-
-      HttpRequest authorizeSecurityGroupIngressRequestGroupTenant = 
-               formSigner.filter(HttpRequest.builder()
-                                 .method("POST")
-                                 .endpoint("https://ec2." + region + ".amazonaws.com/")
-                                 .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                                 .addFormParam("Action", "AuthorizeSecurityGroupIngress")
-                                 .addFormParam("GroupId", "sg-3c6ef654")
-                                 .addFormParam("IpPermissions.0.FromPort", "22")
-                                 .addFormParam("IpPermissions.0.Groups.0.GroupId", "sg-3c6ef654")
-                                 .addFormParam("IpPermissions.0.Groups.0.UserId", "993194456877")
-                                 .addFormParam("IpPermissions.0.IpProtocol", "tcp")
-                                 .addFormParam("IpPermissions.0.ToPort", "40")
-                                 .build());
-
-      Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
-      requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
-      requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
-      requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
-      requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
-      requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
-
-      requestResponseMap.put(authorizeSecurityGroupIngressRequestGroupTenant, authorizeSecurityGroupIngressResponse);
-
-      IpPermission.Builder builder = IpPermission.builder();
-
-      builder.ipProtocol(IpProtocol.TCP);
-      builder.fromPort(22);
-      builder.toPort(40);
-      builder.tenantIdGroupNamePair("993194456877", "sg-3c6ef654");
-
-      IpPermission perm = builder.build();
-
-      SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
-
-      SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
-      groupBuilder.id("us-east-1/sg-3c6ef654");
-      groupBuilder.providerId("sg-3c6ef654");
-      groupBuilder.name("jclouds#some-group");
-      groupBuilder.location(new LocationBuilder()
-                            .scope(LocationScope.REGION)
-                            .id(region)
-                            .description("region")
-                            .build());
-      groupBuilder.ownerId("993194456877");
-      
-      SecurityGroup origGroup = groupBuilder.build();
-
-      SecurityGroup newGroup = extension.addIpPermission(perm, origGroup);
-
-      assertEquals(1, newGroup.getIpPermissions().size());
-
-      IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
-
-      assertNotNull(newPerm);
-      assertEquals(IpProtocol.TCP, newPerm.getIpProtocol());
-      assertEquals(22, newPerm.getFromPort());
-      assertEquals(40, newPerm.getToPort());
-      assertEquals(0, newPerm.getCidrBlocks().size());
-      assertEquals(1, newPerm.getTenantIdGroupNamePairs().size());
-      assertTrue(newPerm.getTenantIdGroupNamePairs().keySet().contains(origGroup.getOwnerId()));
-      assertTrue(newPerm.getTenantIdGroupNamePairs().values().contains(origGroup.getProviderId()));
-   }
-
-
-   public void testAddIpPermissionGroupFromParams() {
-      HttpRequest describeSecurityGroupsSingleRequest = 
-         formSigner.filter(HttpRequest.builder()
-                           .method("POST")
-                           .endpoint("https://ec2." + region + ".amazonaws.com/")
-                           .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                           .addFormParam("Action", "DescribeSecurityGroups")
-                           .addFormParam("GroupId.1", "sg-3c6ef654").build());
-      
-      HttpResponse describeSecurityGroupsSingleResponse = 
-         HttpResponse.builder().statusCode(200)
-         .payload(payloadFromResourceWithContentType(
-                                                     "/describe_securitygroups_extension_group.xml", MediaType.APPLICATION_XML)).build();
-
-
-      HttpRequest authorizeSecurityGroupIngressRequestGroupTenant = 
-               formSigner.filter(HttpRequest.builder()
-                                 .method("POST")
-                                 .endpoint("https://ec2." + region + ".amazonaws.com/")
-                                 .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                                 .addFormParam("Action", "AuthorizeSecurityGroupIngress")
-                                 .addFormParam("GroupId", "sg-3c6ef654")
-                                 .addFormParam("IpPermissions.0.FromPort", "22")
-                                 .addFormParam("IpPermissions.0.Groups.0.GroupId", "sg-3c6ef654")
-                                 .addFormParam("IpPermissions.0.Groups.0.UserId", "993194456877")
-                                 .addFormParam("IpPermissions.0.IpProtocol", "tcp")
-                                 .addFormParam("IpPermissions.0.ToPort", "40")
-                                 .build());
-
-      Builder<HttpRequest, HttpResponse> requestResponseMap = ImmutableMap.<HttpRequest, HttpResponse> builder();
-      requestResponseMap.put(describeRegionsRequest, describeRegionsResponse);
-      requestResponseMap.put(describeAvailabilityZonesRequest, describeAvailabilityZonesResponse);
-      requestResponseMap.put(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
-      requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
-      requestResponseMap.put(createSecurityGroupRequest, createSecurityGroupResponse);
-
-      requestResponseMap.put(authorizeSecurityGroupIngressRequestGroupTenant, authorizeSecurityGroupIngressResponse);
-
-      SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
-
-      SecurityGroupBuilder groupBuilder = new SecurityGroupBuilder();
-      groupBuilder.id("us-east-1/sg-3c6ef654");
-      groupBuilder.providerId("sg-3c6ef654");
-      groupBuilder.name("jclouds#some-group");
-      groupBuilder.ownerId("993194456877");
-      groupBuilder.location(new LocationBuilder()
-                            .scope(LocationScope.REGION)
-                            .id(region)
-                            .description("region")
-                            .build());
-      
-      SecurityGroup origGroup = groupBuilder.build();
-
-      ImmutableMultimap.Builder<String, String> permBuilder = ImmutableMultimap.builder();
-      permBuilder.put(origGroup.getOwnerId(), origGroup.getId());
-      
-      SecurityGroup newGroup = extension.addIpPermission(IpProtocol.TCP,
-                                                         22,
-                                                         40,
-                                                         permBuilder.build(),
-                                                         emptyStringSet(),
-                                                         emptyStringSet(),
-                                                         origGroup);
-
-      assertEquals(1, newGroup.getIpPermissions().size());
-
-      IpPermission newPerm = Iterables.getOnlyElement(newGroup.getIpPermissions());
-
-      assertNotNull(newPerm);
-      assertEquals(IpProtocol.TCP, newPerm.getIpProtocol());
-      assertEquals(22, newPerm.getFromPort());
-      assertEquals(40, newPerm.getToPort());
-      assertEquals(0, newPerm.getCidrBlocks().size());
-      assertEquals(1, newPerm.getTenantIdGroupNamePairs().size());
-      assertTrue(newPerm.getTenantIdGroupNamePairs().keySet().contains(origGroup.getOwnerId()));
-      assertTrue(newPerm.getTenantIdGroupNamePairs().values().contains(origGroup.getProviderId()));
-   }
-
-   public void testCreateSecurityGroup() {
-      HttpRequest createSecurityGroupExtRequest =
-              formSigner.filter(HttpRequest.builder()
-                      .method("POST")
-                      .endpoint("https://ec2." + region + ".amazonaws.com/")
-                      .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                      .addFormParam("Action", "CreateSecurityGroup")
-                      .addFormParam("GroupDescription", "jclouds#some-group")
-                      .addFormParam("GroupName", "jclouds#some-group").build());
-
-      HttpRequest describeSecurityGroupsSingleRequest =
-              formSigner.filter(HttpRequest.builder()
-                      .method("POST")
-                      .endpoint("https://ec2." + region + ".amazonaws.com/")
-                      .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                      .addFormParam("Action", "DescribeSecurityGroups")
-                      .addFormParam("GroupName.1", "jclouds#some-group").build());
-
-      HttpRequest describeSecurityGroupsByIdRequest =
-              formSigner.filter(HttpRequest.builder()
-                      .method("POST")
-                      .endpoint("https://ec2." + region + ".amazonaws.com/")
-                      .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                      .addFormParam("Action", "DescribeSecurityGroups")
-                      .addFormParam("GroupId.1", "sg-3c6ef654").build());
-
-      HttpResponse describeSecurityGroupsSingleResponse =
-              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(describeSecurityGroupsSingleRequest, describeSecurityGroupsSingleResponse);
-      requestResponseMap.put(describeSecurityGroupsByIdRequest, describeSecurityGroupsSingleResponse);
-      requestResponseMap.put(createKeyPairRequest, createKeyPairResponse);
-      requestResponseMap.put(createSecurityGroupExtRequest, createSecurityGroupResponse);
-
-      requestResponseMap.put(authorizeSecurityGroupIngressRequest22, authorizeSecurityGroupIngressResponse);
-      requestResponseMap.put(authorizeSecurityGroupIngressRequestGroup, authorizeSecurityGroupIngressResponse);
-
-
-      SecurityGroupExtension extension = requestsSendResponses(requestResponseMap.build()).getSecurityGroupExtension().get();
-
-      SecurityGroup group = extension.createSecurityGroup("some-group", new LocationBuilder()
-              .scope(LocationScope.REGION)
-              .id(region)
-              .description("region")
-              .build());
-
-      assertEquals("sg-3c6ef654", group.getProviderId());
-      assertEquals(region + "/sg-3c6ef654", group.getId());
-   }
-   
-   private Multimap<String, String> emptyMultimap() {
-      return LinkedHashMultimap.create();
-   }
-
-   private Set<String> emptyStringSet() {
-      return Sets.newLinkedHashSet();
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a449b24e/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/internal/BaseAWSEC2ComputeServiceExpectTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/internal/BaseAWSEC2ComputeServiceExpectTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/internal/BaseAWSEC2ComputeServiceExpectTest.java
deleted file mode 100644
index 376b169..0000000
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/compute/internal/BaseAWSEC2ComputeServiceExpectTest.java
+++ /dev/null
@@ -1,151 +0,0 @@
-/*
- * Licensed to the Apache Software Foundation (ASF) under one or more
- * contributor license agreements.  See the NOTICE file distributed with
- * this work for additional information regarding copyright ownership.
- * The ASF licenses this file to You under the Apache License, Version 2.0
- * (the "License"); you may not use this file except in compliance with
- * the License.  You may obtain a copy of the License at
- *
- *     http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-package org.jclouds.aws.ec2.compute.internal;
-
-import static org.jclouds.aws.ec2.reference.AWSEC2Constants.PROPERTY_EC2_CC_AMI_QUERY;
-import static org.jclouds.ec2.reference.EC2Constants.PROPERTY_EC2_GENERATE_INSTANCE_NAMES;
-
-import java.util.Properties;
-import java.util.concurrent.atomic.AtomicInteger;
-
-import org.jclouds.aws.ec2.config.AWSEC2HttpApiModule;
-import org.jclouds.date.DateService;
-import org.jclouds.ec2.compute.internal.BaseEC2ComputeServiceExpectTest;
-import org.jclouds.http.HttpRequest;
-import org.jclouds.rest.ConfiguresHttpApi;
-import org.testng.annotations.BeforeClass;
-
-import com.google.common.base.Supplier;
-import com.google.inject.Module;
-import com.google.inject.Provides;
-import com.google.inject.TypeLiteral;
-
-/**
- * Tests the compute service abstraction of the EC2 api.
- */
-public abstract class BaseAWSEC2ComputeServiceExpectTest extends BaseEC2ComputeServiceExpectTest {
-
-   protected HttpRequest describeSecurityGroupByIdRequest;
-
-   public BaseAWSEC2ComputeServiceExpectTest() {
-      provider = "aws-ec2";
-   }
-
-   @Override
-   protected Properties setupProperties() {
-      Properties properties = super.setupProperties();
-      // zero out cluster image query for now
-      properties.setProperty(PROPERTY_EC2_CC_AMI_QUERY, "");
-      properties.setProperty(PROPERTY_EC2_GENERATE_INSTANCE_NAMES, "false");
-      return properties;
-   }
-
-   @BeforeClass
-   @Override
-   protected void setupDefaultRequests() {
-      super.setupDefaultRequests();
-
-      describeSecurityGroupByIdRequest =
-              formSigner.filter(HttpRequest.builder()
-                      .method("POST")
-                      .endpoint("https://ec2." + region + ".amazonaws.com/")
-                      .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                      .addFormParam("Action", "DescribeSecurityGroups")
-                      .addFormParam("GroupId.1", "sg-3c6ef654").build());
-
-      authorizeSecurityGroupIngressRequestGroup =
-              formSigner.filter(HttpRequest.builder()
-                      .method("POST")
-                      .endpoint("https://ec2." + region + ".amazonaws.com/")
-                      .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                      .addFormParam("Action", "AuthorizeSecurityGroupIngress")
-                      .addFormParam("SourceSecurityGroupId", "sg-3c6ef654")
-                      .addFormParam("SourceSecurityGroupOwnerId", "993194456877")
-                      .addFormParam("GroupName", "jclouds#test").build());
-
-      authorizeSecurityGroupIngressRequest22 = 
-         formSigner.filter(HttpRequest.builder()
-                           .method("POST")
-                           .endpoint("https://ec2." + region + ".amazonaws.com/")
-                           .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                           .addFormParam("Action", "AuthorizeSecurityGroupIngress")
-                           .addFormParam("GroupId", "sg-3c6ef654")
-                           .addFormParam("IpPermissions.0.FromPort", "22")
-                           .addFormParam("IpPermissions.0.ToPort", "22")
-                           .addFormParam("IpPermissions.0.IpRanges.0.CidrIp", "0.0.0.0/0")
-                           .addFormParam("IpPermissions.0.IpProtocol", "tcp")
-                           .addFormParam("IpPermissions.1.FromPort", "0")
-                           .addFormParam("IpPermissions.1.ToPort", "65535")
-                           .addFormParam("IpPermissions.1.Groups.0.GroupId", "sg-3c6ef654")
-                           .addFormParam("IpPermissions.1.Groups.0.UserId", "993194456877")
-                           .addFormParam("IpPermissions.1.IpProtocol", "tcp")
-                           .addFormParam("IpPermissions.2.FromPort", "0")
-                           .addFormParam("IpPermissions.2.ToPort", "65535")
-                           .addFormParam("IpPermissions.2.Groups.0.GroupId", "sg-3c6ef654")
-                           .addFormParam("IpPermissions.2.Groups.0.UserId", "993194456877")
-                           .addFormParam("IpPermissions.2.IpProtocol", "udp")
-                           .build());
-
-      describeImagesRequest = 
-               formSigner.filter(HttpRequest.builder()
-                          .method("POST")
-                          .endpoint("https://ec2." + region + ".amazonaws.com/")
-                          .addHeader("Host", "ec2." + region + ".amazonaws.com")
-                          .addFormParam("Action", "DescribeImages")
-                          .addFormParam("Filter.1.Name", "owner-id")
-                          .addFormParam("Filter.1.Value.1", "137112412989")
-                          .addFormParam("Filter.1.Value.2", "801119661308")
-                          .addFormParam("Filter.1.Value.3", "063491364108")
-                          .addFormParam("Filter.1.Value.4", "099720109477")
-                          .addFormParam("Filter.1.Value.5", "411009282317")
-                          .addFormParam("Filter.2.Name", "state")
-                          .addFormParam("Filter.2.Value.1", "available")
-                          .addFormParam("Filter.3.Name", "image-type")
-                          .addFormParam("Filter.3.Value.1", "machine").build());
-   }
-
-   @ConfiguresHttpApi
-   protected static class TestAWSEC2HttpApiModule extends AWSEC2HttpApiModule {
-
-      @Override
-      protected void configure() {
-         super.configure();
-         // predicatable node names
-         final AtomicInteger suffix = new AtomicInteger();
-         bind(new TypeLiteral<Supplier<String>>() {
-         }).toInstance(new Supplier<String>() {
-
-            @Override
-            public String get() {
-               return suffix.getAndIncrement() + "";
-            }
-
-         });
-      }
-
-      @Override
-      @Provides
-      protected String provideTimeStamp(DateService dateService) {
-         return CONSTANT_DATE;
-      }
-   }
-
-   @Override
-   protected Module createModule() {
-      return new TestAWSEC2HttpApiModule();
-   }
-}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/a449b24e/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSAMIApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSAMIApiMockTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSAMIApiMockTest.java
new file mode 100644
index 0000000..283ea2d
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSAMIApiMockTest.java
@@ -0,0 +1,254 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.features;
+
+import static org.jclouds.ec2.options.DescribeImagesOptions.Builder.executableBy;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.Map;
+import java.util.Set;
+
+import org.jclouds.aws.ec2.internal.BaseAWSEC2ApiMockTest;
+import org.jclouds.ec2.domain.Image;
+import org.jclouds.ec2.domain.Permission;
+import org.jclouds.ec2.options.CreateImageOptions;
+import org.jclouds.ec2.options.RegisterImageBackedByEbsOptions;
+import org.jclouds.ec2.options.RegisterImageOptions;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+
+@Test(groups = "unit", testName = "AWSAMIApiMockTest", singleThreaded = true)
+public class AWSAMIApiMockTest extends BaseAWSEC2ApiMockTest {
+
+   public void describeImagesInRegion() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/amzn_images.xml");
+
+      Set<? extends Image> result = amiApi().describeImagesInRegion(DEFAULT_REGION);
+
+      assertFalse(result.isEmpty());
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=DescribeImages");
+   }
+
+   public void describeImagesInRegion_options() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/amzn_images.xml");
+
+      Set<? extends Image> result = amiApi()
+            .describeImagesInRegion(DEFAULT_REGION, executableBy("me").ownedBy("fred", "nancy").imageIds("1", "2"));
+
+      assertFalse(result.isEmpty());
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=DescribeImages&ExecutableBy=me&Owner.1=fred&Owner.2=nancy&ImageId.1=1&ImageId.2=2");
+   }
+
+   public void describeImagesInRegion_404() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse().setResponseCode(404));
+
+      Set<? extends Image> result = amiApi().describeImagesInRegion(DEFAULT_REGION);
+
+      assertTrue(result.isEmpty());
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=DescribeImages");
+   }
+
+   public void createImageInRegion() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse().setBody("<CreateImageResponse><ImageId>ami-246f8d4d</ImageId></CreateImageResponse>"));
+
+      String result = amiApi().createImageInRegion(DEFAULT_REGION, "name", "instanceId");
+      assertEquals(result, "ami-246f8d4d");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=CreateImage&Name=name&InstanceId=instanceId");
+   }
+
+   public void createImageInRegion_options() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION,
+            new MockResponse().setBody("<CreateImageResponse><ImageId>ami-246f8d4d</ImageId></CreateImageResponse>"));
+
+      String result = amiApi().createImageInRegion(DEFAULT_REGION, "name", "instanceId",
+            new CreateImageOptions().withDescription("description").noReboot());
+      assertEquals(result, "ami-246f8d4d");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=CreateImage&Name=name&InstanceId=instanceId&Description=description&NoReboot=true");
+   }
+
+   public void registerImageFromManifestInRegion() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse().setBody("<RegisterImageResponse><ImageId>ami-246f8d4d</ImageId></RegisterImageResponse>"));
+
+      String result = amiApi().registerImageFromManifestInRegion(DEFAULT_REGION, "name", "pathToManifest");
+      assertEquals(result, "ami-246f8d4d");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=RegisterImage&Name=name&ImageLocation=pathToManifest");
+   }
+
+   public void registerImageFromManifestInRegion_options() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse().setBody("<RegisterImageResponse><ImageId>ami-246f8d4d</ImageId></RegisterImageResponse>"));
+
+      String result = amiApi().registerImageFromManifestInRegion(DEFAULT_REGION, "name", "pathToManifest",
+            new RegisterImageOptions().withDescription("description"));
+      assertEquals(result, "ami-246f8d4d");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=RegisterImage&Name=name&ImageLocation=pathToManifest&Description=description");
+   }
+
+   public void registerUnixImageBackedByEbsInRegion() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse()
+            .setBody("<RegisterImageResponse><ImageId>ami-246f8d4d</ImageId></RegisterImageResponse>"));
+
+      String result = amiApi().registerUnixImageBackedByEbsInRegion(DEFAULT_REGION, "imageName", "snapshotId");
+      assertEquals(result, "ami-246f8d4d");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=RegisterImage&RootDeviceName=/dev/sda1&BlockDeviceMapping.0.DeviceName=/dev/sda1&Name=imageName&BlockDeviceMapping.0.Ebs.SnapshotId=snapshotId");
+   }
+
+   public void registerUnixImageBackedByEbsInRegion_options() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse().setBody("<RegisterImageResponse><ImageId>ami-246f8d4d</ImageId></RegisterImageResponse>"));
+
+      String result = amiApi().registerUnixImageBackedByEbsInRegion(DEFAULT_REGION, "imageName", "snapshotId",
+            new RegisterImageBackedByEbsOptions().withDescription("description")
+                  .addBlockDeviceFromSnapshot("/dev/device", null, "snapshot", false, "gp2", null, false)
+                  .addNewBlockDevice("/dev/newdevice", "newblock", 100));
+      assertEquals(result, "ami-246f8d4d");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=RegisterImage&RootDeviceName=/dev/sda1&BlockDeviceMapping.0.DeviceName=/dev/sda1&Name=imageName&BlockDeviceMapping.0.Ebs.SnapshotId=snapshotId&Description=description&BlockDeviceMapping.1.Ebs.DeleteOnTermination=false&BlockDeviceMapping.1.Ebs.VolumeType=gp2&BlockDeviceMapping.1.DeviceName=/dev/device&BlockDeviceMapping.1.Ebs.SnapshotId=snapshot&BlockDeviceMapping.2.Ebs.DeleteOnTermination=false&BlockDeviceMapping.2.DeviceName=/dev/newdevice&BlockDeviceMapping.2.VirtualName=newblock&BlockDeviceMapping.2.Ebs.VolumeSize=100");
+   }
+
+   public void deregisterImageInRegion() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse());
+
+      amiApi().deregisterImageInRegion(DEFAULT_REGION, "ami-246f8d4d");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=DeregisterImage&ImageId=ami-246f8d4d");
+   }
+
+   public void getBlockDeviceMappingsForImageInRegion() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/describe_image_attribute_blockDeviceMapping.xml");
+
+      Map<String, Image.EbsBlockDevice> result = amiApi()
+            .getBlockDeviceMappingsForImageInRegion(DEFAULT_REGION, "ami-246f8d4d");
+
+      assertFalse(result.isEmpty());
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=DescribeImageAttribute&Attribute=blockDeviceMapping&ImageId=ami-246f8d4d");
+   }
+
+   public void getLaunchPermissionForImageInRegion() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/describe_image_attribute_launchPermission.xml");
+
+      Permission result = amiApi().getLaunchPermissionForImageInRegion(DEFAULT_REGION, "ami-246f8d4d");
+
+      assertNotNull(result);
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=DescribeImageAttribute&Attribute=launchPermission&ImageId=ami-246f8d4d");
+   }
+
+   public void addLaunchPermissionsToImageInRegion() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse());
+
+      amiApi().addLaunchPermissionsToImageInRegion(DEFAULT_REGION, ImmutableList.of("bob", "sue"),
+            ImmutableList.of("all"), "imageId");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=ModifyImageAttribute&OperationType=add&Attribute=launchPermission&ImageId=imageId&UserId.1=bob&UserId.2=sue&UserGroup.1=all");
+   }
+
+   public void removeLaunchPermissionsFromImageInRegion() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse());
+
+      amiApi().removeLaunchPermissionsFromImageInRegion(DEFAULT_REGION, ImmutableList.of("bob", "sue"),
+            ImmutableList.of("all"), "imageId");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=ModifyImageAttribute&OperationType=remove&Attribute=launchPermission&ImageId=imageId&UserId.1=bob&UserId.2=sue&UserGroup.1=all");
+   }
+
+   public void resetLaunchPermissionsOnImageInRegion() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse());
+
+      amiApi().resetLaunchPermissionsOnImageInRegion(DEFAULT_REGION, "imageId");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=ResetImageAttribute&Attribute=launchPermission&ImageId=imageId");
+   }
+
+   public void getProductCodesForImageInRegion() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/describe_image_attribute_productCodes.xml");
+
+      Set<String> result = amiApi().getProductCodesForImageInRegion(DEFAULT_REGION, "ami-246f8d4d");
+
+      assertFalse(result.isEmpty());
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=DescribeImageAttribute&Attribute=productCodes&ImageId=ami-246f8d4d");
+   }
+
+   public void addProductCodesToImageInRegion() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse());
+
+      amiApi().addProductCodesToImageInRegion(DEFAULT_REGION, ImmutableList.of("code1", "code2"), "imageId");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=ModifyImageAttribute&OperationType=add&Attribute=productCodes&ImageId=imageId&ProductCode.1=code1&ProductCode.2=code2");
+   }
+
+   public void removeProductCodesFromImageInRegion() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse());
+
+      amiApi().removeProductCodesFromImageInRegion(DEFAULT_REGION, ImmutableList.of("code1", "code2"), "imageId");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=ModifyImageAttribute&OperationType=remove&Attribute=productCodes&ImageId=imageId&ProductCode.1=code1&ProductCode.2=code2");
+   }
+
+   private AWSAMIApi amiApi() {
+      return api().getAMIApi().get();
+   }
+}