Finding jobs generated by Job DSL plugin programmatically - jenkins

We have a mix of DSL-seeded and manually created jobs on our Jenkins server.
I'd like to find all jobs NOT generated by DSL (or all generated by DSL at any time in the past).
I found no indication in job's config.xml that it was generated by DSL.
So, is it possible and how?

Well, I have the same problem as you.
I wonder how the link "Seed job" within the generated job is created. I don't see it in all of the generated jobs, either.
Unfortunately, I didn't get very far with my research.
In the script console, I listed the methods for one of my jobs (let's call it foo) :
Jenkins.instance.getItems().each {
if (it.getName() == 'foo') {
println it
it.class.getMethods().each { method ->
println method
}
}
};
However, I didn't see any methods containing jobdsl there.
I found a file $JENKINS_HOME/javaposse.jobdsl.plugin.ExecuteDslScripts.xml that contains generated job names and their seed jobs. But I don't know whether there is an official JobDSL API for reading it.
So... if you find more information, I'd be glad to know - good luck!

Related

How to know where a Jenkins job is created in groovy code

When a Jenkins JobDSL seed job finishes creating other jobs, it shows a list of generated jobs.
For example:
GeneratedJob{name='my_example'}
GeneratedJob{name='my_mvn-test'}
Is there a way to print out at which line and in which file a job is created?
For instance:
10: job ("${prefix}-${prodname}-${suffix}") {
11: ...
...
20: }
Here line 10 is the location of job creation.
We have a big bunch of jobs generated in different dsl/groovy src files, and those jobs don't use fixed job names in the code, so it's hard to find where they are created without knowing the source code well.
Searched for things like Job DSL API hooks, but with no luck…
You can change your jobdsl code to print that information, you should be able to add println with custom messages anywhere in your code and log whatever is relevant to you.
It requires changing your code but it's a one off cost and it's worth evaluating against your current maintenance cost.
You can even add this information to the description of each job, so you don't depend on the seeder job logs.

Get list of jobs which created via job-dsl and list of manual jobs

Part of the job was generated through job-dsl, but there is still part of the job that was created by manual. If Jenkins has a mechanism or api to get a list of all manual jobs.
I see that all jobs through job-dsl have a mark which job created them(seed job). Perhaps having received a list of all generated ones, you can take a list of all jobs and weed out manual ...
JobDSL saves information about generated jobs in the javaposse.jobdsl.plugin.ExecuteDslScripts.xml file, example:
<?xml version='1.1' encoding='UTF-8'?>
<javaposse.jobdsl.plugin.DescriptorImpl plugin="job-dsl#1.77">
<templateJobMap class="com.google.common.collect.HashMultimap" serialization="custom">
<com.google.common.collect.HashMultimap>
<default/>
<int>8</int>
<int>0</int>
</com.google.common.collect.HashMultimap>
</templateJobMap>
<generatedJobMap class="concurrent-hash-map">
<entry>
<string>generated-job-name1</string>
<javaposse.jobdsl.plugin.SeedReference>
<seedJobName>job-which-created-it</seedJobName>
<digest>hash1</digest>
</javaposse.jobdsl.plugin.SeedReference>
</entry>
<entry>
<string>generated-job-name2</string>
<javaposse.jobdsl.plugin.SeedReference>
<seedJobName>job-which-created-it</seedJobName>
<digest>hash2</digest>
</javaposse.jobdsl.plugin.SeedReference>
</entry>
...
</generatedJobMap>
</javaposse.jobdsl.plugin.DescriptorImpl>
If you parse the file and collect all javaposse.jobdsl.plugin.DescriptorImpl/generatedJobMap/entry/string values then you get a list of all generated jobs.
You can next get all jobs by using Jenkins.get().getItems(), collect all names and at the end remove those which were found in the javaposse.jobdsl.plugin.ExecuteDslScripts.xml file.
EDIT:
The file keeps an XML representation of the javaposse.jobdsl.plugin.DescriptorImpl class. You can also get it programmatically: Jenkins.get().getDescriptorByType(Class<?> type).
def jenkins = Jenkins.get()
def clazz = Class.forName('javaposse.jobdsl.plugin.DescriptorImpl', true, jenkins.pluginManager.uberClassLoader)
def descriptor = jenkins.getDescriptorByType(clazz)
descriptor.generatedJobMap // map with listed previously entries
I found a way using the script console!
TL;DR:
Jenkins.instance.jobNames.findAll {
job = Jenkins.instance.getItemByFullName(it)
a = job.getAction(javaposse.jobdsl.plugin.actions.SeedJobAction.class)
return a?.isConfigChanged()
}.each {
println it
}
Explanation
It took some digging (and I've no idea what I'm doing; maybe there's an easy way). I noticed that all the information I was looking for was readily available on the "front page" of jobs. Information here can be added via plugins. After searching the JobDsl code for the string "Seed job:" I came across this file, which is a Jelly file. After some guesswork I came up with the code above.
The a object has getters for the information you see accessed via the it object in the Jelly file, e.g. getSeedJob(). For checking whether the config changed you prefix it with is instead of get, presumably because it returns a boolean. If a is null then it was not generated by a seed job.
If you want to automate: Jenkins has a detailed rest api where you can fetch information about jobs etc. You will get JSON objects back which then need to be interpreted.
https://www.jenkins.io/doc/book/using/remote-access-api/
To check if the Api provides the information you need, you can use http://jenkins:8080/job/yourjob/api/json?pretty=true

Jenkins Job DSL for timestamps is not working

I am working with Jenkins Job DSL and can not seem to get a couple of the tags to work. One of those is timestamps(). In each of my jobs we have checked off the following field
Add timestamps to the Console Output
and I believe this translates to timestamps(). When I run the seed job to create the job Add timestamps to the Console Output is not checked.
My code:
wrappers {
preBuildCleanup {
deleteDirectories(false)
cleanupParameter()
}
timeout {
absolute(10)
}
timestamps()
colorizeOutput("String colorMap = 'xterm'")
}
The DSL was created with the XML Job To DSL plugin for Jenkins which added that field.
I may have misinterpreted something here but it seems pretty straight forward.
Any help would be greatly appreciated. I've google quite a bit but have not found anything that might help.
Thank you.
It required a restart of the Jenkins instance and now it is displaying as expected.

Jenkins Job DSL Plugin: How to Modify Parameters on other jobs

I want to create a job in Jenkins which modifies an existing parameter on another job.
I'm using the Job DSL Plugin. The code I'm using is:
job('jobname'){
using('jobname')
parameters {
choiceParam('PARAMETER1',['newValue1', 'newValue2'],'')
}
}
However, this only adds another parameter with the same name in the other job.
I'm trying the alternative to delete all parameters and start from scratch, but I haven't found the way to do that using Job DSL (not even with the Configure block).
Another alternative would be to define the other job completely and start from scratch, but that would make the job too complicated, specially if I want to apply this change to many jobs at a time.
¿Is there a way to edit or delete lines on the config.xml file using the Job DSL plugin?

How to perform a jenkins job save event through the Jenkins API in Groovy?

I'm using the ez-template to create a template and make other jobs, based on that template. Apparently, however, the template is only applied when you manually click either the save or apply buttons. I've used the following Jenkins Job DSL code to try to achieve this:
job("job_name") {
properties {
templateImplementationProperty {
exclusions(['ez-templates', 'job-params', 'disabled', 'description'])
syncAssignedLabel(true)
syncBuildTriggers(true)
syncDescription(false)
syncDisabled(false)
syncMatrixAxis(true)
syncOwnership(true)
syncScm(true)
syncSecurity(true)
templateJobName('template')
}
}
}
This creates the XML for that job just fine, but it is never applied/saved/submitted. How can I achieve this functionality through the Jenkins Job DSL API?
Job DSL uses two Jenkins API methods to create or update jobs, Jenkins#createProjectFromXML(...) (source) and AbstractItem#updateByXml(...) (source). The first method causes a ItemListener#onCreate(...) event and the second one causes a SavableListener#onChange(...) event.
The EZ Template plugin only reacts on ItemListener#onUpdated(...) (source).
If you are using Job DSL, you do not necessarily need the EZ Template plugin as Job DSL provides it's own template mechanism, see https://jenkinsci.github.io/job-dsl-plugin/#path/job-using.
job('job_name') {
using('template')
}
If you still want to use the EZ Template pluign, I suggest to file a feature request for the EZ Template plugin to also react on the two events mentioned above.
Links API docs:
http://javadoc.jenkins-ci.org/jenkins/model/Jenkins.html#createProjectFromXML(java.lang.String,%20java.io.InputStream)
http://javadoc.jenkins-ci.org/hudson/model/AbstractItem.html#updateByXml(javax.xml.transform.Source)
http://javadoc.jenkins-ci.org/hudson/model/listeners/ItemListener.html#onCreated(hudson.model.Item)
http://javadoc.jenkins-ci.org/hudson/model/listeners/SaveableListener.html#onChange(hudson.model.Saveable,%20hudson.XmlFile)
This behaviour is improved in ez-templates 1.3.0

Resources