Skip to content

Commit

Permalink
Merge pull request #219 from jglick/agents-JENKINS-26398
Browse files Browse the repository at this point in the history
[JENKINS-26398] Use standard `JenkinsRule.createSlave` plus new `InboundAgentRule`
  • Loading branch information
jglick authored May 3, 2022
2 parents 22eedda + da801b8 commit 493c2cb
Show file tree
Hide file tree
Showing 2 changed files with 12 additions and 57 deletions.
1 change: 1 addition & 0 deletions pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -67,6 +67,7 @@
<properties>
<changelist>999999-SNAPSHOT</changelist>
<jenkins.version>2.303.3</jenkins.version>
<jenkins-test-harness.version>1746.v2b_3c5d1983b_e</jenkins-test-harness.version> <!-- TODO until in plugin-pom -->
<useBeta>true</useBeta>
<gitHubRepo>jenkinsci/${project.artifactId}-plugin</gitHubRepo>
<hpi.compatibleSinceVersion>2.40</hpi.compatibleSinceVersion>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -42,17 +42,13 @@
import hudson.model.labels.LabelAtom;
import hudson.model.queue.CauseOfBlockage;
import hudson.model.queue.QueueTaskDispatcher;
import hudson.remoting.Launcher;
import hudson.remoting.Which;
import hudson.security.ACL;
import hudson.security.ACLContext;
import hudson.slaves.DumbSlave;
import hudson.slaves.EnvironmentVariablesNodeProperty;
import hudson.slaves.JNLPLauncher;
import hudson.slaves.OfflineCause;
import hudson.slaves.RetentionStrategy;
import hudson.slaves.WorkspaceList;
import hudson.util.StreamCopyThread;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
Expand All @@ -74,8 +70,6 @@
import java.util.stream.Collectors;

import hudson.util.VersionNumber;
import java.nio.charset.StandardCharsets;
import java.util.Set;
import jenkins.model.Jenkins;
import jenkins.security.QueueItemAuthenticator;
import jenkins.security.QueueItemAuthenticatorConfiguration;
Expand All @@ -84,7 +78,6 @@
import net.sf.json.groovy.JsonSlurper;
import org.acegisecurity.Authentication;
import org.apache.commons.io.IOUtils;
import org.apache.tools.ant.util.JavaEnvUtils;
import static org.hamcrest.Matchers.*;
import org.jenkinsci.plugins.durabletask.FileMonitoringTask;
import org.jenkinsci.plugins.workflow.actions.LogAction;
Expand All @@ -104,7 +97,6 @@
import org.jenkinsci.plugins.workflow.steps.durable_task.DurableTaskStep;
import org.jenkinsci.plugins.workflow.steps.durable_task.Messages;
import org.jenkinsci.plugins.workflow.test.steps.SemaphoreStep;
import org.junit.After;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotEquals;
Expand All @@ -118,6 +110,7 @@
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.jvnet.hudson.test.BuildWatcher;
import org.jvnet.hudson.test.InboundAgentRule;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;
import org.jvnet.hudson.test.LoggerRule;
Expand All @@ -133,6 +126,7 @@ public class ExecutorStepTest {

@ClassRule public static BuildWatcher buildWatcher = new BuildWatcher();
@Rule public JenkinsSessionRule sessions = new JenkinsSessionRule();
@Rule public InboundAgentRule inboundAgents = new InboundAgentRule();
@Rule public TemporaryFolder tmp = new TemporaryFolder();
// Currently too noisy due to unrelated warnings; might clear up if test dependencies updated: .record(ExecutorStepExecution.class, Level.FINE)
@Rule public LoggerRule logging = new LoggerRule();
Expand Down Expand Up @@ -217,33 +211,11 @@ public class ExecutorStepTest {
});
}

private Process jnlpProc;
private void startJnlpProc(JenkinsRule r) throws Exception {
killJnlpProc();
ProcessBuilder pb = new ProcessBuilder(JavaEnvUtils.getJreExecutable("java"), "-Djava.awt.headless=true", "-jar", Which.jarFile(Launcher.class).getAbsolutePath(), "-jnlpUrl", r.getURL() + "computer/dumbo/slave-agent.jnlp");
pb.redirectErrorStream(true);
System.err.println("Running: " + pb.command());
jnlpProc = pb.start();
new StreamCopyThread("jnlp", jnlpProc.getInputStream(), System.err).start();
}
@After public void killJnlpProc() {
if (jnlpProc != null) {
jnlpProc.destroyForcibly();
jnlpProc = null;
}
}

