Why does 'when' conditional test fail without jinja2 templating delimiters?

27 views
Skip to first unread message

Darren S.

unread,
May 26, 2018, 12:24:45 PM5/26/18
to ansible...@googlegroups.com
ansible 2.5.3 on OpenBSD 6.3 amd64
config file = /etc/ansible/ansible.cfg
configured module search path =
[u'/home/dspruell/.ansible/plugins/modules',
u'/usr/share/ansible/plugins/modules']
ansible python module location =
/home/dspruell/.local/lib/python2.7/site-packages/ansible
executable location = /home/dspruell/.local/bin/ansible
python version = 2.7.14 (default, Mar 27 2018, 09:57:43) [GCC 4.2.1
Compatible OpenBSD Clang 5.0.1 (tags/RELEASE_501/final)]


Test playbook: the 'when' conditions on the sysctl tasks are how I
figured were proper to format the tests and avoid using jinja2
templating (and avoid subsequent warning from doing so):

---
- hosts: molodetz
become: yes
vars:
sysctl_limit_semmns: kern.seminfo.semmns
sysctl_limit_semmni: kern.seminfo.semmni
postgres_limit_semmni: 60
postgres_limit_semmns: 1024

tasks:
- name: check sysv semaphore system limits
command: sysctl -n {{ sysctl_limit_semmni |quote }} {{
sysctl_limit_semmns |quote }}
register: sem_limits
changed_when: False

- set_fact:
semmni_cur_limit: '{{ sem_limits.stdout_lines[0]|int }}'
semmns_cur_limit: '{{ sem_limits.stdout_lines[1]|int }}'
changed_when: False

- debug:
var: '{{ item }}'
loop:
- semmni_cur_limit
- semmns_cur_limit
- postgres_limit_semmni
- postgres_limit_semmns
- 'postgres_limit_semmni > {{ semmni_cur_limit }}'
- 'postgres_limit_semmns > {{ semmns_cur_limit }}'
- 'postgres_limit_semmni > 100000'
- 'postgres_limit_semmns > 100000'

- name: set sysv max semaphore identifier system limit
sysctl:
name: '{{ sysctl_limit_semmni }}'
value: '{{ postgres_limit_semmni }}'
sysctl_set: yes
when: postgres_limit_semmni > semmni_cur_limit

- name: set sysv max semaphore count system limit
sysctl:
name: '{{ sysctl_limit_semmns }}'
value: '{{ postgres_limit_semmns }}'
sysctl_set: yes
when: postgres_limit_semmns > semmns_cur_limit


This playbook results in the tasks being skipped because of evaluating
to false. The debug task shows the tests evaluating to true when using
jinja2 templating on the compared variable.


$ ANSIBLE_NOCOLOR=1
$ ansible-playbook -v test.yml
Using /etc/ansible/ansible.cfg as config file
Vault password:

PLAY [molodetz]
*******************************************************************************************************

TASK [Gathering Facts]
************************************************************************************************
ok: [molodetz]

TASK [check sysv semaphore system limits]
*****************************************************************************
ok: [molodetz] => {"changed": false, "cmd": ["sysctl", "-n",
"kern.seminfo.semmni", "kern.seminfo.semmns"], "delta":
"0:00:00.003969", "end": "2018-05-26 08:58:34.221020", "rc": 0,
"start": "2018-05-26 08:58:34.217051", "stderr": "", "stderr_lines":
[], "stdout": "10\n60", "stdout_lines": ["10", "60"]}

TASK [set_fact]
*******************************************************************************************************
ok: [molodetz] => {"ansible_facts": {"semmni_cur_limit": "10",
"semmns_cur_limit": "60"}, "changed": false}

