Skip to content

Commit

Permalink
[FIXED JENKINS-19300] add condition to restrict execution on a set of…
Browse files Browse the repository at this point in the history
… nodes
  • Loading branch information
imod committed Oct 5, 2013
1 parent a3af644 commit 9e35ee7
Show file tree
Hide file tree
Showing 4 changed files with 199 additions and 0 deletions.
@@ -0,0 +1,125 @@
/*
* The MIT License
*
* Copyright (C) 2013 by Dominik Bartholdi
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
* THE SOFTWARE.
*/

package org.jenkins_ci.plugins.run_condition.core;

import hudson.Extension;
import hudson.model.BuildListener;
import hudson.model.AbstractBuild;
import hudson.model.ComputerSet;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;

import jenkins.model.Jenkins;

import org.jenkins_ci.plugins.run_condition.Messages;
import org.jenkins_ci.plugins.run_condition.common.AlwaysPrebuildRunCondition;
import org.kohsuke.stapler.DataBoundConstructor;

public final class NodeCondition extends AlwaysPrebuildRunCondition {

private static final String MASTER = "master";

final List<String> allowedNodes;

@DataBoundConstructor
public NodeCondition(List<String> allowedNodes) {
this.allowedNodes = allowedNodes;
}

public List<String> getAllowedNodes() {
return allowedNodes == null ? Collections.<String> emptyList() : allowedNodes;
}

@Override
public boolean runPerform(final AbstractBuild<?, ?> build, final BuildListener listener) {

String currentNode = build.getExecutor().getOwner().getName();
currentNode = "".equals(currentNode) ? MASTER : currentNode;
listener.getLogger().println(Messages.nodeCondition_check(currentNode, Arrays.toString(getAllowedNodes().toArray())));
return getAllowedNodes().contains(currentNode);

}

/**
* returns all available nodes plus an identifier to identify all slaves at position one.
*
* @return list of node names
*/
public static List<String> getNodeNamesForSelection() {
List<String> slaveNames = NodeConditionDescriptor.getSlaveNames();
Collections.sort(slaveNames, NodeNameComparator.INSTANCE);
return slaveNames;
}

/**
* Comparator preferring the master name
*/
private static final class NodeNameComparator implements Comparator<String> {
public static final NodeNameComparator INSTANCE = new NodeNameComparator();

public int compare(String o1, String o2) {
if (MASTER.endsWith(o1)) {
return -1;
}
return o1.compareTo(o2);
}
}

@Extension
public static class NodeConditionDescriptor extends RunConditionDescriptor {

@Override
public String getDisplayName() {
return Messages.nodeCondition_displayName();
}

/**
* Gets the names of all configured slaves, regardless whether they are online.
*
* @return list with all slave names
*/
@SuppressWarnings("deprecation")
private static List<String> getSlaveNames() {
ComputerSet computers = Jenkins.getInstance().getComputer();
List<String> slaveNames = computers.get_slaveNames();

// slaveNames is unmodifiable, therefore create a new list
List<String> test = new ArrayList<String>();
test.addAll(slaveNames);

// add 'magic' name for master, so all nodes can be handled the same way
if (!test.contains(MASTER)) {
test.add(0, MASTER);
}
return test;
}

}

}
Expand Up @@ -35,6 +35,8 @@ stringsMatchCondition.displayName=Strings match
timeCondition.displayName=Time
dayCondition.displayName=Day of week
causeCondition.displayName=Build Cause
nodeCondition.displayName=Execution node
nodeCondition.check=check if [{0}] is in [{1}]

logic.and.displayName=And
logic.or.displayName=Or
Expand Down
@@ -0,0 +1,44 @@
<?jelly escape-by-default='true'?>
<!--
~ The MIT License
~
~ Copyright (C) 2013 by Dominik Bartholdi
~
~ Permission is hereby granted, free of charge, to any person obtaining a copy
~ of this software and associated documentation files (the "Software"), to deal
~ in the Software without restriction, including without limitation the rights
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
~ copies of the Software, and to permit persons to whom the Software is
~ furnished to do so, subject to the following conditions:
~
~ The above copyright notice and this permission notice shall be included in
~ all copies or substantial portions of the Software.
~
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
~ THE SOFTWARE.
-->

<j:jelly xmlns:j="jelly:core" xmlns:f="/lib/form">

<f:entry name="allowedNodes" title="Execute on" >
<select name="allowedNodes" multiple="multiple" size="5">
<j:invokeStatic className="org.jenkins_ci.plugins.run_condition.core.NodeCondition" method="getNodeNamesForSelection" var="allNodes" />
<j:forEach var="aNode" items="${allNodes}" varStatus="loop">
<j:choose>
<j:when test="${instance.allowedNodes.contains(aNode)}">
<option value="${aNode}" selected="selected">${aNode}</option>
</j:when>
<j:otherwise>
<option value="${aNode}">${aNode}</option>
</j:otherwise>
</j:choose>
</j:forEach>
</select>
</f:entry>

</j:jelly>
@@ -0,0 +1,28 @@
<?jelly escape-by-default='true'?>
<!--
~ The MIT License
~
~ Copyright (C) 2013 by Dominik Bartholdi
~
~ Permission is hereby granted, free of charge, to any person obtaining a copy
~ of this software and associated documentation files (the "Software"), to deal
~ in the Software without restriction, including without limitation the rights
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
~ copies of the Software, and to permit persons to whom the Software is
~ furnished to do so, subject to the following conditions:
~
~ The above copyright notice and this permission notice shall be included in
~ all copies or substantial portions of the Software.
~
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
~ THE SOFTWARE.
-->

<j:jelly xmlns:j="jelly:core">
<div>Run only on selected nodes.</div>
</j:jelly>

0 comments on commit 9e35ee7

Please sign in to comment.