@Test public void buildShellScriptAcrossRestart() throws Throwable {
Assume.assumeFalse("TODO not sure how to write a corresponding batch script", Functions.isWindows());
sessions.then(r -> {
logging.record(DurableTaskStep.class, Level.FINE).record(FileMonitoringTask.class, Level.FINE);
// Cannot use regular JenkinsRule.createSlave due to JENKINS-26398.
// Nor can we can use JenkinsRule.createComputerLauncher, since spawned commands are killed by CommandLauncher somehow (it is not clear how; apparently before its onClosed kills them off).
DumbSlave s = new DumbSlave("dumbo", tmp.getRoot().getAbsolutePath(), new JNLPLauncher(true));
s.setNumExecutors(1);
s.setRetentionStrategy(RetentionStrategy.NOOP);
r.jenkins.addNode(s);
startJnlpProc(r);
DumbSlave s = r.createSlave("dumbo", null, null);
WorkflowJob p = r.createProject(WorkflowJob.class, "demo");
File f1 = new File(r.jenkins.getRootDir(), "f1");
File f2 = new File(r.jenkins.getRootDir(), "f2");
Expand All @@ -259,13 +231,11 @@ private void startJnlpProc(JenkinsRule r) throws Exception {
}
r.waitForMessage("waiting", b);
assertTrue(b.isBuilding());
killJnlpProc();
});
sessions.then(r -> {
WorkflowJob p = (WorkflowJob) r.jenkins.getItem("demo");
WorkflowRun b = p.getLastBuild();
assertTrue(b.isBuilding()); // TODO occasionally fails; log ends with: ‘Running: Allocate node : Body : Start’ (no shell step in sight)
startJnlpProc(r); // Have to relaunch JNLP agent, since the Jenkins port has changed, and we cannot force JenkinsRule to reuse the same port as before.
File f1 = new File(r.jenkins.getRootDir(), "f1");
File f2 = new File(r.jenkins.getRootDir(), "f2");
assertTrue(f2.isFile());
Expand All @@ -276,7 +246,6 @@ private void startJnlpProc(JenkinsRule r) throws Exception {
r.assertBuildStatusSuccess(r.waitForCompletion(b));
r.assertLogContains("finished waiting", b);
r.assertLogContains("OK, done", b);
killJnlpProc();
});
}

Expand All @@ -290,9 +259,7 @@ private void startJnlpProc(JenkinsRule r) throws Exception {
logging.record(DurableTaskStep.class, Level.FINE).record(FileMonitoringTask.class, Level.FINE);
int count = 3_000;
sessions.then(r -> {
DumbSlave s = new DumbSlave("dumbo", tmp.getRoot().getAbsolutePath(), new JNLPLauncher(true));
r.jenkins.addNode(s);
startJnlpProc(r);
DumbSlave s = r.createSlave("dumbo", null, null);
WorkflowJob p = r.createProject(WorkflowJob.class, "p");
p.setDefinition(new CpsFlowDefinition("node('dumbo') {sh 'set +x; i=0; while [ $i -lt " + count + " ]; do echo \"<<<$i>>>\"; sleep .01; i=`expr $i + 1`; done'}", true));
WorkflowRun b = p.scheduleBuild2(0).waitForStart();
Expand All @@ -301,7 +268,6 @@ private void startJnlpProc(JenkinsRule r) throws Exception {
});
sessions.then(r -> {
WorkflowRun b = r.jenkins.getItemByFullName("p", WorkflowJob.class).getBuildByNumber(1);
startJnlpProc(r);
r.assertBuildStatusSuccess(r.waitForCompletion(b));
// Paying attention to the per-node log rather than whole-build log to exclude issues with copyLogs prior to JEP-210:
FlowNode shNode = new DepthFirstScanner().findFirstMatch(b.getExecution(), new NodeStepTypePredicate("sh"));
Expand All @@ -319,19 +285,14 @@ private void startJnlpProc(JenkinsRule r) throws Exception {
}
System.out.printf("Lost content: %.02f%%%n", lost * 100.0 / count);
System.out.printf("Duplicated content: %.02f%%%n", (seen - count) * 100.0 / count);
killJnlpProc();
});
}

@Test public void buildShellScriptAcrossDisconnect() throws Throwable {
Assume.assumeFalse("TODO not sure how to write a corresponding batch script", Functions.isWindows());
sessions.then(r -> {
logging.record(DurableTaskStep.class, Level.FINE).record(FileMonitoringTask.class, Level.FINE);
DumbSlave s = new DumbSlave("dumbo", tmp.getRoot().getAbsolutePath(), new JNLPLauncher(true));
s.setNumExecutors(1);
s.setRetentionStrategy(RetentionStrategy.NOOP);
r.jenkins.addNode(s);
startJnlpProc(r);
Slave s = inboundAgents.createAgent(r, "dumbo");
WorkflowJob p = r.createProject(WorkflowJob.class, "demo");
File f1 = new File(r.jenkins.getRootDir(), "f1");
File f2 = new File(r.jenkins.getRootDir(), "f2");
Expand All @@ -349,11 +310,11 @@ private void startJnlpProc(JenkinsRule r) throws Exception {
assertTrue(b.isBuilding());
Computer c = s.toComputer();
assertNotNull(c);
killJnlpProc();
inboundAgents.stop("dumbo");
while (c.isOnline()) {
Thread.sleep(100);
}
startJnlpProc(r);
inboundAgents.start(r, "dumbo");
while (c.isOffline()) {
Thread.sleep(100);
}
Expand All @@ -365,7 +326,6 @@ private void startJnlpProc(JenkinsRule r) throws Exception {
r.assertBuildStatusSuccess(r.waitForCompletion(b));
r.assertLogContains("finished waiting", b); // TODO sometimes is not printed to log, despite f2 having been removed
r.assertLogContains("OK, done", b);
killJnlpProc();
});
}

Expand All @@ -377,11 +337,7 @@ public void contextualizeFreshFilePathAfterAgentReconnection() throws Throwable
logging.record(DurableTaskStep.class, Level.FINE).
record(FilePathDynamicContext.class, Level.FINE).
record(WorkspaceList.class, Level.FINE);
DumbSlave s = new DumbSlave("dumbo", tmp.getRoot().getAbsolutePath(), new JNLPLauncher(true));
s.setNumExecutors(1);
s.setRetentionStrategy(RetentionStrategy.NOOP);
r.jenkins.addNode(s);
startJnlpProc(r);
Slave s = inboundAgents.createAgent(r, "dumbo");
WorkflowJob p = r.createProject(WorkflowJob.class, "demo");
File f1 = new File(r.jenkins.getRootDir(), "f1");
File f2 = new File(r.jenkins.getRootDir(), "f2");
Expand Down Expand Up @@ -414,18 +370,17 @@ public void contextualizeFreshFilePathAfterAgentReconnection() throws Throwable
String workspacePath = actions.get(0).getWorkspace().getRemote();
assertWorkspaceLocked(computer, workspacePath);
LOGGER.info("killing agent");
jnlpProc.destroyForcibly();
inboundAgents.stop("dumbo");
long lastMessageMillis = System.currentTimeMillis();
while (computer.isOnline()) {
if (TimeUnit.MILLISECONDS.toSeconds(System.currentTimeMillis() - lastMessageMillis) > 30) {
LOGGER.info(() -> "Waiting for " + computer.getNode() + " to go offline. JNLP Process is " + (jnlpProc.isAlive() ? "alive" : "not alive"));
LOGGER.info(() -> "Waiting for " + computer.getNode() + " to go offline. JNLP Process is " + (inboundAgents.isAlive("dumbo") ? "alive" : "not alive"));
lastMessageMillis = System.currentTimeMillis();
}
Thread.sleep(100);
}
jnlpProc = null;
LOGGER.info("restarting agent");
startJnlpProc(r);
inboundAgents.start(r, "dumbo");
while (computer.isOffline()) {
Thread.sleep(100);
}
Expand All @@ -441,7 +396,6 @@ public void contextualizeFreshFilePathAfterAgentReconnection() throws Throwable
r.assertLogContains("finished waiting", b);
r.assertLogContains("Back again", b);
r.assertLogContains("OK, done", b);
killJnlpProc();
});
}

Expand Down

0 comments on commit 493c2cb

Please sign in to comment.