Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to get a list of all Jenkins nodes assigned with label including master node?

I'm creating a Jenkins pipeline job and I need to run a job on all nodes labelled with a certain label.

Therefore I'm trying to get a list of node names assigned with a certain label. (With a node I can get the labels with getAssignedLabels())

The nodes-list in jenkins.model.Jenkins.instance.nodes seems not contain the master-node which I need to include in my search.

My current solution is to iterate over the jenkins.model.Jenkins.instance.computers and use the getNode()-method to get the node. This works, but in the javadoc of Jenkins I'm reading the this list might not be up-to-date.

In the long-run I will add (dynamically) cloud-nodes and I'm afraid that I won't be able to use computers then.

What is the right way to get the list of all current nodes?

This is what I'm doing right now:

@NonCPS
def nodeNames(label) {
    def nodes = []
    jenkins.model.Jenkins.instance.computers.each { c ->
        if (c.node.labelString.contains(label)) {
            nodes.add(c.node.selfLabel.name)
        }
    }   
    return nodes
}
like image 320
Patrick B. Avatar asked Oct 25 '17 13:10

Patrick B.


People also ask

How do I view labels in Jenkins?

I use the Scriptler plugin with the "show labels overview" script that is available from the remote script catalogue. This draws an ascii art table of all nodes versus all labels and makes it easy to see at a glance all the labels that are defined and what nodes use them. Show activity on this post.

How do I get Jenkins nodes?

Click on Manage Jenkins in the left corner on the Jenkins dashboard. Click on Manage Nodes. Select New Node and enter the name of the node in the Node Name field. Select Permanent Agent and click the OK button.

What is label parameter in Jenkins?

Define a parameter for the node(s) that will run the job. Define a label of 'Restrict where this project can be run'.

What is node name in Jenkins?

As part of the terminology cleanup effort, the built-in node was renamed from "master node" to "built-in node" in Jenkins 2.307 and in Jenkins 2.319.


7 Answers

Updated answer: in a pipeline use nodesByLabel to get all nodes assigned to a label.

like image 130
towel Avatar answered Oct 03 '22 23:10

towel


This is the way I'm doing it right now. I haven't found anything else:

@NonCPS
def hostNames(label) {
  def nodes = []
  jenkins.model.Jenkins.get().computers.each { c ->
    if (c.node.labelString.contains(label)) {
      nodes.add(c.node.selfLabel.name)
    }
  }
  return nodes
}

jenkins.model.Jenkins.get.computers contains the master-node and all the slaves.

like image 43
Patrick B. Avatar answered Oct 03 '22 23:10

Patrick B.


Update to @patrick-b answer : contains can be buggy if you have labels containing same string, I've added a split step do check every label separated with spaces.

@NonCPS
def hostNames(label) {
    def nodes = []
    jenkins.model.Jenkins.get.computers.each { c ->
        c.node.labelString.split(/\s+/).each { l ->
            if (l != null && l.equals(label)) {
                nodes.add(c.node.selfLabel.name)
             }
        }
    }

    return nodes
}
like image 45
k4cy Avatar answered Oct 04 '22 00:10

k4cy


Here is a functional solution which is more readable and concise:

def nodes = jenkins.model.Jenkins.get().computers
  .findAll{ it.node.labelString.contains(label) }
  .collect{ it.node.selfLabel.name }

You can verify it in the Jenkins Script Console.

like image 41
Boris Avatar answered Oct 04 '22 01:10

Boris


Try using for (aSlave in hudson.model.Hudson.instance.slaves) {} and aSlave.getLabelString()); to get all the labels for all of your nodes. You can construct a list of nodes per label this way.

like image 42
kirkpatt Avatar answered Oct 03 '22 23:10

kirkpatt


I think that you can do this with:

def nodes = Jenkins.get.getLabel('my-label').getNodes()
for (int i = 0; i < nodes.size(); i++) {
    node(nodes[i].getNodeName()) {
        // on node
    }
}

I don't know for sure whether this works with cloud nodes.

like image 31
Russell Gallop Avatar answered Oct 04 '22 00:10

Russell Gallop


using nodesByLabel as pointed out by @towel is probably the solution in most cases. One limitation I found with nodesByLabel is that there is no way to indiscriminately select all nodes. I can't use any of the other solutions either because of script security, some of these can be pretty dangerous, so I preferred not to approve them for usage.

As an alternatively, you can add a function as a pipeline library, which will allow usage of these functions. Since pipeline libraries can be set up so they are fully under the administrator's control, it's safer to go with this route. To do so, set up a pipeline library (I don't think it matters if it's global or not, but for me it is). Then add the following contents to the file vars/parallelRunOnNodes.groovy:

def call(Closure callback) {
    parallel jenkins.model.Jenkins.get().computers.collectEntries { agent ->
        def nodeLabel = agent.node.selfLabel.name
        ["${nodeLabel}": {
            node("${nodeLabel}") {
                stage("${nodeLabel}") {
                    callback(nodeLabel)
                }
            }
        }]
    }
}

Which can then be used as follows:

pipeline {
    agent none
    stages {
        stage('Parallel on all nodes') {
            steps {
                parallelRunOnNodes { nodeLabel ->
                    println(nodeLabel)
                }
            }
        }
    }
}

Obviously adjust as you see fit, e.g. you can add additional parameters to filter, maybe you don't care about parallel etc.

like image 22
Hosh Sadiq Avatar answered Oct 03 '22 23:10

Hosh Sadiq