TASK [debug] **********************************************************************************************************
ok: [molodetz] => (item=None) => {
"semmni_cur_limit": "10"
}
ok: [molodetz] => (item=None) => {
"semmns_cur_limit": "60"
}
ok: [molodetz] => (item=None) => {
"postgres_limit_semmni": 60
}
ok: [molodetz] => (item=None) => {
"postgres_limit_semmns": 1024
}
ok: [molodetz] => (item=None) => {
"postgres_limit_semmni > 10": true
}
ok: [molodetz] => (item=None) => {
"postgres_limit_semmns > 60": true
}
ok: [molodetz] => (item=None) => {
"postgres_limit_semmni > 100000": false
}
ok: [molodetz] => (item=None) => {
"postgres_limit_semmns > 100000": false
}

TASK [set sysv max semaphore identifier system limit]
*****************************************************************
skipping: [molodetz] => {"changed": false, "skip_reason": "Conditional
result was False"}

TASK [set sysv max semaphore count system limit]
**********************************************************************
skipping: [molodetz] => {"changed": false, "skip_reason": "Conditional
result was False"}

PLAY RECAP ************************************************************************************************************
molodetz : ok=4 changed=0 unreachable=0 failed=0



Here's how the second test playbook is modified to use templating
delimiters in the conditional:

$ diff -u test*.yml
--- test.yml Sat May 26 08:47:09 2018
+++ test2.yml Sat May 26 08:46:47 2018
@@ -35,12 +35,12 @@
name: '{{ sysctl_limit_semmni }}'
value: '{{ postgres_limit_semmni }}'
sysctl_set: yes
- when: postgres_limit_semmni > semmni_cur_limit
+ when: postgres_limit_semmni > {{ semmni_cur_limit }}

- name: set sysv max semaphore count system limit
sysctl:
name: '{{ sysctl_limit_semmns }}'
value: '{{ postgres_limit_semmns }}'
sysctl_set: yes
- when: postgres_limit_semmns > semmns_cur_limit
+ when: postgres_limit_semmns > {{ semmns_cur_limit }}



$ ansible-playbook -v test2.yml
Using /etc/ansible/ansible.cfg as config file
Vault password:

PLAY [molodetz]
*******************************************************************************************************

TASK [Gathering Facts]
************************************************************************************************
ok: [molodetz]

TASK [check sysv semaphore system limits]
*****************************************************************************
ok: [molodetz] => {"changed": false, "cmd": ["sysctl", "-n",
"kern.seminfo.semmni", "kern.seminfo.semmns"], "delta":
"0:00:00.004170", "end": "2018-05-26 08:59:05.262475", "rc": 0,
"start": "2018-05-26 08:59:05.258305", "stderr": "", "stderr_lines":
[], "stdout": "10\n60", "stdout_lines": ["10", "60"]}

TASK [set_fact]
*******************************************************************************************************
ok: [molodetz] => {"ansible_facts": {"semmni_cur_limit": "10",
"semmns_cur_limit": "60"}, "changed": false}

TASK [debug] **********************************************************************************************************
ok: [molodetz] => (item=None) => {
"semmni_cur_limit": "10"
}
ok: [molodetz] => (item=None) => {
"semmns_cur_limit": "60"
}
ok: [molodetz] => (item=None) => {
"postgres_limit_semmni": 60
}
ok: [molodetz] => (item=None) => {
"postgres_limit_semmns": 1024
}
ok: [molodetz] => (item=None) => {
"postgres_limit_semmni > 10": true
}
ok: [molodetz] => (item=None) => {
"postgres_limit_semmns > 60": true
}
ok: [molodetz] => (item=None) => {
"postgres_limit_semmni > 100000": false
}
ok: [molodetz] => (item=None) => {
"postgres_limit_semmns > 100000": false
}

TASK [set sysv max semaphore identifier system limit]
*****************************************************************
[WARNING]: when statements should not include jinja2 templating
delimiters such as {{ }} or {% %}. Found:
postgres_limit_semmni > {{ semmni_cur_limit }}

changed: [molodetz] => {"changed": true}

TASK [set sysv max semaphore count system limit]
**********************************************************************
[WARNING]: when statements should not include jinja2 templating
delimiters such as {{ }} or {% %}. Found:
postgres_limit_semmns > {{ semmns_cur_limit }}

changed: [molodetz] => {"changed": true}

PLAY RECAP ************************************************************************************************************
molodetz : ok=6 changed=2 unreachable=0 failed=0

$ cat /etc/sysctl.conf
kern.seminfo.semmni=60
kern.seminfo.semmns=1024


With jinja2 templating delimiters the comparison evaluates to true and
executes the tasks, but results in the warning. Is there a different
way to structure the conditional properly?


Also would like to understand why do these set_facts still result in
the values being strings instead of integers?

- set_fact:
semmni_cur_limit: '{{ sem_limits.stdout_lines[0]|int }}'
semmns_cur_limit: '{{ sem_limits.stdout_lines[1]|int }}'

ok: [molodetz] => (item=None) => {
"semmni_cur_limit": "10"
}
ok: [molodetz] => (item=None) => {
"semmns_cur_limit": "60"
}


--
Darren Spruell
phatb...@gmail.com

Kai Stian Olstad

unread,
May 26, 2018, 2:27:02 PM5/26/18
to ansible...@googlegroups.com
The semmni_cur_limit and semmns_cur_limit is strings and you need to
cast/filter then through int each time you use them.
This is how Ansible/Jinga combo works at the time.


> Here's how the second test playbook is modified to use templating
> delimiters in the conditional:
>
> $ diff -u test*.yml
> --- test.yml Sat May 26 08:47:09 2018
> +++ test2.yml Sat May 26 08:46:47 2018
> @@ -35,12 +35,12 @@
> name: '{{ sysctl_limit_semmni }}'
> value: '{{ postgres_limit_semmni }}'
> sysctl_set: yes
> - when: postgres_limit_semmni > semmni_cur_limit
> + when: postgres_limit_semmni > {{ semmni_cur_limit }}
>
> - name: set sysv max semaphore count system limit
> sysctl:
> name: '{{ sysctl_limit_semmns }}'
> value: '{{ postgres_limit_semmns }}'
> sysctl_set: yes
> - when: postgres_limit_semmns > semmns_cur_limit
> + when: postgres_limit_semmns > {{ semmns_cur_limit }}

This is not supported in Jinja you can't use {{ }} inside {{ }}.


> With jinja2 templating delimiters the comparison evaluates to true and
> executes the tasks, but results in the warning. Is there a different
> way to structure the conditional properly?

when: postgres_limit_semmns > semmns_cur_limit | int


> Also would like to understand why do these set_facts still result in
> the values being strings instead of integers?
>
> - set_fact:
> semmni_cur_limit: '{{ sem_limits.stdout_lines[0]|int }}'
> semmns_cur_limit: '{{ sem_limits.stdout_lines[1]|int }}'

That is just how Jinja work.
In Jinja 2.10 some new feature is added to support native type, support
in Ansible is probably coming in 2.7.

https://github.com/ansible/ansible/pull/32738

--
Kai Stian Olstad

Darren S.

unread,
May 27, 2018, 3:34:53 AM5/27/18
to ansible...@googlegroups.com
On Sat, May 26, 2018 at 11:26 AM, Kai Stian Olstad
<ansible-pr...@olstad.com> wrote:
>> This playbook results in the tasks being skipped because of evaluating
>> to false. The debug task shows the tests evaluating to true when using
>> jinja2 templating on the compared variable.
>
> The semmni_cur_limit and semmns_cur_limit is strings and you need to
> cast/filter then through int each time you use them.
> This is how Ansible/Jinga combo works at the time.
>
>> With jinja2 templating delimiters the comparison evaluates to true and
>> executes the tasks, but results in the warning. Is there a different
>> way to structure the conditional properly?
>
> when: postgres_limit_semmns > semmns_cur_limit | int

This is enlightening and helped make adjustments. Thanks!

--
Darren Spruell
phatb...@gmail.com
Reply all
Reply to author
Forward
0 new messages