Reputation: 353
props = readProperties file: "src/main/resources/application-DEV.properties";
def DB_HOST = (props['com_db_url'].split(':')[2]).replace('//', '');
def DB_USER = props['com_db_username'];
def DB_PASSWORD = props['com_db_password'];
def DB_PORT = (props['com_db_url'].split(':')[3]).split('/')[0];
def jsonData = "{'$DB_HOST':'${DB_HOST}','$DB_USER':'${DB_USER}','$DB_PASSWORD':'${DB_PASSWORD}','$DB_PORT':'${DB_PORT}'}";
String filenew = readFile('dev/values-dev.yaml')
def jsonObject = readJSON text: jsonData;
jsonObject.each { key, value ->
def _key = "${key}";
_key = '\\\\'+_key
echo "$key : $value, custom key : ${_key}"
filenew = filenew.replaceAll("${_key}", '$value')
}
My values-dev.yaml file as follows
resources:
limits:
cpu: 100m
memory: 128Mi
requests:
cpu: 100m
memory: 128Mi
config:
autoDiscoverDatabases: true
datasource:
host: $DB_HOST
user: $DB_USER
password: $DB_PASSWORD
port: $DB_PORT
sslmode: "require"
database: "ibmclouddb"
I have tried multiple ways in last 4 days to replace token using for loop, but hard luck. With following way it is working for me
//filenew = filenew.replaceAll('\\$DB_HOST', jsonObject.DB_HOST)
//filenew = filenew.replaceAll('\\$DB_USER', jsonObject.DB_USER)
//filenew = filenew.replaceAll('\\$DB_PASSWORD', jsonObject.DB_PASSWORD)
//filenew = filenew.replaceAll('\\$DB_PORT', jsonObject.DB_PORT)
Purposefully I have prepended $
symbol variables in JSON data, i.e. in above jsonData
variable declared initially.
But I wanted to achieve this via a generic way.
Upvotes: 1
Views: 1272
Reputation: 484
Here a simpler solution which works in a generic way as you wish.
import groovy.json.JsonSlurper
String props = '''
user: $DB_USER
pass: $DB_PASS
'''
def DB_USER = 'com_db_username'
def DB_PASS = 'com_db_password'
def jsonData = $/
{
"$$DB_USER":"${DB_USER}",
"$$DB_PASS":"${DB_PASS}",
}/$
//println jsonData
def jsonObject = new JsonSlurper().parseText(jsonData)
jsonObject.each { key, value ->
props = props.replaceAll(/\$key/, value)
}
println props
with the output:
user: com_db_username
pass: com_db_password
The trickiest part is the regex expression and the escaping and what kind of string to use for it for a convenient escaping. In the regex expression /\$key/
the exapnded value of $key
will be $DB_USER
which will output the $
sign that must be also escaped with the \
before.
I had to adapt your code, to work without a Jenkins server.
One error I had to fix is that your JSON do not use double-quotes for key-values. To fix it without mess up the interpolation, I used a groovy dollar-slashy string which is more readable and flexible. In the $-slashy strings you need to escape only the $ signs, everything else can be left as it is without escaping.
For simplicity, instead of yaml file I use just string, for the properties I defined some variables and I reduced everything to 2 variables.
Upvotes: 1
Reputation: 37008
All the replacements can be done in one step and there is no need to use an interim JSON map.
Just build a map with all the replacements you know. Then use
replaceAll
with a regexp, that catches your replacement keys and use
a closure to handle the replacement. The closure simply looks up the
key in your replacements and has some means to generate some error, if
a replacement is unknown (or you could just write the key back).
def replacements = [
DB_USER: "the user",
// ...
]
def yaml = '''
config:
autoDiscoverDatabases: true
datasource:
host: $DB_FAILS
user: $DB_USER
'''
println yaml.replaceAll(/\$([A-Z_]+)/, { _, k -> replacements.getOrDefault(k, "FAILED TO REPLACE $k") })
// →
// config:
// autoDiscoverDatabases: true
// datasource:
// host: FAILED TO REPLACE DB_FAILS
// user: the user
Upvotes: 2