Skip to content

Commit

Permalink
Merge pull request #987 from drullar/prommatic-slavetemplate-update
Browse files Browse the repository at this point in the history
Added support for programmatic update of a SlaveTemplate
  • Loading branch information
res0nance authored Oct 8, 2024
2 parents eded650 + 2cf6ccc commit b9e9e84
Show file tree
Hide file tree
Showing 3 changed files with 54 additions and 12 deletions.
22 changes: 22 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
22 changes: 12 additions & 10 deletions src/main/java/hudson/plugins/ec2/EC2Cloud.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -226,6 +217,17 @@ public void addTemplate(SlaveTemplate newTemplate) throws Exception {
templates = templatesHolder;
}

public void updateTemplate(SlaveTemplate newTemplate, String oldTemplateDescription) throws Exception{
Optional<? extends SlaveTemplate> optionalOldTemplate = templates.stream().filter(template ->
Objects.equals(template.description, oldTemplateDescription)).findFirst();
if (!optionalOldTemplate.isPresent())

Check warning on line 223 in src/main/java/hudson/plugins/ec2/EC2Cloud.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Partially covered line

Line 223 is only partially covered, one branch is missing
throw new Exception(String.format("A SlaveTemplate with description %s does not exist", oldTemplateDescription));

Check warning on line 224 in src/main/java/hudson/plugins/ec2/EC2Cloud.java

View check run for this annotation

ci.jenkins.io / Code Coverage

Not covered line

Line 224 is not covered by tests
int oldTemplateIndex = templates.indexOf(optionalOldTemplate.get());
List<SlaveTemplate> 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<SSHUserPrivateKey> keyCredential = SystemCredentialsProvider.getInstance().getCredentials()
Expand Down
22 changes: 20 additions & 2 deletions src/test/java/hudson/plugins/ec2/EC2CloudTest.java
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;

Expand All @@ -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 */
Expand Down

0 comments on commit b9e9e84

Please sign in to comment.