How to check the actual assigned label of a queued build via REST API?

17 views
Skip to first unread message

Rafael Rezende

unread,
Sep 21, 2019, 10:28:45 PM9/21/19
to Jenkins Users
I would like to use the REST API to get the list of queue builds and their respective "assigned label". Basically, I need to know that a build is waiting in the queue for a node with label X.

Through the REST API (/queue/api/json?pretty=true) I'm able to get the reason why the build is pending, which does not always tell me the label.

Example:
-----
If I trigger a build for a label that's not provided by any of the current nodes, this is the why I get:
"There are no nodes with the label ‘MyTestNonExistingLabel"

The Jenkins API will tell me the exact label 'MyTestNonExistingLabel' through the method Queue.Item#getAssignedLabel()

-----
However, if I trigger a build for a label that's provided by one of the current nodes, and the node in question is busy, the why statement is completely different:
"Waiting for next available executor on ‘NodeWithTestLabels’"

The method Queue.Item#getAssignedLabel() from the Jenkins API, on the other hand, will return the actual label that the queued build is expecting: MyTestLabel.


By all means, the Queue.Item#getAssignedLabel() consistently provides the information I need, which is the label for which the pending build is waiting, regardless of whether there are no matching nodes or if the matching ones are busy.
The why attribute of the REST API is a mere human-readable string with often insufficient information.

So, is there any way of getting that information using only the REST API?

Ivan Fernandez Calvo

unread,
Sep 22, 2019, 12:29:13 PM9/22/19
to Jenkins Users
The short answer is not with that API, we have the same issue several months ago, this API exposes the message that it show in the logs, it is completely useless to grab the labels. We initially try to parse the message but it has several different patterns so we decided that way was error prone and weak, thus we changed the approach and use the groovy console to grab queue objects

Rafael Rezende

unread,
Sep 22, 2019, 5:37:27 PM9/22/19
to Jenkins Users
Do you do that remotely? Like injecting a script using the jenkins-cli.jar?

I considered using the REST API to fetch the labels of the node referenced in the "why" message, but that would be meaningful only if the node had a single label.
For multiple labels, again, I would be unable to tell which one is required.

I wonder how hard it would be to add this element to the REST API. It might be worth checking.

Ivan Fernandez Calvo

unread,
Sep 23, 2019, 5:24:59 AM9/23/19
to Jenkins Users

El domingo, 22 de septiembre de 2019, 23:37:27 (UTC+2), Rafael Rezende escribió:
Do you do that remotely? Like injecting a script using the jenkins-cli.jar?

we use Go but you can use curl or any HTTP client, it is something like this

JENKINS_CRUMB=$(curl --silent "$JENKINS_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,\":\",//crumb)")
curl --silent -X POST -H "${JENKINS_CRUMB}" -F "script=<script.groovy" ${JENKINS_URL}/scriptText

--script.groovy
import hudson.model.*
def queue = Hudson.instance.queue
println "Queue contains ${queue.items.length} items"
queue.items.each{
  println it.toString()
  println "label: ${it.getAssignedLabel()}"
}



 

I considered using the REST API to fetch the labels of the node referenced in the "why" message, but that would be meaningful only if the node had a single label.
For multiple labels, again, I would be unable to tell which one is required.

I wonder how hard it would be to add this element to the REST API. It might be worth checking.


yep, this data should be in the API, probably it is a matter of adding an annotation in the Class
 

Rafael Rezende

unread,
Sep 25, 2019, 5:08:44 AM9/25/19
to Jenkins Users
we use Go but you can use curl or any HTTP client, it is something like this

JENKINS_CRUMB=$(curl --silent "$JENKINS_URL/crumbIssuer/api/xml?xpath=concat(//crumbRequestField,\":\",//crumb)")
curl --silent -X POST -H "${JENKINS_CRUMB}" -F "script=<script.groovy" ${JENKINS_URL}/scriptText
 

Interesting, thanks!
We use jenkins-cli, more or less like this:

cat script.groovy | java -jar ./jenkins-cli.jar -ssh -user userID -i key_rsa -s "${server}" groovy =  >> output.xml

Probably based on an old approach. I'll switch it with curl...
 

yep, this data should be in the API, probably it is a matter of adding an annotation in the Class
 

Indeed, the data is there, it seems that an @Exported annotation would do it:


I'm not sure about the implications though.

Anyway, I would like to get the Label because I need to know in advance whether I should connect a node to that Master or not. But I forgot the fact that the Label can be a regular expression, and that kind of kills my purpose because I would then need to resolve the expression also in advance. And replicating the Jenkins mechanism for that wouldn't be so wise in the long term.

I tried to use the method Jenkins.instance.queue.countBuildableItemsFor(Label) to ask Jenkins itself to check that for me, but that didn't work for me as I expected...

For example, I triggered a build that requests the expression "myLabelA || myLabelB". Then I programmatically created a Label that would match that. Yet, Jenkins couldn't match it for some reason:

import hudson.model.labels.*

Jenkins.instance.queue.items.each {
  println
">> Label expression from the pending build:"
 
def labelFromQueueJob = it.getAssignedLabel()
  println
"Type: " + labelFromQueueJob.class
  println
"Expression: " + labelFromQueueJob
  println
">> countBuildableItemsFor " + labelFromQueueJob + " : " + Jenkins.instance.queue.countBuildableItemsFor(labelFromQueueJob)
}

println
"\n>> Artificially created Label expression:"
LabelExpression artificialLabelExp = new LabelExpression.Or(new LabelAtom("myLabelA"),new LabelAtom("myLabelB"))
println
"Type: " + artificialLabelExp.class
println
"Expression: " + artificialLabelExp
println
">> countBuildableItemsFor " + artificialLabelExp + " : " + Jenkins.instance.queue.countBuildableItemsFor(artificialLabelExp)

Output:

>> Label expression from the pending build:
Type: class hudson.model.labels.LabelExpression$Or
Expression: myLabelA||myLabelB
>> countBuildableItemsFor myLabelA||myLabelB : 1

>> Artificially created Label expression:
Type: class hudson.model.labels.LabelExpression$Or
Expression: myLabelA||myLabelB
>> countBuildableItemsFor myLabelA||myLabelB : 0


No questions left. I'm glad that you pointed out that curl solution. I've certainly overlook it!
Reply all
Reply to author
Forward
0 new messages