writeJSON groovy writes only first value to file - groovy

Below is my jenkins groovy script to read data and write as json file.
import groovy.json.JsonOutput
def arn = ""
def name = ""
def os = ""
pipeline {
agent any
stages {
stage('Hello') {
steps {
script{
def ret = sh(script: 'aws devicefarm list-devices', returnStdout: true)
def jsonObj = readJSON text: ret
def currentVersion = "13.0"
def values = currentVersion.split('\\.')
def json_str = ""
for(String item: jsonObj.devices) {
os = item.os
if(!os.contains("\\.")) {
osV = os + ".0"
} else{
osV = os
}
def osValues = osV.split('\\.')
if(values[0].toInteger() <= osValues[0].toInteger()) {
name = item.name
def data = [
name: "$name",
os: "$os",
]
json_str += JsonOutput.toJson(data)
}
}
def json_beauty = JsonOutput.prettyPrint(json_str)
writeJSON(file: 'message124.json', json: json_beauty)
}
}
}
}
}
But here, it only saves the first value. Not all the values. Could you tell me where I am wrong here

It's not 100% clear what you actually want to end up with, but I think you want a JSON file containing the items where OS is greater than a magic number.
It's helpful to provide enough data to duplicate the problem, and eliminate everything that isn't directly related. I think what you want is something like this:
jsonObj = [
devices: [
[ os: '3', name: 'Name 1'],
[ os: '10.2', name: 'Name 10.2'],
[ os: '7', name: 'Name 7'],
[ os: '3', name: 'Name 3'],
],
]
values = ['5']
def normalizeOs(os) {
os.contains(".") ? os : "$os.0"
}
def shouldSkip(normalizedOs) {
osValues = os.split('\\.')
values[0].toInteger() > osValues[0].toInteger()
}
selected = []
for (item: jsonObj.devices) {
os = normalizeOs(item.os)
if (shouldSkip(os)) continue
selected.push([name: item.name, os: os])
}
json = new groovy.json.JsonBuilder(selected)
println(json)
Outputs:
[{"name":"Name 7","os":"7.0"},{"name":"Name 10.2","os":"10.2"}]

Related

Pass list as a parameter to function and iterate through in Groovy

I am a newbie in groovy thus it might be a broad question but any help will be appreciated. I have to pass each index in the keys Set to the createFixVersion as an argument but could find how should I do this.
The main thing is that I am trying to do is, I have to create a fixversion for each of projects in the keys list where currently prepared for hardcoded and only for a single project. How can I do this?
def keys = [CMPNT, DBCCO, OPP]
def fixVersionFromJira = jira.createFixVersion([
name: fixVersionName,
project: keys, --> not sure this is correct
released: false
])
println fixVersionFromJira
public def createFixVersion(Map args) {
if(!config.jira.projectKey) {
throw new Exception("'jira.projectKey' not set in library configuration!")
}
def defaultArgs = [
name: '',
project: config.jira.projectKey,
archived: false,
released: true
]
def payloadArgs = defaultArgs + args
arguments.checkRequired(payloadArgs, defaultArgs.keySet().collect())
def payload = [
name: payloadArgs.name,
description: payloadArgs.description ? payloadArgs.description : '',
userReleaseDate: payloadArgs.userReleaseDate ? payloadArgs.userReleaseDate : '',
project: payloadArgs.project,
archived: payloadArgs.archived,
released: payloadArgs.released,
]
def json = JsonOutput.toJson(payload)
return
post([data: json, api: "version/"])
}
I'm not sure, I've got the full context, but I see you want to apply some workflow for multiple projects data, so here I tried to show how it might be implemented.
But it's highly likely this code should be adjusted with understanding all the details of your context.
def projects = [
[
key : 'CMPNT',
fixVersionName: '1',
released : false
],
[
key : 'DBCCO',
fixVersionName: '1.1',
released : false
],
[
key : 'OPP',
fixVersionName: '1.2',
released : false
],
]
projects.each { project ->
project.fixVersionFromJira = jira.createFixVersion([
name : project.fixVersionName,
project : project.key,
released: project.released
])
}
projects.each { project ->
createFixVersion(project)
}
public def createFixVersion(Map project) {
if (!project.key) {
throw new Exception("'jira.projectKey' not set in library configuration!")
}
def defaultArgs = [
name : project.fixVersionFromJira,
project : project.key,
archived: false,
released: project.released
]
def payloadArgs = defaultArgs + args
arguments.checkRequired(payloadArgs, defaultArgs.keySet().collect())
def payload = [
name : payloadArgs.name,
description : payloadArgs.description ? payloadArgs.description : '',
userReleaseDate: payloadArgs.userReleaseDate ? payloadArgs.userReleaseDate : '',
project : payloadArgs.project,
archived : payloadArgs.archived,
released : payloadArgs.released,
]
def json = JsonOutput.toJson(payload)
post([data: json, api: "version/"])
}

Nested loop based on json response in Terraform for multiple resource target

