Skip to content

Commit dd2d1e6

Browse files
committedSep 11, 2014
JENKINS-19845, EC2 plugin incorrectly reports current instance count
- Improvement, not a fix. This code checks if the tags match the configured tags
1 parent 7fe8fdf commit dd2d1e6

File tree

1 file changed

+65
-7
lines changed

1 file changed

+65
-7
lines changed
 

‎src/main/java/hudson/plugins/ec2/EC2Cloud.java

+65-7
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
package hudson.plugins.ec2;
2525

2626
import com.amazonaws.ClientConfiguration;
27+
2728
import hudson.ProxyConfiguration;
2829
import hudson.model.Computer;
2930
import hudson.model.Descriptor;
@@ -58,6 +59,8 @@
5859

5960
import jenkins.model.Jenkins;
6061
import jenkins.slaves.iterators.api.NodeIterator;
62+
63+
import org.apache.commons.lang.StringUtils;
6164
import org.kohsuke.stapler.QueryParameter;
6265
import org.kohsuke.stapler.StaplerRequest;
6366
import org.kohsuke.stapler.StaplerResponse;
@@ -76,6 +79,7 @@
7679
import com.amazonaws.services.ec2.model.KeyPairInfo;
7780
import com.amazonaws.services.ec2.model.Reservation;
7881
import com.amazonaws.services.ec2.model.SpotInstanceRequest;
82+
import com.amazonaws.services.ec2.model.Tag;
7983
import com.amazonaws.services.s3.AmazonS3;
8084
import com.amazonaws.services.s3.AmazonS3Client;
8185
import com.amazonaws.services.s3.model.GeneratePresignedUrlRequest;
@@ -206,21 +210,74 @@ public synchronized KeyPair getKeyPair() throws AmazonClientException, IOExcepti
206210
* @param ami If AMI is left null, then all instances are counted.
207211
* <p>
208212
* This includes those instances that may be started outside Hudson.
213+
* @param tags
209214
*/
210-
public int countCurrentEC2Slaves(String ami) throws AmazonClientException {
215+
public int countCurrentEC2Slaves(String ami, List<EC2Tag> tags) throws AmazonClientException {
211216
int n=0;
212217
for (Reservation r : connect().describeInstances().getReservations()) {
213218
for (Instance i : r.getInstances()) {
214-
if (ami == null || ami.equals(i.getImageId())) {
219+
if (looksLikeEc2ProvisionedSlave(i, tags, ami)) {
215220
InstanceStateName stateName = InstanceStateName.fromValue(i.getState().getName());
216-
if (stateName == InstanceStateName.Pending || stateName == InstanceStateName.Running)
221+
if (stateName == InstanceStateName.Pending || stateName == InstanceStateName.Running) {
217222
n++;
223+
}
218224
}
219225
}
220226
}
221227
return n;
222228
}
223229

230+
/**
231+
* This method does check if the slave might be provisionde by this plugin. It does so by
232+
* checking if the slave has the same AMI id and the tags match the tags as configured by
233+
* the plugin. If there are no tags configured, the tags are ignored.
234+
*
235+
* JENKINS-19845
236+
*
237+
* @param i
238+
* @param tags
239+
* @param ami
240+
* @return
241+
*/
242+
private boolean looksLikeEc2ProvisionedSlave(Instance i, List<EC2Tag> tags, String ami) {
243+
// Check if the ami matches
244+
if (ami == null || StringUtils.equals(ami, i.getImageId())) {
245+
if (tags == null || tags.isEmpty()) {
246+
return true;
247+
}
248+
return equalsTags(tags, i.getTags());
249+
}
250+
return false;
251+
}
252+
253+
/**
254+
* Returns true if there is a tag where both the key and value are equal.
255+
* @param configuredTags
256+
* @param instanceTags
257+
* @return true if there is a tag where both the key and value are equal.
258+
*/
259+
private boolean equalsTags(List<EC2Tag> configuredTags, List<Tag> instanceTags) {
260+
for (Tag instanceTag : instanceTags) {
261+
for (EC2Tag ec2Tag : configuredTags) {
262+
if (equalsTag(instanceTag, ec2Tag)) {
263+
return true;
264+
}
265+
}
266+
}
267+
return false;
268+
}
269+
270+
/**
271+
* Returns true if both the key and value are equal.
272+
* @param instanceTag
273+
* @param ec2Tag
274+
* @return true if both the key and value are equal
275+
*/
276+
private boolean equalsTag(Tag instanceTag, EC2Tag ec2Tag) {
277+
return StringUtils.equals(instanceTag.getKey(), ec2Tag.getName())
278+
&& StringUtils.equals(instanceTag.getValue(), ec2Tag.getValue());
279+
}
280+
224281
/**
225282
* Debug command to attach to a running instance.
226283
*/
@@ -266,10 +323,11 @@ public void doProvision(StaplerRequest req, StaplerResponse rsp, @QueryParameter
266323
* Check for the count of EC2 slaves and determine if a new slave can be added.
267324
* Takes into account both what Amazon reports as well as an internal count
268325
* of slaves currently being "provisioned".
326+
* @param tags
269327
*/
270-
private boolean addProvisionedSlave(String ami, int amiCap) throws AmazonClientException {
271-
int estimatedTotalSlaves = countCurrentEC2Slaves(null);
272-
int estimatedAmiSlaves = countCurrentEC2Slaves(ami);
328+
private boolean addProvisionedSlave(String ami, List<EC2Tag> tags, int amiCap) throws AmazonClientException {
329+
int estimatedTotalSlaves = countCurrentEC2Slaves(null, null);
330+
int estimatedAmiSlaves = countCurrentEC2Slaves(ami, tags);
273331

274332
synchronized (provisioningAmis) {
275333
int currentProvisioning;
@@ -358,7 +416,7 @@ public Collection<PlannedNode> provision(Label label, int excessWorkload) {
358416

359417
while (excessWorkload>0) {
360418

361-
if (!addProvisionedSlave(t.ami, amiCap)) {
419+
if (!addProvisionedSlave(t.ami, t.getTags(), amiCap)) {
362420
break;
363421
}
364422

0 commit comments

Comments
 (0)
Please sign in to comment.