Pass a readable JSON as string into Nomad Template - nomad

We are using nomad template to add environment variables for our nomad deployments.
template {
data = <<EOH
Key1=value1
Key2=value2
Key3=AJsonstring
EOH
change_mode = "restart"
destination = "environments/file.env"
env = true
}
I notice that nomad requires me to escape my JSON string in order for me to properly pass it in.
Ie: say i want to pass in {"a":3,"b":4} in Key3
I cannot just write it as is, instead, i had to write "{\"a\":3,\"b\":4}" which is a lot less readable.
Is there a way so I can just pass the plain string in and make it to interprets it as is?

I'd try using single quotes around your JSON object: key3='{"a": 3, "b": 4 }'.
$ echo {"a": 1}
{a: 1}
$ echo '{"a": 1}'
{"a": 1}
note: I haven't tested this! Just a guess based on how I'd expect things are put together.

Related

Pass a parameter as list to argo workflow

I have the following JSON file which will be passed as a parameter file to an Argo workflow:
{
"keys": [
"key1",
"key2",
"key3"
]
}
Accessing "keys" like '{{inputs.parameters.keys}}' reads keys as a string instead of a list.
Is it possible to read an input parameter from a parameter file as a list of values?
Within an Argo Workflow, parameters are always strings.
You can use expression templates to retrieve information from the stringified list.
value: '{{=jsonpath(inputs.parameters.keys, "$.0")}}' # get the first item

How to update value in key using jq inside a file in shell script?

I have file like this(exact format):
{ "test": "10" }
{ "games": "30" }
{ "REPOSITORY": "5"}
I want to update the value of key. For example games to 66. So the new file would be:
{ "test": "10" }
{ "games": "66" }
{ "REPOSITORY":"5"}
I used jq with combination of a temporary file
tmp=$(mktemp);
jq '.games = "66"' pair.json > "$tmp" && mv "$tmp" change.json
but got this kind of output.
{
"test": "10",
"games": "66"
}
{
"games": "66"
}
{
"REPOSITORY": "5",
"games": "66"
}
where games is written all 3 whereas I just want it be updated only at its position.
Furthermore i want the value to be updated using bash variable but that I can try to figure out using --arg after I resolve this issue. Pls assist here.
Your input is a stream of objects. As such your filter expression, .games = "66" asserts that the record games is present in each of the object present in the stream.
To update the specific object alone, select it first and assign the required value or update it.
jq -c 'select(has("games")).games = "66"'
To answer OP's clarification on how to do the same with variables, do
jq -c --arg key "games" 'select(has($key))[$key] = "555"'
A simple solution is using select with assignment. select will return the special value empty if the condition does not match and the input value if it does match.
select(.games).games = "66"
jq -c to generate compact format, i.e. one JSON object/document per line.
To handle arbitrary names, change the syntax slightly:
select(.["games"])["games"] = "66"
and used with arguments passed via CLI:
jq -r --arg key "$var" 'select(.[$key])[$key] = "66"'

Is it safe to parse json with YAML.load?

I am using ruby 2.1.0
I have a json file.
For example: test.json
{
"item":[
{"apple": 1},
{"banana": 2}
]
}
Is it safe to load this file with YAML.load?
YAML.load(File.read('test.json'))
I am trying to load a file which is in either json or yaml format.
YAML can load JSON
YAML.load('{"something": "test", "other": 4 }')
=> {"something"=>"test", "other"=>4}
JSON will not be able to load YAML.
JSON.load("- something\n")
JSON::ParserError: 795: unexpected token at '- something'
There will be some obscure cases that work and produce different output.
YAML.load("")
=> false
JSON.load("")
=> nil
But generally the YAML construct is not JSON compliant.
So, try the JSON.load first because it's probably better at obscure JSON things.Catch the JSON::ParserError error and fall back to YAML.load.
In recent work I did I found a corner case of the sort alluded to by Matt. For example
puts JSON.load('{"x": "foo\/bar"}')['x']
succeeds in printing
foo/bar
despite the gratuitous escaping¹ whereas
puts YAML.load('{"x": "foo\/bar"}')['x']
fails:
Psych::SyntaxError ((<unknown>): found unknown escape character while parsing a quoted scalar at line 1 column 7)
¹In this case by Java as per net.sf.json.util.JSONUtils.quote. Note that they forgot to do the same quoting in their own Javadoc, ironically enough, so you have to browse source to understand!