Array:
regions = [
{name: "region1"},
{name: "region2"},
{name: "region3"},
{name: "region4"},
{name: "region5"},
{name: "region6"}]
Json:
{
"region1" : ["cluster1"],
"region2" : [],
"region3" : ["cluster1"],
"region4" : ["cluster1","cluster2"]
}
resource "type" "name" {
count = length(regionLength)
name = "region-name/cluster-name"
}
I need resource created with such name output like this
region1/cluster1
region2
region3/cluster1
region4/cluster1
region4/cluster2
Can we achieve this too:
Final = []
For r , cs in arr:
for oc in regions:
if r == oc.name:
for c in cs:
oc[‘cluster’] = r-c
Final.push(oc)
Thanks in advance.
You can achieve that as folllows:
variable "regions" {
default = {
"region1" : ["cluster1"],
"region2" : [],
"region3" : ["cluster1"],
"region4" : ["cluster1","cluster2"]
}
}
locals {
region_list = flatten([for region, clusters in var.regions:
[ for cluster in coalescelist(clusters, [""]):
"${region}/${cluster}"
]
])
}
which gives:
region_list = [
"region1/cluster1",
"region2/",
"region3/cluster1",
"region4/cluster1",
"region4/cluster2",
]

Extract nested json map

Have JSON received from some REST API:
{
"advertiser_id": {
"8253":{
"name":"Signify",
"id":8253
},
"2920":{
"name":"Hyundai",
"id":2920
}
}
}
I wan't to extract maps inside numbers like 8253, 2920 but without hard mapping these numbers, they can be different at any time. Anyway these numbers just duplicates id inside.
Expected output after transformation:
[
{
"name":"Signify",
"id":8253
},
{
"name":"Hyundai",
"id":2920
}
]
Tried with:
import groovy.json.*
def json = '''
'''
def p = new JsonSlurper().parseText(json)
def result = p["advertiser_id"].collectEntries{ k, v ->
[
id: v.id,
name: v.name
]
}
But it returns only one "object":
{
"id": 8905,
"name": "Spotify"
}
Also achieved wrong result with next code:
def a = p["advertiser_id"].collectMany {
it.value.collect{ k, v ->
[
id: k,
name: v
]
}
}
you want to build a list - so you need collect instead of collectEntries
def p = new JsonSlurper().parseText(json)
def result = p["advertiser_id"].collect{ k, v ->
[
id: v.id,
name: v.name
]
}
and you are not doing any transformation to nested objects - so, you could simplify the code to this:
def result = p.advertiser_id.collect{ k, v -> v }

How to find and get values from a json file which are in the same level?

I have a JSON file which looks like below. I am getting the parameters for name and product_version. Using both of them I need to get the relese_version and latest boolean value.
eg:- If var1 = section1 var2 = 2.6.0 then the release_version should be taken as 2.6.0.9 and latest as false in groovy.
file.json
{
"platforms": [
{
"name": "section1",
"versions": [
{
"product_version": "2.6.0",
"release_version": "2.6.0.9",
"latest": false
},
{
"product_version": "3.0.0",
"release_version": "3.0.0.3",
"latest": false
}
]
},
{
"name": "section2",
"versions": [
{
"product_version": "2.6.0",
"release_version": "2.6.0.9",
"latest": false
},
{
"product_version": "3.0.0",
"release_version": "3.0.0.3",
"latest": false
}
]
}
]
}
This is the code snippet I tried out.
filename = "file.json"
def jsonSlurper = new JsonSlurper()
parsed_json = jsonSlurper.parse(new File(filename))
release_tag = json.parsed_json.find {platforms.name == "section1".version[].product_version == "2.6.0".release_version}
println release_tag
But this didn't work. Please help me with this
You first have to find the platform by name (which could fail); next
find in the versions the product version. E.g.
def data = new groovy.json.JsonSlurper().parse("data.json" as File)
def name='section1'
def productVersion = '2.6.0'
// XXX
def result = data.platforms.find{ it.name == name }?.versions?.find{ it.product_version == productVersion }
assert result.release_version == '2.6.0.9'
assert result.latest == false
Note the use of the "elvis operator" after the first find to
short-circuit.
If you have to do many such lookups on the same data file, it might make
sense to shape the data into a better form for the lookup you are doing
(e.g. turn that into maps of maps for your two lookup keys)

parsing boto3 describe_stacks response

Is there a more efficient way to parse the following response from cloudformation
I tried for loop but I am wondering if there is a better way
response = {
'Stacks': [
{
'Outputs': [
{
'Description': 'ARN of the load balancer',
'ExportName': 'xx',
'OutputKey': 'LoadBalancerARN',
'OutputValue': 'arn:aws:elasticloadbalancing:ss'
},
{
'Description': 'ARN of the ecs service',
'ExportName': 'xxx',
'OutputKey': 'ServiceARN',
'OutputValue': 'arn:aws:ecs:5O'
},
{
'Description': 'ARN of the ecs task definition',
'ExportName': 'xxx',
'OutputKey': 'TaskDefinitionARN',
'OutputValue': 'arn:aws:ecs:xxx9'
}
]
}
]
}
def main(response):
outputs = response['Stacks'][0]['Outputs']
for output in outputs:
for k, v in output.items():
if 'OutputKey' in k and 'ServiceARN' in v:
print('ServiceARN:{}'.format(output['OutputValue']))
if 'OutputKey' in k and 'TaskDefinitionARN' in v:
print('TaskDefinitionARN:
{}'.format(output['OutputValue']))
main(response)
I trying to get ServiceARN and TaskDefinitionARN values
I found another option
import json
response = {}
def main(response):
json_string = json.dumps(response)
x = json.loads(json_string)
for i in x['Stacks'][0]['Outputs']:
if i['OutputKey'] == "ServiceARN":
print(i['OutputValue'])
main(response)

Resources