JCLOUDS-1114: Adding support for "Placement.Tenancy" and "Placement.HostId" AWS EC2 parameters

This commit is contained in:
Sergey Torgashov 2016-05-17 17:51:28 +03:00 committed by Ignasi Barrera
parent c96cfb6176
commit ccd1ef2b4d
8 changed files with 260 additions and 10 deletions

View File

@ -28,6 +28,7 @@ import java.util.Map;
import java.util.Set;
import org.jclouds.aws.ec2.options.RequestSpotInstancesOptions;
import org.jclouds.aws.ec2.options.Tenancy;
import org.jclouds.compute.options.TemplateOptions;
import org.jclouds.domain.LoginCredentials;
import org.jclouds.ec2.compute.options.EC2TemplateOptions;
@ -89,6 +90,10 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
eTo.spotOptions(getSpotOptions());
if (getPrivateIpAddress() != null)
eTo.privateIpAddress(getPrivateIpAddress());
if (getTenancy() != null)
eTo.tenancy(getTenancy());
if (getDedicatedHostId() != null)
eTo.dedicatedHostId(getDedicatedHostId());
}
}
@ -102,6 +107,8 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
private String iamInstanceProfileArn;
private String iamInstanceProfileName;
private String privateIpAddress;
private Tenancy tenancy;
private String dedicatedHostId;
@Override
public boolean equals(Object o) {
@ -116,13 +123,15 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
&& equal(this.spotPrice, that.spotPrice) && equal(this.spotOptions, that.spotOptions)
&& equal(this.groupIds, that.groupIds) && equal(this.iamInstanceProfileArn, that.iamInstanceProfileArn)
&& equal(this.iamInstanceProfileName, that.iamInstanceProfileName)
&& equal(this.privateIpAddress, that.privateIpAddress);
&& equal(this.privateIpAddress, that.privateIpAddress)
&& equal(this.tenancy, that.tenancy) && equal(this.dedicatedHostId, that.dedicatedHostId);
}
@Override
public int hashCode() {
return Objects.hashCode(super.hashCode(), monitoringEnabled, placementGroup, noPlacementGroup, subnetId,
spotPrice, spotOptions, groupIds, iamInstanceProfileArn, iamInstanceProfileName, privateIpAddress);
spotPrice, spotOptions, groupIds, iamInstanceProfileArn, iamInstanceProfileName, privateIpAddress,
tenancy, dedicatedHostId);
}
@Override
@ -142,6 +151,8 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
toString.add("iamInstanceProfileArn", iamInstanceProfileArn);
toString.add("iamInstanceProfileName", iamInstanceProfileName);
toString.add("privateIpAddress", privateIpAddress);
toString.add("tenancy", tenancy);
toString.add("dedicatedHostId", dedicatedHostId);
return toString;
}
@ -207,6 +218,22 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
return this;
}
/**
* Specifies the tenancy used to run instances with
*/
public AWSEC2TemplateOptions tenancy(Tenancy tenancy) {
this.tenancy = checkNotNull(tenancy, "tenancy must be defined");
return this;
}
/**
* Specifies the ID of the dedicated host on which the instance should resist.
*/
public AWSEC2TemplateOptions dedicatedHostId(String hostId) {
this.dedicatedHostId = checkNotNull(emptyToNull(hostId), "hostId must be defined");
return this;
}
/**
* Specifies the maximum spot price to use
*/
@ -462,6 +489,22 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
return options.privateIpAddress(address);
}
/**
* @see AWSEC2TemplateOptions#tenancy
*/
public static AWSEC2TemplateOptions tenancy(Tenancy tenancy) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return options.tenancy(tenancy);
}
/**
* @see AWSEC2TemplateOptions#dedicatedHostId
*/
public static AWSEC2TemplateOptions dedicatedHostId(String hostId) {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
return options.dedicatedHostId(hostId);
}
/**
* @see AWSEC2TemplateOptions#spotPrice
*/
@ -812,4 +855,12 @@ public class AWSEC2TemplateOptions extends EC2TemplateOptions implements Cloneab
public String getPrivateIpAddress() {
return privateIpAddress;
}
public Tenancy getTenancy() {
return tenancy;
}
public String getDedicatedHostId() {
return dedicatedHostId;
}
}

