7

I have been trying to find a lightweight method in a Groovy scriptler script to list all currently running jobs of any type. The only method I have found to be reliable is this:

start = System.currentTimeMillis()  
def jobsFound = []
def buildingJobs = Jenkins.instance.getAllItems(Job.class).findAll {
            it.isBuilding()
    }
buildingJobs.each { job->
    allRuns = job._getRuns()
    allRuns.each {  item->
        if (!item.isBuilding()) {  return  } // This job is not building
    jobsFound.push(item.getUrl())
    }
}

timespent = (System.currentTimeMillis() - start ) / 1000
println "Time: ${timespent} seconds"
println "{jobsFound.size} jobs"

// RESULTS:
//   Time: 2.015 seconds. 15 jobs

The problem is that the above enumerates ALL currently running jobs - we have thousands! - then enumerate all builds of each of those running jobs (some jobs have as many as 300 builds). The above can take as long as FIVE minutes to complete depending on how many jobs are currently building.

A much more efficient method is to enumerate the active executors but this method MISSES the pipeline (aka Workflow) jobs running on the master:

start = System.currentTimeMillis()  

def busyExecutors = Jenkins.instance.computers.collect { 
   c -> c.executors.findAll { it.isBusy() }
}.flatten() 

def jobsFound = []
busyExecutors.each { e -> 
     job = e.getCurrentExecutable()
     jobsFound.push(job.getUrl())
}

timespent = (System.currentTimeMillis() - start ) / 1000
println "Time: ${timespent} seconds. ${jobsFound.size} jobs"

// RESULTS:  
//    Time: 0.005 seconds. 12 jobs

Sure enough the discrepancy between the two counts are pipeline jobs running on the master.

I guess my question boils down to:

Is there a way to efficiently enumerate all jobs running on the master?

Clearly Jenkins does not include the master in computers, and although there is a MasterComputer class, its not clear how to get it or the OffByOneExecutors on which flyweight (pipeline) jobs run.

1 Answers1

0

Not directly with Jenkins types/objects but via Jenkins' Remote access API derived from From Jenkins, how do I get a list of the currently running jobs in JSON?:

http://localhost:8080/api/xml?&tree=jobs[builds[*]]&xpath=/hudson/job/build[building="true"]&wrapper=builds

results in:

<builds>
    <build _class="hudson.model.FreeStyleBuild">
        <action _class="hudson.model.CauseAction"/>
        <action/>
        <action/>
        <building>true</building>
        <displayName>#10</displayName>
        <duration>0</duration>
        <estimatedDuration>3617</estimatedDuration>
        <executor/>
        <fullDisplayName>Freestyle-Project #10</fullDisplayName>
        <id>10</id>
        <keepLog>false</keepLog>
        <number>10</number>
        <queueId>2</queueId>
        <timestamp>1499611190781</timestamp>
        <url>http://localhost:8080/job/Freestyle-Project/10/</url>
        <builtOn/>
        <changeSet _class="hudson.scm.EmptyChangeLogSet"/>
    </build>
</builds>

Unfortunately <builtOn/>, which, I guess, is supposed to refer to the node, isn't supplied in my Jenkins v2.60.1 (yet?).

With:

http://localhost:8080/api/json?pretty=true

you get:

...
"nodeDescription" : "the master Jenkins node",
...
"jobs" : [
  {
    "_class" : "hudson.model.FreeStyleProject",
    "name" : "Freestyle-Project",
    "url" : "http://xmg:8080/job/Freestyle-Project/",
    "color" : "aborted_anime"
  }
]
...

which you can filter then with:

nodeDescription.equals('the master Jenkins node') && color.endsWith('_anime').
Gerold Broser
  • 14,080
  • 5
  • 48
  • 107
  • Thanks, @Gerold Broser: that URL returns nothing on my system. We are making use of Folders. I am wary of xpath as my understanding is that it constructs the entire tree before doing the filtering... so this `https://MYJENKINS/api/xml?&tree=jobs[builds[*],jobs[builds[*],jobs[builds[*]]]]&xpath=/hudson/job/build[building=%22true%22]&wrapper=builds` works but is very costly. – Steven the Easily Amused Jul 09 '17 at 17:05
  • 1
    By the way the [item you referenced](https://stackoverflow.com/a/22403584/1655780) contains another method which seems to be much more efficient: `http://jenkins.example.com/computer/api/xml?tree=computer[executors[currentExecutable[url]],oneOffExecutors[currentExecutable[url]]]&xpath=//url&wrapper=builds` It is the addition of the "oneOffExecutors" that reveals the pipeline jobs. – Steven the Easily Amused Jul 09 '17 at 17:09
  • 1
    This API call would put Jenkins down on a bigger instance (~1500 jobs/20-30 running). If you are lucky you may endup with a gateway timeout, if not with a down Jenkins instance. – sorin Jun 21 '18 at 10:54