Skip to content
Permalink
Browse files
Merge pull request #52 from ww-mgr/ec2-iamrole
JENKINS-17086 Add iamRole option to slave configuration
  • Loading branch information
francisu committed May 16, 2013
2 parents 3ee74a4 + b5f2eb7 commit 4102f1cf7898dae96f3785d3a196276e5627ffae
Showing 5 changed files with 79 additions and 16 deletions.
@@ -75,6 +75,7 @@ public class SlaveTemplate implements Describable<SlaveTemplate> {
public final String jvmopts;
public final String subnetId;
public final String idleTerminationMinutes;
public final String iamInstanceProfile;
public int instanceCap;
public final boolean stopOnTerminate;
private final List<EC2Tag> tags;
@@ -86,7 +87,7 @@ public class SlaveTemplate implements Describable<SlaveTemplate> {
private transient /*almost final*/ Set<String> securityGroupSet;

@DataBoundConstructor
public SlaveTemplate(String ami, String zone, SpotConfiguration spotConfig, String securityGroups, String remoteFS, String sshPort, InstanceType type, String labelString, Node.Mode mode, String description, String initScript, String userData, String numExecutors, String remoteAdmin, String rootCommandPrefix, String jvmopts, boolean stopOnTerminate, String subnetId, List<EC2Tag> tags, String idleTerminationMinutes, boolean usePrivateDnsName, String instanceCapStr) {
public SlaveTemplate(String ami, String zone, SpotConfiguration spotConfig, String securityGroups, String remoteFS, String sshPort, InstanceType type, String labelString, Node.Mode mode, String description, String initScript, String userData, String numExecutors, String remoteAdmin, String rootCommandPrefix, String jvmopts, boolean stopOnTerminate, String subnetId, List<EC2Tag> tags, String idleTerminationMinutes, boolean usePrivateDnsName, String instanceCapStr, String iamInstanceProfile) {
this.ami = ami;
this.zone = zone;
this.spotConfig = spotConfig;
@@ -114,7 +115,9 @@ public SlaveTemplate(String ami, String zone, SpotConfiguration spotConfig, Stri
} else {
this.instanceCap = Integer.parseInt(instanceCapStr);
}


this.iamInstanceProfile = iamInstanceProfile;

readResolve(); // initialize
}

@@ -218,6 +221,10 @@ public String getSpotMaxBidPrice(){
return null;
return SpotConfiguration.normalizeBid(spotConfig.spotMaxBidPrice);
}

public String getIamInstanceProfile() {
return iamInstanceProfile;
}


/**
@@ -292,7 +299,7 @@ private EC2AbstractSlave provisionOndemand(TaskListener listener) throws AmazonC
diFilters.add(new Filter("key-name").withValues(keyPair.getKeyName()));
riRequest.setInstanceType(type.toString());
diFilters.add(new Filter("instance-type").withValues(type.toString()));

HashSet<Tag> inst_tags = null;
if (tags != null && !tags.isEmpty()) {
inst_tags = new HashSet<Tag>();
@@ -309,7 +316,25 @@ private EC2AbstractSlave provisionOndemand(TaskListener listener) throws AmazonC
logger.println("Looking for existing instances: "+diRequest);

DescribeInstancesResult diResult = ec2.describeInstances(diRequest);
if (diResult.getReservations().size() == 0) {

Instance existingInstance = null;
if (StringUtils.isNotBlank(getIamInstanceProfile())) {
riRequest.setIamInstanceProfile(new IamInstanceProfileSpecification().withArn(getIamInstanceProfile()));
// cannot filter on IAM Instance Profile, so search in result
reservationLoop:
for (Reservation reservation : diResult.getReservations()) {
for (Instance instance : reservation.getInstances()) {
if (instance.getIamInstanceProfile() != null && instance.getIamInstanceProfile().getArn().equals(getIamInstanceProfile())) {
existingInstance = instance;
break reservationLoop;
}
}
}
} else if (diResult.getReservations().size() > 0) {
existingInstance = diResult.getReservations().get(0).getInstances().get(0);
}

if (existingInstance == null) {
// Have to create a new instance
Instance inst = ec2.runInstances(riRequest).getReservation().getInstances().get(0);

@@ -324,28 +349,27 @@ private EC2AbstractSlave provisionOndemand(TaskListener listener) throws AmazonC
return newOndemandSlave(inst);
}

Instance inst = diResult.getReservations().get(0).getInstances().get(0);
logger.println("Found existing stopped instance: "+inst);
logger.println("Found existing stopped instance: "+existingInstance);
List<String> instances = new ArrayList<String>();
instances.add(inst.getInstanceId());
instances.add(existingInstance.getInstanceId());
StartInstancesRequest siRequest = new StartInstancesRequest(instances);
StartInstancesResult siResult = ec2.startInstances(siRequest);
logger.println("Starting existing instance: "+inst+ " result:"+siResult);
logger.println("Starting existing instance: "+existingInstance+ " result:"+siResult);

List<Node> nodes = Hudson.getInstance().getNodes();
for (int i = 0, len = nodes.size(); i < len; i++) {
if (!(nodes.get(i) instanceof EC2AbstractSlave))
continue;
EC2AbstractSlave ec2Node = (EC2AbstractSlave) nodes.get(i);
if (ec2Node.getInstanceId().equals(inst.getInstanceId())) {
if (ec2Node.getInstanceId().equals(existingInstance.getInstanceId())) {
logger.println("Found existing corresponding: "+ec2Node);
return ec2Node;
}
}

// Existing slave not found
logger.println("Creating new slave for existing instance: "+inst);
return newOndemandSlave(inst);
logger.println("Creating new slave for existing instance: "+existingInstance);
return newOndemandSlave(existingInstance);

} catch (FormException e) {
throw new AssertionError(); // we should have discovered all configuration issues upfront
@@ -133,6 +133,10 @@ THE SOFTWARE.
<f:entry title="${%Instance Cap}" field="instanceCapStr">
<f:textbox />
</f:entry>

<f:entry title="${%IAM Instance Profile}" field="iamInstanceProfile">
<f:textbox />
</f:entry>
</f:advanced>

<f:entry title="">
@@ -0,0 +1,7 @@
<div>
<p>IAM Instance Profile ARN e.g. arn:aws:iam::000000000000:instance-profile/SampleName.</p>
<p>An instance profile is a container for a role.
To associate a role to an Amazon EC2 instance, you must use the instance profile ARN.
Roles enable you to manage permissions for applications running on EC2.</p>
<p>The Instance Profile ARN can be found in the IAM Role's <b>Summary</b> tab in the AWS Management Console.</p>
</div>
@@ -59,7 +59,7 @@ public void testConfigRoundtrip() throws Exception {
tags.add( tag1 );
tags.add( tag2 );

SlaveTemplate orig = new SlaveTemplate(ami, EC2AbstractSlave.TEST_ZONE, null, "default", "foo", "22", InstanceType.M1Large, "ttt", Node.Mode.NORMAL, description, "bar", "aaa", "10", "rrr", "fff", "-Xmx1g", false, "subnet 456", tags, null, false, null);
SlaveTemplate orig = new SlaveTemplate(ami, EC2AbstractSlave.TEST_ZONE, null, "default", "foo", "22", InstanceType.M1Large, "ttt", Node.Mode.NORMAL, description, "bar", "aaa", "10", "rrr", "fff", "-Xmx1g", false, "subnet 456", tags, null, false, null, "");

List<SlaveTemplate> templates = new ArrayList<SlaveTemplate>();
templates.add(orig);
@@ -82,7 +82,7 @@ public void testConfigRoundtripWithPrivateDns() throws Exception {
tags.add( tag1 );
tags.add( tag2 );

SlaveTemplate orig = new SlaveTemplate(ami, EC2AbstractSlave.TEST_ZONE, null, "default", "foo", "22", InstanceType.M1Large, "ttt", Node.Mode.NORMAL, description, "bar", "aaa", "10", "rrr", "fff", "-Xmx1g", false, "subnet 456", tags, null, true, null);
SlaveTemplate orig = new SlaveTemplate(ami, EC2AbstractSlave.TEST_ZONE, null, "default", "foo", "22", InstanceType.M1Large, "ttt", Node.Mode.NORMAL, description, "bar", "aaa", "10", "rrr", "fff", "-Xmx1g", false, "subnet 456", tags, null, true, null, "");

List<SlaveTemplate> templates = new ArrayList<SlaveTemplate>();
templates.add(orig);
@@ -112,7 +112,7 @@ public void testConfigWithSpotBidPrice() throws Exception {

SpotConfiguration spotConfig = new SpotConfiguration(".05", SpotInstanceType.OneTime.toString());

SlaveTemplate orig = new SlaveTemplate(ami, EC2AbstractSlave.TEST_ZONE, spotConfig, "default", "foo", "22", InstanceType.M1Large, "ttt", Node.Mode.NORMAL, "foo ami", "bar", "aaa", "10", "rrr", "fff", "-Xmx1g", false, "subnet 456", tags, null, true, null);
SlaveTemplate orig = new SlaveTemplate(ami, EC2AbstractSlave.TEST_ZONE, spotConfig, "default", "foo", "22", InstanceType.M1Large, "ttt", Node.Mode.NORMAL, "foo ami", "bar", "aaa", "10", "rrr", "fff", "-Xmx1g", false, "subnet 456", tags, null, true, null, "");
List<SlaveTemplate> templates = new ArrayList<SlaveTemplate>();
templates.add(orig);

@@ -124,4 +124,32 @@ public void testConfigWithSpotBidPrice() throws Exception {
assertEqualBeans(orig, received, "ami,zone,spotConfig,description,remoteFS,type,jvmopts,stopOnTerminate,securityGroups,subnetId,tags,usePrivateDnsName");
}

/**
* Test to make sure the IAM Role is set properly.
*
* @throws Exception
*/
public void testConfigRoundtripIamRole() throws Exception {
String ami = "ami1";
String description = "foo ami";

EC2Tag tag1 = new EC2Tag( "name1", "value1" );
EC2Tag tag2 = new EC2Tag( "name2", "value2" );
List<EC2Tag> tags = new ArrayList<EC2Tag>();
tags.add( tag1 );
tags.add( tag2 );

SlaveTemplate orig = new SlaveTemplate(ami, EC2AbstractSlave.TEST_ZONE, null, "default", "foo", "22", InstanceType.M1Large, "ttt", Node.Mode.NORMAL, description, "bar", "aaa", "10", "rrr", "fff", "-Xmx1g", false, "subnet 456", tags, null, false, null, "iamInstanceProfile");

List<SlaveTemplate> templates = new ArrayList<SlaveTemplate>();
templates.add(orig);

AmazonEC2Cloud ac = new AmazonEC2Cloud("abc", "def", "us-east-1", "ghi", "3", templates);
hudson.clouds.add(ac);

submit(createWebClient().goTo("configure").getFormByName("config"));
SlaveTemplate received = ((EC2Cloud)hudson.clouds.iterator().next()).getTemplate(description);
assertEqualBeans(orig, received, "ami,zone,description,remoteFS,type,jvmopts,stopOnTerminate,securityGroups,subnetId,usePrivateDnsName,iamInstanceProfile");
}

}
@@ -50,7 +50,7 @@ public void setUp() throws Exception{
tags.add( tag1 );
tags.add( tag2 );

SlaveTemplate template = new SlaveTemplate("ami", "foo", null, "default", "zone", "22", InstanceType.M1Large, LABEL1 + " " + LABEL2, Node.Mode.NORMAL,"foo ami", "bar", "aaa", "10", "rrr", "fff", "-Xmx1g", true, "subnet 456", tags, null, false, null);
SlaveTemplate template = new SlaveTemplate("ami", "foo", null, "default", "zone", "22", InstanceType.M1Large, LABEL1 + " " + LABEL2, Node.Mode.NORMAL,"foo ami", "bar", "aaa", "10", "rrr", "fff", "-Xmx1g", true, "subnet 456", tags, null, false, null, "");
List<SlaveTemplate> templates = new ArrayList<SlaveTemplate>();
templates.add(template);

@@ -79,7 +79,7 @@ public void testEmptyLabel() throws Exception{
tags.add( tag1 );
tags.add( tag2 );

SlaveTemplate temp = new SlaveTemplate("ami", "foo", null, "default", "zone", "22", InstanceType.M1Large, "", Node.Mode.NORMAL, "foo ami", "bar", "aaa", "10", "rrr", "fff", "-Xmx1g", true, "subnet 456", tags, null, false, null);
SlaveTemplate temp = new SlaveTemplate("ami", "foo", null, "default", "zone", "22", InstanceType.M1Large, "", Node.Mode.NORMAL, "foo ami", "bar", "aaa", "10", "rrr", "fff", "-Xmx1g", true, "subnet 456", tags, null, false, null, "");
List<SlaveTemplate> templates = new ArrayList<SlaveTemplate>();
templates.add(temp);

0 comments on commit 4102f1c

Please sign in to comment.