Define variable in Ansible according complex condition - if-statement

I need to define a variable in ansible according several conditions
I know the syntax
VARtodefined: "{{ 'Value1' if condition1 else 'Value2' }}"
I know I have the same result with the following other syntax
VARtodefined: "{% if condition1 %}'Value1'{% else %}'Value2'{% endif %}"
but I don't find the correct syntax for multiple condition (if-elsif-elsif-else)
I have for instance tried this without success
VARtodefined: "{% if condition1 %}'Value1'{% elsif condition2 %}'Value2'{% else %}'Value3'{% endif %}"
If have tried variant with elif, elseif but also without success
In my specific case condition1 is OtherVar==XXX and condition2 OtherVar==YYY (so in both case it depends the value of OtherVar)
So I'm looking for a working solution for this
VARtodefined: "{% if OtherVar==XXX %}'Value1'{% elsif OtherVar==YYY%}'Value2'{% else %}'Value3'{% endif %}"
If have found a workaround to achieve my goal but I'm interested to know the correct syntax for future projects

The example of the correct syntax is below. The task
- debug:
msg: "{% if item=='XXX' %}Value1
{% elif item=='YYY' %}Value2
{% else %}Value3
{% endif %}"
loop: [XXX, ZZZ]
gives
msg: 'Value1 '
msg: 'Value3 '
A simpler solution is putting the logic into a dictionary. For example
conditions:
XXX: Value1
YYY: Value2
default: Value3
Then, use it
- set_fact:
VARtodefined: "{{ conditions[OtherVar]|
default(conditions.default) }}"

this is the expected syntax: if - elif/else - endif
please see and try example PB below:
---
- hosts: localhost
gather_facts: false
vars:
X: 2
tasks:
- set_fact:
VARtodefined: "{% if X == 1 %}Value1{% elif X == 2 %}Value2{% else %}Value3{% endif %}"
- debug:
var: VARtodefined

Related

Conditional text in variable in ansible

H I want to build a warning message with ansible that is stored in a variable:
I have {{total}} and {{wanted}} and I want to store that in a {{outcome}} variable :
I need something like :
if ({{total}} < {{wanted}}): {{outcome}}= "you need to much"
else if ({{total}} = {{wanted}}): {{outcome}}= "Could work out"
else: {{outcome}}= "Ok"
How can I get this to work?
Thanks for any ideas... this is driving me crazy....
The task below does the job
- set_fact:
outcome: |
{% if total|int < wanted|int %}
You need to much
{% elif total|int == wanted|int %}
Could work out
{% else %}
Ok
{% endif %}

The error was: error while evaluating conditional

