diff --git a/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderCloud.java b/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderCloud.java index e65ed56..7668f4f 100644 --- a/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderCloud.java +++ b/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderCloud.java @@ -59,6 +59,7 @@ public class CodeBuilderCloud extends Cloud { private static final String DEFAULT_JNLP_IMAGE = "lsegal/jnlp-docker-agent:alpine"; private static final int DEFAULT_AGENT_TIMEOUT = 120; private static final String DEFAULT_COMPUTE_TYPE = "BUILD_GENERAL1_SMALL"; + private static final boolean DEFAULT_TERMINATE_AGENT = true; static { clearAllNodes(); @@ -78,6 +79,7 @@ public class CodeBuilderCloud extends Cloud { private String jenkinsUrl; private String jnlpImage; private int agentTimeout; + private boolean terminateAgent; private transient AWSCodeBuild client; @@ -327,7 +329,8 @@ public synchronized AWSCodeBuild getClient() { @Override public synchronized Collection provision(Label label, int excessWorkload) { List list = new ArrayList(); - + String labelName = label == null ? getLabel() : label.getDisplayName(); + LOGGER.info("[CodeBuilder]: Excess workload sent by Jenkins: {} for label: {}", excessWorkload, labelName); // guard against non-matching labels if (label != null && !label.matches(Arrays.asList(new LabelAtom(getLabel())))) { return list; @@ -341,7 +344,6 @@ public synchronized Collection provision(Label label, int excessWor return list; } - String labelName = label == null ? getLabel() : label.getDisplayName(); long stillProvisioning = numStillProvisioning(); long numToLaunch = Math.max(excessWorkload - stillProvisioning, 0); LOGGER.info("[CodeBuilder]: Provisioning {} nodes for label '{}' ({} already provisioning)", numToLaunch, labelName, @@ -370,14 +372,20 @@ public synchronized Collection provision(Label label, int excessWor */ private long numStillProvisioning() { return jenkins().getNodes().stream().filter(CodeBuilderAgent.class::isInstance).map(CodeBuilderAgent.class::cast) - .filter(a -> a.getLauncher().isLaunchSupported()).count(); + .filter(a -> !a.getLauncher().isLaunchSupported()).count(); } /** {@inheritDoc} */ @Override public boolean canProvision(Label label) { + LOGGER.info("[CodeBuilder]: Check if can provision node for label '{}'", label); boolean canProvision = label == null ? true : label.matches(Arrays.asList(new LabelAtom(getLabel()))); - LOGGER.info("[CodeBuilder]: Check provisioning capabilities for label '{}': {}", label, canProvision); + if (canProvision) { + LOGGER.info("[CodeBuilder]: Label '{}' matches current label '{}'. Node will be provisioned...", label, getLabel()); + } + else { + LOGGER.info("[CodeBuilder]: Label '{}' DOESN'T MATCH current label '{}'. Node WON'T provisioned...", label, getLabel()); + } return canProvision; } @@ -389,6 +397,14 @@ private static String getDefaultRegion() { } } + public boolean isTerminateAgent() { + return terminateAgent; + } + + public void setTerminateAgent(boolean terminateAgent) { + this.terminateAgent = terminateAgent; + } + @Extension public static class DescriptorImpl extends Descriptor { @Override @@ -408,6 +424,10 @@ public String getDefaultComputeType() { return DEFAULT_COMPUTE_TYPE; } + public boolean getDefaultTerminateAgent() { + return DEFAULT_TERMINATE_AGENT; + } + public ListBoxModel doFillCredentialsIdItems() { return AWSCredentialsHelper.doFillCredentialsIdItems(jenkins()); } diff --git a/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderComputer.java b/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderComputer.java index b28c0bd..3045e08 100644 --- a/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderComputer.java +++ b/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderComputer.java @@ -77,7 +77,9 @@ public void taskAccepted(Executor executor, Queue.Task task) { public void taskCompleted(Executor executor, Queue.Task task, long durationMS) { super.taskCompleted(executor, task, durationMS); LOGGER.info("[CodeBuilder]: [{}]: Task in job '{}' completed in {}ms", this, task.getFullDisplayName(), durationMS); - gracefulShutdown(); + if (cloud.isTerminateAgent()) { + gracefulShutdown(); + } } /** {@inheritDoc} */ @@ -86,7 +88,9 @@ public void taskCompletedWithProblems(Executor executor, Queue.Task task, long d super.taskCompletedWithProblems(executor, task, durationMS, problems); LOGGER.error("[CodeBuilder]: [{}]: Task in job '{}' completed with problems in {}ms", this, task.getFullDisplayName(), durationMS, problems); - gracefulShutdown(); + if (cloud.isTerminateAgent()) { + gracefulShutdown(); + } } /** {@inheritDoc} */ diff --git a/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderLauncher.java b/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderLauncher.java index be856db..d87b006 100644 --- a/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderLauncher.java +++ b/src/main/java/dev/lsegal/jenkins/codebuilder/CodeBuilderLauncher.java @@ -66,7 +66,7 @@ public void launch(@Nonnull SlaveComputer computer, @Nonnull TaskListener listen CodeBuilderComputer cbcpu = (CodeBuilderComputer) computer; StartBuildRequest req = new StartBuildRequest().withProjectName(cloud.getProjectName()) .withSourceTypeOverride(SourceType.NO_SOURCE).withBuildspecOverride(buildspec(computer)) - .withImageOverride(cloud.getJnlpImage()).withPrivilegedModeOverride(true) + .withImageOverride(cloud.getJnlpImage()).withPrivilegedModeOverride(true).withTimeoutInMinutesOverride(480) .withComputeTypeOverride(cloud.getComputeType()); try { diff --git a/src/main/resources/dev/lsegal/jenkins/codebuilder/CodeBuilderCloud/config.jelly b/src/main/resources/dev/lsegal/jenkins/codebuilder/CodeBuilderCloud/config.jelly index d7625dd..cde60a5 100644 --- a/src/main/resources/dev/lsegal/jenkins/codebuilder/CodeBuilderCloud/config.jelly +++ b/src/main/resources/dev/lsegal/jenkins/codebuilder/CodeBuilderCloud/config.jelly @@ -37,5 +37,9 @@ + + + + diff --git a/src/main/resources/dev/lsegal/jenkins/codebuilder/CodeBuilderCloud/help-agentTimeout.html b/src/main/resources/dev/lsegal/jenkins/codebuilder/CodeBuilderCloud/help-agentTimeout.html index 8bd2483..17ccda0 100644 --- a/src/main/resources/dev/lsegal/jenkins/codebuilder/CodeBuilderCloud/help-agentTimeout.html +++ b/src/main/resources/dev/lsegal/jenkins/codebuilder/CodeBuilderCloud/help-agentTimeout.html @@ -1,4 +1,6 @@

The time in seconds to wait before giving up on an agent connection. Default - value is 120 seconds. + value is 120 seconds. If you are using a load balancer its idle connection timeout + should be the same. + Maximum value is the same as configured in the codebuild project.

\ No newline at end of file diff --git a/src/main/resources/dev/lsegal/jenkins/codebuilder/CodeBuilderCloud/help-terminateAgent.html b/src/main/resources/dev/lsegal/jenkins/codebuilder/CodeBuilderCloud/help-terminateAgent.html new file mode 100644 index 0000000..d942778 --- /dev/null +++ b/src/main/resources/dev/lsegal/jenkins/codebuilder/CodeBuilderCloud/help-terminateAgent.html @@ -0,0 +1,7 @@ +

Determines whether to terminate the codebuild Agent after the task is finished.

+

+ After a task is finished default behavior is to terminate the codebuild agent + right after the build is finished. By disabling this option the codebuild agent + will run for the amount of time specified by the Agent Connection Timeout. Each new build + will extend the Agent runtime for the Agent Connection Timeout value. +

diff --git a/src/test/java/dev/lsegal/jenkins/codebuilder/CodeBuilderCloudTest.java b/src/test/java/dev/lsegal/jenkins/codebuilder/CodeBuilderCloudTest.java index 2717834..f366262 100644 --- a/src/test/java/dev/lsegal/jenkins/codebuilder/CodeBuilderCloudTest.java +++ b/src/test/java/dev/lsegal/jenkins/codebuilder/CodeBuilderCloudTest.java @@ -13,7 +13,7 @@ public class CodeBuilderCloudTest { @Test public void initializes_correctly() throws InterruptedException { - CodeBuilderCloud cloud = new CodeBuilderCloud(null, "project", null, null); + CodeBuilderCloud cloud = new CodeBuilderCloud(null, "project", null, "eu-west-1"); assertEquals("project", cloud.getProjectName()); assertEquals("codebuilder_0", cloud.getDisplayName()); assertNotNull(cloud.getClient());