Jinja2 Space in variable - ansible

"custom_fields": {
"Datacentre Code": "p",
"Region": "EU"
},
I have the data format above, and I want to access the "Datacentre code" and return the result.
To access the Region I run the below command
{% set Region = item.resultDC.custom_fields.Region %}
To access the DC code I am running the below command
{% set DCCode= item.resultDC.custom_fields.Datacentre Code %}
This gives me the following error, how do I get this variable
AnsibleError: template error while templating string: expected token 'end of statement block', got 'Code

I believe that you can use the syntax item.resultDC.custom_fields['Datacentre Code'] to access properties of a dict like that.

Related

Liquid::SyntaxError when variable starts with a number

When parsing a template that contains a variable that begins with a number
script = '{% if variable==true or 2variable==false%}{% remove %}{% endif %}'
I get the SyntaxError inside warnings:
Liquid::Template.parse(script, error_mode: :warn).warnings
Liquid::SyntaxError: Liquid syntax error: Expected end_of_string but found id in "variable==true or 2variable==false"
If I change the variable name to not begin with a number I don't get any warnings.
I don't understand why this scenario translates into a SyntaxError. Is there a liquid convention that states variables should not begin with a number?

How to render a literal 'null' in Jinja2 Template

I'm working on an ansible role that allow users to interact with a REST API. I create json.j2 templates that allow me to build the message payload and eventually submit. One of the fields expects either a string value ("") or null.
{
"value": "{{ example.value | default(null, true) }}"
}
This doesn't work and I get this error:
The task includes an option with an undefined variable. The error was: 'null' is undefined
I need that null value and I need to come in as the default value if no other value is provided.
How do I do this?
As pointed in the comments, null has no meaning in Python, None is the Python representation of what your are looking for.
Now, if you want to convert this to a JSON value, then there is a to_json filter in Ansible, so:
'{ "value": {{ example.value | default(None, true) | to_json }} }'
Would end up as:
{ "value": null }

Passing sub vars to Ansible command line

I have an ansible playbook that gets its vars passed in from an extra-vars.json file. It gets passed in at the command line with --extra-vars "#extra-vars.json".
This is an abbreviated version of the var file
{
"source" : {
"access_token" : "abc",
"git_instance_url" : "foo.com",
"repo" : "some-group/some-project/some-repo"
},
"target" : {
"access_token" : "xyz",
"git_instance_url" : "foo.bar.com",
"repo_path" : "lorem/ipsum"
}
}
Because of the var structure, when I call the vars in my playbook I have to use dot notation i.e. {{ source.repo_path }} or {{ target.access_token }}. My problem is that I would like to remove a couple of these vars from the extra-vars.json and pass them individually at the command line. If I remove source.git_instance_url from extra-vars.json I can pass it in without any precedence conflicts.
My issue is that I can't figure out how to pass dot notation vars in at the command line. I don't want to change my playbook to do this. If I pass in --extra-vars "source.git_instance_url=bar.baz.com" I get an error source is undefined.
I tried using bracket notation source[git_instance_url]=bar.baz.com with no success.
Is there a way to pass dot notation vars at the command line or am I going to have to change my playbook from {{ source.git_instance_url }} ==> {{ source_git_instance_url }} to be able to accomplish this?
When passing extra vars, these are always "string variables". I learned it the hard way when trying to pass in boolean variables.
You could pass them as json:
ansible-playbook -e '{"source": { "git_instance_url": "foo" }}' playbook.yml
But I don't know right now, if they get merged with the source var from your vars file. I'd guess, one overwrites the other. So you probably end up with either the source var from your string or with the one from the file.

Jinja2 templated file with json safe multiline include

I have a problem with a Jinja2 template I'm writing (called from Ansible).
The resultant file is a JSON file that I will send to an API (either with Ansible URI module or with curl). The template looks like this and basically works:
{
"description" : "my description",
"pipeline": "{% include 'root/pipeline.j2' %}"
}
The problem is that the content of root/pipeline.j2 is quite complex and includes multiple lines, quote characters and any number of other things that make the json file I'm creating invalid. What I want to do is parse the included file through a filter to convert it to a JSON valid string; something like this:
{
"description" : "my description",
"pipeline": "{% include 'root/pipeline.j2' | to_json %}"
}
But that doesn't work, probably because the filter is acting on the filename, not the included content.
Just for a little clarity when I create the template at the moment I see pipeline gets set to something like this:
"pipeline": "input {
"input1" {
<snipped>
"
It should appear thus:
"pipeline": "input {\n \"input1\" {<snipped>"
NB: I'm only giving the first couple of lines and I am using 'snipped' where I have remove the rest of the config.
Can anyone tell me how I can use an include within a jinja2 template that renders the result as a single line valid json string?
Thanks in advance for any assistance.
I finally managed to find a solution to my own question. Within the template that provides the JSON that is an API payload I am now setting a variable to the content of the pipeline template, which makes it easy to filter it with to_json:
{% set pipeline = lookup('template', 'root/pipeline.j2') %}
{
"description" : "my description",
"pipeline": {{ pipeline | to_json }}
}
I will leave this quesiton answer open for a while in case anyone can supply a better answer or explain why this is not a good one.
Thanks.

Access value through index number from ansible gather facts variable

I am using gather fact variable to get size information about host. for some server I am getting variable "ansible_devices": { "sda" and for few server getting "ansible_devices": { "cciss!c0d0".
Problem:- When I am using variable {{ ansible_devices.sda.size }} in my playbook and if sda key not found in ansible_device variable then obviously it gives me error
fatal: [xyz101] =>One or more undefined variables: dict object has no element sda
Getting value in ansible_device variable like below
"ansible_devices": {
"sda": {
"size": "68.33 GB",
........
}
},
"item": ""
or
"ansible_devices": {
"cciss!c0d0": {
"size": "68.33 GB",
........
}
},
"item": ""
Also I can access size here using {{ ansible_devices.sda.size }} in first case But unable to fetch value in {{ ansible_devices.cciss!c0d0.size }} in second case.
It might be the case special character in a json key that's why I am unable to fetch its value.
Is there any way to access this variable through key index {{ ansible_devices[0].size }} ?
or any other better way to access it.
You could use a conditional?
when: ansible_devices.sda exists
Or you can iterate through ansible_devices.keys() and with_items.
We can check key by using has_key in ansible playbook like below.
when: ansible_devices.has_key('sda')
Above check resolve my fetal error as I have added two task for these two keys. But still I am looking the solution where I can get these key value through index number. It will replace multiple condition into one.

Resources