You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jclouds.apache.org by na...@apache.org on 2017/05/10 22:31:49 UTC

jclouds git commit: Add an InternetGatewayApi to AWSEC2Api.

Repository: jclouds
Updated Branches:
  refs/heads/master 89ae3b4fa -> cff2f87e1


Add an InternetGatewayApi to AWSEC2Api.

This is a follow-up to https://github.com/jclouds/jclouds/pull/1091
and particularly the comment at
https://github.com/jclouds/jclouds/pull/1091#issuecomment-299202429:

I have been trying this out and I think we will need to extend it for
practical purposes; if you want to create a VPC and subnet and then
deploy a machine on to it, you also need to jump through a few other
hoops apart from creating the subnet:

 - modify the subnet attributes to permit auto-assign public
   IP ("ModifySubnetAttribute")
 - create an Internet Gateway on the VPC ("CreateInternetGateway")
 - get and then modify the routing table of the subnet to add a public
   (0.0.0.0/0) route through the newly added gateway ("CreateRoute" and
   friends)

There are three AWS APIs needed for the above, an `InternetGatewayApi`,
a `RouteTableApi` and a method in the subnet API, I guess, for modifying
attributes on subnets. This PR contains the `InternetGatewayApi`.


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

Branch: refs/heads/master
Commit: cff2f87e113307a304fe10b1d6d850f1df91bc53
Parents: 89ae3b4
Author: Geoff Macartney <ge...@cloudsoftcorp.com>
Authored: Thu May 4 17:34:37 2017 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Thu May 11 00:11:29 2017 +0200

----------------------------------------------------------------------
 .../java/org/jclouds/aws/ec2/AWSEC2Api.java     |  16 ++
 ...ndInternetGatewayIdsToIndexedFormParams.java |  32 +++
 .../jclouds/aws/ec2/domain/InternetGateway.java |  83 ++++++++
 .../ec2/domain/InternetGatewayAttachment.java   |  75 +++++++
 .../aws/ec2/features/InternetGatewayApi.java    | 205 ++++++++++++++++++
 .../aws/ec2/options/InternetGatewayOptions.java |  64 ++++++
 ...DescribeInternetGatewaysResponseHandler.java |  84 ++++++++
 .../InternetGatewayAttachmentSetHandler.java    |  70 ++++++
 .../aws/ec2/xml/InternetGatewayHandler.java     | 100 +++++++++
 .../features/InternetGatewayApiLiveTest.java    | 162 ++++++++++++++
 .../features/InternetGatewayApiMockTest.java    | 211 +++++++++++++++++++
 .../test/resources/attach_internet_gateway.xml  |   5 +
 .../attach_internet_gateway_failed.xml          |   5 +
 .../test/resources/create_internet_gateway.xml  |   9 +
 .../create_internet_gateway_dry_run.xml         |  11 +
 .../test/resources/delete_internet_gateway.xml  |   6 +
 .../resources/describe_internet_gateways.xml    |  37 ++++
 .../test/resources/detach_internet_gateway.xml  |   5 +
 .../src/test/resources/get_internet_gateway.xml |  21 ++
 .../aws-ec2/src/test/resources/logback-test.xml |  42 ++++
 20 files changed, 1243 insertions(+)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/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 851597f..a094ce6 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
@@ -21,6 +21,7 @@ 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.InternetGatewayApi;
 import org.jclouds.aws.ec2.features.MonitoringApi;
 import org.jclouds.aws.ec2.features.PlacementGroupApi;
 import org.jclouds.aws.ec2.features.SpotInstanceApi;
