Jenkins Groovy with XMLSlurper Error "failed to serialize" - jenkins

I am on Jenksin 2.46.2 and have a job that uses Active Choices Reactive Parameter. I select my servers in my first selection from a XML file using XMLSlurper and reference that for my second selection. When I hardcode the server name the code works fine. When I use the variable in my code I get an error.
This code works:
def serverList = new XmlSlurper().parse("/app/jenkins/jobs/servers.xml")
def SERVER = 'testserver1'
def output = []
serverList.Server.find { it.#name == SERVER}.CleanUp.GZIP.File.each{
it.output.add(p)
}
return output
When I reference the variable selection from my previous selection I get the error:
def serverList = new XmlSlurper().parse("/app/jenkins/jobs/servers.xml")
def SERVER = SERVER
def output = []
serverList.Server.find { it.#name == SERVER}.CleanUp.GZIP.File.each{
it.output.add(p)
}
return output
The error that I am getting is below. Any idea why I get an error?
WARNING: failed to serialize [[/app/test2/log], [/app/test2/log]] for ...*other text*... net.sf.json.JSONException: There is a cycle in the hierarchy!
Here is my XML file:
<ServerList>
<Server name="testserver1">
<CleanUP>
<GZIP>
<File KeepDays="30">/app/test1/log</File>
</GZIP>
</CleanUP>
</Server>
<Server name="testserver2">
<CleanUP>
<GZIP>
<File KeepDays="30">/app/test2/log</File>
</GZIP>
</CleanUP>
</Server>
</ServerList>
NE.jpg

