Reading a specific yaml value using Groovy - groovy

I have this yaml config file :
environmentMapping:
ci-develop:
inner: ABCD-npr-XA
outer: ABCD-npr-XB
outer-public: ABCD-npr-XC
frontend: ABCD-npr-XD
dev-develop:
inner: BCDE-npr-ZA
outer: BCDE-npr-ZB
outer-public: BCDE-npr-ZC
frontend: BCDE-npr-ZD
And would like to know how I can access a specific value.
here's my code :
configs = readYaml file: 'configs.yaml'
def env = 'ci-develop'
def zone = 'inner'
echo configs.environmentMapping.${env}.${zone}
This does not work.
How can I get the value for ci-develop -> inner ?

configs = readYaml file: 'configs.yaml'
def env = 'ci-develop'
def zone = 'inner'
echo configs.environmentMapping[env][zone]

Related

import json as variable in shell script on windows and linux?

I want to read data from a json file into my azure devops as variable.
I saw this post:
import Azure Devops pipeline variables from json file
But the answer here is only powershell compatible.
Is ther any solution that works with linux and windows agents?
First, powershell should not only works on windows but also works on linux.
Install PowerShell on Linux
Second, for your requirement, I write a demo YAML for you(based on python):
1, Get the value of the specific route of json, and set it as variables in pipeline concept.
trigger:
- none
pool:
vmImage: ubuntu-latest
steps:
- task: PythonScript#0
inputs:
scriptSource: 'inline'
script: |
import json
def get_json_content_of_specific_route(json_file_path, json_route):
length = len(json_route)
# print(length)
#open json file
with open(json_file_path, 'r') as f:
data = json.load(f)
content = data
#get the content f data[json_route[0]][json_route[1]]...[json_route[length-1]]
for i in range(length):
if i == 0:
content = data[json_route[i]]
else:
content = content[json_route[i]]
#get the content
return content
json_file_path = 'Json_Files/parameters.json' #This is the path of the json file.
route = ['parameters', 'secretsPermissions', 'value'] #This is the route of the content you want to get.
content = get_json_content_of_specific_route(json_file_path, route)
print(content)
print("##vso[task.setvariable variable=myJobVar]"+str(content))
- powershell: |
Write-Host $(myJobVar) #you can get the content after you using logging command to set the variables.
The above variables getting from json can be Temporary set and use in pipeline run.
See using logging command to set the variables.
This is the structure of my repository:
Set and get the variable successfully in pipeline run lifecycle:
2, If you want permanent variables, there are two situations.
1' When based on classic pipeline, you need to use these REST API to achieve your requirements:
Get pipeline definition
Change pipeline definition
A python script that can change the variables of the classic pipeline:
import json
import requests
org_name = "xxx"
project_name = "xxx"
pipeline_definition_id = "xxx"
personal_access_token = "xxx"
key = 'variables'
var_name = 'BUILDNUMBER'
url = "https://dev.azure.com/"+org_name+"/"+project_name+"/_apis/build/definitions/"+pipeline_definition_id+"?api-version=6.0"
payload={}
headers = {
'Authorization': 'Basic '+personal_access_token
}
response = requests.request("GET", url, headers=headers, data=payload)
print(response.text)
json_content = response.text
def get_content_of_json(json_content, key, var_name):
data = json.loads(json_content)
return data[key][var_name].get('value')
def change_content_of_json(json_content, key, var_name):
data = json.loads(json_content)
data[key][var_name]['value'] = str(int(get_content_of_json(json_content,key,var_name)) + 1)
return data
json_data = change_content_of_json(json_content, key, var_name)
url2 = "https://dev.azure.com/"+org_name+"/"+project_name+"/_apis/build/definitions/"+pipeline_definition_id+"?api-version=6.0"
payload2 = json.dumps(json_data)
headers2 = {
'Authorization': 'Basic '+personal_access_token,
'Content-Type': 'application/json'
}
response2 = requests.request("PUT", url2, headers=headers2, data=payload2)
2' If your pipeline is based on non-classic pipeline, then you need to change the variables part of YAML file definition.
After you change the YAML definition during pipeline run, you can follow this to push back the changes:
Push Back Changes to Repository
Also, you can make your pipeline based on variables group and update the variables group via REST API:
Variablegroups - Update

Groovy: A groovy linkedhashmap gets converted to a new format when evaluated in a shell module

I am writing a terraform infrastructure pipeline, wherein I take multi-line string param from Jenkins, try to convert it to a map and pass it on to a terraform command.
Following is the code:
import groovy.json.JsonOutput
def parameters = env.params
def config
def service_map = [:]
def service_returned = [:]
node ("master"){
withEnv(['variable="test"', 'DB_ENGINE=sqlite']) {
stage('Input') {
config = readYaml text: "$parameters"
println(config)
config.each{ key, value ->
service_map = "$value"
service_returned = stringToMap(service_map)
println(service_returned)
}
}
stage('Terraform Plan') {
sh
"""
terraform init
terraform plan -var="instance=$service_returned"
"""
}
}
}
def stringToMap(service_string){
def map = [:]
service_string.split(" ").each { param ->
def nameAndValue = param.split(":")
map[nameAndValue[0]] = nameAndValue[1]
}
return map
}
When I print the service_returned map from the method "stringToMap". it gives a map like so:
{service="service", ec2_type="t2.micro"}
which is exactly what is need for terraform as a variable.
But the above code evaluates to this in the console output:
terraform plan -var='instance_ids=[service:"service", ec2_type:"t2.micro"]'
which does not work for terraform.
For reference, this is the input passed in Jenkins:
services:
service:"service"
ec2_type:"t2.micro"
What could be the reason for this?
Is there a way to use the same returned map in the shell module in above code?
there is a problem in terraform command line in your code. should be -var 'foo=bar'
and stringToMap returns not a correct go map syntax
import groovy.json.JsonOutput
//i assume you got this config from yaml
def config = [
services:[
service:"service",
ec2_type:"t2.micro"
]
]
//function that converts groovy plain map to a go lang representation of map
def map2go(map){
return "{"+map.collect{k,v-> "$k=${JsonOutput.toJson(v)}" }.join(",")+"}"
}
goMap = map2go(config.services)
sh """
terraform plan -var 'instance_ids=${goMap}'
"""

