Possible to use Jinja2 expressions in role vars file - ansible

I'm wondering if it's possible to use a Jinja2 {% if %} expression inside a vars file?
So say I have:
az:
az1: foo
az2: bar
az3: foobar
{% if az == az['az1'] %}
floating_ip_pool = bar
{% endif %}
Basically, I'm trying to avoid having to set these variables each time since they'll always be based on the az.
Thanks.

That's not valid syntax. A vars file must first be parsed as a YAML document, and introducing that Jinja syntax results in something that is no longer valid YAML.
You can do something like this instead:
az:
az1: foo
az2: bar
az3: foobar
floating_ip_pool: "{% if target_az == az['az1'] %}bar{% endif %}"

Related

Validate yaml path in Ansible Jinja2 template

I have Cloudformation template in yaml format.
The template is rendered by Ansible Jinja2.
I need to find a way to add validation of some elements inside the template. Something like this ("if" statement is a pseudo code of what I want to get):
Parameters:
EnvironmentType:
Default: {{profile}}
Mappings:
Environments:
dev:
DbSnapshotArn: ""
test:
DbSnapshotArn: "AAA"
Type: AWS::RDS::DBInstance
Properties:
{% if Mappings.Environments.{{profile}}.DbInstanceClass %}
DBSnapshotIdentifier: !FindInMap [Environments, !Ref 'EnvironmentType', DbSnapshotArn]
{% endif %}
Is it possible?
Not if Mappings.Environments.{{profile}}.DbInstanceClass references something inside the template.
But if you define a variable like this:
Mappings:
Environments:
Dev:
DbInstanceClass: "..."
And another variable that contains the value of profile, then inside your template you can create an if statement like this:
{% if Mappings.Environments[profile].DbInstanceClass is defined %}
...
{% endif %}
See also:
Jinja2 Tests

Using Jinja2 Expression within Jinja2 Statement

Let's say I have the following Jinja2 variables:
'dev_ami' = 'ami-123456'
'dev_located_ami' = 'ami-123456'
'prod_ami' = 'ami-654321'
'prod_located_ami' = 'ami-654321'
I would like to set a condition upon when the 'dev_ami' variable is equal to the 'dev_located_ami' variable. This would easily be done as shown in the following statement:
{% if dev_ami == dev_located_ami %}
... do some stuff
{% else %}
... do some other stuff
{% endif %}
But I would like to dynamically compare amis based on the deployment environment contained in a list ['dev','prod', etc...]. The following contains a templating error since there is an expression within a statement as such - {% {{ .. }} %}:
{% for env_type in ['dev','prod'] %}
{% if {{ env_type }}_ami == {{ env_type }}_located_ami %}
... do stuff
{% else %}
... do other stuff
{% endif %}
{% endfor %}
I have tried to set variables to represent the expressions I would like in the following code but unfortunately they are compiled literally as 'dev_ami' and 'dev_located_ami' whereas I would like them compiled to their corresponding variable values 'ami-123456' and 'ami-123456':
{% for env_type in ['dev','prod'] %}
{% set ami = "%s_ami"|format(env_type) %}
{% set located_ami = "%s_located_ami"|format(env_type) %}
{% if ami == located_ami %}
... do stuff
{% else %}
... do other stuff
{% endif %}
{% endfor %}
I have checked through various filters and so far have had no success. Would appreciate advice on getting this specific implementation to work properly. Thank you in advance.
I think you might be approaching the problem with the wrong datastructure in mind.
Dynamically generating variable names in order to compare amis in different environemts sounds like a massive overkill to me. Are you familiar with lists & dictionaries?
Try to start from something like this (pseudocode):
dict = { environments:
prod:
ami1: foo
ami1_located: foo
dev:
ami1: bar
ami1_located:baz
}
for env in dict[environments]:
if env[ami1] == env[ami1_located]:
[...]

Ansible, how to use jinja2 template to access specific value in a list

New to Jinja2 templating
I can iterate over a list using a for conditional which is simple enough but i am trying to do the below...
I have a variable that contains a un-ordered lists of values which are group names. I would like to access the group_names lists/variable and check if a specific item in this list exists and then perform an action if that value is found.
group_names: [ "groupname1", "groupname2", "groupname3", "groupname4"]
Sounds like you want:
{% if "somevalue" in group_names %}
whatever stuff
{% endif %}
http://jinja.pocoo.org/docs/2.9/templates/

Change variable in Ansible template based on group with children?

I found Change variable in Ansible template based on group. However how do I extend the answer in groups with children?
If I extend the group vars file in the link above to
[host0]
host0.my-network.com
[host1]
host1.my-network.com
[es-masters:children]
host0
host1
How can I extend the above post's answer (shown below) to make it work with the group vars file above? Simply putting the FQDN in the jinja2 statement does not work.
{% if ansible_fqdn in groups['es-masters'] %}
node_master=true
{% else %}
node_master=false
{% endif %}
What you should do is:
Provide default in template
# role_name/templates/template.j2
node_master={{ role_name_node_master | default(true) }}
Than override in group_vars
# group_vars/es-masters.yml
role_name_node_master: false

In Nunjucks, how to conditionally output a line?

I want to output a line conditionally in nunjucks, but don't want to have an empty line if the condition is false.
Example:
Before
{{ 'Something' if false }}
After
renders like this:
Before
After
I would like to remove the empty line without lowering the readability of the template. Is there a nice way to do that?
I would expect something like {{- 'Something' if false }} but that doesn't work.
Nunjucks has it's own conditional methods. Note the percent symbol instead of double moustaches.
https://mozilla.github.io/nunjucks/templating.html#if
{% if hungry %}
I am hungry
{% elif tired %}
I am tired
{% else %}
I am good!
{% endif %}

Resources