Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[JENKINS-37809] Throttling based on parameters does not work with Pipeline jobs #117

Merged
merged 1 commit into from
Mar 12, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -315,7 +315,7 @@ private boolean isAnotherBuildWithSameParametersRunningOnAnyNode(Queue.Item item
private boolean isAnotherBuildWithSameParametersRunningOnNode(Node node, Queue.Item item) {
ThrottleJobProperty tjp = getThrottleJobProperty(item.task);
if (tjp == null) {
// If the property has been ocasionally deleted by this call,
// If the property has been occasionally deleted by this call,
// it does not make sense to limit the throttling by parameter.
return false;
}
Expand Down Expand Up @@ -389,11 +389,22 @@ private List<ParameterValue> doFilterParams(List<String> params, List<ParameterV
public List<ParameterValue> getParametersFromWorkUnit(WorkUnit unit) {
List<ParameterValue> paramsList = new ArrayList<>();

if (unit != null && unit.context != null && unit.context.actions != null) {
List<Action> actions = unit.context.actions;
for (Action action : actions) {
if (action instanceof ParametersAction) {
paramsList = ((ParametersAction)action).getParameters();
if (unit != null && unit.context != null) {
if (unit.context.actions != null && !unit.context.actions.isEmpty()) {
List<Action> actions = unit.context.actions;
for (Action action : actions) {
if (action instanceof ParametersAction) {
paramsList = ((ParametersAction) action).getParameters();
}
}
} else if (unit.context.task instanceof PlaceholderTask) {
PlaceholderTask placeholderTask = (PlaceholderTask) unit.context.task;
Run<?, ?> run = placeholderTask.run();
if (run != null) {
List<ParametersAction> actions = run.getActions(ParametersAction.class);
for (ParametersAction action : actions) {
paramsList = action.getParameters();
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ public class TestUtil {

// TODO move this into ThrottleJobProperty and use consistently; same for "project".
static final String THROTTLE_OPTION_CATEGORY = "category";
static final String THROTTLE_OPTION_PROJECT = "project";

static final ThrottleJobProperty.ThrottleCategory ONE_PER_NODE =
new ThrottleJobProperty.ThrottleCategory("one_per_node", 1, 0, null);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,9 @@
import hudson.model.FreeStyleProject;
import hudson.model.Label;
import hudson.model.Node;
import hudson.model.ParametersDefinitionProperty;
import hudson.model.Queue;
import hudson.model.StringParameterDefinition;
import hudson.model.queue.QueueTaskFuture;
import hudson.plugins.throttleconcurrents.testutils.ExecutorWaterMarkRetentionStrategy;
import hudson.security.GlobalMatrixAuthorizationStrategy;
Expand All @@ -59,7 +61,6 @@
import org.jvnet.hudson.test.SleepBuilder;
import org.jvnet.hudson.test.TestBuilder;

import java.io.IOException;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
Expand Down Expand Up @@ -266,6 +267,60 @@ public void twoTotal() throws Exception {
j.assertBuildStatusSuccess(j.waitForCompletion(thirdJobFirstRun));
}

@Test
public void limitOneJobWithMatchingParams() throws Exception {
Node agent = TestUtil.setupAgent(j, firstAgentTmp, agents, null, null, 2, null);

FreeStyleProject project = j.createFreeStyleProject();
project.setAssignedNode(agent);
ParametersDefinitionProperty pdp =
new ParametersDefinitionProperty(
new StringParameterDefinition("FOO", "foo", ""),
new StringParameterDefinition("BAR", "bar", ""));
project.addProperty(pdp);
project.setConcurrentBuild(true);
project.addProperty(
new ThrottleJobProperty(
null, // maxConcurrentPerNode
null, // maxConcurrentTotal
Collections.emptyList(),
true, // throttleEnabled
TestUtil.THROTTLE_OPTION_PROJECT, // throttleOption
true,
"FOO,BAR",
ThrottleMatrixProjectOptions.DEFAULT));
SequenceLock firstRunSeq = new SequenceLock();
SequenceLock secondRunSeq = new SequenceLock();
project.getBuildersList().add(new SequenceLockBuilder(firstRunSeq, secondRunSeq));

FreeStyleBuild firstRun = project.scheduleBuild2(0).waitForStart();
firstRunSeq.phase(1);

QueueTaskFuture<FreeStyleBuild> secondRunFuture = project.scheduleBuild2(0);
j.jenkins.getQueue().maintain();
assertFalse(j.jenkins.getQueue().isEmpty());
Queue.Item queuedItem =
Iterables.getOnlyElement(Arrays.asList(j.jenkins.getQueue().getItems()));
Set<String> blockageReasons = TestUtil.getBlockageReasons(queuedItem.getCauseOfBlockage());
assertThat(
blockageReasons,
hasItem(
Messages._ThrottleQueueTaskDispatcher_OnlyOneWithMatchingParameters()
.toString()));
assertEquals(1, agent.toComputer().countBusy());

firstRunSeq.done();
j.assertBuildStatusSuccess(j.waitForCompletion(firstRun));

FreeStyleBuild secondRun = secondRunFuture.waitForStart();
secondRunSeq.phase(1);
j.jenkins.getQueue().maintain();
assertTrue(j.jenkins.getQueue().isEmpty());
assertEquals(1, agent.toComputer().countBusy());
secondRunSeq.done();
j.assertBuildStatusSuccess(j.waitForCompletion(secondRun));
}

@Issue("JENKINS-25326")
@Test
public void testThrottlingWithCategoryInFolder() throws Exception {
Expand Down Expand Up @@ -314,17 +369,21 @@ public void testThrottlingWithCategoryInFolder() throws Exception {

private static class SequenceLockBuilder extends TestBuilder {

private final SequenceLock sequenceLock;
private final List<SequenceLock> sequenceLocks;

private SequenceLockBuilder(SequenceLock sequenceLock) {
this.sequenceLock = sequenceLock;
private SequenceLockBuilder(SequenceLock... sequenceLock) {
this.sequenceLocks = Arrays.asList(sequenceLock);
}

@Override
public boolean perform(AbstractBuild<?, ?> build, Launcher launcher, BuildListener listener)
throws InterruptedException, IOException {
sequenceLock.phase(0);
sequenceLock.phase(2);
throws InterruptedException {
for (int i = 0; i < sequenceLocks.size(); i++) {
if ((build.number - 1) == i) {
sequenceLocks.get(i).phase(0);
sequenceLocks.get(i).phase(2);
}
}
return true;
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,9 @@
import com.google.common.collect.Iterables;

import hudson.model.Node;
import hudson.model.ParametersDefinitionProperty;
import hudson.model.Queue;
import hudson.model.StringParameterDefinition;
import hudson.model.queue.QueueTaskFuture;

import org.jenkinsci.plugins.workflow.cps.CpsFlowDefinition;
Expand All @@ -23,6 +25,7 @@
import org.junit.Test;
import org.junit.rules.TemporaryFolder;
import org.jvnet.hudson.test.BuildWatcher;
import org.jvnet.hudson.test.Issue;
import org.jvnet.hudson.test.JenkinsRule;

import java.util.ArrayList;
Expand Down Expand Up @@ -192,6 +195,60 @@ public void twoTotal() throws Exception {
j.assertBuildStatusSuccess(j.waitForCompletion(thirdJobFirstRun));
}

@Issue("JENKINS-37809")
@Test
public void limitOneJobWithMatchingParams() throws Exception {
Node agent = TestUtil.setupAgent(j, firstAgentTmp, agents, null, null, 2, null);

WorkflowJob project = j.createProject(WorkflowJob.class);
ParametersDefinitionProperty pdp =
new ParametersDefinitionProperty(
new StringParameterDefinition("FOO", "foo", ""),
new StringParameterDefinition("BAR", "bar", ""));
project.addProperty(pdp);
project.setConcurrentBuild(true);
project.setDefinition(getJobFlow(project.getName(), agent.getNodeName()));
project.addProperty(
new ThrottleJobProperty(
null, // maxConcurrentPerNode
null, // maxConcurrentTotal
Collections.emptyList(),
true, // throttleEnabled
TestUtil.THROTTLE_OPTION_PROJECT, // throttleOption
true,
"FOO,BAR",
ThrottleMatrixProjectOptions.DEFAULT));

WorkflowRun firstRun = project.scheduleBuild2(0).waitForStart();
SemaphoreStep.waitForStart("wait-" + project.getName() + "-job/1", firstRun);

QueueTaskFuture<WorkflowRun> secondRunFuture = project.scheduleBuild2(0);
j.jenkins.getQueue().maintain();
assertFalse(j.jenkins.getQueue().isEmpty());
Queue.Item queuedItem =
Iterables.getOnlyElement(Arrays.asList(j.jenkins.getQueue().getItems()));
Set<String> blockageReasons = TestUtil.getBlockageReasons(queuedItem.getCauseOfBlockage());
assertThat(
blockageReasons,
hasItem(
Messages._ThrottleQueueTaskDispatcher_OnlyOneWithMatchingParameters()
.toString()));
assertEquals(1, agent.toComputer().countBusy());
TestUtil.hasPlaceholderTaskForRun(agent, firstRun);

SemaphoreStep.success("wait-" + project.getName() + "-job/1", null);
j.assertBuildStatusSuccess(j.waitForCompletion(firstRun));

WorkflowRun secondRun = secondRunFuture.waitForStart();
SemaphoreStep.waitForStart("wait-" + project.getName() + "-job/2", secondRun);
j.jenkins.getQueue().maintain();
assertTrue(j.jenkins.getQueue().isEmpty());
assertEquals(1, agent.toComputer().countBusy());
TestUtil.hasPlaceholderTaskForRun(agent, secondRun);
SemaphoreStep.success("wait-" + project.getName() + "-job/2", null);
j.assertBuildStatusSuccess(j.waitForCompletion(secondRun));
}

static CpsFlowDefinition getJobFlow(String jobName, String label) {
return new CpsFlowDefinition(getThrottleScript(jobName, label), true);
}
Expand Down