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/29 08:31:28 UTC
[1/4] jclouds git commit: Add RouteTable API.
Repository: jclouds
Updated Branches:
refs/heads/master a9006288e -> 28c3c33bf
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/RouteTableApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/RouteTableApiMockTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/RouteTableApiMockTest.java
new file mode 100644
index 0000000..2541a93
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/RouteTableApiMockTest.java
@@ -0,0 +1,301 @@
+/*
+ * 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 javax.ws.rs.core.Response.Status.PRECONDITION_FAILED;
+import static org.jclouds.aws.ec2.options.RouteOptions.Builder.destinationCidrBlock;
+import static org.jclouds.aws.ec2.options.RouteOptions.Builder.gatewayId;
+import static org.jclouds.aws.ec2.options.RouteTableOptions.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.assertNull;
+import static org.testng.Assert.assertTrue;
+
+import org.jclouds.aws.AWSResponseException;
+import org.jclouds.aws.ec2.domain.Route;
+import org.jclouds.aws.ec2.domain.RouteTable;
+import org.jclouds.aws.ec2.internal.BaseAWSEC2ApiMockTest;
+import org.testng.Assert;
+import org.testng.annotations.Test;
+
+import com.google.common.collect.ImmutableList;
+import com.squareup.okhttp.mockwebserver.MockResponse;
+
+@Test(groups = "unit", testName = "RouteTableApiMockTest", singleThreaded = true)
+public class RouteTableApiMockTest extends BaseAWSEC2ApiMockTest {
+
+ public void describeRouteTables() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueue(DEFAULT_REGION, new MockResponse().setResponseCode(404));
+ final ImmutableList<RouteTable> routeTables = routeTableApi().describeRouteTables(DEFAULT_REGION).toList();
+
+ assertTrue(routeTables.isEmpty(), "Returned " + routeTables.size() + " results for 404 response: " + routeTables);
+
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION, "Action=DescribeRouteTables");
+ }
+
+ public void describeRouteTablesNotFound() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueueXml(DEFAULT_REGION, "/describe_route_tables.xml");
+ final ImmutableList<RouteTable> routeTables = routeTableApi().describeRouteTables(DEFAULT_REGION).toList();
+
+ assertNotNull(routeTables, "Failed to create route table description object");
+ assertEquals(routeTables.size(), 3, "Failed to return all entries from test data, returned: " + routeTables);
+
+ for (RouteTable table : routeTables) {
+ if (ImmutableList.of("rtb-80a3fae4", "rtb-d4605bb0").contains(table.id())) {
+ assertRoutesForNormalVpc(table, table.id());
+ } else if (table.id().equals("rtb-e6c98381")) {
+ assertRoutesForTestVpc(table, table.id());
+ }
+ }
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION, "Action=DescribeRouteTables");
+ }
+
+ public void describeRouteTablesWithInvalidStateValue() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueueXml(DEFAULT_REGION, "/describe_route_tables_invalid.xml");
+ final ImmutableList<RouteTable> routeTables = routeTableApi().describeRouteTables(DEFAULT_REGION).toList();
+
+ assertNotNull(routeTables, "Failed to create route table description object");
+ assertEquals(routeTables.size(), 1, "Failed to return expected entry from test data, returned: " + routeTables);
+
+ assertEquals(routeTables.get(0).routeSet().get(0).state(), Route.RouteState.UNRECOGNIZED);
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION, "Action=DescribeRouteTables");
+ }
+
+ private void assertRoutesForNormalVpc(RouteTable table, String id) {
+ assertEquals(table.routeSet().size(), 2, "Failed to match test data route set size for " + id);
+ final String actual = table.associationSet().get(0).routeTableId();
+ assertEquals(actual, id, "Test data mismatch in " + id + " association set routeTableId(): " + actual);
+ assertTrue(table.associationSet().get(0).main(), "Test data mismatch in " + id + " association 'main'");
+ }
+
+ private void assertRoutesForTestVpc(RouteTable table, String id) {
+ assertEquals(table.routeSet().size(), 1, "Failed to match test data route set size for " + id);
+
+ assertEquals(table.routeSet().get(0).destinationCidrBlock(), "10.20.30.0/24",
+ "Mismatch in test data for " + id + " route set destinationCidrBlock");
+ assertEquals(table.routeSet().get(0).gatewayId(), "local",
+ "Mismatch in test data for " + id + " route set gatewayId");
+ assertEquals(table.routeSet().get(0).state(), Route.RouteState.ACTIVE,
+ "Mismatch in test data for " + id + " route set state");
+
+ final String actual = table.associationSet().get(0).routeTableId();
+ assertEquals(actual, id, "Test data mismatch in " + id + " association set routeTableId(): " + actual);
+ assertTrue(table.associationSet().get(0).main(), "Test data mismatch in " + id + " association 'main'");
+ }
+
+ public void createRouteTable() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueueXml(DEFAULT_REGION, "/create_route_table.xml");
+ RouteTable result = routeTableApi().createRouteTable(DEFAULT_REGION, "vpc-1a2b3c4d");
+
+ assertNotNull(result, "Failed to create RouteTable object");
+ assertEquals(result.id(), "rtb-8bda6cef", "Gateway id does not match mock data: " + result.id());
+ assertEquals(result.routeSet().size(), 2, "Should have 2 routes");
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION, "Action=CreateRouteTable&VpcId=vpc-1a2b3c4d");
+ }
+
+ public void createRouteTableWithOptions() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueueXml(PRECONDITION_FAILED, DEFAULT_REGION, "/dry_run.xml");
+ try {
+ routeTableApi().createRouteTable(DEFAULT_REGION, "vpc-1a2b3c4d", dryRun());
+ Assert.fail("Expected 'DryRunOperation' exception was not thrown");
+ } catch (AWSResponseException e) {
+ assertDryRun(e);
+ }
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION, "Action=CreateRouteTable&VpcId=vpc-1a2b3c4d&DryRun=true");
+ }
+
+ public void deleteRouteTable() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueueXml(DEFAULT_REGION, "/delete_route_table.xml");
+ final boolean deleted = routeTableApi().deleteRouteTable(DEFAULT_REGION, "rtb-8bda6cef");
+ assertTrue(deleted, "Failed to match 'true' data in test response");
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION, "Action=DeleteRouteTable&RouteTableId=rtb-8bda6cef");
+ }
+
+ public void deleteRouteTableWithOptions() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueueXml(PRECONDITION_FAILED, DEFAULT_REGION, "/dry_run.xml");
+ try {
+ routeTableApi().deleteRouteTable(DEFAULT_REGION, "rtb-8bda6cef", dryRun());
+ Assert.fail("Expected 'DryRunOperation' exception was not thrown");
+ } catch (AWSResponseException e) {
+ assertDryRun(e);
+ }
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION, "Action=DeleteRouteTable&RouteTableId=rtb-8bda6cef&DryRun=true");
+ }
+
+ public void deleteRouteTableNotFound() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueue(DEFAULT_REGION, new MockResponse().setResponseCode(404));
+ final boolean deleted = routeTableApi().deleteRouteTable(DEFAULT_REGION, "rtb-8bda6cef");
+ assertFalse(deleted, "Non-existent table reported as successfully deleted");
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION, "Action=DeleteRouteTable&RouteTableId=rtb-8bda6cef");
+ }
+
+ public void associateRouteTable() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueueXml(DEFAULT_REGION, "/associate_route_table.xml");
+ final String associationId = routeTableApi().associateRouteTable(DEFAULT_REGION, "rtb-8c95c0eb", "subnet-6986410e");
+ assertEquals(associationId, "rtbassoc-fb7fed9d", "Failed to associate route");
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION, "Action=AssociateRouteTable&RouteTableId=rtb-8c95c0eb&SubnetId=subnet-6986410e");
+ }
+
+ public void associateRouteTableNotFound() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueue(DEFAULT_REGION, new MockResponse().setResponseCode(404));
+ final String associationId = routeTableApi().associateRouteTable(DEFAULT_REGION, "rtb-8c95c0eb", "subnet-6986410e");
+ assertNull(associationId, "Returned id for non-existent route table: " + associationId);
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION, "Action=AssociateRouteTable&RouteTableId=rtb-8c95c0eb&SubnetId=subnet-6986410e");
+ }
+
+ public void associateRouteTableWithOptions() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueueXml(PRECONDITION_FAILED, DEFAULT_REGION, "/dry_run.xml");
+ try {
+ routeTableApi().associateRouteTable(DEFAULT_REGION, "rtb-8c95c0eb", "subnet-6986410e", dryRun());
+ } catch (AWSResponseException e) {
+ assertDryRun(e);
+ }
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION,
+ "Action=AssociateRouteTable&RouteTableId=rtb-8c95c0eb&SubnetId=subnet-6986410e&DryRun=true");
+ }
+
+ public void disassociateRouteTable() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueueXml(DEFAULT_REGION, "/disassociate_route_table.xml");
+ final boolean result = routeTableApi().disassociateRouteTable(DEFAULT_REGION, "rtbassoc-fb7fed9d");
+ assertTrue(result, "Failed to disassociate route");
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION, "Action=DisassociateRouteTable&AssociationId=rtbassoc-fb7fed9d");
+ }
+
+ public void disassociateRouteTableNotFound() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueue(DEFAULT_REGION, new MockResponse().setResponseCode(404));
+ final boolean result = routeTableApi().disassociateRouteTable(DEFAULT_REGION, "rtbassoc-fb7fed9d");
+ assertFalse(result, "Non-existent table reported as successfully disassociated");
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION, "Action=DisassociateRouteTable&AssociationId=rtbassoc-fb7fed9d");
+ }
+
+ public void disassociateRouteTablewithOptions() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueueXml(PRECONDITION_FAILED, DEFAULT_REGION, "/dry_run.xml");
+ try {
+ routeTableApi().disassociateRouteTable(DEFAULT_REGION, "rtbassoc-fb7fed9d", dryRun());
+ } catch (AWSResponseException e) {
+ assertDryRun(e);
+ }
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION, "Action=DisassociateRouteTable&AssociationId=rtbassoc-fb7fed9d&DryRun=true");
+ }
+
+ public void createRoute() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueueXml(DEFAULT_REGION, "/create_route.xml");
+ final boolean created = routeTableApi().createRoute(DEFAULT_REGION, "rtb-a77f2ac0",
+ gatewayId("igw-97e68af3").destinationCidrBlock("172.18.19.0/24"));
+ assertTrue(created, "Failed to match 'true' in test data response");
+
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION,
+ "Action=CreateRoute&RouteTableId=rtb-a77f2ac0&GatewayId=igw-97e68af3&DestinationCidrBlock=172.18.19.0/24");
+ }
+
+ public void createRouteNotFound() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueueXml(DEFAULT_REGION, "/create_route.xml");
+ final boolean created = routeTableApi().createRoute(DEFAULT_REGION, "rtb-a77f2ac0",
+ gatewayId("igw-97e68af3").destinationCidrBlock("172.18.19.0/24"));
+ assertTrue(created, "Failed to match 'true' in test data response");
+
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION,
+ "Action=CreateRoute&RouteTableId=rtb-a77f2ac0&GatewayId=igw-97e68af3&DestinationCidrBlock=172.18.19.0/24");
+ }
+
+ public void replaceRoute() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueue(DEFAULT_REGION, new MockResponse().setResponseCode(404));
+ final boolean created = routeTableApi().replaceRoute(DEFAULT_REGION, "rtb-a77f2ac0",
+ gatewayId("vgw-1d00376e").destinationCidrBlock("172.18.19.0/24"));
+ assertFalse(created, "Reported successful replace of route in non-existent route table");
+
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION,
+ "Action=ReplaceRoute&RouteTableId=rtb-a77f2ac0&GatewayId=vgw-1d00376e&DestinationCidrBlock=172.18.19.0/24");
+ }
+
+ public void replaceRouteNotFound() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueueXml(DEFAULT_REGION, "/replace_route.xml");
+ final boolean created = routeTableApi().replaceRoute(DEFAULT_REGION, "rtb-a77f2ac0",
+ gatewayId("vgw-1d00376e").destinationCidrBlock("172.18.19.0/24"));
+ assertTrue(created, "Failed to match 'true' in test data response");
+
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION,
+ "Action=ReplaceRoute&RouteTableId=rtb-a77f2ac0&GatewayId=vgw-1d00376e&DestinationCidrBlock=172.18.19.0/24");
+ }
+
+ public void deleteRoute() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueueXml(DEFAULT_REGION, "/delete_route.xml");
+ final boolean deleted = routeTableApi().deleteRoute(DEFAULT_REGION, "rtb-a77f2ac0",
+ destinationCidrBlock("172.18.19.0/24"));
+ assertTrue(deleted, "Failed to match 'true' in test data response");
+
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION, "Action=DeleteRoute&RouteTableId=rtb-a77f2ac0&DestinationCidrBlock=172.18.19.0/24");
+ }
+
+ public void deleteRouteNotFound() throws Exception {
+ enqueueRegions(DEFAULT_REGION);
+ enqueue(DEFAULT_REGION, new MockResponse().setResponseCode(404));
+ final boolean deleted = routeTableApi().deleteRoute(DEFAULT_REGION, "rtb-a77f2ac0",
+ destinationCidrBlock("172.18.19.0/24"));
+ assertFalse(deleted, "Reported successful delete of route in non-existent route table");
+
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION, "Action=DeleteRoute&RouteTableId=rtb-a77f2ac0&DestinationCidrBlock=172.18.19.0/24");
+ }
+
+ private void assertDryRun(AWSResponseException e) {
+ assertEquals(e.getError().getCode(), "DryRunOperation", "Expected DryRunOperation but got " + e.getError());
+ }
+
+ private RouteTableApi routeTableApi() {
+ return api().getRouteTableApi().get();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/internal/BaseAWSEC2ApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/internal/BaseAWSEC2ApiMockTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/internal/BaseAWSEC2ApiMockTest.java
index 060e577..d528fe5 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/internal/BaseAWSEC2ApiMockTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/internal/BaseAWSEC2ApiMockTest.java
@@ -26,10 +26,13 @@ import static org.jclouds.util.Strings2.toStringAndClose;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
+import java.io.InputStream;
import java.util.Map;
import java.util.Properties;
import java.util.Set;
+import javax.ws.rs.core.Response;
+
import org.jclouds.Constants;
import org.jclouds.ContextBuilder;
import org.jclouds.aws.ec2.AWSEC2Api;
@@ -155,6 +158,13 @@ public class BaseAWSEC2ApiMockTest {
new MockResponse().addHeader(CONTENT_TYPE, APPLICATION_XML).setBody(describeRegionsResponse.toString()));
}
+ protected void enqueueXml(Response.Status status, String region, String resource) {
+ enqueue(region, new MockResponse()
+ .setStatus("HTTP/1.1 " + status.getStatusCode() + " " + status.getReasonPhrase())
+ .addHeader(CONTENT_TYPE, APPLICATION_XML)
+ .setBody(stringFromResource(resource)));
+ }
+
protected void enqueueXml(String region, String resource) {
enqueue(region,
new MockResponse().addHeader(CONTENT_TYPE, APPLICATION_XML).setBody(stringFromResource(resource)));
@@ -162,7 +172,12 @@ public class BaseAWSEC2ApiMockTest {
protected String stringFromResource(String resourceName) {
try {
- return toStringAndClose(getClass().getResourceAsStream(resourceName));
+ final InputStream resourceAsStream = getClass().getResourceAsStream(resourceName);
+ if (resourceAsStream == null) {
+ throw new IllegalArgumentException(
+ "Could not find resource '" + resourceName + "' in class " + getClass().getSimpleName());
+ }
+ return toStringAndClose(resourceAsStream);
} catch (IOException e) {
throw propagate(e);
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/test/resources/associate_route_table.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/associate_route_table.xml b/providers/aws-ec2/src/test/resources/associate_route_table.xml
new file mode 100644
index 0000000..88e2db5
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/associate_route_table.xml
@@ -0,0 +1,4 @@
+<AssociateRouteTableResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
+ <requestId>f87d1645-3919-4e26-b98f-852c47def4ee</requestId>
+ <associationId>rtbassoc-fb7fed9d</associationId>
+</AssociateRouteTableResponse>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/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
deleted file mode 100644
index 037d770..0000000
--- a/providers/aws-ec2/src/test/resources/create_internet_gateway_dry_run.xml
+++ /dev/null
@@ -1,11 +0,0 @@
-<?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/b3d21f96/providers/aws-ec2/src/test/resources/create_route.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/create_route.xml b/providers/aws-ec2/src/test/resources/create_route.xml
new file mode 100644
index 0000000..e2e31ca
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/create_route.xml
@@ -0,0 +1,4 @@
+<CreateRouteResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
+ <requestId>3b1d5abc-0d50-4367-87c1-a4dcc2f8b928</requestId>
+ <return>true</return>
+</CreateRouteResponse>
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/test/resources/create_route_table.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/create_route_table.xml b/providers/aws-ec2/src/test/resources/create_route_table.xml
new file mode 100644
index 0000000..8234a4f
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/create_route_table.xml
@@ -0,0 +1,24 @@
+<CreateRouteTableResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
+ <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
+ <routeTable>
+ <routeTableId>rtb-8bda6cef</routeTableId>
+ <vpcId>vpc-1a2b3c4d</vpcId>
+ <routeSet>
+ <item>
+ <destinationCidrBlock>10.0.0.0/16</destinationCidrBlock>
+ <gatewayId>local</gatewayId>
+ <state>active</state>
+ <origin>CreateRouteTable</origin>
+ </item>
+ <item>
+ <destinationIpv6CidrBlock>2001:db8:1234:1a00::/56</destinationIpv6CidrBlock>
+ <gatewayId>local</gatewayId>
+ <state>active</state>
+ <origin>CreateRouteTable</origin>
+ </item>
+ </routeSet>
+ <associationSet/>
+ <propagatingVgwSet/>
+ <tagSet/>
+ </routeTable>
+</CreateRouteTableResponse>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/test/resources/delete_route.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/delete_route.xml b/providers/aws-ec2/src/test/resources/delete_route.xml
new file mode 100644
index 0000000..4dce471
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/delete_route.xml
@@ -0,0 +1,4 @@
+<DeleteRouteResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
+ <requestId>6d6d0513-5af2-46ae-8f8a-24c8c3ab0f70</requestId>
+ <return>true</return>
+</DeleteRouteResponse>
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/test/resources/delete_route_table.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/delete_route_table.xml b/providers/aws-ec2/src/test/resources/delete_route_table.xml
new file mode 100644
index 0000000..8ea49fb
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/delete_route_table.xml
@@ -0,0 +1,4 @@
+<DeleteRouteTableResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
+ <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
+ <return>true</return>
+</DeleteRouteTableResponse>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/test/resources/describe_route_tables.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/describe_route_tables.xml b/providers/aws-ec2/src/test/resources/describe_route_tables.xml
new file mode 100644
index 0000000..a23a3ca
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/describe_route_tables.xml
@@ -0,0 +1,74 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DescribeRouteTablesResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
+ <requestId>0fe3e6ca-5b09-4722-9d81-1f341376c830</requestId>
+ <routeTableSet>
+ <item>
+ <routeTableId>rtb-80a3fae4</routeTableId>
+ <vpcId>vpc-6dcb5609</vpcId>
+ <routeSet>
+ <item>
+ <destinationCidrBlock>172.31.0.0/16</destinationCidrBlock>
+ <gatewayId>local</gatewayId>
+ <state>active</state>
+ </item>
+ <item>
+ <destinationCidrBlock>0.0.0.0/0</destinationCidrBlock>
+ <gatewayId>igw-dcdcc7b9</gatewayId>
+ <state>active</state>
+ </item>
+ </routeSet>
+ <associationSet>
+ <item>
+ <routeTableAssociationId>rtbassoc-f173c296</routeTableAssociationId>
+ <routeTableId>rtb-80a3fae4</routeTableId>
+ <main>true</main>
+ </item>
+ </associationSet>
+ <tagSet/>
+ </item>
+ <item>
+ <routeTableId>rtb-d4605bb0</routeTableId>
+ <vpcId>vpc-924731f6</vpcId>
+ <routeSet>
+ <item>
+ <destinationCidrBlock>10.0.0.0/16</destinationCidrBlock>
+ <gatewayId>local</gatewayId>
+ <state>active</state>
+ </item>
+ <item>
+ <destinationCidrBlock>0.0.0.0/0</destinationCidrBlock>
+ <gatewayId>igw-5af2023e</gatewayId>
+ <state>active</state>
+ </item>
+ </routeSet>
+ <associationSet>
+ <item>
+ <routeTableAssociationId>rtbassoc-a08aefc7</routeTableAssociationId>
+ <routeTableId>rtb-d4605bb0</routeTableId>
+ <main>true</main>
+ </item>
+ </associationSet>
+ <tagSet/>
+ </item>
+ <item>
+ <routeTableId>rtb-e6c98381</routeTableId>
+ <vpcId>vpc-6fa76308</vpcId>
+ <routeSet>
+ <item>
+ <destinationCidrBlock>10.20.30.0/24</destinationCidrBlock>
+ <gatewayId>local</gatewayId>
+ <state>active</state>
+ </item>
+ </routeSet>
+ <associationSet>
+ <item>
+ <routeTableAssociationId>rtbassoc-2d2dbe4b</routeTableAssociationId>
+ <routeTableId>rtb-e6c98381</routeTableId>
+ <main>true</main>
+ </item>
+ </associationSet>
+ <tagSet/>
+ </item>
+ </routeTableSet>
+</DescribeRouteTablesResponse>
+
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/test/resources/describe_route_tables_invalid.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/describe_route_tables_invalid.xml b/providers/aws-ec2/src/test/resources/describe_route_tables_invalid.xml
new file mode 100644
index 0000000..a7109fa
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/describe_route_tables_invalid.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<DescribeRouteTablesResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
+ <requestId>0fe3e6ca-5b09-4722-9d81-1f341376c830</requestId>
+ <routeTableSet>
+ <item>
+ <routeTableId>rtb-80a3fae4</routeTableId>
+ <vpcId>vpc-6dcb5609</vpcId>
+ <routeSet>
+ <item>
+ <destinationCidrBlock>172.31.0.0/16</destinationCidrBlock>
+ <gatewayId>local</gatewayId>
+ <state>bogus</state>
+ </item>
+ </routeSet>
+ <associationSet/>
+ <tagSet/>
+ </item>
+ </routeTableSet>
+</DescribeRouteTablesResponse>
+
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/test/resources/disassociate_route_table.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/disassociate_route_table.xml b/providers/aws-ec2/src/test/resources/disassociate_route_table.xml
new file mode 100644
index 0000000..1a05743
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/disassociate_route_table.xml
@@ -0,0 +1,4 @@
+<DisassociateRouteTableResponse xmlns="http://ec2.amazonaws.com/doc/2012-06-01/">
+ <requestId>36e6a0e6-cd7a-45fc-8539-ba05cc070a3f</requestId>
+ <return>true</return>
+</DisassociateRouteTableResponse>
\ No newline at end of file
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/test/resources/dry_run.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/dry_run.xml b/providers/aws-ec2/src/test/resources/dry_run.xml
new file mode 100644
index 0000000..037d770
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/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/b3d21f96/providers/aws-ec2/src/test/resources/replace_route.xml
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/resources/replace_route.xml b/providers/aws-ec2/src/test/resources/replace_route.xml
new file mode 100644
index 0000000..dbbca61
--- /dev/null
+++ b/providers/aws-ec2/src/test/resources/replace_route.xml
@@ -0,0 +1,4 @@
+<ReplaceRouteResponse xmlns="http://ec2.amazonaws.com/doc/2016-11-15/">
+ <requestId>59dbff89-35bd-4eac-99ed-be587EXAMPLE</requestId>
+ <return>true</return>
+</ReplaceRouteResponse>
\ No newline at end of file
[4/4] jclouds git commit: Temporarily use a custom annotation instead
of @SinceApiVersion.
Posted by na...@apache.org.
Temporarily use a custom annotation instead of @SinceApiVersion.
The intention is to use @SinceApiVersion for this purpose, but that
would affect a number of APIs, and we would want to have good test
coverage before merging that change (in
FormSignerUtils#getAnnotatedApiVersion). However, there is some issue
wth certain tests at resent that means we cannot successfully test
all APIs that make use of @SinceApiVersion in order to assure
ourselves that FormSignerUtils will not introduce some problem.
See https://github.com/jclouds/jclouds/pull/1102#issuecomment-302682049
for details.
This annotation is introduced as a temporary measure in order to
decouple the functionality of FormSignerUtils#getAnnotatedApiVersion
from @SinceApiVersion and the tests in question. It can be removed and
replaced by @SinceApiVersion when those tests are fixed.
Designates that a method overrides the {@link ApiVersion} on the class
with a specific value.
Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/28c3c33b
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/28c3c33b
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/28c3c33b
Branch: refs/heads/master
Commit: 28c3c33bf07b4d4ddbd5516f952992088d09e76b
Parents: ce0a0ad
Author: Geoff Macartney <ge...@cloudsoftcorp.com>
Authored: Fri May 26 15:22:21 2017 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Mon May 29 10:24:52 2017 +0200
----------------------------------------------------------------------
.../jclouds/aws/filters/FormSignerUtils.java | 12 ++---
.../rest/annotations/ApiVersionOverride.java | 56 ++++++++++++++++++++
.../jclouds/aws/ec2/features/AWSSubnetApi.java | 3 +-
3 files changed, 64 insertions(+), 7 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds/blob/28c3c33b/apis/sts/src/main/java/org/jclouds/aws/filters/FormSignerUtils.java
----------------------------------------------------------------------
diff --git a/apis/sts/src/main/java/org/jclouds/aws/filters/FormSignerUtils.java b/apis/sts/src/main/java/org/jclouds/aws/filters/FormSignerUtils.java
index 84ff04b..4a5d6d6 100644
--- a/apis/sts/src/main/java/org/jclouds/aws/filters/FormSignerUtils.java
+++ b/apis/sts/src/main/java/org/jclouds/aws/filters/FormSignerUtils.java
@@ -18,7 +18,7 @@ package org.jclouds.aws.filters;
import org.jclouds.http.HttpRequest;
import org.jclouds.reflect.Invocation;
-import org.jclouds.rest.annotations.SinceApiVersion;
+import org.jclouds.rest.annotations.ApiVersionOverride;
import org.jclouds.rest.internal.GeneratedHttpRequest;
import com.google.common.base.Optional;
@@ -32,7 +32,7 @@ public final class FormSignerUtils {
private FormSignerUtils() {}
/**
- * Get the version from a @SinceApiVersion() annotation on an API method or its owning class.
+ * Get the version from a @ApiVersionOverride() annotation on an API method or its owning class.
* @param request The API request for the method.
* @return An optional of the value of the annotation.
*/
@@ -47,12 +47,12 @@ public final class FormSignerUtils {
private static Optional<String> getAnnotatedApiVersion(Invocation invocation) {
final Invokable<?, ?> invokable = invocation.getInvokable();
- if (invokable.isAnnotationPresent(SinceApiVersion.class)) {
- return Optional.fromNullable(invokable.getAnnotation(SinceApiVersion.class).value());
+ if (invokable.isAnnotationPresent(ApiVersionOverride.class)) {
+ return Optional.fromNullable(invokable.getAnnotation(ApiVersionOverride.class).value());
} else {
final Class<?> owner = invokable.getOwnerType().getRawType();
- if (owner.isAnnotationPresent(SinceApiVersion.class)) {
- return Optional.fromNullable(owner.getAnnotation(SinceApiVersion.class).value());
+ if (owner.isAnnotationPresent(ApiVersionOverride.class)) {
+ return Optional.fromNullable(owner.getAnnotation(ApiVersionOverride.class).value());
}
}
return Optional.absent();
http://git-wip-us.apache.org/repos/asf/jclouds/blob/28c3c33b/core/src/main/java/org/jclouds/rest/annotations/ApiVersionOverride.java
----------------------------------------------------------------------
diff --git a/core/src/main/java/org/jclouds/rest/annotations/ApiVersionOverride.java b/core/src/main/java/org/jclouds/rest/annotations/ApiVersionOverride.java
new file mode 100644
index 0000000..0307806
--- /dev/null
+++ b/core/src/main/java/org/jclouds/rest/annotations/ApiVersionOverride.java
@@ -0,0 +1,56 @@
+/*
+ * 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.rest.annotations;
+
+import static java.lang.annotation.ElementType.METHOD;
+import static java.lang.annotation.RetentionPolicy.RUNTIME;
+
+import java.lang.annotation.Retention;
+import java.lang.annotation.Target;
+
+import javax.inject.Qualifier;
+
+
+/**
+ * @Deprecated The intention is to use @SinceApiVersion for this purpose, but that would affect
+ * a number of APIs, and we would want to have good test coverage before merging that change
+ * (in {@link FormSignerUtils#getAnnotatedApiVersion}). However, there is some issue with certain tests at
+ * present that means we cannot successfully test all APIs that make use of @SinceApiVersion in order
+ * to assure ourselves that FormSignerUtils will not introduce some problem. See
+ * <a href="https://github.com/jclouds/jclouds/pull/1102#issuecomment-302682049">
+ * comments on github</a> for details
+ * This annotation is introduced as a temporary measure in order to decouple the functionality of
+ * {@link FormSignerUtils#getAnnotatedApiVersion} from @SinceApiVersion and the tests in question.
+ * It can be removed and replaced by @SinceApiVersion when those tests are fixed.
+ *
+ * Designates that a method overrides the {@link ApiVersion} on the class with a specific value.
+ *
+ * @see ApiVersion
+ */
+@Deprecated
+@Target({ METHOD })
+@Retention(RUNTIME)
+@Qualifier
+public @interface ApiVersionOverride {
+
+ /**
+ * Value to override the default {@link ApiVersion}.
+ *
+ */
+ String value();
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/28c3c33b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSubnetApi.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSubnetApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSubnetApi.java
index b0f245a..f11699b 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSubnetApi.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSubnetApi.java
@@ -36,6 +36,7 @@ import org.jclouds.ec2.xml.DescribeSubnetsResponseHandler;
import org.jclouds.ec2.xml.SubnetHandler;
import org.jclouds.javax.annotation.Nullable;
import org.jclouds.location.functions.RegionToEndpointOrProviderIfNull;
+import org.jclouds.rest.annotations.ApiVersionOverride;
import org.jclouds.rest.annotations.BinderParam;
import org.jclouds.rest.annotations.EndpointParam;
import org.jclouds.rest.annotations.Fallback;
@@ -141,7 +142,7 @@ public interface AWSSubnetApi extends SubnetApi {
* @param options The options containing the attribute to modify. You can only modify one attribute at a time.
* @return true if the modification was successful
*/
- @SinceApiVersion("2014-06-15")
+ @ApiVersionOverride("2014-06-15")
@Named("ModifySubnetAttribute")
@POST
@Path("/")
[3/4] jclouds git commit: Add ModifySubnetAttribute
Posted by na...@apache.org.
Add ModifySubnetAttribute
Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/ce0a0ad2
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/ce0a0ad2
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/ce0a0ad2
Branch: refs/heads/master
Commit: ce0a0ad213a331cec53fae6309b32d73388adf7e
Parents: b3d21f9
Author: Geoff Macartney <ge...@cloudsoftcorp.com>
Authored: Wed May 17 16:19:52 2017 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Mon May 29 10:24:52 2017 +0200
----------------------------------------------------------------------
.../org/jclouds/aws/filters/FormSigner.java | 12 ++-
.../jclouds/aws/filters/FormSignerUtils.java | 61 ++++++++++++++
.../org/jclouds/aws/filters/FormSignerV4.java | 25 +++++-
.../jclouds/aws/ec2/features/AWSSubnetApi.java | 22 +++++
.../options/ModifySubnetAttributeOptions.java | 86 ++++++++++++++++++++
.../aws/ec2/features/AWSSubnetApiLiveTest.java | 24 +++++-
.../aws/ec2/features/AWSSubnetApiMockTest.java | 20 +++++
.../aws/ec2/internal/BaseAWSEC2ApiMockTest.java | 9 +-
8 files changed, 250 insertions(+), 9 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds/blob/ce0a0ad2/apis/sts/src/main/java/org/jclouds/aws/filters/FormSigner.java
----------------------------------------------------------------------
diff --git a/apis/sts/src/main/java/org/jclouds/aws/filters/FormSigner.java b/apis/sts/src/main/java/org/jclouds/aws/filters/FormSigner.java
index aeb3647..b63f5a9 100644
--- a/apis/sts/src/main/java/org/jclouds/aws/filters/FormSigner.java
+++ b/apis/sts/src/main/java/org/jclouds/aws/filters/FormSigner.java
@@ -22,6 +22,7 @@ import static com.google.common.base.Preconditions.checkState;
import static com.google.common.collect.Ordering.natural;
import static com.google.common.io.BaseEncoding.base64;
import static com.google.common.io.ByteStreams.readBytes;
+import static org.jclouds.aws.filters.FormSignerUtils.getAnnotatedApiVersion;
import static org.jclouds.aws.reference.FormParameters.ACTION;
import static org.jclouds.aws.reference.FormParameters.AWS_ACCESS_KEY_ID;
import static org.jclouds.aws.reference.FormParameters.SECURITY_TOKEN;
@@ -59,6 +60,7 @@ import org.jclouds.rest.annotations.ApiVersion;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.base.Objects;
+import com.google.common.base.Optional;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
@@ -100,7 +102,15 @@ public interface FormSigner extends HttpRequestFilter {
public HttpRequest filter(HttpRequest request) throws HttpException {
checkNotNull(request.getFirstHeaderOrNull(HttpHeaders.HOST), "request is not ready to sign; host not present");
Multimap<String, String> decodedParams = queryParser().apply(request.getPayload().getRawContent().toString());
- decodedParams.replaceValues(VERSION, ImmutableSet.of(apiVersion));
+ Optional<String> optAnnotatedVersion = getAnnotatedApiVersion(request);
+ String version;
+ if (optAnnotatedVersion.isPresent()) {
+ String annotatedVersion = optAnnotatedVersion.get();
+ version = annotatedVersion.compareTo(apiVersion) > 0 ? annotatedVersion : apiVersion;
+ } else {
+ version = apiVersion;
+ }
+ decodedParams.replaceValues(VERSION, ImmutableSet.of(version));
addSigningParams(decodedParams);
validateParams(decodedParams);
String stringToSign = createStringToSign(request, decodedParams);
http://git-wip-us.apache.org/repos/asf/jclouds/blob/ce0a0ad2/apis/sts/src/main/java/org/jclouds/aws/filters/FormSignerUtils.java
----------------------------------------------------------------------
diff --git a/apis/sts/src/main/java/org/jclouds/aws/filters/FormSignerUtils.java b/apis/sts/src/main/java/org/jclouds/aws/filters/FormSignerUtils.java
new file mode 100644
index 0000000..84ff04b
--- /dev/null
+++ b/apis/sts/src/main/java/org/jclouds/aws/filters/FormSignerUtils.java
@@ -0,0 +1,61 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.filters;
+
+import org.jclouds.http.HttpRequest;
+import org.jclouds.reflect.Invocation;
+import org.jclouds.rest.annotations.SinceApiVersion;
+import org.jclouds.rest.internal.GeneratedHttpRequest;
+
+import com.google.common.base.Optional;
+import com.google.common.reflect.Invokable;
+
+/**
+ * Utilities for FormSigner implementations.
+ */
+public final class FormSignerUtils {
+
+ private FormSignerUtils() {}
+
+ /**
+ * Get the version from a @SinceApiVersion() annotation on an API method or its owning class.
+ * @param request The API request for the method.
+ * @return An optional of the value of the annotation.
+ */
+ public static Optional<String> getAnnotatedApiVersion(HttpRequest request) {
+ if (request instanceof GeneratedHttpRequest) {
+ GeneratedHttpRequest generatedRequest = (GeneratedHttpRequest) request;
+ return getAnnotatedApiVersion(generatedRequest.getInvocation());
+ } else {
+ return Optional.absent();
+ }
+ }
+
+ private static Optional<String> getAnnotatedApiVersion(Invocation invocation) {
+ final Invokable<?, ?> invokable = invocation.getInvokable();
+ if (invokable.isAnnotationPresent(SinceApiVersion.class)) {
+ return Optional.fromNullable(invokable.getAnnotation(SinceApiVersion.class).value());
+ } else {
+ final Class<?> owner = invokable.getOwnerType().getRawType();
+ if (owner.isAnnotationPresent(SinceApiVersion.class)) {
+ return Optional.fromNullable(owner.getAnnotation(SinceApiVersion.class).value());
+ }
+ }
+ return Optional.absent();
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/ce0a0ad2/apis/sts/src/main/java/org/jclouds/aws/filters/FormSignerV4.java
----------------------------------------------------------------------
diff --git a/apis/sts/src/main/java/org/jclouds/aws/filters/FormSignerV4.java b/apis/sts/src/main/java/org/jclouds/aws/filters/FormSignerV4.java
index a1359bb..7dfbd12 100644
--- a/apis/sts/src/main/java/org/jclouds/aws/filters/FormSignerV4.java
+++ b/apis/sts/src/main/java/org/jclouds/aws/filters/FormSignerV4.java
@@ -23,6 +23,7 @@ import static com.google.common.hash.Hashing.sha256;
import static com.google.common.io.BaseEncoding.base16;
import static com.google.common.net.HttpHeaders.AUTHORIZATION;
import static com.google.common.net.HttpHeaders.HOST;
+import static org.jclouds.aws.filters.FormSignerUtils.getAnnotatedApiVersion;
import static org.jclouds.aws.reference.FormParameters.ACTION;
import static org.jclouds.aws.reference.FormParameters.VERSION;
import static org.jclouds.http.utils.Queries.queryParser;
@@ -46,6 +47,7 @@ import org.jclouds.providers.ProviderMetadata;
import org.jclouds.rest.annotations.ApiVersion;
import com.google.common.base.Joiner;
+import com.google.common.base.Optional;
import com.google.common.base.Splitter;
import com.google.common.base.Supplier;
import com.google.common.collect.ImmutableMap;
@@ -101,7 +103,18 @@ public final class FormSignerV4 implements FormSigner {
this.serviceAndRegion = serviceAndRegion;
}
- @Override public HttpRequest filter(HttpRequest request) throws HttpException {
+ /**
+ * Adds the Authorization header to the request.
+ *
+ * Also if the method for the operation (or its class) is annotated with a version that is higher than the
+ * default (apiVersion), then the Version parameter of the request is set to be the value from the annotation.
+ *
+ * @param request The HTTP request for the API call.
+ * @return The request
+ * @throws HttpException
+ */
+ @Override
+ public HttpRequest filter(HttpRequest request) throws HttpException {
checkArgument(request.getHeaders().containsKey(HOST), "request is not ready to sign; host not present");
String host = request.getFirstHeaderOrNull(HOST);
String form = request.getPayload().getRawContent().toString();
@@ -126,7 +139,15 @@ public final class FormSignerV4 implements FormSigner {
.replaceHeader("X-Amz-Date", timestamp);
if (!decodedParams.containsKey(VERSION)) {
- requestBuilder.addFormParam(VERSION, apiVersion);
+ Optional<String> optAnnotatedVersion = getAnnotatedApiVersion(request);
+ if (optAnnotatedVersion.isPresent()) {
+ String annotatedVersion = optAnnotatedVersion.get();
+ // allow an explicit version annotation to _upgrade_ the version past apiVersion (but not downgrade)
+ String greater = annotatedVersion.compareTo(apiVersion) > 0 ? annotatedVersion : apiVersion;
+ requestBuilder.addFormParam(VERSION, greater);
+ } else {
+ requestBuilder.addFormParam(VERSION, apiVersion);
+ }
}
Credentials credentials = creds.get();
http://git-wip-us.apache.org/repos/asf/jclouds/blob/ce0a0ad2/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSubnetApi.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSubnetApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSubnetApi.java
index ccafebe..b0f245a 100644
--- a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSubnetApi.java
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/AWSSubnetApi.java
@@ -25,6 +25,8 @@ import javax.ws.rs.Path;
import org.jclouds.Fallbacks;
import org.jclouds.aws.ec2.options.CreateSubnetOptions;
+import org.jclouds.aws.ec2.options.ModifySubnetAttributeOptions;
+import org.jclouds.aws.ec2.xml.ReturnValueHandler;
import org.jclouds.aws.filters.FormSigner;
import org.jclouds.ec2.binders.BindFiltersToIndexedFormParams;
import org.jclouds.ec2.binders.BindSubnetIdsToIndexedFormParams;
@@ -130,4 +132,24 @@ public interface AWSSubnetApi extends SubnetApi {
FluentIterable<Subnet> describeSubnetsInRegionWithFilter(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
@BinderParam(BindFiltersToIndexedFormParams.class) Multimap<String, String> filter);
+
+ /**
+ * Modifies a subnet attribute. You can only modify one attribute at a time.
+ *
+ * @param region The region for the subnet
+ * @param subnetId The ID of the subnet
+ * @param options The options containing the attribute to modify. You can only modify one attribute at a time.
+ * @return true if the modification was successful
+ */
+ @SinceApiVersion("2014-06-15")
+ @Named("ModifySubnetAttribute")
+ @POST
+ @Path("/")
+ @FormParams(keys = ACTION, values = "ModifySubnetAttribute")
+ @XMLResponseParser(ReturnValueHandler.class)
+ @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+ boolean modifySubnetAttribute(
+ @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+ @FormParam("SubnetId") String subnetId,
+ ModifySubnetAttributeOptions options);
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/ce0a0ad2/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/ModifySubnetAttributeOptions.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/ModifySubnetAttributeOptions.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/ModifySubnetAttributeOptions.java
new file mode 100644
index 0000000..b18b850
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/ModifySubnetAttributeOptions.java
@@ -0,0 +1,86 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.options;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
+import org.jclouds.rest.annotations.SinceApiVersion;
+
+/**
+ * Contains options supported in the Form API for the ModifySubnetAttribute
+ * operation. <h2>
+ * Usage</h2> The recommended way to instantiate a ModifySubnetAttributeOptions
+ * object is to statically import ModifySubnetAttributeOptions.Builder.* and
+ * invoke a static creation method followed by an instance mutator (if needed):
+ * <p/>
+ * <code>
+ * import static org.jclouds.aws.ec2.options.ModifySubnetAttributeOptions.Builder.*
+ * <p/>
+ * group = connection.getAWSSubnetApi().modifySubnetAttribute(region, subnetId, mapPublicIpOnLaunch(true));
+ * <code>
+ *
+ * @see <a href=
+ * "http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_ModifySubnetAttribute.html"
+ * />
+ */
+@SinceApiVersion("2014-06-15")
+public class ModifySubnetAttributeOptions extends BaseEC2RequestOptions {
+
+ /**
+ * The Availability Zone for the subnet.
+ */
+ public ModifySubnetAttributeOptions assignIpv6AddressOnCreation(Boolean assignIpv6AddressOnCreation) {
+ formParameters.put("AssignIpv6AddressOnCreation.Value",
+ checkNotNull(assignIpv6AddressOnCreation, "assignIpv6AddressOnCreation").toString());
+ return this;
+ }
+
+ public Boolean isAssignIpv6AddressOnCreation() {
+ return Boolean.parseBoolean("AssignIpv6AddressOnCreation.Value");
+ }
+
+ public ModifySubnetAttributeOptions mapPublicIpOnLaunch(Boolean mapPublicIpOnLaunch) {
+ formParameters.put("MapPublicIpOnLaunch.Value",
+ checkNotNull(mapPublicIpOnLaunch, "mapPublicIpOnLaunch").toString());
+ return this;
+ }
+
+ public Boolean isMapPublicIpOnLaunch() {
+ return Boolean.parseBoolean(getFirstFormOrNull("MapPublicIpOnLaunch.Value"));
+ }
+
+ public static class Builder {
+
+ /**
+ * @see ModifySubnetAttributeOptions#assignIpv6AddressOnCreation(Boolean )
+ */
+ public static ModifySubnetAttributeOptions assignIpv6AddressOnCreation(Boolean assignIpv6AddressOnCreation) {
+ ModifySubnetAttributeOptions options = new ModifySubnetAttributeOptions();
+ return options.assignIpv6AddressOnCreation(assignIpv6AddressOnCreation);
+ }
+
+ /**
+ * @see ModifySubnetAttributeOptions#mapPublicIpOnLaunch(Boolean)
+ */
+ public static ModifySubnetAttributeOptions mapPublicIpOnLaunch(Boolean mapPublicIpOnLaunch) {
+ ModifySubnetAttributeOptions options = new ModifySubnetAttributeOptions();
+ return options.mapPublicIpOnLaunch(mapPublicIpOnLaunch);
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/ce0a0ad2/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSubnetApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSubnetApiLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSubnetApiLiveTest.java
index b851f3a..e06ae6e 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSubnetApiLiveTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSubnetApiLiveTest.java
@@ -16,15 +16,19 @@
*/
package org.jclouds.aws.ec2.features;
+import static org.jclouds.aws.ec2.options.ModifySubnetAttributeOptions.Builder.mapPublicIpOnLaunch;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertNotNull;
import static org.testng.Assert.assertTrue;
+import java.util.Random;
+
import org.jclouds.aws.ec2.AWSEC2Api;
import org.jclouds.aws.ec2.domain.VPC;
import org.jclouds.aws.ec2.options.CreateVpcOptions;
import org.jclouds.compute.internal.BaseComputeServiceContextLiveTest;
import org.jclouds.ec2.domain.Subnet;
+import org.jclouds.ec2.features.TagApi;
import org.testng.annotations.AfterClass;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@@ -33,6 +37,7 @@ import com.google.common.base.Optional;
import com.google.common.base.Predicate;
import com.google.common.collect.FluentIterable;
import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableMultimap;
import com.google.common.collect.Iterables;
@@ -47,13 +52,15 @@ public class AWSSubnetApiLiveTest extends BaseComputeServiceContextLiveTest {
private AWSEC2Api api;
private AWSSubnetApi subnetClient;
private VPCApi vpcClient;
+ private TagApi tagApi;
+ private String simpleName = getClass().getSimpleName() + new Random().nextInt(10000);
private Subnet subnet;
private VPC vpc;
public AWSSubnetApiLiveTest() {
provider = "aws-ec2";
- region = "us-west-2";
+ region = "eu-west-1";
}
@Override
@@ -63,6 +70,7 @@ public class AWSSubnetApiLiveTest extends BaseComputeServiceContextLiveTest {
api = view.unwrapApi(AWSEC2Api.class);
subnetClient = api.getAWSSubnetApi().get();
vpcClient = view.unwrapApi(AWSEC2Api.class).getVPCApi().get();
+ tagApi = api.getTagApiForRegion(region).get();
}
@Override
@@ -85,10 +93,12 @@ public class AWSSubnetApiLiveTest extends BaseComputeServiceContextLiveTest {
@Test
public void testCreateSubnetInRegion() {
- vpc = vpcClient.createVpc(region, "10.0.0.0/16", CreateVpcOptions.NONE);
- subnet = subnetClient.createSubnetInRegion(region, vpc.id(), "10.0.0.0/20");
+ vpc = vpcClient.createVpc(region, "10.21.0.0/16", CreateVpcOptions.NONE);
+ // tag the VPC for ease of identification in console if things go wrong
+ tagApi.applyToResources(ImmutableMap.of("Name", simpleName), ImmutableList.of(vpc.id()));
+ subnet = subnetClient.createSubnetInRegion(region, vpc.id(), "10.21.0.0/20");
assertNotNull(subnet);
- assertEquals(subnet.getCidrBlock(), "10.0.0.0/20");
+ assertEquals(subnet.getCidrBlock(), "10.21.0.0/20");
}
@Test(dependsOnMethods = "testCreateSubnetInRegion")
@@ -107,6 +117,12 @@ public class AWSSubnetApiLiveTest extends BaseComputeServiceContextLiveTest {
}
@Test(dependsOnMethods = "testCreateSubnetInRegion")
+ public void testModifySubnetAttribute() {
+ final boolean result = subnetClient.modifySubnetAttribute(region, subnet.getSubnetId(), mapPublicIpOnLaunch(true));
+ assertTrue(result, "Failed to modify subnet attribute");
+ }
+
+ @Test(dependsOnMethods = "testCreateSubnetInRegion")
public void testList() {
FluentIterable<Subnet> subnets = subnetClient.describeSubnetsInRegionWithFilter(region,
ImmutableMultimap.<String, String>of());
http://git-wip-us.apache.org/repos/asf/jclouds/blob/ce0a0ad2/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSubnetApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSubnetApiMockTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSubnetApiMockTest.java
index b8f81ca..191a51b 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSubnetApiMockTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/AWSSubnetApiMockTest.java
@@ -16,6 +16,7 @@
*/
package org.jclouds.aws.ec2.features;
+import static org.jclouds.aws.ec2.options.ModifySubnetAttributeOptions.Builder.mapPublicIpOnLaunch;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertTrue;
@@ -203,6 +204,25 @@ public class AWSSubnetApiMockTest extends BaseAWSEC2ApiMockTest {
assertPosted(region, "Action=DescribeSubnets");
}
+ public void modifySubnetAttribute() throws Exception {
+ String region = "us-west-2";
+ enqueueRegions(DEFAULT_REGION);
+ enqueue(DEFAULT_REGION,
+ new MockResponse().setBody("<ModifySubnetAttributeResponse xmlns=\"http://ec2.amazonaws.com/doc/2016-09-15/\">\n" +
+ " <requestId>7a62c49f-347e-4fc4-9331-6e8eEXAMPLE</requestId>\n" +
+ " <return>true</return>\n" +
+ "</ModifySubnetAttributeResponse>"));
+
+ final boolean result =
+ subnetApiForRegion(DEFAULT_REGION).modifySubnetAttribute(DEFAULT_REGION, "subnet-9d4a7b6c", mapPublicIpOnLaunch(true));
+ assertTrue(result, "Failed to match expected test result of 'true'");
+ assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
+ assertPosted(DEFAULT_REGION,
+ "Action=ModifySubnetAttribute&SubnetId=subnet-9d4a7b6c&MapPublicIpOnLaunch.Value=true",
+ "2014-06-15");
+
+ }
+
private AWSSubnetApi subnetApi() {
return api().getAWSSubnetApi().get();
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/ce0a0ad2/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/internal/BaseAWSEC2ApiMockTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/internal/BaseAWSEC2ApiMockTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/internal/BaseAWSEC2ApiMockTest.java
index d528fe5..7ad46c8 100644
--- a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/internal/BaseAWSEC2ApiMockTest.java
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/internal/BaseAWSEC2ApiMockTest.java
@@ -183,7 +183,12 @@ public class BaseAWSEC2ApiMockTest {
}
}
+
protected RecordedRequest assertPosted(String region, String postParams) throws InterruptedException {
+ return assertPosted(region, postParams, "2012-06-01");
+ }
+
+ protected RecordedRequest assertPosted(String region, String postParams, String apiVersion) throws InterruptedException {
RecordedRequest request = regionToServers.get(region).takeRequest();
assertEquals(request.getMethod(), "POST");
assertEquals(request.getPath(), "/");
@@ -192,8 +197,8 @@ public class BaseAWSEC2ApiMockTest {
request.getHeader(AUTHORIZATION)).startsWith("AWS4-HMAC-SHA256 Credential=AKIAIOSFODNN7EXAMPLE/20120416/" +
region + "/ec2/aws4_request, SignedHeaders=content-type;host;x-amz-date, Signature=");
String body = new String(request.getBody(), Charsets.UTF_8);
- assertThat(body).contains("&Version=2012-06-01");
- assertEquals(body.replace("&Version=2012-06-01", ""), postParams);
+ assertThat(body).contains("&Version=" + apiVersion);
+ assertEquals(body.replace("&Version=" + apiVersion, ""), postParams);
return request;
}
}
[2/4] jclouds git commit: Add RouteTable API.
Posted by na...@apache.org.
Add RouteTable API.
Limitations:
Does not contain support for VgwRoutePropagation.
Project: http://git-wip-us.apache.org/repos/asf/jclouds/repo
Commit: http://git-wip-us.apache.org/repos/asf/jclouds/commit/b3d21f96
Tree: http://git-wip-us.apache.org/repos/asf/jclouds/tree/b3d21f96
Diff: http://git-wip-us.apache.org/repos/asf/jclouds/diff/b3d21f96
Branch: refs/heads/master
Commit: b3d21f965288b44cadc750ff1dde2ec7ac45fff6
Parents: a900628
Author: Geoff Macartney <ge...@cloudsoftcorp.com>
Authored: Fri May 12 16:44:30 2017 +0100
Committer: Ignasi Barrera <na...@apache.org>
Committed: Mon May 29 10:22:46 2017 +0200
----------------------------------------------------------------------
.../java/org/jclouds/aws/ec2/AWSEC2Api.java | 17 +-
.../BindRouteTableIdsToIndexedFormParams.java | 32 ++
.../java/org/jclouds/aws/ec2/domain/Route.java | 107 +++++++
.../org/jclouds/aws/ec2/domain/RouteTable.java | 99 ++++++
.../aws/ec2/domain/RouteTableAssociation.java | 71 +++++
.../jclouds/aws/ec2/features/RouteTableApi.java | 279 +++++++++++++++++
.../aws/ec2/options/InternetGatewayOptions.java | 5 +-
.../jclouds/aws/ec2/options/RouteOptions.java | 254 ++++++++++++++++
.../aws/ec2/options/RouteTableOptions.java | 75 +++++
.../xml/AssociateRouteTableResponseHandler.java | 40 +++
.../xml/CreateRouteTableResponseHandler.java | 55 ++++
.../xml/DescribeRouteTablesResponseHandler.java | 100 ++++++
.../org/jclouds/aws/ec2/xml/RouteHandler.java | 48 +++
.../jclouds/aws/ec2/xml/RouteSetHandler.java | 77 +++++
.../xml/RouteTableAssociationSetHandler.java | 79 +++++
.../jclouds/aws/ec2/xml/RouteTableHandler.java | 116 +++++++
.../features/InternetGatewayApiLiveTest.java | 8 +-
.../features/InternetGatewayApiMockTest.java | 8 +-
.../aws/ec2/features/RouteTableApiLiveTest.java | 293 ++++++++++++++++++
.../aws/ec2/features/RouteTableApiMockTest.java | 301 +++++++++++++++++++
.../aws/ec2/internal/BaseAWSEC2ApiMockTest.java | 17 +-
.../test/resources/associate_route_table.xml | 4 +
.../create_internet_gateway_dry_run.xml | 11 -
.../aws-ec2/src/test/resources/create_route.xml | 4 +
.../src/test/resources/create_route_table.xml | 24 ++
.../aws-ec2/src/test/resources/delete_route.xml | 4 +
.../src/test/resources/delete_route_table.xml | 4 +
.../test/resources/describe_route_tables.xml | 74 +++++
.../resources/describe_route_tables_invalid.xml | 20 ++
.../test/resources/disassociate_route_table.xml | 4 +
.../aws-ec2/src/test/resources/dry_run.xml | 11 +
.../src/test/resources/replace_route.xml | 4 +
32 files changed, 2225 insertions(+), 20 deletions(-)
----------------------------------------------------------------------
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/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 a094ce6..d2808af 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
@@ -24,6 +24,7 @@ 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.RouteTableApi;
import org.jclouds.aws.ec2.features.SpotInstanceApi;
import org.jclouds.aws.ec2.features.VPCApi;
import org.jclouds.ec2.EC2Api;
@@ -142,10 +143,24 @@ public interface AWSEC2Api extends EC2Api {
Optional<? extends InternetGatewayApi> getInternetGatewayApi();
/**
- * Provides synchronous access to InternetGateway services in a given region.
+ * Provides synchronous access to Internet Gateway services in a given region.
*/
@Delegate
Optional<? extends InternetGatewayApi> getInternetGatewayApiForRegion(
@EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region
);
+
+ /**
+ * Provides synchronous access to Route Table services.
+ */
+ @Delegate
+ Optional<? extends RouteTableApi> getRouteTableApi();
+
+ /**
+ * Provides synchronous access to Route Table services in a given region.
+ */
+ @Delegate
+ Optional<? extends RouteTableApi> getRouteTableApiForRegion(
+ @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region
+ );
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/binders/BindRouteTableIdsToIndexedFormParams.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/binders/BindRouteTableIdsToIndexedFormParams.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/binders/BindRouteTableIdsToIndexedFormParams.java
new file mode 100644
index 0000000..4c2ec42
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/binders/BindRouteTableIdsToIndexedFormParams.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 RouteTableId.index
+ */
+public class BindRouteTableIdsToIndexedFormParams implements Binder {
+ @Override
+ public <R extends HttpRequest> R bindToRequest(R request, Object input) {
+ return AWSUtils.indexStringArrayToFormValuesWithPrefix(request, "RouteTableId", input);
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/Route.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/Route.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/Route.java
new file mode 100644
index 0000000..39d2d92
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/Route.java
@@ -0,0 +1,107 @@
+/*
+ * 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 org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+/**
+ * A route in an Amazon EC2 Route Table.
+ *
+ * @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_Route.html" >doc</a>
+ */
+@AutoValue
+public abstract class Route {
+
+ public enum RouteState {
+
+ /**
+ * An active route.
+ */
+ ACTIVE,
+
+ /**
+ * Indicates that the route's target isn't available (for example, the specified gateway isn't attached
+ * to the VPC, or the specified NAT instance has been terminated).
+ */
+ BLACKHOLE,
+
+ /**
+ * Value supplied was not valid.
+ */
+ UNRECOGNIZED;
+
+ public String value() {
+ return name().toLowerCase();
+ }
+
+ public static RouteState fromValue(String v) {
+ if (v == null || v.isEmpty()) {
+ throw new IllegalArgumentException("Value cannot be null or empty");
+ }
+ try {
+ return valueOf(v.toUpperCase());
+ } catch (IllegalArgumentException e) {
+ return UNRECOGNIZED;
+ }
+ }
+ }
+
+
+ @Nullable
+ public abstract String destinationCidrBlock();
+
+ @Nullable
+ public abstract String gatewayId();
+
+ @Nullable
+ public abstract RouteState state();
+
+ @Nullable
+ public abstract String origin();
+
+ @SerializedNames({"destinationCidrBlock", "gatewayId", "state", "origin"})
+ public static Route create(String destinationCidrBlock, String gatewayId, RouteState state, String origin) {
+ return builder()
+ .destinationCidrBlock(destinationCidrBlock)
+ .gatewayId(gatewayId)
+ .state(state)
+ .origin(origin)
+ .build();
+ }
+
+ Route() {}
+
+ public static Builder builder() {
+ return new AutoValue_Route.Builder();
+ }
+
+ @AutoValue.Builder
+ public abstract static class Builder {
+ public abstract Builder destinationCidrBlock(String destinationCidrBlock);
+
+ public abstract Builder gatewayId(String gatewayId);
+
+ public abstract Builder state(RouteState state);
+
+ public abstract Builder origin(String origin);
+
+ public abstract Route build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/RouteTable.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/RouteTable.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/RouteTable.java
new file mode 100644
index 0000000..b4eb182
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/RouteTable.java
@@ -0,0 +1,99 @@
+/*
+ * 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 Route Table.
+ *
+ * @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RouteTable.html" >doc</a>
+ */
+@AutoValue
+public abstract class RouteTable {
+
+ @Nullable
+ public abstract String id();
+
+ @Nullable
+ public abstract String vpcId();
+
+ @Nullable
+ public abstract List<Route> routeSet();
+
+ @Nullable
+ public abstract List<RouteTableAssociation> associationSet();
+
+ @Nullable
+ public abstract Map<String, String> tags();
+
+ @SerializedNames({"routeTableId", "vpcId", "routeSet", "associationSet", "tagSet"})
+ public static RouteTable create(String id,
+ String vpcId,
+ List<Route> routeSet,
+ List<RouteTableAssociation> associationSet,
+ Map<String, String> tags) {
+ return builder()
+ .id(id)
+ .vpcId(vpcId)
+ .routeSet(routeSet)
+ .associationSet(associationSet)
+ .tags(tags)
+ .build();
+ }
+
+ RouteTable() {}
+
+ public static Builder builder() {
+ return new AutoValue_RouteTable.Builder();
+ }
+
+ @AutoValue.Builder
+ public abstract static class Builder {
+
+ public abstract Builder id(String id);
+ public abstract Builder vpcId(String vpcId);
+ public abstract Builder routeSet(List<Route> routeSet);
+ public abstract Builder associationSet(List<RouteTableAssociation> associationSet);
+ public abstract Builder tags(Map<String, String> tags);
+
+ @Nullable abstract List<Route> routeSet();
+ @Nullable abstract List<RouteTableAssociation> associationSet();
+ @Nullable abstract Map<String, String> tags();
+
+ abstract RouteTable autoBuild();
+
+ public RouteTable build() {
+ routeSet(routeSet() != null ? ImmutableList.copyOf(routeSet()) : ImmutableList.<Route>of());
+ associationSet(associationSet() != null
+ ? ImmutableList.copyOf(associationSet())
+ : ImmutableList.<RouteTableAssociation>of());
+ tags(tags() != null ? ImmutableMap.copyOf(tags()) : ImmutableMap.<String, String>of());
+ return autoBuild();
+ }
+
+ }
+
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/RouteTableAssociation.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/RouteTableAssociation.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/RouteTableAssociation.java
new file mode 100644
index 0000000..2b25afa
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/domain/RouteTableAssociation.java
@@ -0,0 +1,71 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.domain;
+
+import org.jclouds.javax.annotation.Nullable;
+import org.jclouds.json.SerializedNames;
+
+import com.google.auto.value.AutoValue;
+
+/**
+ * An association of a route to a subnet.
+ *
+ * @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RouteTableAssociation.html">AWS docs</a>
+ */
+@AutoValue
+public abstract class RouteTableAssociation {
+
+
+ @Nullable
+ public abstract String id();
+
+ @Nullable
+ public abstract String routeTableId();
+
+ @Nullable
+ public abstract String subnetId();
+
+ @Nullable
+ public abstract Boolean main();
+
+ @SerializedNames({"routeTableAssociationId", "routeTableId", "subnetId", "main"})
+ public static RouteTableAssociation create(String id, String routeTableId, String subnetId, Boolean main) {
+ return builder()
+ .id(id)
+ .routeTableId(routeTableId)
+ .subnetId(subnetId)
+ .main(main)
+ .build();
+ }
+
+ RouteTableAssociation() {}
+
+ public static Builder builder() {
+ return new AutoValue_RouteTableAssociation.Builder();
+ }
+
+ @AutoValue.Builder
+ public abstract static class Builder {
+ public abstract Builder id(String id);
+ public abstract Builder routeTableId(String routeTableId);
+ public abstract Builder subnetId(String subnetId);
+ public abstract Builder main(Boolean main);
+
+ public abstract RouteTableAssociation build();
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/RouteTableApi.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/RouteTableApi.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/RouteTableApi.java
new file mode 100644
index 0000000..3190e60
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/features/RouteTableApi.java
@@ -0,0 +1,279 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.features;
+
+import static org.jclouds.aws.reference.FormParameters.ACTION;
+
+import javax.inject.Named;
+import javax.ws.rs.FormParam;
+import javax.ws.rs.POST;
+import javax.ws.rs.Path;
+
+import org.jclouds.Fallbacks;
+import org.jclouds.aws.ec2.binders.BindRouteTableIdsToIndexedFormParams;
+import org.jclouds.aws.ec2.domain.RouteTable;
+import org.jclouds.aws.ec2.options.RouteOptions;
+import org.jclouds.aws.ec2.options.RouteTableOptions;
+import org.jclouds.aws.ec2.xml.AssociateRouteTableResponseHandler;
+import org.jclouds.aws.ec2.xml.CreateRouteTableResponseHandler;
+import org.jclouds.aws.ec2.xml.DescribeRouteTablesResponseHandler;
+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 AWS Route Table services.
+ *
+ * @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RouteTable.html">RouteTable docs</a>
+ */
+@RequestFilters(FormSigner.class)
+@VirtualHost
+@Path("/")
+public interface RouteTableApi {
+
+ /**
+ * Creates a {@link RouteTable}
+ *
+ * @param region The region to create the table in.
+ * @param vpcId The ID of the VPC
+ * @return The route table
+ */
+ @Named("CreateRouteTable")
+ @POST
+ @FormParams(keys = ACTION, values = "CreateRouteTable")
+ @XMLResponseParser(CreateRouteTableResponseHandler.class)
+ RouteTable createRouteTable(
+ @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+ @FormParam("VpcId") String vpcId);
+
+ /**
+ * Creates a {@link RouteTable}, supplying options.
+ *
+ * @param region The region to create the table in
+ * @param vpcId The ID of the VPC
+ * @param options Options for the request
+ * @return The route table
+ */
+ @Named("CreateRouteTable")
+ @POST
+ @FormParams(keys = ACTION, values = "CreateRouteTable")
+ @XMLResponseParser(CreateRouteTableResponseHandler.class)
+ RouteTable createRouteTable(
+ @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+ @FormParam("VpcId") String vpcId,
+ RouteTableOptions options);
+
+ /**
+ * Deletes a {@link RouteTable}
+ *
+ * @param region The region to delete the table from
+ * @param routeTableId The ID of the table to delete
+ * @return true if the route table was found and deleted
+ */
+ @Named("DeleteRouteTable")
+ @POST
+ @FormParams(keys = ACTION, values = "DeleteRouteTable")
+ @XMLResponseParser(ReturnValueHandler.class)
+ @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+ boolean deleteRouteTable(
+ @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+ @FormParam("RouteTableId") String routeTableId);
+
+ /**
+ * Delete a {@link RouteTable}, supplying options.
+ *
+ * @param region The region to delete the table from
+ * @param routeTableId The ID of the table to delete
+ * @param options Options for the request
+ * @return true if the route table was found and deleted
+ */
+ @Named("DeleteRouteTable")
+ @POST
+ @FormParams(keys = ACTION, values = "DeleteRouteTable")
+ @XMLResponseParser(ReturnValueHandler.class)
+ @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+ boolean deleteRouteTable(
+ @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+ @FormParam("RouteTableId") String routeTableId,
+ RouteTableOptions options);
+
+ /**
+ * Associates a subnet with a route table. The subnet and route table must be in the same VPC.
+ * This association causes traffic originating from the subnet to be routed according to the routes in the route table.
+ * The action returns an association ID, which you need in order to disassociate the route table from the subnet later.
+ * A route table can be associated with multiple subnets.
+ *
+ * @param region Region of the VPC for the route table
+ * @param routeTableId ID of the route table
+ * @param subnetId ID of the subnet to associate
+ *
+ * @return The association ID which you need in order to disassociate the route table from the subnet later.
+ */
+ @Named("AssociateRouteTable")
+ @POST
+ @FormParams(keys = ACTION, values = "AssociateRouteTable")
+ @XMLResponseParser(AssociateRouteTableResponseHandler.class)
+ @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+ String associateRouteTable(
+ @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+ @FormParam("RouteTableId") String routeTableId,
+ @FormParam("SubnetId") String subnetId);
+
+ /**
+ * @see #associateRouteTable(java.lang.String, java.lang.String, java.lang.String)
+ *
+ * @param region Region of the VPC for the route table
+ * @param routeTableId ID of the route table
+ * @param subnetId ID of the subnet to associate
+ * @param options Options for the request
+ *
+ * @return The association ID which you need in order to disassociate the route table from the subnet later.
+ */
+ @Named("AssociateRouteTable")
+ @POST
+ @FormParams(keys = ACTION, values = "AssociateRouteTable")
+ @XMLResponseParser(AssociateRouteTableResponseHandler.class)
+ @Fallback(Fallbacks.NullOnNotFoundOr404.class)
+ String associateRouteTable(
+ @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+ @FormParam("RouteTableId") String routeTableId,
+ @FormParam("SubnetId") String subnetId,
+ RouteTableOptions options);
+
+ /**
+ * Disassociates a subnet from a route table.
+ * After you perform this action, the subnet no longer uses the routes in the route table.
+ * Instead, it uses the routes in the VPC's main route table.
+ * @param region Region of the route table
+ * @param associationId association id returned by {@link #associateRouteTable(String, String, String)}
+ * @return true if the subnet was found and disassociated.
+ */
+ @Named("DisassociateRouteTable")
+ @POST
+ @FormParams(keys = ACTION, values = "DisassociateRouteTable")
+ @XMLResponseParser(ReturnValueHandler.class)
+ @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+ boolean disassociateRouteTable(
+ @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+ @FormParam("AssociationId") String associationId);
+
+ /**
+ * @see #disassociateRouteTable(String, String)
+ * @param region Region of the route table
+ * @param associationId association id returned by {@link #associateRouteTable(String, String, String)}
+ * @param options Options for the request
+ * @return true if the subnet was found and disassociated.
+ */
+ @Named("DisassociateRouteTable")
+ @POST
+ @FormParams(keys = ACTION, values = "DisassociateRouteTable")
+ @XMLResponseParser(ReturnValueHandler.class)
+ @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+ boolean disassociateRouteTable(
+ @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+ @FormParam("AssociationId") String associationId,
+ RouteTableOptions options);
+
+ /**
+ * Creates a route in a route table within a VPC.
+ *
+ * @param region region of the VPC
+ * @param routeTableId ID of the route table to put the route in
+ * @param options You must specify one of the following targets: Internet gateway or virtual
+ * private gateway, NAT instance, NAT gateway, VPC peering connection,
+ * network interface, or egress-only Internet gateway.
+ * @return true if the route was created
+ */
+ @Named("CreateRoute")
+ @POST
+ @FormParams(keys = ACTION, values = "CreateRoute")
+ @XMLResponseParser(ReturnValueHandler.class)
+ @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+ boolean createRoute(
+ @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+ @FormParam("RouteTableId") String routeTableId,
+ RouteOptions options);
+
+ /**
+ * Replaces a route in a route table within a VPC.
+ *
+ * @param region region of the VPC
+ * @param routeTableId ID of the route table containing the route to replace
+ * @param options You must specify only one of the following targets: Internet gateway or virtual
+ * private gateway, NAT instance, NAT gateway, VPC peering connection,
+ * network interface, or egress-only Internet gateway.
+ * @return true if the route was found and replaced
+ */
+ @Named("ReplaceRoute")
+ @POST
+ @FormParams(keys = ACTION, values = "ReplaceRoute")
+ @XMLResponseParser(ReturnValueHandler.class)
+ @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+ boolean replaceRoute(
+ @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+ @FormParam("RouteTableId") String routeTableId,
+ RouteOptions options);
+
+ /**
+ * Delete a route from a route table.
+ *
+ * @param region region of the VPC
+ * @param routeTableId ID of the route table owning the route
+ * @param options This should include the destination CIDR block of the route to delete
+ *
+ * @return true if the route was found and deleted
+ *
+ * <p>
+ * <b>Example:</b>
+ * <pre>
+ * api.deleteRoute(region, routeTable.id(), destinationCidrBlock("10.20.30.0/24"))
+ * </pre>
+ * </p>
+ */
+ @Named("DeleteRoute")
+ @POST
+ @FormParams(keys = ACTION, values = "DeleteRoute")
+ @XMLResponseParser(ReturnValueHandler.class)
+ @Fallback(Fallbacks.FalseOnNotFoundOr404.class)
+ boolean deleteRoute(
+ @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+ @FormParam("RouteTableId") String routeTableId,
+ RouteOptions options);
+
+ /**
+ * Describes route tables.
+ * @param region The region to search for route tables.
+ */
+ @Named("DescribeRouteTables")
+ @POST
+ @FormParams(keys = ACTION, values = "DescribeRouteTables")
+ @XMLResponseParser(DescribeRouteTablesResponseHandler.class)
+ @Fallback(Fallbacks.EmptyFluentIterableOnNotFoundOr404.class)
+ FluentIterable<RouteTable> describeRouteTables(
+ @EndpointParam(parser = RegionToEndpointOrProviderIfNull.class) @Nullable String region,
+ @BinderParam(BindRouteTableIdsToIndexedFormParams.class) String... routeTableIds);
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/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
index 6449ae4..cff7311 100644
--- 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
@@ -28,7 +28,7 @@ import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
* import static org.jclouds.ec2.options.InternetGatewayOptions.Builder.*
* <p/>
* EC2Api connection = // get connection
- * Future<Set<ImageMetadata>> images =
+ * InternetGateway gw =
* connection.getInternetGatewayApi().get().createInternetGateway(region, dryRun());
* <code>
*
@@ -41,7 +41,8 @@ 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.
+ * 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");
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/RouteOptions.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/RouteOptions.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/RouteOptions.java
new file mode 100644
index 0000000..751bb29
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/RouteOptions.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.options;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
+
+/**
+ * Contains options supported in the Form API for the Route operations. <h2>
+ * Usage</h2> The recommended way to instantiate such an object is to statically import
+ * RouteOptions.Builder.* and invoke a static creation method followed by an instance mutator
+ * (if needed):
+ * <p/>
+ * <code>
+ * import static org.jclouds.ec2.options.RouteOptions.Builder.*
+ * <p/>
+ * EC2Api connection = // get connection
+ * Route r = connection.getRouteTableApi().get()
+ * .createRoute(region, routeTableId, gatewayId("igw-97e68af3").destinationCidrBlock("172.18.19.0/24"));
+ * <code>
+ *
+ * @see <a
+ * href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateRoute.html"
+ * />
+ */
+public class RouteOptions extends BaseEC2RequestOptions {
+
+ /**
+ * Checks whether you have the required permissions for the action, without actually making the request,
+ * and provides an error response.
+ */
+ public RouteOptions dryRun() {
+ formParameters.put("DryRun", "true");
+ return this;
+ }
+
+ public boolean isDryRun() {
+ return getFirstFormOrNull("DryRun") != null;
+ }
+
+ /**
+ * The IPv4 CIDR address block used for the destination match.
+ * Routing decisions are based on the most specific match.
+ */
+ public RouteOptions destinationCidrBlock(String destinationCidrBlock) {
+ formParameters.put("DestinationCidrBlock", checkNotNull(destinationCidrBlock, "destinationCidrBlock"));
+ return this;
+ }
+
+ /**
+ * @see RouteOptions#destinationCidrBlock(java.lang.String)
+ */
+ public String getDestinationCidrBlock() {
+ return getFirstFormOrNull("DestinationCidrBlock");
+ }
+
+ /**
+ * The IPv6 CIDR block used for the destination match. Routing decisions are based on the most specific match.
+ */
+ public RouteOptions destinationIpv6CidrBlock(String destinationIpv6CidrBlock) {
+ formParameters.put("DestinationIpv6CidrBlock", checkNotNull(destinationIpv6CidrBlock, "destinationIpv6CidrBlock"));
+ return this;
+ }
+
+ /**
+ * @see RouteOptions#destinationIpv6CidrBlock(java.lang.String)
+ */
+ public String getDestinationIpv6CidrBlock() {
+ return getFirstFormOrNull("DestinationIpv6CidrBlock");
+ }
+
+ /**
+ * The ID of an Internet gateway or virtual private gateway attached to your VPC.
+ */
+ public RouteOptions gatewayId(String gatewayId) {
+ formParameters.put("GatewayId", checkNotNull(gatewayId, "gatewayId"));
+ return this;
+ }
+
+ /**
+ * @see RouteOptions#gatewayId(java.lang.String)
+ */
+ public String getGatewayId() {
+ return getFirstFormOrNull("GatewayId");
+ }
+
+ /**
+ * [IPv6 traffic only] The ID of an egress-only Internet gateway.
+ */
+ public RouteOptions egressOnlyInternetGatewayId(String egressOnlyInternetGatewayId) {
+ formParameters.put("EgressOnlyInternetGatewayId",
+ checkNotNull(egressOnlyInternetGatewayId, "egressOnlyInternetGatewayId"));
+ return this;
+ }
+
+ /**
+ * @see RouteOptions#egressOnlyInternetGatewayId(java.lang.String)
+ */
+ public String getEgressOnlyInternetGatewayId() {
+ return getFirstFormOrNull("EgressOnlyInternetGatewayId");
+ }
+
+ /**
+ * [IPv4 traffic only] The ID of a NAT gateway.
+ */
+ public RouteOptions natGatewayId(String natGatewayId) {
+ formParameters.put("NatGatewayId", checkNotNull(natGatewayId, "natGatewayId"));
+ return this;
+ }
+
+ /**
+ * @see RouteOptions#natGatewayId(String)
+ */
+ public String getNatGatewayId() {
+ return getFirstFormOrNull("NatGatewayId");
+ }
+
+ /**
+ * The ID of a network interface.
+ */
+ public RouteOptions networkInterfaceId(String networkInterfaceId) {
+ formParameters.put("NetworkInterfaceId", checkNotNull(networkInterfaceId, "networkInterfaceId"));
+ return this;
+ }
+
+ /**
+ * @see RouteOptions#networkInterfaceId(String)
+ */
+ public String getNetworkInterfaceId() {
+ return getFirstFormOrNull("NetworkInterfaceId");
+ }
+
+ /**
+ * The ID of a NAT instance in your VPC. The operation fails if you specify an instance ID unless
+ * exactly one network interface is attached.
+ */
+ public RouteOptions instanceId(String instanceId) {
+ formParameters.put("InstanceId", checkNotNull(instanceId, "instanceId"));
+ return this;
+ }
+
+ /**
+ * @see RouteOptions#instanceId(String)
+ */
+ public String getInstanceId() {
+ return getFirstFormOrNull("InstanceId");
+ }
+
+ /**
+ * The ID of a VPC peering connection.
+ */
+ public RouteOptions vpcPeeringConnectionId(String vpcPeeringConnectionId) {
+ formParameters.put("VpcPeeringConnectionId", checkNotNull(vpcPeeringConnectionId, "vpcPeeringConnectionId"));
+ return this;
+ }
+
+ /**
+ * @see RouteOptions#vpcPeeringConnectionId(String)
+ */
+ public String getVpcPeeringConnectionId() {
+ return getFirstFormOrNull("VpcPeeringConnectionId");
+ }
+
+
+ public static class Builder {
+ /**
+ * @see RouteOptions#dryRun()
+ */
+ public static RouteOptions dryRun() {
+ RouteOptions options = new RouteOptions();
+ return options.dryRun();
+ }
+
+ /**
+ * @see RouteOptions#destinationCidrBlock(java.lang.String)
+ */
+ public static RouteOptions destinationCidrBlock(String destinationCidrBlock) {
+ RouteOptions options = new RouteOptions();
+ return options.destinationCidrBlock(destinationCidrBlock);
+ }
+
+ /**
+ * @see RouteOptions#destinationIpv6CidrBlock(java.lang.String)
+ */
+ public static RouteOptions destinationIpv6CidrBlock(String destinationIpv6CidrBlock) {
+ RouteOptions options = new RouteOptions();
+ return options.destinationIpv6CidrBlock(destinationIpv6CidrBlock);
+ }
+
+ /**
+ * @see RouteOptions#gatewayId(java.lang.String)
+ */
+ public static RouteOptions gatewayId(String gatewayId) {
+ RouteOptions options = new RouteOptions();
+ return options.gatewayId(gatewayId);
+ }
+
+ /**
+ * @see RouteOptions#egressOnlyInternetGatewayId(java.lang.String)
+ */
+ public static RouteOptions egressOnlyInternetGatewayId(String egressOnlyInternetGatewayId) {
+ RouteOptions options = new RouteOptions();
+ return options.egressOnlyInternetGatewayId(egressOnlyInternetGatewayId);
+ }
+
+ /**
+ * @see RouteOptions#natGatewayId(String)
+ */
+ public static RouteOptions natGatewayId(String natGatewayId) {
+ RouteOptions options = new RouteOptions();
+ return options.natGatewayId(natGatewayId);
+ }
+
+ /**
+ * @see RouteOptions#networkInterfaceId(String)
+ */
+ public static RouteOptions networkInterfaceId(String networkInterfaceId) {
+ RouteOptions options = new RouteOptions();
+ return options.networkInterfaceId(networkInterfaceId);
+ }
+
+ /**
+ * @see RouteOptions#vpcPeeringConnectionId(String)
+ */
+ public static RouteOptions vpcPeeringConnectionId(String vpcPeeringConnectionId) {
+ RouteOptions options = new RouteOptions();
+ return options.vpcPeeringConnectionId(vpcPeeringConnectionId);
+ }
+
+ /**
+ * @see RouteOptions#instanceId(String)
+ */
+ public static RouteOptions instanceId(String instanceId) {
+ RouteOptions options = new RouteOptions();
+ return options.instanceId(instanceId);
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/RouteTableOptions.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/RouteTableOptions.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/RouteTableOptions.java
new file mode 100644
index 0000000..4960d4e
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/options/RouteTableOptions.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.options;
+
+import static com.google.common.base.Preconditions.checkNotNull;
+
+import org.jclouds.ec2.options.internal.BaseEC2RequestOptions;
+
+/**
+ * Contains options supported in the Form API for the RouteTable operations. <h2>
+ * Usage</h2> The recommended way to instantiate such an object is to statically import
+ * RouteTableOptions.Builder.* and invoke a static creation method followed by an instance mutator
+ * (if needed):
+ * <p/>
+ * <code>
+ * import static org.jclouds.ec2.options.RouteTableOptions.Builder.*
+ * <p/>
+ * EC2Api connection = // get connection
+ * RouteTable table = connection.getRouteTableApi().get().createRouteTable(vpcId, dryRun());
+ * <code>
+ *
+ * @see <a
+ * href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_CreateRouteTable.html"
+ * />
+ */
+public class RouteTableOptions extends BaseEC2RequestOptions {
+
+ /**
+ * Checks whether you have the required permissions for the action, without actually making the request,
+ * and provides an error response.
+ */
+ public RouteTableOptions dryRun() {
+ formParameters.put("DryRun", "true");
+ return this;
+ }
+
+ public boolean isDryRun() {
+ return getFirstFormOrNull("DryRun") != null;
+ }
+
+ /**
+ * The IPv4 CIDR address block used for the destination match.
+ * Routing decisions are based on the most specific match.
+ */
+ public RouteTableOptions destinationCidrBlock(String destinationCidrBlock) {
+ formParameters.put("DestinationCidrBlock", checkNotNull(destinationCidrBlock, "destinationCidrBlock"));
+ return this;
+ }
+
+
+ public static class Builder {
+ /**
+ * @see RouteTableOptions#dryRun()
+ */
+ public static RouteTableOptions dryRun() {
+ RouteTableOptions options = new RouteTableOptions();
+ return options.dryRun();
+ }
+
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AssociateRouteTableResponseHandler.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AssociateRouteTableResponseHandler.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AssociateRouteTableResponseHandler.java
new file mode 100644
index 0000000..fa104fb
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/AssociateRouteTableResponseHandler.java
@@ -0,0 +1,40 @@
+/*
+ * 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 org.jclouds.http.functions.ParseSax;
+
+public class AssociateRouteTableResponseHandler extends ParseSax.HandlerWithResult<String> {
+
+ private StringBuilder currentText = new StringBuilder();
+ private String value;
+
+ public String getResult() {
+ return value;
+ }
+
+ public void endElement(String uri, String name, String qName) {
+ if (qName.equalsIgnoreCase("associationId")) {
+ this.value = currentText.toString().trim();
+ }
+ currentText.setLength(0);
+ }
+
+ public void characters(char[] ch, int start, int length) {
+ currentText.append(ch, start, length);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/CreateRouteTableResponseHandler.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/CreateRouteTableResponseHandler.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/CreateRouteTableResponseHandler.java
new file mode 100644
index 0000000..eacb4f2
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/CreateRouteTableResponseHandler.java
@@ -0,0 +1,55 @@
+/*
+ * 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 javax.inject.Inject;
+
+import org.jclouds.aws.ec2.domain.RouteTable;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.Attributes;
+
+/**
+ * @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RouteTable.html">RouteTable docs</a>
+ */
+public class CreateRouteTableResponseHandler extends ParseSax.HandlerForGeneratedRequestWithResult<RouteTable> {
+
+ private RouteTableHandler routeTableHandler;
+
+ @Inject
+ CreateRouteTableResponseHandler(RouteTableHandler routeTableHandler) {
+ this.routeTableHandler = routeTableHandler;
+ }
+
+ public RouteTable getResult() {
+ return routeTableHandler.getResult();
+ }
+
+ @Override
+ public void startElement(String uri, String name, String qName, Attributes attrs) {
+ routeTableHandler.startElement(uri, name, qName, attrs);
+ }
+
+ @Override
+ public void endElement(String uri, String name, String qName) {
+ routeTableHandler.endElement(uri, name, qName);
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) {
+ routeTableHandler.characters(ch, start, length);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/DescribeRouteTablesResponseHandler.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/DescribeRouteTablesResponseHandler.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/DescribeRouteTablesResponseHandler.java
new file mode 100644
index 0000000..0146f67
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/DescribeRouteTablesResponseHandler.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.equalsOrSuffix;
+
+import java.util.List;
+
+import javax.inject.Inject;
+
+import org.jclouds.aws.ec2.domain.RouteTable;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.Attributes;
+
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.Lists;
+
+/**
+ * @see <a href="http://docs.aws.amazon.com/AWSEC2/latest/APIReference/API_RouteTable.html">RouteTable docs</a>
+ */
+public class DescribeRouteTablesResponseHandler
+ extends ParseSax.HandlerForGeneratedRequestWithResult<FluentIterable<RouteTable>> {
+
+ private RouteTableHandler routeTableHandler;
+ private List<RouteTable> tables = Lists.newArrayList();
+
+ private boolean inRouteSet;
+ private boolean inAssociationSet;
+ private boolean inPropagatingVgwSet;
+ private boolean inTagSet;
+
+ @Inject
+ DescribeRouteTablesResponseHandler(RouteTableHandler routeTableHandler) {
+ this.routeTableHandler = routeTableHandler;
+ }
+
+ public FluentIterable<RouteTable> getResult() {
+ try {
+ return FluentIterable.from(tables);
+ } finally {
+ tables = Lists.newArrayList();
+ }
+ }
+
+ @Override
+ public void startElement(String uri, String name, String qName, Attributes attrs) {
+ if (equalsOrSuffix(qName, "routeSet")) {
+ inRouteSet = true;
+ } else if (equalsOrSuffix(qName, "associationSet")) {
+ inAssociationSet = true;
+ } else if (equalsOrSuffix(qName, "tagSet")) {
+ inTagSet = true;
+ } else if (equalsOrSuffix(qName, "propagatingVgwSet")) {
+ inPropagatingVgwSet = true;
+ }
+ routeTableHandler.startElement(uri, name, qName, attrs);
+ }
+
+ private boolean inSubElement() {
+ return inRouteSet || inTagSet || inAssociationSet || inPropagatingVgwSet;
+ }
+
+ @Override
+ public void endElement(String uri, String name, String qName) {
+ if (equalsOrSuffix(qName, "routeSet")) {
+ inRouteSet = false;
+ routeTableHandler.endElement(uri, name, qName);
+ } else if (equalsOrSuffix(qName, "associationSet")) {
+ inAssociationSet = false;
+ routeTableHandler.endElement(uri, name, qName);
+ } else if (equalsOrSuffix(qName, "tagSet")) {
+ inTagSet = false;
+ routeTableHandler.endElement(uri, name, qName);
+ } else if (equalsOrSuffix(qName, "item") && !inSubElement()) {
+ final RouteTable table = routeTableHandler.getResult();
+ tables.add(table);
+ } else {
+ routeTableHandler.endElement(uri, name, qName);
+ }
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) {
+ routeTableHandler.characters(ch, start, length);
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteHandler.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteHandler.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteHandler.java
new file mode 100644
index 0000000..2956cff
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteHandler.java
@@ -0,0 +1,48 @@
+/*
+ * 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 org.jclouds.aws.ec2.domain.Route;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.Attributes;
+
+public class RouteHandler extends ParseSax.HandlerForGeneratedRequestWithResult<Route> {
+
+ private StringBuilder currentText = new StringBuilder();
+
+ Route.Builder builder = Route.builder();
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) {
+
+ }
+
+ @Override
+ public void endElement(String uri, String localName, String qName) {
+
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) {
+ currentText.append(ch, start, length);
+ }
+
+ @Override
+ public Route getResult() {
+ return builder.build();
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteSetHandler.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteSetHandler.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteSetHandler.java
new file mode 100644
index 0000000..d5326c4
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteSetHandler.java
@@ -0,0 +1,77 @@
+/*
+ * 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 java.util.List;
+
+import org.jclouds.aws.ec2.domain.Route;
+import org.jclouds.aws.ec2.domain.Route.RouteState;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.Attributes;
+
+import com.google.common.collect.Lists;
+
+public class RouteSetHandler extends ParseSax.HandlerForGeneratedRequestWithResult<List<Route>> {
+
+ private StringBuilder currentText = new StringBuilder();
+ List<Route> results = Lists.newArrayList();
+
+ Route.Builder builder;
+
+ @Override
+ public List<Route> getResult() {
+ try {
+ return results;
+ } finally {
+ results = Lists.newArrayList();
+ }
+ }
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) {
+ currentText.setLength(0);
+ if (qName.equalsIgnoreCase("item")) {
+ builder = Route.builder();
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String name, String qName) {
+ if (builder == null) {
+ return;
+ }
+ if (equalsOrSuffix(qName, "item")) {
+ results.add(builder.build());
+ builder = null;
+ } else if (equalsOrSuffix(qName, "destinationCidrBlock")) {
+ builder.destinationCidrBlock(currentText.toString());
+ } else if (equalsOrSuffix(qName, "gatewayId")) {
+ builder.gatewayId(currentText.toString());
+ } else if (equalsOrSuffix(qName, "state")) {
+ builder.state(RouteState.fromValue(currentText.toString()));
+ } else if (equalsOrSuffix(qName, "origin")) {
+ builder.origin(currentText.toString());
+ }
+ }
+
+ @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/b3d21f96/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteTableAssociationSetHandler.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteTableAssociationSetHandler.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteTableAssociationSetHandler.java
new file mode 100644
index 0000000..4a355d7
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteTableAssociationSetHandler.java
@@ -0,0 +1,79 @@
+/*
+ * 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 java.util.List;
+
+import org.jclouds.aws.ec2.domain.RouteTableAssociation;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.Attributes;
+
+import com.google.common.collect.Lists;
+
+public class RouteTableAssociationSetHandler extends
+ ParseSax.HandlerForGeneratedRequestWithResult<List<RouteTableAssociation>> {
+
+ private StringBuilder currentText = new StringBuilder();
+ RouteTableAssociation.Builder builder;
+
+ List<RouteTableAssociation> results = Lists.newArrayList();
+
+ @Override
+ public List<RouteTableAssociation> getResult() {
+ try {
+ return results;
+ } finally {
+ results = Lists.newArrayList();
+ }
+ }
+
+
+ @Override
+ public void startElement(String uri, String localName, String qName, Attributes attributes) {
+ currentText.setLength(0);
+ if (qName.equalsIgnoreCase("item")) {
+ builder = RouteTableAssociation.builder();
+ }
+ }
+
+ @Override
+ public void endElement(String uri, String name, String qName) {
+ if (builder == null) {
+ return;
+ }
+ if (equalsOrSuffix(qName, "item")) {
+ results.add(builder.build());
+ builder = null;
+ } else if (equalsOrSuffix(qName, "routeTableAssociationId")) {
+ builder.id(currentText.toString());
+ } else if (equalsOrSuffix(qName, "routeTableId")) {
+ builder.routeTableId(currentText.toString());
+ } else if (equalsOrSuffix(qName, "subnetId")) {
+ builder.subnetId(currentText.toString());
+ } else if (equalsOrSuffix(qName, "main")) {
+ builder.main(Boolean.valueOf(currentText.toString()));
+ }
+ }
+
+ @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/b3d21f96/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteTableHandler.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteTableHandler.java b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteTableHandler.java
new file mode 100644
index 0000000..733815d
--- /dev/null
+++ b/providers/aws-ec2/src/main/java/org/jclouds/aws/ec2/xml/RouteTableHandler.java
@@ -0,0 +1,116 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.xml;
+
+import static org.jclouds.util.SaxUtils.equalsOrSuffix;
+
+import javax.inject.Inject;
+
+import org.jclouds.aws.ec2.domain.RouteTable;
+import org.jclouds.ec2.xml.TagSetHandler;
+import org.jclouds.http.functions.ParseSax;
+import org.xml.sax.Attributes;
+
+public class RouteTableHandler extends ParseSax.HandlerWithResult<RouteTable> {
+
+ RouteTable.Builder builder = RouteTable.builder();
+ private StringBuilder currentText = new StringBuilder();
+ private RouteSetHandler routeSetHandler;
+ private RouteTableAssociationSetHandler routeTableAssociationSetHandler;
+ private TagSetHandler tagSetHandler;
+ boolean inRouteSet;
+ boolean inRouteTableAssociationSet;
+ boolean inTagSet;
+ // TODO propagatingVgwSetHandler
+
+
+ @Inject
+ RouteTableHandler(TagSetHandler tagSetHandler, RouteSetHandler routeSetHandler,
+ RouteTableAssociationSetHandler routeTableAssociationSetHandler) {
+ this.tagSetHandler = tagSetHandler;
+ this.routeSetHandler = routeSetHandler;
+ this.routeTableAssociationSetHandler = routeTableAssociationSetHandler;
+ }
+
+ @Override
+ public RouteTable getResult() {
+ try {
+ return builder.build();
+ } finally {
+ builder = RouteTable.builder();
+ }
+ }
+
+
+ @Override
+ public void startElement(String uri, String name, String qName, Attributes attrs) {
+ currentText.setLength(0);
+ if (equalsOrSuffix(qName, "routeSet")) {
+ inRouteSet = true;
+ } else if (equalsOrSuffix(qName, "associationSet")) {
+ inRouteTableAssociationSet = true;
+ } else if (equalsOrSuffix(qName, "tagSet")) {
+ inTagSet = true;
+ }
+
+ if (inTagSet) {
+ tagSetHandler.startElement(uri, name, qName, attrs);
+ } else if (inRouteTableAssociationSet) {
+ routeTableAssociationSetHandler.startElement(uri, name, qName, attrs);
+ } else if (inRouteSet) {
+ routeSetHandler.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, "routeSet")) {
+ inRouteSet = false;
+ builder.routeSet(routeSetHandler.getResult());
+ } else if (equalsOrSuffix(qName, "associationSet")) {
+ inRouteTableAssociationSet = false;
+ builder.associationSet(routeTableAssociationSetHandler.getResult());
+ } else if (inRouteSet) {
+ routeSetHandler.endElement(uri, name, qName);
+ } else if (inRouteTableAssociationSet) {
+ routeTableAssociationSetHandler.endElement(uri, name, qName);
+ } else if (inTagSet) {
+ tagSetHandler.endElement(uri, name, qName);
+ } else if (equalsOrSuffix(qName, "vpcId")) {
+ builder.vpcId(currentText.toString());
+ } else if (equalsOrSuffix(qName, "routeTableId")) {
+ builder.id(currentText.toString());
+ }
+ currentText.setLength(0);
+ }
+
+ @Override
+ public void characters(char[] ch, int start, int length) {
+ if (inRouteSet) {
+ routeSetHandler.characters(ch, start, length);
+ } else if (inRouteTableAssociationSet) {
+ routeTableAssociationSetHandler.characters(ch, start, length);
+ } else if (inTagSet) {
+ tagSetHandler.characters(ch, start, length);
+ } else {
+ currentText.append(ch, start, length);
+ }
+ }
+}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/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
index c44acf4..e2b2d5f 100644
--- 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
@@ -36,6 +36,7 @@ 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.Assert;
import org.testng.annotations.BeforeClass;
import org.testng.annotations.Test;
@@ -49,7 +50,9 @@ import com.google.common.collect.ImmutableMap;
@Test(groups = "live")
public class InternetGatewayApiLiveTest extends BaseApiLiveTest<AWSEC2Api> {
- private static final String TEST_REGION = "eu-west-1";
+ // Define -Djclouds.test.region=whatever to test in your preferred region;
+ // defaults to null, jclouds will pick the provider's default region
+ private static final String TEST_REGION = System.getProperty("jclouds.test.region");
public InternetGatewayApiLiveTest() {
provider = "aws-ec2";
@@ -60,8 +63,8 @@ public class InternetGatewayApiLiveTest extends BaseApiLiveTest<AWSEC2Api> {
private VPCApi vpcClient;
private VPC vpc;
-
private InternetGateway gateway;
+
private String simpleName = InternetGatewayApiLiveTest.class.getSimpleName() + new Random().nextInt(10000);
@BeforeClass(groups = {"integration", "live"})
@@ -149,6 +152,7 @@ public class InternetGatewayApiLiveTest extends BaseApiLiveTest<AWSEC2Api> {
try {
gwClient.createInternetGateway(TEST_REGION, dryRun());
+ Assert.fail("Operation completed when exception was expected");
} catch (AWSResponseException e) {
assertEquals(e.getError().getCode(), "DryRunOperation", "Expected DryRunOperation but got " + e.getError());
}
http://git-wip-us.apache.org/repos/asf/jclouds/blob/b3d21f96/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
index 8c65702..ef39e93 100644
--- 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
@@ -16,6 +16,7 @@
*/
package org.jclouds.aws.ec2.features;
+import static javax.ws.rs.core.Response.Status.PRECONDITION_FAILED;
import static org.jclouds.aws.ec2.options.InternetGatewayOptions.Builder.dryRun;
import static org.testng.Assert.assertEquals;
import static org.testng.Assert.assertFalse;
@@ -29,6 +30,7 @@ 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.Assert;
import org.testng.annotations.Test;
import com.google.common.collect.FluentIterable;
@@ -164,7 +166,6 @@ public class InternetGatewayApiMockTest extends BaseAWSEC2ApiMockTest {
assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
assertPosted(DEFAULT_REGION, "Action=DescribeInternetGateways");
-
}
public void deleteInternetGateway() throws Exception {
@@ -193,18 +194,19 @@ public class InternetGatewayApiMockTest extends BaseAWSEC2ApiMockTest {
public void testWithOptions() throws Exception {
enqueueRegions(DEFAULT_REGION);
- enqueueXml(DEFAULT_REGION, "/create_internet_gateway_dry_run.xml");
+ enqueueXml(PRECONDITION_FAILED, DEFAULT_REGION, "/dry_run.xml");
try {
gatewayApi().createInternetGateway(DEFAULT_REGION, dryRun());
+ Assert.fail("Expected 'DryRunOperation' exception was not thrown");
} 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/b3d21f96/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/RouteTableApiLiveTest.java
----------------------------------------------------------------------
diff --git a/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/RouteTableApiLiveTest.java b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/RouteTableApiLiveTest.java
new file mode 100644
index 0000000..3c57984
--- /dev/null
+++ b/providers/aws-ec2/src/test/java/org/jclouds/aws/ec2/features/RouteTableApiLiveTest.java
@@ -0,0 +1,293 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements. See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.jclouds.aws.ec2.features;
+
+import static java.util.logging.Logger.getAnonymousLogger;
+import static org.jclouds.aws.ec2.options.RouteOptions.Builder.destinationCidrBlock;
+import static org.jclouds.aws.ec2.options.RouteOptions.Builder.gatewayId;
+import static org.jclouds.aws.ec2.options.RouteTableOptions.Builder.dryRun;
+import static org.testng.Assert.assertEquals;
+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.Route;
+import org.jclouds.aws.ec2.domain.RouteTable;
+import org.jclouds.aws.ec2.domain.VPC;
+import org.jclouds.aws.ec2.options.InternetGatewayOptions;
+import org.jclouds.ec2.domain.Subnet;
+import org.jclouds.ec2.features.TagApi;
+import org.testng.Assert;
+import org.testng.annotations.AfterClass;
+import org.testng.annotations.BeforeClass;
+import org.testng.annotations.Test;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Predicate;
+import com.google.common.collect.FluentIterable;
+import com.google.common.collect.ImmutableList;
+import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.Iterables;
+
+/**
+ * Tests behavior of {@link RouteTableApi}
+ */
+@Test(groups = "live")
+public class RouteTableApiLiveTest extends BaseApiLiveTest<AWSEC2Api> {
+
+ // Define -Djclouds.test.region=whatever to test in your preferred region;
+ // defaults to null, jclouds will pick the provider's default region
+ public static final String TEST_REGION = System.getProperty("jclouds.test.region");
+ public static final String TEST_DESTINATION_CIDR = "172.18.19.0/24";
+ public static final String VPC_CIDR = "10.20.30.0/24";
+ public static final String VPC_SUBNET = "10.20.30.0/28";
+
+ public RouteTableApiLiveTest() {
+ provider = "aws-ec2";
+ }
+
+ private RouteTableApi routeTableApi;
+ private InternetGatewayApi gwApi;
+ private TagApi tagger;
+ private VPCApi vpcClient;
+ private AWSSubnetApi subnetApi;
+
+ private VPC vpc;
+ private InternetGateway gateway;
+
+ private RouteTable routeTable;
+ private String associationId;
+ private Subnet subnet;
+
+ private String simpleName = RouteTableApiLiveTest.class.getSimpleName() + new Random().nextInt(10000);
+
+ @BeforeClass(groups = {"integration", "live"})
+ public void setupContext() {
+ routeTableApi = api.getRouteTableApiForRegion(TEST_REGION).get();
+ vpcClient = api.getVPCApi().get();
+ tagger = api.getTagApiForRegion(TEST_REGION).get();
+ gwApi = api.getInternetGatewayApiForRegion(TEST_REGION).get();
+ subnetApi = api.getAWSSubnetApi().get();
+ }
+
+ @Test
+ public void testDescribe() {
+ vpc = vpcClient.createVpc(TEST_REGION, VPC_CIDR);
+ assertNotNull(vpc, "Failed to create VPC to test attachments");
+ tagger.applyToResources(ImmutableMap.of("Name", simpleName), ImmutableList.of(vpc.id()));
+
+ // When you create a VPC it automatically gets a route table whose single route has the CIDR of the VPC
+ // and whose "target" is "local".
+ final FluentIterable<RouteTable> routeTables = routeTableApi.describeRouteTables(TEST_REGION);
+ assertNotNull(routeTables, "Failed to return list of RouteTables");
+ Optional<RouteTable> vpcRT = Iterables.tryFind(routeTables, new Predicate<RouteTable>() {
+ @Override public boolean apply(RouteTable input) {
+ return vpc.id().equals(input.vpcId());
+ }
+ });
+ assertTrue(vpcRT.isPresent(), "Could not find VPC " + vpc.id() + " in described route tables");
+ RouteTable rt = vpcRT.get();
+ assertEquals(rt.associationSet().size(), 1,
+ "Route for test VPC has wrong number of associations, should be 1: " + rt.associationSet());
+ assertTrue(rt.associationSet().get(0).main(), "Association for route " + rt.id() + "should be 'main'");
+ assertEquals(rt.routeSet().size(), 1,
+ "Wrong number of routes in default route table for VPC " + vpc.id());
+ final String defaultCidr = rt.routeSet().get(0).destinationCidrBlock();
+ assertEquals(defaultCidr, vpc.cidrBlock(),
+ "Route in default route table does not match CIDR of VPC, " + defaultCidr + " should be " + vpc.cidrBlock());
+
+ }
+
+ @Test(dependsOnMethods = "testDescribe")
+ public void testCreate() {
+
+ // When you create a new route table for the VPC it automatically gets a route to match the VPC CIDR
+ routeTable = routeTableApi.createRouteTable(TEST_REGION, vpc.id());
+ assertNotNull(routeTable, "Gateway was not successfully created");
+
+ assertEquals(routeTable.vpcId(), vpc.id(),
+ "RouteTable VPC ID " + routeTable.vpcId() + " does not match VPC's ID " + vpc.id());
+ final List<Route> routes = routeTable.routeSet();
+ assertEquals(routes.size(), 1, "Unexpected number of routes in new table: " + routes.size());
+ assertEquals(routes.get(0).destinationCidrBlock(), vpc.cidrBlock(),
+ "CIDR for route table " + routes.get(0).destinationCidrBlock() +
+ " does not match VPC CIDR" + vpc.cidrBlock());
+ assertEquals(routes.get(0).state(), Route.RouteState.ACTIVE, "Route should be active");
+ assertEquals(routeTable.tags().size(), 0, "Freshly created routeTable has tags");
+
+ tagger.applyToResources(ImmutableMap.of("Name", simpleName), ImmutableList.of(routeTable.id()));
+ getAnonymousLogger().info("Created routeTable " + simpleName + " with id " + routeTable.id());
+ }
+
+ @Test(dependsOnMethods = "testDescribe")
+ public void testCreateWithOptions() {
+
+ try {
+ routeTableApi.createRouteTable(TEST_REGION, vpc.id(), dryRun());
+ Assert.fail("Expected 'DryRunOperation' exception was not thrown");
+ } catch (AWSResponseException e) {
+ assertDryRun(e);
+ }
+ }
+
+ @Test(dependsOnMethods = "testCreate")
+ public void testAssociateWithOptions() {
+ subnet = subnetApi.createSubnetInRegion(TEST_REGION, vpc.id(), VPC_SUBNET);
+ assertNotNull(subnet, "Failed to create subnet in " + vpc.id());
+
+ try {
+ routeTableApi.associateRouteTable(TEST_REGION, routeTable.id(), subnet.getSubnetId(), dryRun());
+ Assert.fail("Expected 'DryRunOperation' exception was not thrown");
+ } catch (AWSResponseException e) {
+ assertDryRun(e);
+ }
+ }
+
+ @Test(dependsOnMethods = "testAssociateWithOptions")
+ public void testAssociate() {
+ associationId = routeTableApi.associateRouteTable(TEST_REGION, routeTable.id(), subnet.getSubnetId());
+ assertNotNull(associationId,
+ "Failed to obtain association id for " + routeTable.id() + " and " + subnet.getSubnetId());
+
+ routeTable = routeTableApi.describeRouteTables(TEST_REGION, routeTable.id()).toList().get(0);
+ assertEquals(routeTable.associationSet().size(), 1,
+ "Could not find expected association in routeTable " + routeTable.id());
+ }
+
+ @Test(dependsOnMethods = "testAssociate")
+ public void testDisassociateWithOptions() {
+ try {
+ routeTableApi.disassociateRouteTable(TEST_REGION, associationId, dryRun());
+ Assert.fail("Expected 'DryRunOperation' exception was not thrown");
+ } catch (AWSResponseException e) {
+ assertDryRun(e);
+ }
+ }
+
+ @Test(dependsOnMethods = "testDisassociateWithOptions")
+ public void testDisassociate() {
+ final boolean result = routeTableApi.disassociateRouteTable(TEST_REGION, associationId);
+ assertTrue(result, "Failed to disassociate " + associationId + " from " + routeTable.id());
+
+ routeTable = routeTableApi.describeRouteTables(TEST_REGION, routeTable.id()).toList().get(0);
+ assertEquals(routeTable.associationSet().size(), 0,
+ "Found associations where none should exist in " + routeTable.id() + ": " + routeTable.associationSet());
+
+ subnetApi.deleteSubnetInRegion(TEST_REGION, subnet.getSubnetId());
+ }
+
+ @Test(dependsOnMethods = "testCreate")
+ public void testCreateRoute() {
+
+ // If you attach an Internet Gateway, Network Interface, or Virtual Private Gateway to the VPC
+ // you can then add a route through it to the route table. Issue a CreateRoute request specifying
+ // the gateway (or network interface id etc.) to route through, and supplying the CIDR range that should
+ // be routed through it. This can be any CIDR.
+
+ gateway = gwApi.createInternetGateway(TEST_REGION, InternetGatewayOptions.NONE);
+ assertNotNull(gateway, "Gateway was not successfully created");
+
+ final Boolean attached = gwApi.attachInternetGateway(TEST_REGION, gateway.id(), vpc.id());
+ assertTrue(attached, "Gateway " + gateway.id() + " failed to attach to VPC " + vpc.id());
+
+ final boolean created = routeTableApi.createRoute(TEST_REGION, routeTable.id(),
+ gatewayId(gateway.id())
+ .destinationCidrBlock(TEST_DESTINATION_CIDR));
+ assertTrue(created, "Failed to add route to table " + routeTable.id());
+
+ final ImmutableList<RouteTable> routeTables =
+ routeTableApi.describeRouteTables(TEST_REGION, routeTable.id()).toList();
+ assertEquals(routeTables.size(), 1, "Could not find existing route table " + routeTable.id());
+ Optional<Route> optRoute = Iterables.tryFind(routeTables.get(0).routeSet(), new Predicate<Route>() {
+ @Override
+ public boolean apply(Route route) {
+ return route.gatewayId().equals(gateway.id());
+ }
+ });
+ assertTrue(optRoute.isPresent(), "Could not find route added to gateway " + gateway.id());
+ Route route = optRoute.get();
+ assertEquals(route.destinationCidrBlock(), TEST_DESTINATION_CIDR,
+ "CIDR routed through " + gateway.id() + " does not match specification " + TEST_DESTINATION_CIDR);
+ }
+
+ @Test(dependsOnMethods = "testCreateRoute")
+ public void testDeleteRoute() {
+ final boolean deleted =
+ routeTableApi.deleteRoute(TEST_REGION, routeTable.id(), destinationCidrBlock(TEST_DESTINATION_CIDR));
+ assertTrue(deleted, "Failed to delete " + TEST_DESTINATION_CIDR + " route from route table " + routeTable.id());
+
+ // clean up the test gateway
+ final Boolean cleaned = gwApi.detachInternetGateway(TEST_REGION, gateway.id(), vpc.id());
+ assertTrue(cleaned, "Failed to delete gateway " + gateway.id());
+
+ final boolean gatewayDeleted = gwApi.deleteInternetGateway(TEST_REGION, gateway.id());
+ assertTrue(gatewayDeleted, "Failed to delete test gateway " + gateway.id());
+ }
+
+ @Test(enabled = false /* dependsOnMethods = "testCreateRoute" */)
+ public void testReplaceRoute() {
+ // TODO:
+ // At present there is support for creating internet gateways and attaching them to VPCs.
+ // However, you can't attach two internet gateways to the same VPC, so the replaceRoute test must replace
+ // the internet gateway target with one of an virtual private gateway, NAT instance,
+ // NAT gateway, VPC peering connection, network interface, or egress-only Internet gateway.
+ // Add this test when e.g. NATGatewayApi is added.
+ }
+
+ @Test(dependsOnMethods = "testDeleteRoute")
+ public void testDeleteRouteTableWithOptions() {
+ try {
+ routeTableApi.deleteRouteTable(TEST_REGION, routeTable.id(), dryRun());
+ Assert.fail("Expected 'DryRunOperation' exception was not thrown");
+ } catch (AWSResponseException e) {
+ assertDryRun(e);
+ }
+ }
+
+ @Test(dependsOnMethods = "testDeleteRouteTableWithOptions")
+ public void testDeleteRouteTable() {
+
+ final ImmutableList<RouteTable> before =
+ routeTableApi.describeRouteTables(TEST_REGION, routeTable.id()).toList();
+ assertEquals(before.size(), 1, "Unexpected response to describe of " + routeTable.id() + ": " + before);
+ assertEquals(before.get(0).id(), routeTable.id(), "Wrong table returned for " + routeTable.id() + ": " + before);
+
+ final boolean deleted = routeTableApi.deleteRouteTable(TEST_REGION, routeTable.id());
+ assertTrue(deleted, "Failed to delete route table " + routeTable.id());
+
+ final ImmutableList<RouteTable> after = routeTableApi.describeRouteTables(TEST_REGION, routeTable.id()).toList();
+ assertEquals(after.size(), 0, "Unexpected response to describe after deleting " + routeTable.id() + ": " + after);
+ }
+
+ @AfterClass(alwaysRun = true)
+ public void cleanup() {
+ if (vpc != null) {
+ assertTrue(vpcClient.deleteVpc(TEST_REGION, vpc.id()));
+ }
+ }
+
+ private void assertDryRun(AWSResponseException e) {
+ assertEquals(e.getError().getCode(), "DryRunOperation", "Expected DryRunOperation but got " + e.getError());
+ }
+
+}