Here is the script that you need, which reads the value of File element and returns a list:
def serverList = new XmlSlurper().parse("/app/jenkins/jobs/servers.xml")
return serverList.'**'.findAll{ it.name() == 'File'}*.text()
Output:
[/app/test1/log, /app/test2/log]
EDIT: based on OP comments
def server = 'testserver1'
def serverList = new XmlSlurper().parse("/app/jenkins/jobs/servers.xml")
def result = serverList.'**'.find{ it.#name == server}.CleanUP.GZIP.File
println result
return result
EDIT2:
If you want list or array, try below:
def server = 'testserver1'
def serverList = new XmlSlurper().parse("/app/jenkins/jobs/servers.xml")
def result = serverList.'**'.findAll{ it.#name == server}*.CleanUP.GZIP.File.text()
println result
return result

Related

Jenkins: Set job timeout from a variable in scripted pipeline

I premise that I am not very familiar with Jenkins and Groovy.
I am trying to set a timeout with a time value that can change based on a specific condition. I was wondering if it is possible to do this and how.
This is a shortened example for simplicity, of the pipeline I'm dealing with:
/**
* prepare tests for parallel
* #param filename Name of the file that contains the testsuites list
*/
def doDynamicParallelSteps(filename){
tests = [:]
echo "doDynamicParallelSteps"
def w = pwd()
def path = "$w/$filename"
// read all the lines into a list, each line is an element in the list
def fh = new File(path)
def lines = fh.readLines()
for (line in lines) {
def values = line.split(":")
def testsuite_name = values[0].trim()
def test_path = values[1].trim()
def test_filename_or_directory = test_path.split("/").getAt(-1);
def is_file = test_filename_or_directory.matches("(.*).php")
def is_custom_mycondition = test_filename_or_directory.matches("MyMatchCondition")
if (is_custom_mycondition){ // large timeout
def time_val = 10
} else { // default timeout
def time_val = 5
}
tests["${test_filename_or_directory}"] = {
stage("UnitTest ${test_filename_or_directory}") {
timeout(time: time_val, unit: 'MINUTES') { // scripted syntax
// other stuff here
} // end timeout
} // end stage
} // end MAP
}
parallel tests
}
If I run this pipeline I got the following output:
hudson.remoting.ProxyException: groovy.lang.MissingPropertyException: No such property: time_val for class: mycustomJob
Then I've tried to set it as global value and it worked but not as expected, because its value doesn't seems to changed, it outputs "5" ignoring my condition.
What am I doing wrong? Can anyone show me the right way or a better approach?
What you are doing looks more pythonic than groovy. You must define the variable 'time_val' on a higher level to make it visible in your scope, like:
def time_val = 5
if (is_custom_mycondition){ // large timeout
time_val = 10
}
Instead of your else part.
You can also define it in a single line, like:
def time_val = is_custom_mycondition ? 10 : 5
Your 'timeout' usage looks correct to me. Just define the variable properly.

Getting a second parameter based on the first parameter in Jenkins

I have a task where my Jenkins job needs two parameters for build. The first specifies the application name and can be either QA, Dev, Prod etc and the second is a server which is dependent on the first one.
Example: If I chose the app name as QA, the second parameter should display values like QAServer1, QAServer2, QAServer3.
I'm using Active Choices Plugin (https://wiki.jenkins.io/display/JENKINS/Active+Choices+Plugin) to get this done but facing an problem in fetching the second parameter contents.
Snapshots:
For obtaining the second parameter, I've written a Groovy code which reads the respective files of the selected first parameter and gets the details.
code:
#!/usr/bin/env groovy
import hudson.model.*
def Appliname = System.getenv("APPNAME")
//println Appliname
def list1 = []
def directoryName = "C:/Users/Dev/Desktop/JSONSTest"
def fileSubStr = Appliname
def filePattern = ~/${fileSubStr}/
def directory = new File(directoryName)
def findFilenameClosure =
{
if (filePattern.matcher(it.name).find())
{
def jsoname = it.name
def jsoname1 = jsoname.reverse().take(9).reverse()
list1.add(jsoname1.substring(1,4))
String listAsString = "[\'${list1.join("', '")}\']"
println "return"+listAsString
}
}
directory.eachFileRecurse(findFilenameClosure)
The above code will print the output as return['QAServer1', 'QAServer2'] which i want to use it as input for the second parameter.
Snapshot of Second parameter:
Somehow the Groovy script is not being executed and second parameter value remains empty. How can i get this done dynamically. Am i following the right away to it. Kindly help me figure out. TIA
Would you like to try below change
From:
def findFilenameClosure =
{
if (filePattern.matcher(it.name).find())
{
def jsoname = it.name
def jsoname1 = jsoname.reverse().take(9).reverse()
list1.add(jsoname1.substring(1,4))
String listAsString = "[\'${list1.join("', '")}\']"
println "return"+listAsString
}
}
directory.eachFileRecurse(findFilenameClosure)
To:
directory.eachFileRecurse {
if (filePattern.matcher(it.name).find()) {
def jsoname = it.name
def jsoname1 = jsoname.reverse().take(9).reverse()
list1.add(jsoname1.substring(1,4))
}
}
return list1

Groovy Variable $ Dollar Sign in JSON

I've got a JSON file that I am slurping with groovy.
{
"team": "${GLOBAL_TEAM_NAME}",
"jobs": [
{
In the JSON above is a property 'team' that contains a groovy-like variable I want to be resolved at runtime.
teamList.each { tl ->
try
{
def teamSlurper = new JsonSlurperClassic()
def t = teamSlurper.parseText(tl.text)
println "*********************"
println "PROVISIONING JOB FOR: " + t.team
Output:
PROVISIONING JOB FOR: ${GLOBAL_TEAM_NAME}
The above outputs the raw value, but I would like it to resolve the global variable that has been defined for the system.
How can I resolve ${GLOBAL_TEAM_NAME} to its actual system value?
You can do this with Groovy Templates.
def slurper = new groovy.json.JsonSlurperClassic()
def engine = new groovy.text.SimpleTemplateEngine()
def binding = ["GLOBAL_TEAM_NAME": "Avengers"]
def json = '{"team":"${GLOBAL_TEAM_NAME}"}'
def t = slurper.parseText(engine.createTemplate(json).make(binding).toString())
t.team // "Avengers"

Jenkins…Access XML Tag value in xml file using Groovy in Jenkins

I am using groovy script for automated deployment in jenkins.
In have a xml file, I want to read specific xml tag value from that xml file and assign it's value to a variable. Letter I am using that variable to write excel file. Below is the script. After executing the build it seems that I am not able to access the xml tag value. It seems the code inside of each function is not working. Can anyone please help me on this
def Build_Name= ""
def Build_Number= ""
def CR_Number=""
def Build_Status= ""
def Build_Failure_Reason=""
def Build_Date=""
Build_Number= "1201"
CR_Number="123"
Build_Status= "SUCCESS"
Build_Failure_Reason="NA"
Build_Date=""
boolean fileSuccessfullyDeleted = new File("/export/home/webm/.jenkins/Build_Report.csv").delete()
f = new File("/export/home/webm/.jenkins/Build_Report.csv")
def Job_Result_file = new File("/export/home/webm/.jenkins/global-build-stats/jobresults/Temp_Job_Result.xml")
//Parse it with XmlSlurper
def xml = new XmlSlurper().parse(Job_Result_file)
xml.list.jbr.each { sd ->
Build_Name= sd.n[0].value
f.append("\r\n"+Build_Name+","+Build_Number+","+CR_Number+","+Build_Status+","+Build_Failure_Reason+","+Build_Date+"")
}
EDIT: based on OP added as answer.
Below is the xml available in xml file and I want to read the value of tag and want to assign that value to a variable. In below xml tag n has value Send_Deployment_Request.
Xml:
<list>
<jbr plugin="global-build-stats#1.4">
<r>SUCCESS</r>
<n>Send_Deployment_Request</n>
<nb>187</nb>
<d>
<time>1502879887698</time>
<timezone></timezone>
</d>
<du>973</du>
<nn>master</nn>
<un></un>
</jbr>
<jbr plugin="global-build-stats#1.4">
<r>SUCCESS</r>
<n>Deploy</n>
<nb>187</nb>
<d>
<time>1502879887698</time>
<timezone></timezone>
</d>
<du>973</du>
<nn>master</nn>
<un></un>
</jbr>
</list>
Dear Rao,
Please see my code below.
//Delete if Build_Report fiile already exist
boolean fileSuccessfullyDeleted = new File("/export/home/webmadm/.jenkins/Build_Report.csv").delete()
//Craete new csv file
f = new File("/export/home/webmadm/.jenkins/Build_Report.csv")
def Job_Result_file = new File("/export/home/webmadm/.jenkins/global-build-stats/jobresults/Temp_Job_Result.xml")
def xml = new XmlSlurper().parse(Job_Result_file)
//Change the element name if needed
def Temp_Build_Name= "n"
def Temp_Build_Number= "nb"
def CR_Number=""
def Temp_Build_Status= "r"
def Build_Failure_Reason=""
def Temp_Build_Date="time"
def Temp_Build_Executor="un"
def Build_Name= ""
def Build_Number= ""
def Build_Status= ""
def Build_Date=""
def Build_Executor=""
//Get all the values of Tag - elementToFind
def Build_Name_List= xml.'**'.findAll{'it.name() == Temp_Build_Name'}
def Build_Number_List= xml.'**'.findAll{'it.name() == Temp_Build_Number'}
def Build_Status_List= xml.'**'.findAll{'it.name() == Temp_Build_Status'}
def Build_Date_List= xml.'**'.findAll{'it.name() == Temp_Build_Date'}
def Build_Executor_List= xml.'**'.findAll{'it.name() == Temp_Build_Executor'}
for(int i = 0; i<2; i++)
{
Build_Name= Build_Name_List[i].text()
Build_Number= Build_Number_List[i].text()
Build_Status= Build_Status_List[i].text()
Build_Date= Build_Date_List[i].text()
Build_Executor= Build_Executor_List[i].text()
f.append("\r\n"+Build_Name+","+Build_Number+","+CR_Number+","+Build_Status+","+Build_Failure_Reason+","+Build_Date+"")
}
I am trying to write .csv file. If you see f.append as per that in csc we have Build_Name value , Build_Number value and so on.
But actul result is different, Build_Name also contain the Build_Number, Build_Status Build_Date. Seems .findAll method reading entire tag from xml.
Can't we use .each method as we use it to update the xml node value in xml file
?
Here is what you would need and comments in-line:
def xml = new XmlSlurper().parse(Job_Result_file)
//Change the element name if needed
def elementToFind = 'n'
//Get all the values of Tag - elementToFind
def result = xml.'**'.findAll{it.name() == elementToFind}
println result
//Get the first item from the result
def requiredValue = result[0].text()
println "User required value : $requiredValue"
//Test if the value is as expected
assert 'Send_Deployment_Request' == requiredValue
You can quickly see it online demo

Grails 3 Cookie Plugin - return Null

i am trying to use cookie in grails 3.
i tried this plugin but i don't know why its not work at all..
cookieService.setCookie('username', customer?.email)
and i use this code for call it from gsp
<g:cookie name="username"/>
i also tried this way..
def cokusername = cookieService.setCookie('username', customer?.email)
println "cookieService.getCookie('username') = "+cookieService.getCookie('username')
redirect(controller: "toko",cokusername: cokusername)
and this is in my tokoController.groovy index :
def index={
def toko = CifLogo.executeQuery("from CifLogo order by rand()",[max: 10])
// def itemRandom = Item.executeQuery("from Item where cif = :cif order by rand()",[max:12,cif:cif])
def awdf = cookieService.getCookie('username')
println "awdf = "+awdf
println "cokusername = "+params.cokusername
[tokoList:toko,cokusername:awdf]
}
i have no idea to retrieve my cookie. :(
update
def index(){
def toko = CifLogo.executeQuery("from CifLogo order by rand()",[max: 10])
// def itemRandom = Item.executeQuery("from Item where cif = :cif order by rand()",[max:12,cif:cif])
def awdf = cookieService.getCookie('username')
println "awdf = "+awdf
println "cokusername = "+params.cokusername
[tokoList:toko,cokusername:awdf]
}
i tried to print cookie like this..
def awdf = request.getCookie('username')
println "awdf = "+awdf
println "cokusername = "+params.cokusername
request.cookies.each { println "${it.name} == ${it.value}" }
and this is what the result
From what I can see this line:
redirect(controller: "toko",cokusername: cokusername)
Should be:
redirect(controller: "toko",params:[cokusername: cokusername])
Also actions using closures in grails 3 will have undesired results. You should change to methods. Hence this line:
def index={
SHould be:
def index(){
Apart from this it seems the cookieService code should work fine, so I can only assume its being caused my the closure index that should be a method.
Another thing could be the fact that you are doing a redirect, which will clear the request and not persist any cookies that were set before the redirect
I don't know why, but maybe it's a bug.
i use this code to setCookie
cookieService.setCookie(name:"username", value: customer?.email, maxAge: 24*60*60, path: "/")
after read this code.
and i cannot deleteCookie with this code.
cookieService.deleteCookie(cookieService.findCookie("username"))
because when i print cookieService.findCookie("username") it returns javax.servlet.http.Cookie#78cbf320
and method deleteCookie(Cookie cookie) from this link
so i think it mustbe deleted.
but still availlable.
so i can answer this question about setCookie not deleteCookie
i also tried this way to delete cookie..but still failed.
CookieService.setCookie(name:"username", value: "", maxAge: 0, path: "/")

Resources