executing code dynamically in groovy - grails

I am trying to run code dynamically in groovy. I have someNode[0], which is the value, in variable var1
I then added double quotes to it like this
var2 = "\""+var1+"\""
then I tried to run this
request.abc."$var2"=Value
I saw here that something of this sort can be done on properties and methods. But the above code is not working. Giving me error
An error occurred [Cannot set property '"someNode[0]"' on null object], see error log for details
Any help is appreciated. Thanks.
Edit
Heres a snippet of my request
{
"app":{
"bundle":"531323947",
"cat":[
"IAB1",
"IAB9",
"IAB9-30",
"entertainment",
"games"
],
"id":"agltb3B1Yi1pbmNyDAsSA0FwcBitsL4UDA",
.
.
The field I am trying to manipulate is cat[0], which is IAB1 (I just used abc and someNode[0] in the code that i wrote above but actually they are app and cat[0])
Also, I parsed the request with jsonslurper befor running the above code
Thank you for your help

One way to do this, is by Eval
def request =[
"app":[
"bundle":"531323947",
"cat":[
"IAB1",
"IAB9",
"IAB9-30",
"entertainment",
"games"
],
]
]
assert request.app.cat[0]=='IAB1'
def var = 'request.app.cat[0]'
Eval.me('request', request, "$var = 'new value'")
assert request.app.cat[0]=='new value'

You are accessing/updating values from a map and a list. The request.app node will be a map, the request.app.cat node will be a list. Getting and setting the values in a map can be done in many different ways:
Use the put & get methods directly.
Use brackets [].
Use missing properties as map keys (i.e. the way you are using it).
For what you want to achieve, i.e. to access values from variable keys, it is much easier to use method 1 or 2 instead of method 3 with a variable inside a GString.
Example using brackets:
import groovy.json.JsonBuilder
import groovy.json.JsonSlurper
def request = new JsonSlurper().parseText '''{
"app":{
"bundle":"531323947",
"cat":[
"IAB1",
"IAB9",
"IAB9-30",
"entertainment",
"games"
],
"id":"agltb3B1Yi1pbmNyDAsSA0FwcBitsL4UDA"
}
}'''
def level0 = 'app'
def level1 = 'cat'
def node = request[level0][level1]
assert request instanceof Map
assert node instanceof List
assert node[0] == 'IAB1'
node[0] = 'new value'
assert node[0] == 'new value'
println new JsonBuilder(request).toPrettyString()
Output:
{
"app": {
"cat": [
"new value",
"IAB9",
"IAB9-30",
"entertainment",
"games"
],
"id": "agltb3B1Yi1pbmNyDAsSA0FwcBitsL4UDA",
"bundle": "531323947"
}
}

Related

ParallelFor in Kubeflow Pipelines

I'd like to use a custom list to run parallel Ops in a Kubeflow Pipeline, and I want to use the value of the element of the list into the definition of the Op. I'm trying something like this:
my_list = ['foo', 'bar']
with dsl.ParallelFor(my_list) as item:
op_first = dsl.ContainerOp(
name=f'{item} - First Op',
image=f'gcr.io/...',
arguments=[
...
]
)
...
But I'm getting an error like this:
ValueError: Only letters, numbers, spaces, "_", and "-" are allowed in name.
Must begin with letter: {{pipelineparam:op=;name=loop-item-param-103a50f1}} - First Op
I've also tried
my_dict = [{'name': 'foo'}, {'name': 'bar'}]
with dsl.ParallelFor(my_list) as item:
name = item.name
op_first = dsl.ContainerOp(
name=f'{name} - First Op',
image=f'gcr.io/...',
arguments=[
...
]
)
...
But i get a similar error. How can I retrieve the "original" name of the item?
I know this is an old question, but I just encountered the same issue, so hopefully, this will help somebody else.
For the second option you tried, replace the dictionary key 'name' with something else as below.
my_dict = [{'job_name': 'foo'}, {'job_name': 'bar'}]
It seems that the key 'name' is used internally by Kubeflow, and assigning a value to it causes your error.
I think the problem is the name you are giving to the ContainerOp.
name=f'{name} - First Op'
Just name=f'{name} should work

how to add dynamicity in a variable value in jenkins groovy

i have a json file like the below one..
{
"env1":{
"region":{
"region1":{
"var1":"test"
},
"region2":{
"var1":"test"
},
"region3":{
"var1":"test"
}
}
},
"env2":{
"region":{
"region1":{
"var1":"test"
},
"region2":{
"var1":"test"
},
"region3":{
"var1":"test"
}
}
}
}
config_all = readJSON file: "${env.WORKSPACE}/<above-json-name>.json"
my concern is how do i dynamically get the config for different region at runtime..
i want to do something like this based on a variable..
def region = env.getProperty("region")
config = config_all.env2.${region} << something like this.. but i cannot aceive it..
is there a way to aceive this sort of dynamicity in the varilable value assignment in jenkins groovy.. thanks in advance
If you want to access values in a map with dynamic/variable keys, then you cannot use the object syntax, but rather must use the native syntax for accessing values from keys in a Map with [<key>].
Following this, we update your code snippet like:
config = config_all['env2'][region]
However, based on your JSON, that is probably not going to traverse your data correctly since it is missing the top-level region key and the var1 key. In that case, it would more likely need to be:
config = config_all['env2']['region'][region]['var1']
That will assign the value test to your variable config.

Is there a way to replace mapping values with another variables value in jenkins pipeline

I have following mapping defined
def e_environments = [["demo1#mystuff.com":"file1"], ["demo2#mystuff.com":"file1"], ["insurance1#mystuff.com":"file2"], ["insurance2#mystuff.com":"file2"]]
Is there a way to replace URL's with same file name from a variable value. For example
def demo_env = ["demo1#mystuff.com","demo2#mystuff.com"]
def insurance_env= ["insurance1#mystuff.com","insurance2#mystuff.com"]
def def e_environments = [[${demo_env}:"file1"], [${insurance_env}:"file2"]]
I hope you must have made some efforts from your side before asking here.
Here is something for you to work upon,
def e_environments = [ "demo1#mystuff.com":"file1", "demo2#mystuff.com":"file1" , "insurance1#mystuff.com":"file2" ,"insurance2#mystuff.com":"file2" ]
def temp = []
e_environments.keySet().each{
temp.add(e_environments[it])
}
temp.unique().each{ val ->
println e_environments.findAll{it.value==val}
}
Got all keys from Map
Created a unique list of it
And a little bit of groovy magic for you to fix and figure it out.

Rails - Accessing JSON members

I am new to Rails, and working with some JSON, and not sure how to get to the data as the examples below:
1) If i were to use JSON.parse(response)['Response']['test']['data']['123456'], i will need to parse another response for 123457, is there a better way to loop through all the objects in data?
2) base on the membershipId, identify the top level object, ie data.
"test": {
"data": {
"123456": {
"membershipId": "321321312",
"membershipType": a,
},
"123457": {
"membershipId": "321321312",
"membershipType": a,
},
}
JSON.parse(response)['Response']['test']['data'].each do |key, object|
puts key
puts object['membershipID']
...
end
To select the data record associated with a particular membership
match_membership = '321321312'
member = JSON.parse(response)['Response']['test']['data'].select |_key, object|
object['membershipID'] == match_membership
end
puts member.key
=> 123456
For 1:
Assumption:
By you saying "need to parse another response", you were doing something like below:
# bad code: because you are parsing `response` multiple times
JSON.parse(response)['Response']['test']['data']['123456']
JSON.parse(response)['Response']['test']['data']['123457']
then simply:
Solution 1:
If you are gonna be accessing 2+ level deep hash values for just maybe 2 or 3 times,
response_hash = JSON.parse(response)
response_hash['Response']['test']['data']['123456']
response_hash['Response']['test']['data']['123457']
Solution 2:
If you are gonna be accessing 2+ level deep hash values for loooooots of times,
response_hash = JSON.parse(response)
response_hash_response_test_data = response_hash['Response']['test']['data']
response_hash_response_test_data['123456']
response_hash_response_test_data['123457']
response_hash_response_test_data['123458']
response_hash_response_test_data['123459']
response_hash_response_test_data['123460']
# ...
Solution 2 is better than Solution 1 because it saves repetitive method calls for Hash#[] which is the "getter" method each time you do like ...['test'] then ['data'] then ['123456'], and so is better-off doing Solution 2 which you store the nested-level of the hash into a variable (this does not duplicate the values in-memory!). Plus it's more readable this way.

Cannot access params map using Groovy

I want little help which I suspect is due to my lack of understanding for Groovy syntax. So, here's the thing:
On the GSP page I want to set a field's value from the params map which is
["id":"107901", "Field_10.value":"2", "Field_10":["value":"2"],"Field_11.value":"", "Field_11":["value":""],action:'abc']
On the gsp page, I want to find the value against the key Field_{some-id}.value
So I am calling a tag like, g.testTag(id:field.id) with its implementation as
def testTag = { attrs,body->
println "params are ${params}"
def result = ""
def keyRequired = "Field_${attrs.id}.value"
println "keyRequired >>>>> ${keyRequired.toString()}"
params.each { key,value->
println "key is ${key}"
println "Value is ${value}"
if (key.equals(keyRequired.toString())) {
result = params.value
}
}
println "Final result is >>>>>> ${result}"
}
The value passed in id is 10 and with my params printed as above, I was expecting a value
of 2 which is corresponding to the key in the params to show up. But apparently I see the
result as null..
What am I doing wrong ? Can anyone help please...
Thanks
Not result = params.value, but result = value.
You have to change the line:
result = params.value
to:
result = value
At the each loop, you're basically saying that inside the params iteration, you're naming every key "key" and every value "value". So, params.value will actually look for the key value inside your params map, which is null.
Funny that you do that right with key but not with value. Probably just got distracted.
it is likely what you want to do, the groovy way (no need to loop over the keys of the map) to access "Field_10.value":"2"
result=params["Field_${attrs.id}.value"]
Alternatively, this also works because you have "Field_10":["value":"2"] in your map
result=params["Field_${attrs.id}"].value

Resources