View File

@ -102,6 +102,10 @@ public class CreateKeyPairPlacementAndSecurityGroupsAsNeededAndReturnRunOptions
instanceOptions.withIAMInstanceProfileName(awsTemplateOptions.getIAMInstanceProfileName());
if (awsTemplateOptions.getPrivateIpAddress() != null)
instanceOptions.withPrivateIpAddress(awsTemplateOptions.getPrivateIpAddress());
if (awsTemplateOptions.getTenancy() != null)
instanceOptions.withTenancy(awsTemplateOptions.getTenancy());
if (awsTemplateOptions.getDedicatedHostId() != null)
instanceOptions.withDedicatedHostId(awsTemplateOptions.getDedicatedHostId());
return instanceOptions;
}

View File

@ -60,6 +60,22 @@ public class AWSRunInstancesOptions extends RunInstancesOptions {
return this;
}
/**
* Specifies the tenancy of the instance within which to launch the instance(s).
*/
public AWSRunInstancesOptions withTenancy(Tenancy tenancy) {
formParameters.put("Placement.Tenancy", checkNotNull(tenancy, "tenancy").toString());
return this;
}
/**
* Specifies the ID of the dedicated host on which the instance should resist.
*/
public AWSRunInstancesOptions withDedicatedHostId(String hostId) {
formParameters.put("Placement.HostId", checkNotNull(hostId, "hostId"));
return this;
}
/**
* Enables monitoring for the instance.
*/
@ -142,6 +158,22 @@ public class AWSRunInstancesOptions extends RunInstancesOptions {
return options.inPlacementGroup(placementGroup);
}
/**
* @see AWSRunInstancesOptions#withTenancy(Tenancy)
*/
public static AWSRunInstancesOptions withTenancy(Tenancy tenancy) {
AWSRunInstancesOptions options = new AWSRunInstancesOptions();
return options.withTenancy(tenancy);
}
/**
* @see AWSRunInstancesOptions#withDedicatedHostId(String)
*/
public static AWSRunInstancesOptions withDedicatedHostId(String hostId) {
AWSRunInstancesOptions options = new AWSRunInstancesOptions();
return options.withDedicatedHostId(hostId);
}
/**
* @see AWSRunInstancesOptions#enableMonitoring()
*/

View File

@ -0,0 +1,37 @@
/*
* 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;
/**
* Contains valid values for the 'Placement.Tenancy' parameter in the Form API for the RunInstances operation.
*/
public enum Tenancy {
DEFAULT("default"),
DEDICATED("dedicated"),
HOST("host");
private final String value;
Tenancy(String value) {
this.value = value;
}
@Override
public String toString() {
return value;
}
}

View File