I try to use insert a unique number to each server I have by using Ansible.
As below, I wish these is:
"1" in 192.168.60.6's myid.txt
"2" in 192.168.60.7's myid.txt
- hosts: all
gather_facts:True
vars:
servers:
host1:
ip: 192.168.60.6
num: 1
host2:
ip: 192.168.60.7
num: 2
host3:
ip: 192.168.60.8
num: 3
tasks:
-name: write a unique number in myid.txt
lineinfile:
dest: "/home/user/myid.txt"
line: "{{ item.value.num }}"
when: "{{ item.value.ip }} == {{ ansible_all_ipv4_addresses[1] }}"
`enter code here`with_dict: "{{ servers }}"
Unfortunately, I got this error:
TASK [write unique number in myid]
*********************************************
fatal: [192.168.60.6]: FAILED! => {"failed": true, "msg": "The conditional check '{{item.value.ip}} == {{ ansible_all_ipv4_addresses[1] }}' failed.
The error was: error while evaluating conditional ({{item.value.ip}} == {{ ansible_all_ipv4_addresses[1] }}): float object has no element 60
The error appears to have been in '/home/shihhao/Desktop/BlueTech/ansible/kafka_playbook.yml': line 101, column 7,
but may be elsewhere in the file depending on the exact syntax problem.
The offending line appears to be:
- name: write unique number in myid
^ here\n"}
It seems once I add this line I will get the error.
when: "{{item.value.ip}} == {{ ansible_all_ipv4_addresses[1] }}"
BTW: {{ ansible_all_ipv4_addresses[1] }} is 192.168.60.6
You should use bare variables in your when: statement:
when: item.value.ip == ansible_all_ipv4_addresses[1]
From the documentation:
This is easy to do in Ansible with the when clause, which contains a raw Jinja2 expression without double curly braces
Raw expressions are used in when: statement, with assert module and with debug: var=varname (but debug: msg="{{varname}}").

How to compared a nested pillar key value in an if statement in jinja2 for saltstack

I am working on a saltstack state with some salt wrapped in jinja2.
When I attempt to compare a value from a pillar using jinja2 it appears argument evaluates to nothing.
If I query the value using salt cli, it returns the expected value.
I expect I am referencing the value incorrectly in the if statement with jinja2.
Here is all the needed info to understand and look at this problem:
Salt Master id is salt-dev
Salt Minion id is on same instance and is salt-dev
Here is the pillar top file:
base:
'salt-dev':
- docker-daemon.docker-daemon
Here is the nested pillar file locate at /srv/pillar/docker-daemon/docker-daemon.sls
docker-daemon:
- action: start
- runlevel: enabled
Here is the output of the salt cli command returning the content of the pillar for the minion salt-dev:
# salt 'salt-dev' pillar.items
salt-dev:
----------
docker-daemon:
|_
----------
action:
start
|_
----------
runlevel:
enabled
Here is the output of the value I am using in the if statement where the value returns nothing with jinja2, but returns as expected here with cli:
# salt 'salt-dev' pillar.get docker-daemon:action
salt-dev:
start
The line of jinja2 that is incorrect is:
{% if salt['pillar.get']('docker-daemon:action') == 'start' %}
It appears: salt['pillar.get']('docker-daemon:action') returns nothing, but from cli as shown above it does return something.
Also if I add a default value, which is used in the event this arg returned nothing it also works.
An example of adding a default value is:
{% if salt['pillar.get']('docker-daemon:action', 'def_value') == 'start' %}
I have shown it in context below:
Here is the state file where the if statements are having the same issue:
{% if ( (grains['osfinger'] == 'Oracle Linux Server-6') and (grains['osarch'] == 'x86_64')) %}
sync_docker-init:
file.managed:
- name: /etc/init.d/docker
- source: salt://docker-daemon/templates/docker-init
- user: root
- group: root
- mode: 755
action_docker-init:
{% if salt['pillar.get']('docker-daemon:action') == 'start' %}
service.running:
{% endif %}
{% if salt['pillar.get']('docker-daemon:action') == 'stop' %}
service.dead:
{% endif %}
- name: docker
- require:
- pkg: install_docker-engine
- watch:
- file: sync_docker-init
{% if salt['pillar.get']('docker-daemon:runlevel') == 'enabled' %}
-- enable: True
{% endif %}
{% if salt['pillar.get']('docker-daemon:runlevel') == 'disabled' %}
-- enable: False
{% endif %}
{% else %}
event.send:
- tag: 'salt/custom/docker-init/failure'
- data: "Management of docker init failed, OS not permitted."
{% endif %}
I am quite new at the moment to salt and jinja2, so this is 101 stuff, but I would appreciate some help, I have found nothing for some hours yet.
I attempted to echo this out and it seemed I just get a blank line
I found the solution.
The pillar file /srv/pillar/docker-daemon/docker-daemon.sls was formed as a list instead of a map.
I changed it to this:
docker-daemon:
action: restart
runlevel: disabled

Saltstack load pillar in a for loop

I am developing a automatic proftd installation whit Salt, i wont to get the ftp users from a template but I cant get work the pillar, i initialized the pillar whit the users data and call it into a for loop, but you don't get the pillar user data in the loop.
When i make salt-call pillar.get ftpusers in the minion, the response is:
local:
This is my pillar ftpusers.sls:
ftp-server.ftpusers:
user:
- user: user
- passhash: j2k3hk134123l1234ljh!"ยท$ser
- uuid: 1001
- guid: 1001
- home: /srv/ftp/user
- shel: /bin/false
And this is the for loop:
{% for users in pillar.get('ftpusers', {}).items() %}
/srv/herma-ftp/.ftpusers:
file.managed:
- user: root
- group: root
- mode: 444
- contents:'{{ user }}:{{ args['passhash'] }}:{{args['uuid'] }}:{{ args['guid'] }}::{{ args['home'] }}:{{ args['shel'] }}'
- require:
- file: /srv/herma-ftp
/srv/herma-ftp/{{user}}:
file.directory:
- user: nobody
- group: nobody
- dir_mode: 775
- makedirs: True
- require:
- file: /srv/herma-ftp
- watch:
- file: /srv/herma-ftp
module.run:
- name: file.set_selinux_context
- path: {{ args['home']}}
- type: public_content_t
- unless:
- stat -c %C {{ args['home'] }} |grep -q public_content_t
{% endfor %}
When I make in the minion
salt-call -l debug state.sls herma-ftp-server saltenv=My-enviroment test=True
Don't expect this for because don't can get the pillar data.
Your loop should also look like:
{% for user, args in pillar.get('ftpusers', {}).items() %}
Also, contents argument for a file.managed doesn't support templating. What you need to do is move /srv/herma-ftp/.ftpusers state outside of the loop, and make the loop inside the file template. The final layout of your state should look like:
/srv/herma-ftp/.ftpusers
file.managed:
source: salt://ftpserver/dot.ftpusers
template: jinja
...
...
{% for user, args in pillar.get('ftpusers', {}).items() %}
/srv/herma-ftp/{{user}}:
file.managed:
...
{% endfor %}
And your ftpserver/dot.ftpusers would look like:
{% for user, args in pillar.get('ftpusers', {}).items() %}
{{ user }}:{{ args['passhash'] }}:{{args['uuid'] }}:{{ args['guid'] }}::{{ args['home'] }}:{{ args['shel'] }}
{% endfor %}

django and condition in ifequal statement throws error

I need to display a portion of HTML on the following condition,
var1=="google" and var2 is True
I wrote the following code ,
{% ifequal var1 "google" and var2 %}
/*HTML CODE */
{% endif %}
and i got an error
TemplateSyntaxError at /process/apply.html
u'ifequal' takes two arguments
I know i can split the above two nested IF statements,still is there a way in django to combine them to a single if statement?
From django ifequal documentation
It is only possible to compare an argument to template variables or strings. You cannot check for equality with Python objects such as True or False. If you need to test if something is true or false, use the if tag instead.
So if you want to check for True or False, so need to use if.
{%if var1 == "google" and var2 %}
....
{%endif%}