String interpolation not replacing with actual value in Jenkins Groovy - jenkins

I am trying to replace value of a Yaml file with yq and global variable declared in my jenkins.groovy script. The Code does not throw any error but it is not replacing the values and Yaml remains unchanged.
stage('Clone abc repository and prepare abc-installer') {
agent { label LABEL_CICD }
steps {
sshagent(credentials:['jenkins-deploy-password']) {
sh 'whoami; PWD=$(pwd); SCRIPT_DIR=${PWD}/installer; \
yq -i \'.abc-server.image.tag = $IMAGE_TAG\' ${SCRIPT_DIR}/manifests/abc/values-single.yaml; \
cat ${SCRIPT_DIR}/manifests/abc/values-single.yaml; \
yq -i \'.spec.source.targetRevision = $ARGO_TARGETREVISION\' ${SCRIPT_DIR}/manifests/abc/abc.yaml; \
cat ${SCRIPT_DIR}/manifests/abc/abc.yaml; \
}
}
}

You should be using double quotes for String interpolation to work.
sh """
whoami; PWD=$(pwd); SCRIPT_DIR=${PWD}/installer; \
yq -i \'.abc-server.image.tag = $IMAGE_TAG\' ${SCRIPT_DIR}/manifests/abc/values-single.yaml; \
cat ${SCRIPT_DIR}/manifests/abc/values-single.yaml; \
yq -i \'.spec.source.targetRevision = $ARGO_TARGETREVISION\' ${SCRIPT_DIR}/manifests/abc/abc.yaml; \
cat ${SCRIPT_DIR}/manifests/abc/abc.yaml;
"""

Related

Dynamic variable in Jenkins pipeline with configFileProvider

I am trying to replace the the DB cred based on the env name in Jenkins, but I am unable to achieve the same.
I have a JSON Config Files like this named 'JsonConfig'
{
"production": {
"DB_USERNAME": "userABC"
},
"development": {
"DB_USERNAME": "userXYZ"
}
}
and this what I have in Jenkinsfile
def getEnvName() {
if ("master".equals(env.BRANCH_NAME)) {
return "production";
}
return env.BRANCH_NAME;
}
def config;
node(){
configFileProvider([configFile(fileId: 'secret-credentials', targetLocation: 'JsonConfig')]) {
config = readJSON file: 'JsonConfig'
}
}
pipeline {
agent any
stages {
stage("Setup") {
when {
beforeAgent true
anyOf { branch 'master', branch 'development' }
}
steps {
sh """
sed -i 's#__DB_USERNAME__#config.${getEnvName()}.DB_USERNAME#' ./secret-data.yml
cat ./secret-data.yml
"""
//Alternative
sh "sed -i 's#__DB_USERNAME__#${config.getEnvName().DB_USERNAME}#' ./secret-data.yml"
}
}
}
}
If I statically pass the var name like this, then it is working fine.
sh "sed -i 's#__DB_USERNAME__#${config.production.DB_USERNAME}#' ./k8s/secret-data.yml"
I want to make "production" dynamic so that it reads the value which is returned from getEnvName() method.
The problematic line is
sh """
sed -i 's#__DB_USERNAME__#config.${getEnvName()}.DB_USERNAME#' ./secret-data.yml
"""
This will evaluate as the shell command
sed -i 's#__DB_USERNAME__#config.production.DB_USERNAME#' ./secret-data.yml
But you want to be evaluated to
sed -i 's#__DB_USERNAME__#userABC#' ./secret-data.yml
Since the config is a Groovy object representing the parsed JSON file we can access its properties dynamically using the subscript operator ([]):
sh """
sed -i 's#__DB_USERNAME__#${config[getEnvName()].DB_USERNAME}#' ./secret-data.yml
"""

Jenkinsfile groovy unable to use arguments in method

How do I call a method with arguments from a Jenkinsfile.
def upload_nightly_build(local_filename, remote_filename)
{
sh 'curl --output $local_filename http://someserver:8000/firmware/$remote_filename'
sh 'curl -F upload_file=#$local_filename http://someserver:8000/frontend/file_upload_handler'
sh 'rm $local_filename'
}
pipeline
{
agent
{
dockerfile
{
dir 'dockerfiles'
filename 'Dockerfile-integration.tests'
}
}
stages
{
stage('upload binaries')
{
steps
{
dir ("firmware")
{
upload_nightly_build('iobox-1024-nightly.bin', 'iobox-1024.bin')
}
}
}
}
}
Tried so far
encapsulate usage of arguments in method with braces
define arguments as String
define arguments with def
used named arguments using Map
Whatever I try, in Jenkins console output I will always see
+ curl --output http://someserver:8000/firmware/
curl: no URL specified!
Sigh... found it myself eventually..
sh "curl --output $local_filename http://someserver:8000/firmware/$remote_filename"
Double quote the sh argument... I should've known...

Jenkins script how to compare two string variables

def pname = "netstat -ntlp|grep 8080|awk '{printf \$7}'|cut -d/ -f2"
sh "echo $pname" \ java
if ("java".equals(pname)) { sh "echo 1111" }
The process corresponding to port 8080 is a java process, and the 2nd line print "java". But the body of the if statement just doesn't execute.
You seem to be not executing the command correctly. Please refer to the following sample. Please note the returnStdout: true to return output of the command.
pipeline {
agent any
stages {
stage('Test') {
steps {
script {
def pname = sh(returnStdout: true, script: "netstat -ntlp|grep 8080|awk '{printf \$7}'|cut -d/ -f2").trim()
if (pname == "java") {
echo "echo 1111"
}
}
}
}
}
}
try
"==" for equal
or you can read doc.
https://groovy-lang.org/operators.html#_relational_operators

Error while executing 'curl' inside jenkins groovy

I'm trying to use Groovy and curl to create a ServiceNow change ticket using their REST API. I get the below error every time I run the Jenkins pipeline
{"error":{"message":"Exception while reading request","detail":"Cannot decode: java.io.StringReader#90e4d8"},"status":"failure"}
What am I doing wrong here?
Jenkins version 2.150.2
{
node(){
stage ('Create Change Request') {
echo("Creating Change Request")
sh(script: """curl ${SERVICENOW_URL}/table/change_request \
--request POST \
--header 'Accept:application/json' \
--header 'Content-Type:application/json' \
--data '{"requested_by": "${params.requested_by}",
"u_verifier":"${params.u_verifier}",
"assigned_to":"${params.assigned_to}",
"reason":"${params.reason}",
"type":"${params.type}",
"start_date":"${params.start_date}",
"end_date":"${params.end_date}",
"change_plan":"${params.change_plan}",
"short_description":"${SHORT_DESCRIPTION}",
"description":"${DESCRIPTION}",
"backout_plan":"${BACKOUT_PLAN}",
"u_verification_plan":"${U_VERIFICATION_PLAN}",
"u_department_subsidiary":"${U_DEPARTMENT_SUBSIDIARY}",
"u_tested":"${U_TESTED}",
"u_have_verification_plan":"${U_HAVE_VERIFICATION_PLAN}",
"u_have_implementation_plan":"${U_HAVE_IMPLEMENTATION_PLAN}",
"u_have_backout_plan":"${U_HAVE_BACKOUT_PLAN}",
"assignment_group":"${U_ASSIGNMENT_GROUP}",
"category":"${CATEGORY}",
"cmdb_ci":"${CMDB_CI}",
"u_approval_group":"${U_APPROVAL_GROUP}",
"approval":"requested",
"state":"${_STATE}"
}' \
--user 'xxxx':'password' > CREATE_CHG_REQUEST_OUTPUT
""")
}
stage ('Parsing Change Result') {
def REQUEST_OUTPUT = ""
REQUEST_OUTPUT = readFile ('CREATE_CHG_REQUEST_OUTPUT').trim()
//var jsonStr = JSON.stringify(REQUEST_OUTPUT);
echo "REQUEST_OUTPUT:"
echo REQUEST_OUTPUT
def jsonSlurper = new JsonSlurper()
def object = jsonSlurper.parseText(REQUEST_OUTPUT)
NEW_CHANGE_NUMBER = object.result.number
NEW_SYS_ID = object.result.sys_id
echo("New Change Number is : " + NEW_CHANGE_NUMBER )
echo("New sys_id for Change Number : " + NEW_SYS_ID )
}
}
} catch(e) {
echo e.message
} finally {
}
The data has certain variables declared using . in the variable name. Groovy doesn't support the replacement of the variables declared inside the double quotes "". Replace all the variable names having . in them with single quotes ''.
Hope so this helps

Jenkins groovy : set environment variable between quote

I am trying to set a environment variable to a http request header.
For example
""" --header 'Authorization: "${auth}"' """
But probaly due to the quote '...', the ${auth} is not correctly set.
A simple example:
job(jobName) {
wrappers {
environmentVariables {
env('auth', 'something I want to set')
}
}
steps {
shell(''' echo "${auth}" ''')
}
}
my test:
shell(''' echo "${auth}" ''') --> correctly echo
shell(''' echo '"${auth}"' ''') --> not echo correctly
shell(""" echo '"${auth}"' """) --> not echo correctly
per-character escaping: \"
~ auth="test"
~ echo "\"${auth}\""
"test"
concatenation: '"' ${auth} '"'
~ echo '"'${auth}'"'
"test"

Resources