@ -20,6 +20,7 @@ import static org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions.Builder.blockUnt
import static org.testng.Assert.assertEquals;
import org.jclouds.aws.ec2.internal.BaseAWSEC2ApiMockTest;
import org.jclouds.aws.ec2.options.Tenancy;
import org.jclouds.compute.ComputeService;
import org.jclouds.compute.domain.NodeMetadata;
import org.jclouds.compute.domain.Template;
@ -232,6 +233,40 @@ public class AWSEC2ComputeServiceApiMockTest extends BaseAWSEC2ApiMockTest {
assertPosted(DEFAULT_REGION, "Action=CreateTags&Tag.1.Key=Name&Tag.1.Value=test-2baa5550&ResourceId.1=i-2baa5550");
}
public void createNodeWithDedicatedTenancyAndHostId() throws Exception {
enqueueRegions(DEFAULT_REGION);
enqueueXml(DEFAULT_REGION, "/amzn_images.xml");
enqueueXml(DEFAULT_REGION, "/describe_images_cc.xml");
enqueueXml(DEFAULT_REGION, "/availabilityZones.xml");
enqueueXml(DEFAULT_REGION, "/created_securitygroup.xml");
enqueueXml(DEFAULT_REGION, "/new_securitygroup.xml");
enqueueXml(DEFAULT_REGION, "/new_securitygroup.xml");
enqueueXml(DEFAULT_REGION, "/authorize_securitygroup_ingress_response.xml");
enqueueXml(DEFAULT_REGION, "/new_instance.xml");
enqueueXml(DEFAULT_REGION, "/describe_instances_running-1.xml");
enqueueXml(DEFAULT_REGION, "/describe_images.xml");
enqueue(DEFAULT_REGION, new MockResponse()); // create tags
ComputeService computeService = computeService();
NodeMetadata node = Iterables.getOnlyElement(computeService.createNodesInGroup("test", 1,
blockUntilRunning(false).noKeyPair().tenancy(Tenancy.HOST).dedicatedHostId("TestHostId")));
assertEquals(node.getId(), "us-east-1/i-2baa5550");
assertPosted(DEFAULT_REGION, "Action=DescribeRegions");
assertPosted(DEFAULT_REGION, "Action=DescribeImages&Filter.1.Name=owner-id&Filter.1.Value.1=137112412989&Filter.1.Value.2=801119661308&Filter.1.Value.3=063491364108&Filter.1.Value.4=099720109477&Filter.1.Value.5=411009282317&Filter.2.Name=state&Filter.2.Value.1=available&Filter.3.Name=image-type&Filter.3.Value.1=machine");
assertPosted(DEFAULT_REGION, "Action=DescribeImages&Filter.1.Name=virtualization-type&Filter.1.Value.1=hvm&Filter.2.Name=architecture&Filter.2.Value.1=x86_64&Filter.3.Name=owner-id&Filter.3.Value.1=137112412989&Filter.3.Value.2=099720109477&Filter.4.Name=hypervisor&Filter.4.Value.1=xen&Filter.5.Name=state&Filter.5.Value.1=available&Filter.6.Name=image-type&Filter.6.Value.1=machine&Filter.7.Name=root-device-type&Filter.7.Value.1=ebs");
assertPosted(DEFAULT_REGION, "Action=DescribeAvailabilityZones");
assertPosted(DEFAULT_REGION, "Action=CreateSecurityGroup&GroupName=jclouds%23test&GroupDescription=jclouds%23test");
assertPosted(DEFAULT_REGION, "Action=DescribeSecurityGroups&GroupName.1=jclouds%23test");
assertPosted(DEFAULT_REGION, "Action=DescribeSecurityGroups&GroupName.1=jclouds%23test");
assertPosted(DEFAULT_REGION, "Action=AuthorizeSecurityGroupIngress&GroupId=sg-3c6ef654&IpPermissions.0.IpProtocol=tcp&IpPermissions.0.FromPort=22&IpPermissions.0.ToPort=22&IpPermissions.0.IpRanges.0.CidrIp=0.0.0.0/0&IpPermissions.1.IpProtocol=tcp&IpPermissions.1.FromPort=0&IpPermissions.1.ToPort=65535&IpPermissions.1.Groups.0.UserId=993194456877&IpPermissions.1.Groups.0.GroupId=sg-3c6ef654&IpPermissions.2.IpProtocol=udp&IpPermissions.2.FromPort=0&IpPermissions.2.ToPort=65535&IpPermissions.2.Groups.0.UserId=993194456877&IpPermissions.2.Groups.0.GroupId=sg-3c6ef654");
assertPosted(DEFAULT_REGION, "Action=RunInstances&ImageId=ami-8ce4b5c9&MinCount=1&MaxCount=1&InstanceType=" + getDefaultParavirtualInstanceType() + "&SecurityGroupId.1=sg-3c6ef654&UserData=I2Nsb3VkLWNvbmZpZwpyZXBvX3VwZ3JhZGU6IG5vbmUK&Placement.Tenancy=host&Placement.HostId=TestHostId");
assertPosted(DEFAULT_REGION, "Action=DescribeInstances&InstanceId.1=i-2baa5550");
assertPosted(DEFAULT_REGION, "Action=DescribeImages&ImageId.1=ami-aecd60c7");
assertPosted(DEFAULT_REGION, "Action=CreateTags&Tag.1.Key=Name&Tag.1.Value=test-2baa5550&ResourceId.1=i-2baa5550");
}
public void listNodesWhereImageDoesntExist() throws Exception {
enqueueRegions(DEFAULT_REGION);
enqueueXml(DEFAULT_REGION, "/describe_instances_running-1.xml");

View File

@ -18,6 +18,7 @@ package org.jclouds.aws.ec2.compute.options;
import static org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions.Builder.authorizePublicKey;
import static org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions.Builder.blockOnPort;
import static org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions.Builder.dedicatedHostId;
import static org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions.Builder.enableMonitoring;
import static org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions.Builder.iamInstanceProfileArn;
import static org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions.Builder.iamInstanceProfileName;
@ -28,11 +29,13 @@ import static org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions.Builder.noKeyPai
import static org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions.Builder.privateIpAddress;
import static org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions.Builder.securityGroupIds;
import static org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions.Builder.securityGroups;
import static org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions.Builder.tenancy;
import static org.testng.Assert.assertEquals;
import java.io.IOException;
import org.jclouds.aws.ec2.compute.AWSEC2TemplateOptions;
import org.jclouds.aws.ec2.options.Tenancy;
import org.jclouds.compute.options.TemplateOptions;
import org.testng.annotations.Test;
@ -425,4 +428,40 @@ public class AWSEC2TemplateOptionsTest {
public void testPrivateIpAddressNPE() {
privateIpAddress(null);
}
@Test
public void testTenancy() {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
options.tenancy(Tenancy.DEDICATED);
assertEquals(options.getTenancy(), Tenancy.DEDICATED);
}
@Test
public void testTenancyStatic() {
AWSEC2TemplateOptions options = tenancy(Tenancy.HOST);
assertEquals(options.getTenancy(), Tenancy.HOST);
}
@Test(expectedExceptions = NullPointerException.class)
public void testTenancyNPE() {
tenancy(null);
}
@Test
public void testDedicatedHostId() {
AWSEC2TemplateOptions options = new AWSEC2TemplateOptions();
options.dedicatedHostId("hostId-1234");
assertEquals(options.getDedicatedHostId(), "hostId-1234");
}
@Test
public void testDedicatedHostIdStatic() {
AWSEC2TemplateOptions options = dedicatedHostId("hostId-5678");
assertEquals(options.getDedicatedHostId(), "hostId-5678");
}
@Test(expectedExceptions = NullPointerException.class)
public void testDedicatedHostIdStaticNPE() {
dedicatedHostId(null);
}
}

View File

@ -23,6 +23,7 @@ import java.util.Map;
import org.jclouds.Fallbacks.EmptySetOnNotFoundOr404;
import org.jclouds.aws.ec2.options.AWSRunInstancesOptions;
import org.jclouds.aws.ec2.options.Tenancy;
import org.jclouds.aws.ec2.xml.AWSDescribeInstancesResponseHandler;
import org.jclouds.aws.ec2.xml.AWSRunInstancesResponseHandler;
import org.jclouds.ec2.domain.BlockDevice;
@ -121,19 +122,21 @@ public class AWSInstanceApiTest extends BaseAWSEC2ApiTest<AWSInstanceApi> {
String.class, int.class, int.class, RunInstancesOptions[].class);
GeneratedHttpRequest request = processor.createRequest(
method,
Lists.<Object> newArrayList("us-east-1",
"us-east-1a",
"ami-voo",
1,
5,
new AWSRunInstancesOptions().withKernelId("kernelId").enableMonitoring()
.withSecurityGroups("group1", "group2")));
Lists.<Object> newArrayList(
"us-east-1",
"us-east-1a",
"ami-voo",
1,
5,
new AWSRunInstancesOptions().withKernelId("kernelId").enableMonitoring()
.withSecurityGroups("group1", "group2")
.withTenancy(Tenancy.HOST).withDedicatedHostId("hostId")));
assertRequestLineEquals(request, "POST https://ec2.us-east-1.amazonaws.com/ HTTP/1.1");
assertNonPayloadHeadersEqual(request, "Host: ec2.us-east-1.amazonaws.com\n");
assertPayloadEquals(
request,
"Action=RunInstances&ImageId=ami-voo&MinCount=1&MaxCount=5&KernelId=kernelId&Monitoring.Enabled=true&SecurityGroup.1=group1&SecurityGroup.2=group2&Placement.AvailabilityZone=us-east-1a",
"Action=RunInstances&ImageId=ami-voo&MinCount=1&MaxCount=5&KernelId=kernelId&Monitoring.Enabled=true&SecurityGroup.1=group1&SecurityGroup.2=group2&Placement.Tenancy=host&Placement.HostId=hostId&Placement.AvailabilityZone=us-east-1a",
"application/x-www-form-urlencoded", false);
assertResponseParserClassEquals(method, request, ParseSax.class);
assertSaxResponseParserClassEquals(method, AWSRunInstancesResponseHandler.class);