@@ -132,4 +133,19 @@ public interface AWSEC2Api extends EC2Api {
    @Delegate
    Optional<? extends AWSSubnetApi> getAWSSubnetApiForRegion(
            @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+
+
+   /**
+    * Provides synchronous access to InternetGateway services.
+    */
+   @Delegate
+   Optional<? extends InternetGatewayApi> getInternetGatewayApi();
+
+   /**
+    * Provides synchronous access to InternetGateway services in a given region.
+    */
+   @Delegate
+   Optional<? extends InternetGatewayApi> getInternetGatewayApiForRegion(
+      @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region
+   );
 }

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

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/InternetGateway.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/InternetGateway.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/InternetGateway.java
new file mode 100644
index 0000000..d99ad5e
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/InternetGateway.java
@@ -0,0 +1,83 @@
+/*
+ * 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.domain;
+
+import java.util.List;
+import java.util.Map;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Amazon EC2 Internet Gateway.
+ *
+ * @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_InternetGateway.html" >doc</a>
+ */
+@AutoValue
+public abstract class InternetGateway {
+
+   @Nullable
+   public abstract String id();
+
+   @Nullable
+   public abstract List<InternetGatewayAttachment> attachmentSet();
+
+   @Nullable
+   public abstract Map<String, String> tags();
+
+   @SerializedNames({"internetGatewayId", "attachmentSet", "tagSet"})
+   public static InternetGateway create(String id, List<InternetGatewayAttachment> attachmentSet,
+                                        Map<String, String> tags) {
+      return builder()
+         .id(id)
+         .attachmentSet(attachmentSet)
+         .tags(tags)
+         .build();
+   }
+
+   InternetGateway() {}
+
+   public static Builder builder() {
+      return new AutoValue_InternetGateway.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+
+      public abstract Builder id(String id);
+      public abstract Builder attachmentSet(List<InternetGatewayAttachment> attachmentSet);
+      public abstract Builder tags(Map<String, String> tags);
+
+      @Nullable abstract List<InternetGatewayAttachment> attachmentSet();
+      @Nullable abstract Map<String, String> tags();
+
+      abstract InternetGateway autoBuild();
+
+      public InternetGateway build() {
+         tags(tags() != null ? ImmutableMap.copyOf(tags()) : ImmutableMap.<String, String>of());
+         attachmentSet(attachmentSet() != null
+            ? ImmutableList.copyOf(attachmentSet()) : ImmutableList.<InternetGatewayAttachment>of());
+         return autoBuild();
+      }
+
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/InternetGatewayAttachment.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/InternetGatewayAttachment.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/InternetGatewayAttachment.java
new file mode 100644
index 0000000..d20fc54
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/InternetGatewayAttachment.java
@@ -0,0 +1,75 @@
+/*
+ * 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.domain;
+
+
+import org.jclouds.javax.annotation.Nullable;
+
+import com.google.auto.value.AutoValue;
+
+/**
+ * Amazon EC2 Internet Gateway attachment to VPC.
+ *
+ * @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_InternetGatewayAttachment.html" >doc</a>
+ */
+@AutoValue
+public abstract class InternetGatewayAttachment {
+
+   public enum State {
+      UNRECOGNIZED,
+      ATTACHING,
+      ATTACHED,
+      AVAILABLE,
+      DETATCHING,
+      DETATCHED;
+
+      public String value() {
+         return name().toLowerCase();
+      }
+
+      public static State fromValue(String v) {
+         try {
+            return valueOf(v.toUpperCase());
+         } catch (IllegalArgumentException e) {
+            return UNRECOGNIZED;
+         }
+      }
+   }
+
+   @Nullable
+   public abstract State state();
+
+   @Nullable
+   public abstract String vpcId();
+
+   InternetGatewayAttachment() {}
+
+   public static Builder builder() {
+      return new AutoValue_InternetGatewayAttachment.Builder();
+   }
+
+   @AutoValue.Builder
+   public abstract static class Builder {
+
+      public abstract Builder state(State state);
+
+      public abstract Builder vpcId(String vpcId);
+
+      public abstract InternetGatewayAttachment build();
+
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/InternetGatewayApi.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/InternetGatewayApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/InternetGatewayApi.java
new file mode 100644
index 0000000..8bbd1f0
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/InternetGatewayApi.java
@@ -0,0 +1,205 @@
+/*
+ * 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.EmptyFluentIterableOnNotFoundOr404;
+import org.jclouds.Fallbacks.FalseOnNotFoundOr404;
+import org.jclouds.aws.ec2.binders.BindInternetGatewayIdsToIndexedFormParams;
+import org.jclouds.aws.ec2.domain.InternetGateway;
+import org.jclouds.aws.ec2.options.InternetGatewayOptions;
+import org.jclouds.aws.ec2.xml.DescribeInternetGatewaysResponseHandler;
+import org.jclouds.aws.ec2.xml.InternetGatewayHandler;
+import org.jclouds.aws.ec2.xml.ReturnValueHandler;
+import org.jclouds.aws.filters.FormSigner;
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.BinderParam;
+import org.jclouds.rest.annotations.EndpointParam;
+import org.jclouds.rest.annotations.Fallback;
+import org.jclouds.rest.annotations.FormParams;
+import org.jclouds.rest.annotations.RequestFilters;
+import org.jclouds.rest.annotations.VirtualHost;
+import org.jclouds.rest.annotations.XMLResponseParser;
+
+import com.google.common.collect.FluentIterable;
+
+/**
+ * Provides access to InternetGateway Services.
+ *
+ * @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_InternetGateway.html">InternetGateway docs</a>
+ * <p/>
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+@Path("/")
+public interface InternetGatewayApi {
+
+   /**
+    * Detaches an {@link InternetGateway} from a {@link org.jclouds.aws.ec2.domain.VPC}
+    *
+    * @param region Region where the VPC exists
+    * @param internetGatewayId ID of the gateway to detach
+    * @param vpcId The ID of the VPC
+    */
+   @Named("DetachInternetGateway")
+   @POST
+   @FormParams(keys = ACTION, values = "DetachInternetGateway")
+   @XMLResponseParser(ReturnValueHandler.class)
+   @Fallback(FalseOnNotFoundOr404.class)
+   Boolean detachInternetGateway(
+      @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+      @FormParam("InternetGatewayId") String internetGatewayId,
+      @FormParam("VpcId") String vpcId);
+
+   /**
+    * Detaches an {@link InternetGateway} from a {@link org.jclouds.aws.ec2.domain.VPC}, supplying options.
+    *
+    * @param region Region where the VPC exists
+    * @param internetGatewayId ID of the gateway to detach
+    * @param vpcId The ID of the VPC
+    * @param options Options for the request
+    */
+   @Named("DetachInternetGateway")
+   @POST
+   @FormParams(keys = ACTION, values = "DetachInternetGateway")
+   @XMLResponseParser(ReturnValueHandler.class)
+   @Fallback(FalseOnNotFoundOr404.class)
+   Boolean detachInternetGateway(
+      @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+      @FormParam("InternetGatewayId") String internetGatewayId,
+      @FormParam("VpcId") String vpcId,
+      InternetGatewayOptions options);
+
+   /**
+    * Attaches an {@link InternetGateway} to a {@link org.jclouds.aws.ec2.domain.VPC}
+    *
+    * @param region Region where the VPC exists
+    * @param internetGatewayId ID of the gateway to attach
+    * @param vpcId The ID of the VPC
+    */
+   @Named("AttachInternetGateway")
+   @POST
+   @FormParams(keys = ACTION, values = "AttachInternetGateway")
+   @XMLResponseParser(ReturnValueHandler.class)
+   @Fallback(FalseOnNotFoundOr404.class)
+   Boolean attachInternetGateway(
+      @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+      @FormParam("InternetGatewayId") String internetGatewayId,
+      @FormParam("VpcId") String vpcId);
+
+   /**
+    * Attaches an {@link InternetGateway} to a {@link org.jclouds.aws.ec2.domain.VPC}, supplying options.
+    *
+    * @param region Region where the VPC exists
+    * @param internetGatewayId ID of the gateway to attach
+    * @param vpcId The ID of the VPC
+    * @param options Options for the request
+    */
+   @Named("AttachInternetGateway")
+   @POST
+   @FormParams(keys = ACTION, values = "AttachInternetGateway")
+   @XMLResponseParser(ReturnValueHandler.class)
+   @Fallback(FalseOnNotFoundOr404.class)
+   Boolean attachInternetGateway(
+      @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+      @FormParam("InternetGatewayId") String internetGatewayId,
+      @FormParam("VpcId") String vpcId,
+      InternetGatewayOptions options);
+
+   /**
+    * Creates an {@link InternetGateway}
+    *
+    * @param region The region to create the gateway in.
+    */
+   @Named("CreateInternetGateway")
+   @POST
+   @FormParams(keys = ACTION, values = "CreateInternetGateway")
+   @XMLResponseParser(InternetGatewayHandler.class)
+   InternetGateway createInternetGateway(
+      @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region);
+
+   /**
+    * Creates an {@link InternetGateway}, supplying options.
+    *
+    * @param region The region to create the gateway in
+    * @param options Options for the request
+    */
+   @Named("CreateInternetGateway")
+   @POST
+   @FormParams(keys = ACTION, values = "CreateInternetGateway")
+   @XMLResponseParser(InternetGatewayHandler.class)
+   InternetGateway createInternetGateway(
+      @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+      InternetGatewayOptions options);
+
+   /**
+    * Deletes an {@code InternetGateway}.
+    *
+    * @param region gateways are tied to the Region where its files are located within Amazon S3.
+    * @param internetGatewayId  The gateway ID.
+    */
+   @Named("DeleteInternetGateway")
+   @POST
+   @FormParams(keys = ACTION, values = "DeleteInternetGateway")
+   @XMLResponseParser(ReturnValueHandler.class)
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean deleteInternetGateway(
+      @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+      @FormParam("InternetGatewayId") String internetGatewayId);
+
+   /**
+    * Deletes an {@code InternetGateway}, supplying options.
+    *
+    * @param region gateways are tied to the Region where its files are located within Amazon S3.
+    * @param internetGatewayId  The gateway ID.
+    * @param options Options for the request
+    */
+   @Named("DeleteInternetGateway")
+   @POST
+   @FormParams(keys = ACTION, values = "DeleteInternetGateway")
+   @XMLResponseParser(ReturnValueHandler.class)
+   @Fallback(FalseOnNotFoundOr404.class)
+   boolean deleteInternetGateway(
+      @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+      @FormParam("InternetGatewayId") String internetGatewayId,
+      InternetGatewayOptions options);
+
+   /**
+    * Describes {@link InternetGateway}s.
+    *
+    * @return InternetGateways or empty if there are none.
+    *
+    * @param region The region to search for gateways.
+    * @param internetGatewayIds Optional list of known gateway ids to restrict the search
+    */
+   @Named("DescribeInternetGateways")
+   @POST
+   @FormParams(keys = ACTION, values = "DescribeInternetGateways")
+   @XMLResponseParser(DescribeInternetGatewaysResponseHandler.class)
+   @Fallback(EmptyFluentIterableOnNotFoundOr404.class)
+   FluentIterable<InternetGateway> describeInternetGatewaysInRegion(
+      @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+      @BinderParam(BindInternetGatewayIdsToIndexedFormParams.class) String... internetGatewayIds);
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/InternetGatewayOptions.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/InternetGatewayOptions.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/InternetGatewayOptions.java
new file mode 100644
index 0000000..6449ae4
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/InternetGatewayOptions.java
@@ -0,0 +1,64 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.options;
+
+import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
+
+/**
+ * Contains options supported in the Form API for the InternetGateway operations. <h2>
+ * Usage</h2> The recommended way to instantiate such an object is to statically import
+ * InternetGatewayOptions.Builder.* and invoke a static creation method followed by an instance mutator
+ * (if needed):
+ * <p/>
+ * <code>
+ * import static org.jclouds.ec2.options.InternetGatewayOptions.Builder.*
+ * <p/>
+ * EC2Api connection = // get connection
+ * Future<Set<ImageMetadata>> images =
+ * connection.getInternetGatewayApi().get().createInternetGateway(region, dryRun());
+ * <code>
+ *
+ * @see <a
+ * href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateInternetGateway.html"
+ * />
+ */
+public class InternetGatewayOptions extends BaseEC2RequestOptions {
+
+   public static final InternetGatewayOptions NONE = new InternetGatewayOptions();
+
+   /**
+    * Checks whether you have the required permissions for the action, without actually making the request, and provides an error response.
+    */
+   public InternetGatewayOptions dryRun() {
+      formParameters.put("DryRun", "true");
+      return this;
+   }
+
+   public boolean isDryRun() {
+      return getFirstFormOrNull("DryRun") != null;
+   }
+
+   public static class Builder {
+      /**
+       * @see InternetGatewayOptions#dryRun()
+       */
+      public static InternetGatewayOptions dryRun() {
+         InternetGatewayOptions options = new InternetGatewayOptions();
+         return options.dryRun();
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/DescribeInternetGatewaysResponseHandler.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/DescribeInternetGatewaysResponseHandler.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/DescribeInternetGatewaysResponseHandler.java
new file mode 100644
index 0000000..66272e6
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/DescribeInternetGatewaysResponseHandler.java
@@ -0,0 +1,84 @@
+/*
+ * 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.xml;
+
+import static org.jclouds.util.SaxUtils.equalsOrSuffix;
+
+import org.jclouds.aws.ec2.domain.InternetGateway;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.Attributes;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableSet;
+import com.google.common.collect.ImmutableSet.Builder;
+import com.google.inject.Inject;
+
+/**
+ * @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_DescribeVpcs.html">xml</a>
+ */
+public class DescribeInternetGatewaysResponseHandler extends
+      ParseSax.HandlerForGeneratedRequestWithResult<FluentIterable<InternetGateway>> {
+   private final InternetGatewayHandler gatewayHandler;
+   private boolean inAttachmentSet;
+   private boolean inTagSet;
+   private Builder<InternetGateway> gateways = ImmutableSet.builder();
+
+   @Inject
+   DescribeInternetGatewaysResponseHandler(InternetGatewayHandler gatewayHandler) {
+      this.gatewayHandler = gatewayHandler;
+   }
+
+   @Override
+   public FluentIterable<InternetGateway> getResult() {
+      try {
+         return FluentIterable.from(gateways.build());
+      } finally {
+         gateways = ImmutableSet.builder();
+      }
+   }
+
+   @Override
+   public void startElement(String url, String name, String qName, Attributes attributes) {
+      if (equalsOrSuffix(qName, "attachmentSet")) {
+         inAttachmentSet = true;
+      } else if (equalsOrSuffix(qName, "tagSet")) {
+         inTagSet = true;
+      }
+      gatewayHandler.startElement(url, name, qName, attributes);
+   }
+
+   @Override
+   public void endElement(String uri, String name, String qName) {
+      if (equalsOrSuffix(qName, "attachmentSet")) {
+         inAttachmentSet = false;
+         gatewayHandler.endElement(uri, name, qName);
+      } else if (equalsOrSuffix(qName, "tagSet")) {
+         inTagSet = false;
+         gatewayHandler.endElement(uri, name, qName);
+      } else if (equalsOrSuffix(qName, "item") && !inTagSet && !inAttachmentSet) {
+         gateways.add(gatewayHandler.getResult());
+      } else {
+         gatewayHandler.endElement(uri, name, qName);
+      }
+   }
+
+   @Override
+   public void characters(char[] ch, int start, int length) {
+      gatewayHandler.characters(ch, start, length);
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/InternetGatewayAttachmentSetHandler.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/InternetGatewayAttachmentSetHandler.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/InternetGatewayAttachmentSetHandler.java
new file mode 100644
index 0000000..9a8942c
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/InternetGatewayAttachmentSetHandler.java
@@ -0,0 +1,70 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.xml;
+
+
+import java.util.List;
+
+import org.jclouds.aws.ec2.domain.InternetGatewayAttachment;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.Attributes;
+
+import com.google.common.collect.Lists;
+
+public class InternetGatewayAttachmentSetHandler extends ParseSax.HandlerWithResult<List<InternetGatewayAttachment>> {
+
+   private StringBuilder currentText = new StringBuilder();
+   private List<InternetGatewayAttachment> result = Lists.newArrayList();
+   private InternetGatewayAttachment.Builder itemBuilder;
+
+   @Override
+   public void startElement(String uri, String name, String qName, Attributes attrs) {
+      currentText.setLength(0);
+      if (qName.equalsIgnoreCase("item")) {
+         itemBuilder = InternetGatewayAttachment.builder();
+      }
+   }
+
+   @Override
+   public void endElement(String uri, String name, String qName) {
+      if (itemBuilder == null) {
+         return;
+      }
+      if (qName.equalsIgnoreCase("item")) {
+         result.add(itemBuilder.build());
+         itemBuilder = null;
+      } else if (qName.equalsIgnoreCase("vpcId")) {
+         itemBuilder.vpcId(currentText.toString());
+      } else if (qName.equalsIgnoreCase("state")) {
+         itemBuilder.state(InternetGatewayAttachment.State.valueOf(currentText.toString().toUpperCase()));
+      }
+   }
+
+   @Override
+   public List<InternetGatewayAttachment> getResult() {
+      try {
+         return result;
+      } finally {
+         result = Lists.newArrayList();
+      }
+   }
+
+   @Override
+   public void characters(char[] ch, int start, int length) {
+      currentText.append(ch, start, length);
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/InternetGatewayHandler.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/InternetGatewayHandler.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/InternetGatewayHandler.java
new file mode 100644
index 0000000..1082f62
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/InternetGatewayHandler.java
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.xml;
+
+import static org.jclouds.util.SaxUtils.currentOrNull;
+import static org.jclouds.util.SaxUtils.equalsOrSuffix;
+
+import javax.inject.Inject;
+
+import org.jclouds.aws.ec2.domain.InternetGateway;
+import org.jclouds.ec2.xml.TagSetHandler;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.Attributes;
+
+/**
+ * @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_InternetGateway.html">InternetGateway docs</a>
+ */
+public class InternetGatewayHandler extends ParseSax.HandlerForGeneratedRequestWithResult<InternetGateway> {
+   private StringBuilder currentText = new StringBuilder();
+   private InternetGateway.Builder builder = InternetGateway.builder();
+   private final TagSetHandler tagSetHandler;
+   private final InternetGatewayAttachmentSetHandler attachmentSetHandler;
+   private boolean inTagSet;
+   private boolean inAttachmentSet;
+
+
+   @Inject
+   InternetGatewayHandler(TagSetHandler tagSetHandler, InternetGatewayAttachmentSetHandler attachmentHandler) {
+      this.tagSetHandler = tagSetHandler;
+      this.attachmentSetHandler = attachmentHandler;
+   }
+
+   @Override
+   public InternetGateway getResult() {
+      try {
+         return builder.build();
+      } finally {
+         builder = InternetGateway.builder();
+      }
+   }
+
+   @Override
+   public void startElement(String uri, String name, String qName, Attributes attrs) {
+      currentText.setLength(0);
+      if (equalsOrSuffix(qName, "tagSet")) {
+         inTagSet = true;
+      }
+      if (equalsOrSuffix(qName, "attachmentSet")) {
+         inAttachmentSet = true;
+      }
+      if (inTagSet) {
+         tagSetHandler.startElement(uri, name, qName, attrs);
+      } else if (inAttachmentSet) {
+         attachmentSetHandler.startElement(uri, name, qName, attrs);
+      }
+   }
+
+   @Override
+   public void endElement(String uri, String name, String qName) {
+      if (equalsOrSuffix(qName, "tagSet")) {
+         inTagSet = false;
+         builder.tags(tagSetHandler.getResult());
+      } else if (equalsOrSuffix(qName, "attachmentSet")) {
+         inAttachmentSet = false;
+         builder.attachmentSet(attachmentSetHandler.getResult());
+      } else if (inTagSet) {
+         tagSetHandler.endElement(uri, name, qName);
+      } else if (inAttachmentSet) {
+         attachmentSetHandler.endElement(uri, name, qName);
+      } else if (equalsOrSuffix(qName, "internetGatewayId")) {
+         builder.id(currentOrNull(currentText));
+      }
+      currentText.setLength(0);
+   }
+
+   @Override
+   public void characters(char[] ch, int start, int length) {
+      if (inTagSet) {
+         tagSetHandler.characters(ch, start, length);
+      } else if (inAttachmentSet) {
+         attachmentSetHandler.characters(ch, start, length);
+      } else {
+        currentText.append(ch, start, length);
+      }
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/InternetGatewayApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/InternetGatewayApiLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/InternetGatewayApiLiveTest.java
new file mode 100644
index 0000000..c44acf4
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/InternetGatewayApiLiveTest.java
@@ -0,0 +1,162 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.features;
+
+import static java.util.logging.Logger.getAnonymousLogger;
+import static org.jclouds.aws.ec2.options.InternetGatewayOptions.Builder.dryRun;
+import static org.testng.Assert.assertEquals;
+import static org.testng.Assert.assertFalse;
+import static org.testng.Assert.assertNotEquals;
+import static org.testng.Assert.assertNotNull;
+import static org.testng.Assert.assertTrue;
+
+import java.util.List;
+import java.util.Random;
+
+import org.jclouds.apis.BaseApiLiveTest;
+import org.jclouds.aws.AWSResponseException;
+import org.jclouds.aws.ec2.AWSEC2Api;
+import org.jclouds.aws.ec2.domain.InternetGateway;
+import org.jclouds.aws.ec2.domain.InternetGatewayAttachment;
+import org.jclouds.aws.ec2.domain.VPC;
+import org.jclouds.aws.ec2.options.CreateVpcOptions;
+import org.jclouds.aws.ec2.options.InternetGatewayOptions;
+import org.jclouds.ec2.features.TagApi;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+
+/**
+ * Tests behavior of {@link InternetGatewayApi}
+ */
+@Test(groups = "live")
+public class InternetGatewayApiLiveTest extends BaseApiLiveTest<AWSEC2Api> {
+
+   private static final String TEST_REGION = "eu-west-1";
+
+   public InternetGatewayApiLiveTest() {
+      provider = "aws-ec2";
+   }
+
+   private InternetGatewayApi gwClient;
+   private TagApi tagger;
+
+   private VPCApi vpcClient;
+   private VPC vpc;
+
+   private InternetGateway gateway;
+   private String simpleName = InternetGatewayApiLiveTest.class.getSimpleName() + new Random().nextInt(10000);
+
+   @BeforeClass(groups = {"integration", "live"})
+   public void setupContext() {
+      gwClient = api.getInternetGatewayApiForRegion(TEST_REGION).get();
+      vpcClient = api.getVPCApi().get();
+      tagger = api.getTagApiForRegion(TEST_REGION).get();
+   }
+
+   @Test
+   public void testCreate() {
+      gateway = gwClient.createInternetGateway(TEST_REGION, InternetGatewayOptions.NONE);
+      assertNotNull(gateway, "Gateway was not successfully created");
+
+      assertEquals(gateway.tags().size(), 0, "Freshly created gateway has tags");
+      assertEquals(gateway.attachmentSet().size(), 0, "Freshly created gateway is attached");
+
+      tagger.applyToResources(ImmutableMap.of("Name", simpleName), ImmutableList.of(gateway.id()));
+      getAnonymousLogger().info("Created gateway " +  simpleName + " with id " + gateway.id());
+   }
+
+
+   @Test(dependsOnMethods = "testCreate")
+   public void testAttach() {
+      vpc = vpcClient.createVpc(TEST_REGION, "10.20.30.0/24", CreateVpcOptions.NONE);
+      assertNotNull(vpc, "Failed to create VPC to test attachments");
+      tagger.applyToResources(ImmutableMap.of("Name", simpleName), ImmutableList.of(vpc.id()));
+
+      final Boolean attached = gwClient.attachInternetGateway(TEST_REGION, gateway.id(), vpc.id());
+      assertTrue(attached, "Gateway " + gateway.id() + " failed to attach to VPC " + vpc.id());
+   }
+
+   @Test(dependsOnMethods = "testAttach")
+   public void testGetAndVerifyAttach() {
+      getAnonymousLogger().info("Testing retrieval of gateway " + simpleName);
+      FluentIterable<InternetGateway> gateways = gwClient.describeInternetGatewaysInRegion(TEST_REGION, gateway.id());
+      final ImmutableList<InternetGateway> internetGateways = gateways.toList();
+      getAnonymousLogger().info("Gateway count " + internetGateways.size());
+      assertTrue(internetGateways.size() == 1, "Failed to retrieve list with expected gateway " + gateway.id());
+
+      final InternetGateway gw = internetGateways.get(0);
+      getAnonymousLogger().info("Found gateway " + gw.id() + " with " +  gw.tags().size() + " tags");
+      assertEquals(gw.tags().get("Name"), simpleName);
+
+      final List<InternetGatewayAttachment> attachments = gw.attachmentSet();
+      assertEquals(attachments.size(), 1, "Gateway " + gateway.id() + " has no attachments, should have " + vpc.id());
+      final String attached = attachments.get(0).vpcId();
+      assertEquals(attached, vpc.id(), "Gateway " + gateway.id() + " attached to " + attached + " not " + vpc.id());
+   }
+
+   @Test(dependsOnMethods = "testGetAndVerifyAttach")
+   public void testDetach() {
+      final Boolean detached = gwClient.detachInternetGateway(TEST_REGION, gateway.id(), vpc.id());
+      assertTrue(detached, "Gateway " + gateway.id() + " was not detached from VPC " + vpc.id());
+   }
+
+   @Test(dependsOnMethods = "testDetach")
+   public void testListAndVerifyResultsOfDetach() {
+      FluentIterable<InternetGateway> gateways = gwClient.describeInternetGatewaysInRegion(TEST_REGION);
+      final ImmutableList<InternetGateway> asList = gateways.toList();
+      assertFalse(asList.isEmpty());
+      boolean found = false;
+      for (InternetGateway gw : asList) {
+         if (gw.id().equals(gateway.id())) {
+            found = true;
+            assertEquals(gw.attachmentSet().size(), 0, "Gateway " + gw.id() + " is attached to " + gw.attachmentSet());
+         }
+      }
+      assertTrue(found, "Could not find gateway " + gateway.id() + " in result of list");
+   }
+
+   @Test(dependsOnMethods = "testListAndVerifyResultsOfDetach", alwaysRun = true)
+   public void testDelete() {
+      if (gateway != null) {
+         assertTrue(gwClient.deleteInternetGateway(TEST_REGION, gateway.id()));
+      }
+      if (vpc != null) {
+         assertTrue(vpcClient.deleteVpc(TEST_REGION, vpc.id()));
+      }
+   }
+
+   @Test
+   public void testWithOptions() {
+      FluentIterable<InternetGateway> before = gwClient.describeInternetGatewaysInRegion(TEST_REGION);
+
+      try {
+         gwClient.createInternetGateway(TEST_REGION, dryRun());
+      } catch (AWSResponseException e) {
+         assertEquals(e.getError().getCode(), "DryRunOperation", "Expected DryRunOperation but got " + e.getError());
+      }
+
+      FluentIterable<InternetGateway> after = gwClient.describeInternetGatewaysInRegion(TEST_REGION);
+
+      assertNotEquals(before, after, "Dry run 'CreateInternetGateway' operation modified live account");
+
+   }
+
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/InternetGatewayApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/InternetGatewayApiMockTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/InternetGatewayApiMockTest.java
new file mode 100644
index 0000000..8c65702
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/InternetGatewayApiMockTest.java
@@ -0,0 +1,211 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ *
+ *     http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.features;
+
+import static org.jclouds.aws.ec2.options.InternetGatewayOptions.Builder.dryRun;
+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.List;
+
+import org.jclouds.aws.AWSResponseException;
+import org.jclouds.aws.ec2.domain.InternetGateway;
+import org.jclouds.aws.ec2.domain.InternetGatewayAttachment;
+import org.jclouds.aws.ec2.internal.BaseAWSEC2ApiMockTest;
+import org.jclouds.aws.ec2.options.InternetGatewayOptions;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Lists;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+
+@Test(groups = "unit", testName = "InternetGatewayApiMockTest", singleThreaded = true)
+public class InternetGatewayApiMockTest extends BaseAWSEC2ApiMockTest {
+
+   public void createInternetGateway() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/create_internet_gateway.xml");
+      InternetGateway result = gatewayApi().createInternetGateway(DEFAULT_REGION, InternetGatewayOptions.NONE);
+
+      assertNotNull(result, "Failed to create InternetGateway object");
+      assertEquals(result.id(), "igw-fada7c9c", "Gateway id does not match mock data: " + result.id());
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=CreateInternetGateway");
+   }
+
+   public void attachInternetGateway() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/attach_internet_gateway.xml");
+
+      final Boolean attached = gatewayApi().attachInternetGateway(DEFAULT_REGION, "igw-fada7c9c", "vpc-6250b91b");
+      assertTrue(attached, "Failed to attach InternetGateway");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=AttachInternetGateway&InternetGatewayId=igw-fada7c9c&VpcId=vpc-6250b91b");
+   }
+
+   public void attachInternetGatewayFail() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/attach_internet_gateway_failed.xml");
+
+      final Boolean attached = gatewayApi().attachInternetGateway(DEFAULT_REGION, "igw-fada7c9c", "vpc-6250b91b");
+      assertFalse(attached, "Gateway reported as created despite failure response");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=AttachInternetGateway&InternetGatewayId=igw-fada7c9c&VpcId=vpc-6250b91b");
+   }
+
+   public void attachInternetGatewayNotFound() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse().setResponseCode(404));
+
+      final Boolean attached = gatewayApi().attachInternetGateway(DEFAULT_REGION, "igw-fada7c9c", "vpc-6250b91b");
+      assertFalse(attached, "Somehow attached gateway despite NotFound response");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=AttachInternetGateway&InternetGatewayId=igw-fada7c9c&VpcId=vpc-6250b91b");
+   }
+
+   public void detachInternetGateway() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/detach_internet_gateway.xml");
+
+      final Boolean detached = gatewayApi().detachInternetGateway(DEFAULT_REGION, "igw-fada7c9c", "vpc-6250b91b");
+      assertTrue(detached, "Gateway not successfully detached");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=DetachInternetGateway&InternetGatewayId=igw-fada7c9c&VpcId=vpc-6250b91b");
+
+   }
+
+   public void detachInternetGatewayNotFound() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse().setResponseCode(404));
+
+      final Boolean detached = gatewayApi().detachInternetGateway(DEFAULT_REGION, "igw-fada7c9c", "vpc-6250b91b");
+      assertFalse(detached, "Non-existent gateway somehow successfully detached");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=DetachInternetGateway&InternetGatewayId=igw-fada7c9c&VpcId=vpc-6250b91b");
+
+   }
+
+   public void getInternetGateway() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/get_internet_gateway.xml");
+
+      final String igwId = "igw-fada7c9c";
+      final FluentIterable<InternetGateway> internetGateways =
+         gatewayApi().describeInternetGatewaysInRegion(DEFAULT_REGION, igwId);
+
+      final ImmutableList<InternetGateway> gateways = internetGateways.toList();
+      assertEquals(gateways.size(), 1);
+      assertEquals(gateways.get(0).id(), igwId);
+      assertEquals(gateways.get(0).tags().get("Name"), "get_internet_gateway_test");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=DescribeInternetGateways&InternetGatewayId.1=igw-fada7c9c");
+   }
+
+   public void getInternetGatewayNotFound() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse().setResponseCode(404));
+
+      final String igwId = "igw-fada7c9c";
+      final FluentIterable<InternetGateway> internetGateways =
+         gatewayApi().describeInternetGatewaysInRegion(DEFAULT_REGION, igwId);
+
+      final ImmutableList<InternetGateway> gateways = internetGateways.toList();
+      assertEquals(gateways.size(), 0);
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=DescribeInternetGateways&InternetGatewayId.1=igw-fada7c9c");
+
+   }
+
+   public void describeInternetGateways() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/describe_internet_gateways.xml");
+
+      final FluentIterable<InternetGateway> internetGateways =
+         gatewayApi().describeInternetGatewaysInRegion(DEFAULT_REGION);
+
+      final List<InternetGateway> gateways = Lists.newArrayList(internetGateways.toList());
+
+      assertEquals(gateways.size(), 3);
+      final ImmutableMap<String, InternetGateway> asMap =
+         ImmutableMap.of(gateways.get(0).id(), gateways.get(0),
+            gateways.get(1).id(), gateways.get(1),
+            gateways.get(2).id(), gateways.get(2));
+
+      assertEquals(asMap.get("igw-fada7c9c").tags().get("Name"), "describe_internet_gateways_test");
+      final InternetGatewayAttachment gw6bca130c = asMap.get("igw-6bca130c").attachmentSet().iterator().next();
+      assertEquals(gw6bca130c.vpcId(), "vpc-a13d29c6");
+      assertEquals(gw6bca130c.state(), InternetGatewayAttachment.State.AVAILABLE);
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=DescribeInternetGateways");
+
+   }
+
+   public void deleteInternetGateway() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/delete_internet_gateway.xml");
+
+      final boolean deleted = gatewayApi().deleteInternetGateway(DEFAULT_REGION, "igw-fada7c9c");
+      assertTrue(deleted, "Failed to delete gateway");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=DeleteInternetGateway&InternetGatewayId=igw-fada7c9c");
+   }
+
+   public void deleteInternetGatewayNotFound() throws Exception {
+      enqueueRegions(DEFAULT_REGION);
+      enqueue(DEFAULT_REGION, new MockResponse().setResponseCode(404));
+
+      final boolean deleted = gatewayApi().deleteInternetGateway(DEFAULT_REGION, "igw-fada7c9c");
+      assertFalse(deleted, "Somehow deleted a gateway that does not exist");
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=DeleteInternetGateway&InternetGatewayId=igw-fada7c9c");
+   }
+
+   @Test
+   public void testWithOptions() throws Exception {
+
+      enqueueRegions(DEFAULT_REGION);
+      enqueueXml(DEFAULT_REGION, "/create_internet_gateway_dry_run.xml");
+
+      try {
+         gatewayApi().createInternetGateway(DEFAULT_REGION, dryRun());
+      } catch (AWSResponseException e) {
+         assertEquals(e.getError().getCode(), "DryRunOperation", "Expected DryRunOperation but got " + e.getError());
+      }
+
+      assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+      assertPosted(DEFAULT_REGION, "Action=CreateInternetGateway&DryRun=true");
+
+   }
+   private InternetGatewayApi gatewayApi() {
+      return api().getInternetGatewayApi().get();
+   }
+}

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/test/resources/attach_internet_gateway.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/attach_internet_gateway.xml b/providers/aws-ec2/src/test/resources/attach_internet_gateway.xml
new file mode 100644
index 0000000..e59b5c6
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/attach_internet_gateway.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AttachInternetGatewayResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
+    <requestId>87565c19-59bf-4f71-8f9a-9dcfec2b6640</requestId>
+    <return>true</return>
+</AttachInternetGatewayResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/test/resources/attach_internet_gateway_failed.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/attach_internet_gateway_failed.xml b/providers/aws-ec2/src/test/resources/attach_internet_gateway_failed.xml
new file mode 100644
index 0000000..1c8158c
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/attach_internet_gateway_failed.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<AttachInternetGatewayResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
+    <requestId>87565c19-59bf-4f71-8f9a-9dcfec2b6640</requestId>
+    <return>false</return>
+</AttachInternetGatewayResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/test/resources/create_internet_gateway.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/create_internet_gateway.xml b/providers/aws-ec2/src/test/resources/create_internet_gateway.xml
new file mode 100644
index 0000000..491057d
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/create_internet_gateway.xml
@@ -0,0 +1,9 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<CreateInternetGatewayResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
+    <requestId>85c22645-f966-4025-9cb3-64bb5c833a54</requestId>
+    <internetGateway>
+        <internetGatewayId>igw-fada7c9c</internetGatewayId>
+        <attachmentSet/>
+        <tagSet/>
+    </internetGateway>
+</CreateInternetGatewayResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/test/resources/create_internet_gateway_dry_run.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/create_internet_gateway_dry_run.xml b/providers/aws-ec2/src/test/resources/create_internet_gateway_dry_run.xml
new file mode 100644
index 0000000..037d770
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/create_internet_gateway_dry_run.xml
@@ -0,0 +1,11 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<Response>
+    <Errors>
+        <Error>
+            <Code>DryRunOperation</Code>
+            <Message>Request would have succeeded, but DryRun flag is set.</Message>
+        </Error>
+    </Errors>
+    <RequestID>344ef005-e34b-42fb-a334-1180fe317e7c</RequestID>
+</Response>
+

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/test/resources/delete_internet_gateway.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/delete_internet_gateway.xml b/providers/aws-ec2/src/test/resources/delete_internet_gateway.xml
new file mode 100644
index 0000000..bd76425
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/delete_internet_gateway.xml
@@ -0,0 +1,6 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DeleteInternetGatewayResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
+    <requestId>de1da0ea-085f-4783-b270-af5338060497</requestId>
+    <return>true</return>
+</DeleteInternetGatewayResponse>
+

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/test/resources/describe_internet_gateways.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/describe_internet_gateways.xml b/providers/aws-ec2/src/test/resources/describe_internet_gateways.xml
new file mode 100644
index 0000000..5822112
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/describe_internet_gateways.xml
@@ -0,0 +1,37 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DescribeInternetGatewaysResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
+    <requestId>3ed08c74-7a82-48b1-96d6-58ec1a41e560</requestId>
+    <internetGatewaySet>
+        <item>
+            <internetGatewayId>igw-fada7c9c</internetGatewayId>
+            <attachmentSet/>
+            <tagSet>
+                <item>
+                    <key>Name</key>
+                    <value>describe_internet_gateways_test</value>
+                </item>
+            </tagSet>
+        </item>
+        <item>
+            <internetGatewayId>igw-6bca130c</internetGatewayId>
+            <attachmentSet>
+                <item>
+                    <vpcId>vpc-a13d29c6</vpcId>
+                    <state>available</state>
+                </item>
+            </attachmentSet>
+            <tagSet/>
+        </item>
+        <item>
+            <internetGatewayId>igw-d09a79b6</internetGatewayId>
+            <attachmentSet>
+                <item>
+                    <vpcId>vpc-17587171</vpcId>
+                    <state>available</state>
+                </item>
+            </attachmentSet>
+            <tagSet/>
+        </item>
+    </internetGatewaySet>
+</DescribeInternetGatewaysResponse>
+

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/test/resources/detach_internet_gateway.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/detach_internet_gateway.xml b/providers/aws-ec2/src/test/resources/detach_internet_gateway.xml
new file mode 100644
index 0000000..cd088b9
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/detach_internet_gateway.xml
@@ -0,0 +1,5 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DetachInternetGatewayResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
+    <requestId>3aa4e5fb-2395-4560-bd0d-d229bdc75391</requestId>
+    <return>true</return>
+</DetachInternetGatewayResponse>

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/test/resources/get_internet_gateway.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/get_internet_gateway.xml b/providers/aws-ec2/src/test/resources/get_internet_gateway.xml
new file mode 100644
index 0000000..4dc1c7d
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/get_internet_gateway.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DescribeInternetGatewaysResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
+    <requestId>b4064e62-7923-4559-8b7c-d8e6b4174d48</requestId>
+    <internetGatewaySet>
+        <item>
+            <internetGatewayId>igw-fada7c9c</internetGatewayId>
+            <attachmentSet>
+                <item>
+                    <vpcId>vpc-6250b91b</vpcId>
+                    <state>available</state>
+                </item>
+            </attachmentSet>
+            <tagSet>
+                <item>
+                    <key>Name</key>
+                    <value>get_internet_gateway_test</value>
+                </item>
+            </tagSet>
+        </item>
+    </internetGatewaySet>
+</DescribeInternetGatewaysResponse>
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/jclouds/blob/cff2f87e/providers/aws-ec2/src/test/resources/logback-test.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/logback-test.xml b/providers/aws-ec2/src/test/resources/logback-test.xml
new file mode 100644
index 0000000..b9e9616
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/logback-test.xml
@@ -0,0 +1,42 @@
+<?xml version="1.0"?>
+<configuration scan="false">
+    <appender name="FILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds.log</file>
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+    <appender name="WIREFILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds-wire.log</file>
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+    <appender name="COMPUTEFILE" class="ch.qos.logback.core.FileAppender">
+        <file>target/test-data/jclouds-compute.log</file>
+        <encoder>
+            <Pattern>%d %-5p [%c] [%thread] %m%n</Pattern>
+        </encoder>
+    </appender>
+
+    <logger name="org.jclouds">
+        <level value="DEBUG" />
+        <appender-ref ref="FILE" />
+    </logger>
+    <logger name="jclouds.compute">
+        <level value="DEBUG" />
+        <appender-ref ref="COMPUTEFILE" />
+    </logger>
+    <logger name="jclouds.wire">
+        <level value="DEBUG" />
+        <appender-ref ref="WIREFILE" />
+    </logger>
+    <logger name="jclouds.headers">
+        <level value="DEBUG" />
+        <appender-ref ref="WIREFILE" />
+    </logger>
+
+    <root>
+        <level value="INFO" />
+    </root>
+</configuration>