diff --git a/pom.xml b/pom.xml
index 7e3390dd7..ad7f305a1 100644
--- a/pom.xml
+++ b/pom.xml
@@ -51,7 +51,29 @@ THE SOFTWARE.
HEAD
+
+ 1.6.2
+
+
+
+ org.powermock
+ powermock-module-junit4
+ ${powermock.version}
+ test
+
+
+ org.powermock
+ powermock-api-mockito
+ ${powermock.version}
+ test
+
+
+ junit
+ junit
+ 4.12
+ test
+
bouncycastle
diff --git a/src/main/java/hudson/plugins/ec2/SlaveTemplate.java b/src/main/java/hudson/plugins/ec2/SlaveTemplate.java
index 4ef900ac5..67c62bbf2 100644
--- a/src/main/java/hudson/plugins/ec2/SlaveTemplate.java
+++ b/src/main/java/hudson/plugins/ec2/SlaveTemplate.java
@@ -42,6 +42,7 @@
import java.io.PrintStream;
import java.net.URL;
import java.util.*;
+import java.util.logging.Level;
import java.util.logging.Logger;
import javax.servlet.ServletException;
@@ -421,18 +422,7 @@ private EC2AbstractSlave provisionOndemand(TaskListener listener) throws AmazonC
/* Now that we have our instance, we can set tags on it */
if (inst_tags != null) {
- for (int i = 0; i < 5; i++) {
- try {
- updateRemoteTags(ec2, inst_tags, inst.getInstanceId());
- break;
- } catch (AmazonServiceException e) {
- if (e.getErrorCode().equals("InvalidInstanceRequestID.NotFound")) {
- Thread.sleep(5000);
- continue;
- }
- throw e;
- }
- }
+ updateRemoteTags(ec2, inst_tags, "InvalidInstanceID.NotFound", inst.getInstanceId());
// That was a remote request - we should also update our local instance data.
inst.setTags(inst_tags);
@@ -676,18 +666,7 @@ private EC2AbstractSlave provisionSpot(TaskListener listener) throws AmazonClien
/* Now that we have our Spot request, we can set tags on it */
if (inst_tags != null) {
- for (int i = 0; i < 5; i++) {
- try {
- updateRemoteTags(ec2, inst_tags, spotInstReq.getSpotInstanceRequestId());
- break;
- } catch (AmazonServiceException e) {
- if (e.getErrorCode().equals("InvalidSpotInstanceRequestID.NotFound")) {
- Thread.sleep(5000);
- continue;
- }
- throw e;
- }
- }
+ updateRemoteTags(ec2, inst_tags, "InvalidSpotInstanceRequestID.NotFound", spotInstReq.getSpotInstanceRequestId());
// That was a remote request - we should also update our local instance data.
spotInstReq.setTags(inst_tags);
@@ -724,12 +703,29 @@ private KeyPair getKeyPair(AmazonEC2 ec2) throws IOException, AmazonClientExcept
}
/**
- * Update the tags stored in EC2 with the specified information
+ * Update the tags stored in EC2 with the specified information.
+ * Re-try 5 times if instances isn't up by catchErrorCode - e.g. InvalidSpotInstanceRequestID.NotFound or InvalidInstanceRequestID.NotFound
+ * @param ec2
+ * @param inst_tags
+ * @param catchErrorCode
+ * @param params
+ * @throws InterruptedException
*/
- private void updateRemoteTags(AmazonEC2 ec2, Collection inst_tags, String... params) {
- CreateTagsRequest tag_request = new CreateTagsRequest();
- tag_request.withResources(params).setTags(inst_tags);
- ec2.createTags(tag_request);
+ private void updateRemoteTags(AmazonEC2 ec2, Collection inst_tags, String catchErrorCode, String... params) throws InterruptedException {
+ for (int i = 0; i < 5; i++) {
+ try {
+ CreateTagsRequest tag_request = new CreateTagsRequest();
+ tag_request.withResources(params).setTags(inst_tags);
+ ec2.createTags(tag_request);
+ break;
+ } catch (AmazonServiceException e) {
+ if (e.getErrorCode().equals(catchErrorCode)) {
+ Thread.sleep(5000);
+ continue;
+ }
+ LOGGER.log(Level.SEVERE, e.getErrorMessage(), e);
+ }
+ }
}
/**
diff --git a/src/test/java/hudson/plugins/ec2/SlaveTemplateUnitTest.java b/src/test/java/hudson/plugins/ec2/SlaveTemplateUnitTest.java
new file mode 100644
index 000000000..3ce5f9476
--- /dev/null
+++ b/src/test/java/hudson/plugins/ec2/SlaveTemplateUnitTest.java
@@ -0,0 +1,146 @@
+package hudson.plugins.ec2;
+
+import com.amazonaws.AmazonServiceException;
+import com.amazonaws.services.ec2.AmazonEC2;
+import com.amazonaws.services.ec2.AmazonEC2Client;
+import com.amazonaws.services.ec2.model.InstanceType;
+import com.amazonaws.services.ec2.model.Tag;
+import hudson.model.Node;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.powermock.reflect.Whitebox;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.logging.Handler;
+import java.util.logging.LogRecord;
+import java.util.logging.Logger;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+
+public class SlaveTemplateUnitTest {
+
+ Logger logger;
+ TestHandler handler;
+
+ @Before
+ public void setUp() throws Exception {
+ AmazonEC2Cloud.testMode = true;
+
+ handler = new TestHandler();
+ logger = Logger.getLogger(SlaveTemplate.class.getName());
+ logger.addHandler(handler);
+ }
+
+ @After
+ public void tearDown() throws Exception {
+ AmazonEC2Cloud.testMode = false;
+ }
+
+ @Test
+ public void testUpdateRemoteTags() throws Exception {
+ AmazonEC2 ec2 = new AmazonEC2Client() {
+ @Override
+ public void createTags(com.amazonaws.services.ec2.model.CreateTagsRequest createTagsRequest) {
+
+ }
+ };
+
+ String ami = "ami1";
+ String description = "foo ami";
+
+ EC2Tag tag1 = new EC2Tag("name1", "value1");
+ EC2Tag tag2 = new EC2Tag("name2", "value2");
+ List tags = new ArrayList();
+ tags.add(tag1);
+ tags.add(tag2);
+ String instanceId = "123";
+
+ SlaveTemplate orig = new SlaveTemplate(ami, EC2AbstractSlave.TEST_ZONE, null, "default", "foo", InstanceType.M1Large, "ttt", Node.Mode.NORMAL, description, "bar", "bbb", "aaa", "10", "fff", null, "-Xmx1g", false, "subnet 456", tags, null, false, null, "", true, false, "", false, "") {
+ @Override
+ protected Object readResolve() {
+ return null;
+ }
+ };
+
+ ArrayList awsTags = new ArrayList();
+ awsTags.add(new Tag(EC2Tag.TAG_NAME_JENKINS_SLAVE_TYPE, "value1"));
+ awsTags.add(new Tag(EC2Tag.TAG_NAME_JENKINS_SLAVE_TYPE, "value2"));
+
+ final Object params[] = {ec2, awsTags, "InvalidInstanceRequestID.NotFound", instanceId};
+ Whitebox.invokeMethod(orig, "updateRemoteTags", params);
+ assertEquals(0, handler.getRecords().size());
+ }
+
+ @Test
+ public void testUpdateRemoteTagsInstanceNotFound() throws Exception {
+ AmazonEC2 ec2 = new AmazonEC2Client() {
+ @Override
+ public void createTags(com.amazonaws.services.ec2.model.CreateTagsRequest createTagsRequest) {
+ AmazonServiceException e = new AmazonServiceException("Instance not found - InvalidInstanceRequestID.NotFound");
+ e.setErrorCode("InvalidInstanceRequestID.NotFound");
+ throw e;
+ }
+ };
+
+ String ami = "ami1";
+ String description = "foo ami";
+
+ EC2Tag tag1 = new EC2Tag("name1", "value1");
+ EC2Tag tag2 = new EC2Tag("name2", "value2");
+ List tags = new ArrayList();
+ tags.add(tag1);
+ tags.add(tag2);
+ String instanceId = "123";
+
+ SlaveTemplate orig = new SlaveTemplate(ami, EC2AbstractSlave.TEST_ZONE, null, "default", "foo", InstanceType.M1Large, "ttt", Node.Mode.NORMAL, description, "bar", "bbb", "aaa", "10", "fff", null, "-Xmx1g", false, "subnet 456", tags, null, false, null, "", true, false, "", false, "") {
+ @Override
+ protected Object readResolve() {
+ return null;
+ }
+ };
+
+ ArrayList awsTags = new ArrayList();
+ awsTags.add(new Tag(EC2Tag.TAG_NAME_JENKINS_SLAVE_TYPE, "value1"));
+ awsTags.add(new Tag(EC2Tag.TAG_NAME_JENKINS_SLAVE_TYPE, "value2"));
+
+ final Object params[] = {ec2, awsTags, "InvalidSpotInstanceRequestID.NotFound", instanceId};
+ Whitebox.invokeMethod(orig, "updateRemoteTags", params);
+
+ assertEquals(5, handler.getRecords().size());
+
+ Iterator logs = handler.getRecords().iterator();
+ while (logs.hasNext()) {
+ String log = logs.next().getMessage();
+ assertTrue(log.contains("Instance not found - InvalidInstanceRequestID.NotFound"));
+ }
+
+ }
+}
+
+class TestHandler extends Handler {
+ private List records = new LinkedList();
+
+ @Override
+ public void close() throws SecurityException {
+ }
+
+ @Override
+ public void flush() {
+ }
+
+ @Override
+ public void publish(LogRecord record) {
+ records.add(record);
+ }
+
+ public List getRecords() {
+ return records;
+ }
+}
+