View File

@ -19,6 +19,7 @@ package org.jclouds.aws.ec2.options;
import static org.jclouds.aws.ec2.options.AWSRunInstancesOptions.Builder.asType;
import static org.jclouds.aws.ec2.options.AWSRunInstancesOptions.Builder.enableMonitoring;
import static org.jclouds.aws.ec2.options.AWSRunInstancesOptions.Builder.withBlockDeviceMappings;
import static org.jclouds.aws.ec2.options.AWSRunInstancesOptions.Builder.withDedicatedHostId;
import static org.jclouds.aws.ec2.options.AWSRunInstancesOptions.Builder.withIAMInstanceProfileArn;
import static org.jclouds.aws.ec2.options.AWSRunInstancesOptions.Builder.withIAMInstanceProfileName;
import static org.jclouds.aws.ec2.options.AWSRunInstancesOptions.Builder.withKernelId;
@ -28,6 +29,7 @@ import static org.jclouds.aws.ec2.options.AWSRunInstancesOptions.Builder.withRam
import static org.jclouds.aws.ec2.options.AWSRunInstancesOptions.Builder.withSecurityGroup;
import static org.jclouds.aws.ec2.options.AWSRunInstancesOptions.Builder.withSecurityGroupId;
import static org.jclouds.aws.ec2.options.AWSRunInstancesOptions.Builder.withSubnetId;
import static org.jclouds.aws.ec2.options.AWSRunInstancesOptions.Builder.withTenancy;
import static org.jclouds.aws.ec2.options.AWSRunInstancesOptions.Builder.withUserData;
import static org.testng.Assert.assertEquals;
@ -383,4 +385,51 @@ public class AWSRunInstancesOptionsTest {
withPrivateIpAdress(null);
}
@Test
public void testNullWithTenancy() {
AWSRunInstancesOptions options = new AWSRunInstancesOptions();
assertEquals(options.buildFormParameters().get("Placement.Tenancy"), ImmutableList.of());
}
@Test
public void testWithTenancy() {
AWSRunInstancesOptions options = new AWSRunInstancesOptions();
options.withTenancy(Tenancy.DEDICATED);
assertEquals(options.buildFormParameters().get("Placement.Tenancy"), ImmutableList.of("dedicated"));
}
@Test
public void testWithTenancyStatic() {
AWSRunInstancesOptions options = withTenancy(Tenancy.HOST);
assertEquals(options.buildFormParameters().get("Placement.Tenancy"), ImmutableList.of("host"));
}
@Test(expectedExceptions = NullPointerException.class)
public void testWithTenancyStaticNPE() {
withTenancy(null);
}
@Test
public void testNullWithDedicatedHostId() {
AWSRunInstancesOptions options = new AWSRunInstancesOptions();
assertEquals(options.buildFormParameters().get("Placement.HostId"), ImmutableList.of());
}
@Test
public void testWithDedicatedHostId() {
AWSRunInstancesOptions options = new AWSRunInstancesOptions();
options.withDedicatedHostId("hostId-1234");
assertEquals(options.buildFormParameters().get("Placement.HostId"), ImmutableList.of("hostId-1234"));
}
@Test
public void testWithDedicatedHostIdStatic() {
AWSRunInstancesOptions options = withDedicatedHostId("hostId-5678");
assertEquals(options.buildFormParameters().get("Placement.HostId"), ImmutableList.of("hostId-5678"));
}
@Test(expectedExceptions = NullPointerException.class)
public void testWithDedicatedHostIdStaticNPE() {
withDedicatedHostId(null);
}
}