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:30 UTC

[3/4] jclouds git commit: Add ModifySubnetAttribute

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;
    }
 }