diff --git a/README.md b/README.md index 9db4f92f6..3aeaff214 100644 --- a/README.md +++ b/README.md @@ -483,6 +483,28 @@ jenkins.clouds.add(amazonEC2Cloud) jenkins.save() ``` +## Programmatically adding/updating CloudTemplates + +The plugin supports programmatic addition and update of `CloudTemplates` in an already existing `Cloud` - +both can be accomplished via the Jenkins script console [Jenkins script console](https://wiki.jenkins.io/display/JENKINS/Jenkins+Script+Console). + +Example: + +```java + // Assuming on the Jenkins instance, there exists an EC2Cloud with the name "AwsCloud" + + AmazonEC2Cloud cloud = (AmazonEC2Cloud) Jenkins.get().clouds.stream().filter(cloud1 -> Objects.equals(cloud.getDisplayName(), "AwsCloud")).findFirst().get(); + + SlaveTemplate template = new SlaveTemplate(/*constructor*/); // View available constructors at https://github.com/jenkinsci/ec2-plugin/blob/master/src/main/java/hudson/plugins/ec2/SlaveTemplate.java + + // Adding a template + cloud.addTemplate(template); + + SlaveTemplate template2 = new SlaveTemplate(/*constructor*/); + // Updating a template. Note the description of an existing SlaveTemplate needs to passed in order for there to be a successful update, otherwise an Exception is thrown + cloud.updateTemplate(template2, template.description); +``` + # Security ## Securing the connection to Unix AMIs When you set up a template for a *Unix* instance (`Type AMI` field), you can select the strategy used to guarantee the diff --git a/src/main/java/hudson/plugins/ec2/EC2Cloud.java b/src/main/java/hudson/plugins/ec2/EC2Cloud.java index fb3670180..76f8d112c 100644 --- a/src/main/java/hudson/plugins/ec2/EC2Cloud.java +++ b/src/main/java/hudson/plugins/ec2/EC2Cloud.java @@ -87,16 +87,7 @@ import java.net.MalformedURLException; import java.net.Proxy; import java.net.URL; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Date; -import java.util.EnumSet; -import java.util.HashSet; -import java.util.List; -import java.util.Optional; -import java.util.Set; -import java.util.UUID; +import java.util.*; import java.util.concurrent.Callable; import java.util.concurrent.TimeUnit; import java.util.concurrent.locks.ReentrantLock; @@ -226,6 +217,17 @@ public void addTemplate(SlaveTemplate newTemplate) throws Exception { templates = templatesHolder; } + public void updateTemplate(SlaveTemplate newTemplate, String oldTemplateDescription) throws Exception{ + Optional optionalOldTemplate = templates.stream().filter(template -> + Objects.equals(template.description, oldTemplateDescription)).findFirst(); + if (!optionalOldTemplate.isPresent()) + throw new Exception(String.format("A SlaveTemplate with description %s does not exist", oldTemplateDescription)); + int oldTemplateIndex = templates.indexOf(optionalOldTemplate.get()); + List templatesHolder = new ArrayList<>(templates); + templatesHolder.set(oldTemplateIndex, newTemplate); + templates = templatesHolder; + } + private void migratePrivateSshKeyToCredential(String privateKey) { // GET matching private key credential from Credential API if exists Optional keyCredential = SystemCredentialsProvider.getInstance().getCredentials() diff --git a/src/test/java/hudson/plugins/ec2/EC2CloudTest.java b/src/test/java/hudson/plugins/ec2/EC2CloudTest.java index 1fb8de13e..eb0461a21 100644 --- a/src/test/java/hudson/plugins/ec2/EC2CloudTest.java +++ b/src/test/java/hudson/plugins/ec2/EC2CloudTest.java @@ -6,6 +6,7 @@ import com.amazonaws.services.ec2.model.InstanceType; import hudson.model.Node; import jenkins.model.Jenkins; +import org.junit.Assert; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.MockedStatic; @@ -19,8 +20,7 @@ import java.util.Collections; import java.util.List; -import static org.junit.Assert.assertArrayEquals; -import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.*; import static org.mockito.ArgumentMatchers.eq; import static org.mockito.Mockito.times; @@ -37,6 +37,24 @@ public void testSlaveTemplateAddition() throws Exception { assertNotNull(cloud.getTemplate(orig.description)); } + @Test + public void testSlaveTemplateUpdate() throws Exception{ + AmazonEC2Cloud cloud = new AmazonEC2Cloud("us-east-1", true, + "abc", "us-east-1", null, "ghi", + "3", Collections.emptyList(), "roleArn", "roleSessionName"); + SlaveTemplate oldSlaveTemplate = new SlaveTemplate("ami-123", EC2AbstractSlave.TEST_ZONE, null, "default", "foo", InstanceType.M1Large, false, "ttt", Node.Mode.NORMAL, "OldSlaveDescription", "bar", "bbb", "aaa", "10", "fff", null, "-Xmx1g", false, "subnet 456", null, null, 0, 0, null, "iamInstanceProfile", true, false, "", false, "", false, false, false, ConnectionStrategy.PUBLIC_IP, -1, null, null, Tenancy.Default, EbsEncryptRootVolume.DEFAULT); + SlaveTemplate secondSlaveTemplate = new SlaveTemplate("ami-123", EC2AbstractSlave.TEST_ZONE, null, "default", "foo", InstanceType.M1Large, false, "ttt", Node.Mode.NORMAL, "SecondSlaveDescription", "bar", "bbb", "aaa", "10", "fff", null, "-Xmx1g", false, "subnet 456", null, null, 0, 0, null, "iamInstanceProfile", true, false, "", false, "", false, false, false, ConnectionStrategy.PUBLIC_IP, -1, null, null, Tenancy.Default, EbsEncryptRootVolume.DEFAULT); + cloud.addTemplate(oldSlaveTemplate); + cloud.addTemplate(secondSlaveTemplate); + SlaveTemplate newSlaveTemplate = new SlaveTemplate("ami-456", EC2AbstractSlave.TEST_ZONE, null, "default", "foo", InstanceType.M1Large, false, "ttt", Node.Mode.NORMAL, "NewSlaveDescription", "bar", "bbb", "aaa", "10", "fff", null, "-Xmx1g", false, "subnet 456", null, null, 0, 0, null, "iamInstanceProfile", true, false, "", false, "", false, false, false, ConnectionStrategy.PUBLIC_IP, -1, null, null, Tenancy.Default, EbsEncryptRootVolume.DEFAULT); + int index = cloud.getTemplates().indexOf(oldSlaveTemplate); + + cloud.updateTemplate(newSlaveTemplate, "OldSlaveDescription"); + assertNull(cloud.getTemplate("OldSlaveDescription")); + assertNotNull(cloud.getTemplate("NewSlaveDescription")); + Assert.assertEquals(index, cloud.getTemplates().indexOf(newSlaveTemplate)); // assert order of templates is kept + } + @Test public void testReattachOrphanStoppedNodes() throws Exception { /* Mocked items */