Skip to content

Commit

Permalink
JENKINS-17086 Add iamInstanceProfile option to slave configuration
Browse files Browse the repository at this point in the history
  • Loading branch information
ww-mgr committed May 16, 2013
1 parent 7d8a169 commit b5f2eb7
Show file tree
Hide file tree
Showing 5 changed files with 40 additions and 20 deletions.
44 changes: 30 additions & 14 deletions src/main/java/hudson/plugins/ec2/SlaveTemplate.java
Expand Up @@ -75,7 +75,7 @@ public class SlaveTemplate implements Describable<SlaveTemplate> {
public final String jvmopts;
public final String subnetId;
public final String idleTerminationMinutes;
public final String iamRole;
public final String iamInstanceProfile;
public int instanceCap;
public final boolean stopOnTerminate;
private final List<EC2Tag> tags;
Expand All @@ -87,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, String iamRole) {
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;
Expand Down Expand Up @@ -116,7 +116,7 @@ public SlaveTemplate(String ami, String zone, SpotConfiguration spotConfig, Stri
this.instanceCap = Integer.parseInt(instanceCapStr);
}

this.iamRole = iamRole;
this.iamInstanceProfile = iamInstanceProfile;

readResolve(); // initialize
}
Expand Down Expand Up @@ -222,8 +222,8 @@ public String getSpotMaxBidPrice(){
return SpotConfiguration.normalizeBid(spotConfig.spotMaxBidPrice);
}

public String getIamRole() {
return iamRole;
public String getIamInstanceProfile() {
return iamInstanceProfile;
}


Expand Down Expand Up @@ -299,7 +299,6 @@ 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()));
riRequest.setIamInstanceProfile(new IamInstanceProfileSpecification().withName(getIamRole()));

HashSet<Tag> inst_tags = null;
if (tags != null && !tags.isEmpty()) {
Expand All @@ -317,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);

Expand All @@ -332,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
Expand Down
Expand Up @@ -134,7 +134,7 @@ THE SOFTWARE.
<f:textbox />
</f:entry>

<f:entry title="${%IAM Role}" field="iamRole">
<f:entry title="${%IAM Instance Profile}" field="iamInstanceProfile">
<f:textbox />
</f:entry>
</f:advanced>
Expand Down
@@ -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>

This file was deleted.

4 changes: 2 additions & 2 deletions src/test/java/hudson/plugins/ec2/SlaveTemplateTest.java
Expand Up @@ -139,7 +139,7 @@ public void testConfigRoundtripIamRole() 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, "iamRole");
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);
Expand All @@ -149,7 +149,7 @@ public void testConfigRoundtripIamRole() throws Exception {

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,iamRole");
assertEqualBeans(orig, received, "ami,zone,description,remoteFS,type,jvmopts,stopOnTerminate,securityGroups,subnetId,usePrivateDnsName,iamInstanceProfile");
}

}

0 comments on commit b5f2eb7

Please sign in to comment.