Getting variables from a different file in Jenkins Pipeline

I have a contants.groovy file as below
def testFilesList = 'test-package.xml'
def testdataFilesList = 'TestData.xml'
def gitId = '9ddfsfc4-fdfdf-sdsd-bd18-fgdgdgdf'
I have another groovy file that will be called in Jenkins pipeline job
def constants
node ('auto111') {
stage("First Stage") {
container('alpine') {
script {
constants = evaluate readTrusted('jenkins_pipeline/constants.groovy')
def gitCredentialsId = constants."${gitId}"
}
}
}
}
But constants."${gitId}" is says "cannot get gitID from null object". How do I get it?
It's because they are local variables and cannot be referenced from outside. Use #Field to turn them into fields.
import groovy.transform.Field
#Field
def testFilesList = 'test-package.xml'
#Field
def testdataFilesList = 'TestData.xml'
#Field
def gitId = '9ddfsfc4-fdfdf-sdsd-bd18-fgdgdgdf'
return this;
Then in the main script you should load it using load step.
script {
//make sure that file exists on this node
checkout scm
def constants = load 'jenkins_pipeline/constants.groovy'
def gitCredentialsId = constants.gitId
}
You can find more details about variable scope in this answer

Parsing xml file at build time and modify its values/content

I want to parse a xml file during build time in build.gradle file and want to modify some values of xml, i follow this SO question and answer Load, modify, and write an XML document in Groovy but not able to get any change in my xml file. can anyone help me out. Thanks
code in build.gradle :
def overrideLocalyticsValues(String token) {
def xmlFile = "/path_to_file_saved_in_values/file.xml"
def locXml = new XmlParser().parse(xmlFile)
locXml.resources[0].each {
it.#ll_app_key = "ll_app_key"
it.value = "123456"
}
XmlNodePrinter nodePrinter = new XmlNodePrinter(new PrintWriter(new FileWriter(xmlFile)))
nodePrinter.preserveWhitespace = true
nodePrinter.print(locXml)
}
xml file :
<resources>
<string name="ll_app_key" translatable="false">MY_APP_KEY</string>
<string name="ll_gcm_sender_id" translatable="false">MY_GCM_SENDER_ID</string>
</resources>
In your code : Is it right ...? Where is node name and attribute ..?
locXml.resources[0].each { // Wrongly entered without node name
it.#ll_app_key = "ll_app_key" // Attribute name #name
it.value = "123456" // you can't change or load values here
}
You tried to read and write a same file. Try this code which replaces the exact node of the xml file. XmlSlurper provides this facility.
Updated :
import groovy.util.XmlSlurper
import groovy.xml.XmlUtil
def xmlFile = "test.xml"
def locXml = new XmlSlurper().parse(xmlFile)
locXml.'**'.findAll{ if (it.name() == 'string' && it.#name == "ll_app_key") it.replaceBody 12345 }
new File (xmlFile).text = XmlUtil.serialize(locXml)
Groovy has a better method for this than basic replacement like you're trying to do - the SimpleTemplateEngine
static void main(String[] args) {
def templateEngine = new SimpleTemplateEngine()
def template = '<someXml>${someValue}</someXml>'
def templateArgs = [someValue: "Hello world!"]
println templateEngine.createTemplate(template).make(templateArgs).toString()
}
Output:
<someXml>Hello world!</someXml>

Variable substitution not happening in job dsl

Trying to create new jobs whenever there is a new branch entry in my SVN repo and below is the script.
svnCommand = "svn list --xml http://myrepo/svn/repo_name/branches"
def proc = svnCommand.execute()
proc.waitFor()
def xmlOutput = proc.in.text
def lists = new XmlSlurper().parseText(xmlOutput)
def listOfBranches = lists.list.entry.name
listOfBranches.each(){
def branchName = it.text()
println "found branch: '${branchName}'"
}
mavenJob('${branchName}'){
mavenInstallation('M3.3.9')
logRotator(365, 25, -1, -1)
scm {
svn {
location('http://myrepo/svn/repo_name/branches/${branchName}') {
credentials('4t4d8ef-p67a-5298-a011-580ghe898a65')
}
}
}
}
Script is able to iterate thru branches and print the branch names,
found branch: 'feature_01'
but I'm facing the issue , while variable substitution while creating the job name and with the svn branch name.
hudson.model.Failure: ‘$’ is an unsafe character
Jenkins - V.2.32
Job DSL - V.1.57
Any suggestions please.Thanks.
#Rao is right: first - you have to change:
mavenJob('${branchName}')
to:
mavenJob(branchName)
and:
location('http://myrepo/svn/repo_name/branches/${branchName}‌​')
to:
location("http://myrepo/svn/repo_name/branches/${branchName}‌​")
Moreover def branchName = it.text() inside iteration limits scope of variable to this iteration only. Try:
listOfBranches.each() {
branchName = it.text()
println "found branch: '${branchName}'"
}

Resources