Read values from puppet template

Hi I've a puppet template with below values.
myfile.erb
name = "abc"
desg = "engineer"
Sal = "10000"
And I try to read these values from my puppet script like below
init.pp
$value = template("d:/puppet/modules/mymodule/templates/myfile.erb")
now my $value is containing all values from the myfile.erb file. Is there any way to divide the values like $value[0], $value[1] etc..
I want to display only "abc" "engineer" "1000"
When your data lookup starts getting complicated, I highly recommend you move away from templates towards an external data lookup, like hiera. For a guide to setting up, I've written a small tutorial here. You can substitute yaml for json.
Your hiera file could look as simple as this:
{
"myfile": {
"name": "abc",
"desg": "engineer"
"Sal": "10000"
}
}
And then in your file:
$vars = hiera('myfile')
// Gives "abc"
$vars['name']
// Gives "engineer"
$vars['desg']

Rails String Interpolation in a string from a database

So here is my problem.
I want to retrieve a string stored in a model and at runtime change a part of it using a variable from the rails application. Here is an example:
I have a Message model, which I use to store several unique messages. So different users have the same message, but I want to be able to show their name in the middle of the message, e.g.,
"Hi #{user.name}, ...."
I tried to store exactly that in the database but it gets escaped before showing in the view or gets interpolated when storing in the database, via the rails console.
Thanks in advance.
I don't see a reason to define custom string helper functions. Ruby offers very nice formatting approaches, e.g.:
"Hello %s" % ['world']
or
"Hello %{subject}" % { subject: 'world' }
Both examples return "Hello world".
If you want
"Hi #{user.name}, ...."
in your database, use single quotes or escape the # with a backslash to keep Ruby from interpolating the #{} stuff right away:
s = 'Hi #{user.name}, ....'
s = "Hi \#{user.name}, ...."
Then, later when you want to do the interpolation you could, if you were daring or trusted yourself, use eval:
s = pull_the_string_from_the_database
msg = eval '"' + s + '"'
Note that you'll have to turn s into a double quoted string in order for the eval to work. This will work but it isn't the nicest approach and leaves you open to all sorts of strange and confusing errors; it should be okay as long as you (or other trusted people) are writing the strings.
I think you'd be better off with a simple micro-templating system, even something as simple as this:
def fill_in(template, data)
template.gsub(/\{\{(\w+)\}\}/) { data[$1.to_sym] }
end
#...
fill_in('Hi {{user_name}}, ....', :user_name => 'Pancakes')
You could use whatever delimiters you wanted of course, I went with {{...}} because I've been using Mustache.js and Handlebars.js lately. This naive implementation has issues (no in-template formatting options, no delimiter escaping, ...) but it might be enough. If your templates get more complicated then maybe String#% or ERB might work better.
one way I can think of doing this is to have templates stored for example:
"hi name"
then have a function in models that just replaces the template tags (name) with the passed arguments.
It can also be User who logged in.
Because this new function will be a part of model, you can use it like just another field of model from anywhere in rails, including the html.erb file.
Hope that helps, let me know if you need more description.
Adding another possible solution using Procs:
#String can be stored in the database
string = "->(user){ 'Hello ' + user.name}"
proc = eval(string)
proc.call(User.find(1)) #=> "Hello Bob"
gsub is very powerful in Ruby.
It takes a hash as a second argument so you can supply it with a whitelist of keys to replace like that:
template = <<~STR
Hello %{user_email}!
You have %{user_voices_count} votes!
Greetings from the system
STR
template.gsub(/%{.*?}/, {
"%{user_email}" => 'schmijos#example.com',
"%{user_voices_count}" => 5,
"%{release_distributable_total}" => 131,
"%{entitlement_value}" => 2,
})
Compared to ERB it's secure. And it doesn't complain about single % and unused or inexistent keys like string interpolation with %(sprintf) does.

Resources