$ ansible --version
ansible 2.3.0 (devel a8910e78ca) last updated 2017/03/08 02:46:53 (GMT -500)
config file =
configured module search path = Default w/o overrides
python version = 2.7.10 (default, Jul 30 2016, 19:40:32) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)]
Stock ansible.cfg
Management host macOS 10.12.3
Task I've been using for over 7 months started throwing a warning.
- name: install powershell
win_chocolatey:
name: '{{ item }}'
state: 'present'
upgrade: True
with_items:
- "powershell"
register: check_powershell5
when: "{{ ansible_PSVersionTable.Major|int < 5 }}"
tags: win_powershell
Task would run without a warning
TASK [win_powershell : install powershell] *************************************
[WARNING]: when statements should not include jinja2 templating delimiters
such as {{ }} or {% %}. Found: {{ ansible_PSVersionTable.Major|int < 5 }}
This is expected. The warning was recently added to the 2.3 release purposefully.
As the warning states, you should not use jinja2 delimiters in a when statement. Instead it should read:
when: ansible_PSVersionTable.Major|int < 5
If you have further questions please feel free to use the mailing list.
How to workaround this warning if the when expression is stored in a variable (for whatever reason, e.g. due to it being used mutlitple times in different plays).
e.g.: mycondition: ansible_PSVersionTable.Major|int < 5
to be used as when: mycondition
.
-> This is not working because mycondition
doesn't get evaluated/expanded and is treated as a String.
What works is to declare mycondition: "{{ ansible_PSVersionTable.Major|int < 5 }}"
or when: "{{ mycondition }}"
but both will result in the above mentioned WARNING.
This works for me
when: "(ansible_PSVersionTable.Major|int < 5) and ('Microsoft Windows 7' in ansible_distribution)"
with
$ ansible --version
ansible 2.4.0 (devel 53c52cf65f) last updated 2017/03/30 07:29:39 (GMT -500)
config file =
configured module search path = [u'/Users/tanner/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
python version = 2.7.10 (default, Jul 30 2016, 19:40:32) [GCC 4.2.1 Compatible Apple LLVM 8.0.0 (clang-800.0.34)]
That works for me too. But now move the condition to a variable and try to use the variable instead.
ansible_PSVersionTable is a variable from a custom fact I have installed on all Window computers.
Try the following and I assume it won't work (given that the condition is true
):
mycond: "(ansible_PSVersionTable.Major|int < 5) and ('Microsoft Windows 7' in ansible_distribution)"
...
when: mycond
In that case you would need the "{{ ... }}" - its only the 'when' conditional where the "{{ .... }}" is implied, I think.
also might want to make use of | bool filter to ensure var is stored as a boolean.
That's what I'm saying... you will either need the "{{ ... }}" within the variable declaration or the when condition as it won't work (correctly) otherwise. And then you will get the mentioned WARNING.
You can use something like:
- set_fact: content1="{{ var1.stdout }}" content2="{{ var2.stdout }}"
and compare that.
possibly a dup of #23578
I'm also a bit confused by this. I understand we can now do myvar
instead of "{{ myvar }}"
or {{ myvar }}
but there are certain uses cases where this still isn't enough. E.g.
when: myvar.stdout != ansible_date_time.date
^ This will NOT return the current date (YYYY-MM-DD). In this instance I have no way to use anything else but the jinja2 delimiters with something like:
- set_fact:
ansible_date: "{{ ansible_date_time.date }}"
Another use case is, e.g.
- name: "TEST: The files directory should have correct ownership"
shell: stat -c %U:%G {{ files_dir }}
register: styles_dir_ownership
changed_when: styles_dir_ownership.stdout != "{{ user }}:{{ apache_user }}"
failed_when: styles_dir_ownership.stdout != "{{ user }}:{{ apache_user }}"
I have no way to simply do user:apache_user
because I need to pass a colon and thus have to resort to e.g.
- set_fact:
expected_ownership: "{{ user }}:{{ apache_user }}"
So my question is: how can I both account for those 2 use cases if jinja2 delimiters are deprecated starting with Ansible 2.3? Is set_fact
now the preferred option?
Adding another use case:
consider the following variable:
to_be_removed_users:
- name: 'adm'
remove: False
- name: 'ftp'
remove: True
- name: 'games'
remove: False
- name: 'gopher'
remove: True
- name: 'operator'
remove: False
- name: 'uucp'
remove: True
then the following tasks generate the warning. Not sure how to avoid it as item.name is the result of iteration on the list
```
name: Get users list
getent:
database: passwd
tags:
- userdel
@PhilEv , you can do something like this to avoid that problem (note you dont need the true check):
```---
- name: Favourite colours!
command: echo "I like {{ item }}"
# when: COLOURS.{{item}} is defined and COLOURS.{{item}}
when: item in COLOURS and COLOURS[item]
with_items:
- "GREEN"
- "BLUE"
- "PURPLE"
- "YELLOW"```
We're seeing these warnings as well, and removing the jinja delimiters from when
seems to break this:
- name: Check if redis is installed
shell: redis-server --version || /bin/true
register: redis_is_installed
- include: redis_build.yml
when: "redis_is_installed.stdout.find('v={{ redis_version }}') == -1"
Any suggestions for an alternative way of writing this?
@jsuter
when: "redis_is_installed.stdout.find('v=' ~ redis_version) == -1"
@sivel Awesome, thank you. What is the tilde doing specifically in this case? I can't find the docs on it and would love to read up.
@jsuter http://jinja.pocoo.org/docs/dev/templates/#other-operators
~
Converts all operands into strings and concatenates them.{{ "Hello " ~ name ~ "!" }} would return (assuming name is set to 'John') Hello John!.
Thanks @streetster as posted in ansible group (thanks @sivel and Josh)
when: getent_passwd[item['name']] is defined
was all good for my case
I honestly don't see how you can write a meaningful playbook without triggering this new warning message. The whole point of Ansible is that things can be modularised into roles. If you want to stop this warning from being triggered you have no chance unless you are writing flat playbooks with ugly when expressions.
Examples that are seemingly not able to be worked around:
defaults
auth_service : none
auth_service_aws : aws
auth_service_is_aws: '{{ (auth_service == auth_service_aws) | bool }}'
meta
dependencies:
- { role: apollo/auth/aws, when: auth_service_is_aws }
throws warnings....
And finally (this is really difficult to work around!)
Parent Role - defaults
bootstrap_ping : true
Parent Role - meta
dependencies:
- { role: apollo/platform/ping, ping: '{{ bootstrap_ping }}' }
Child Role - tasks
- name: execute
when: ping
win_ping:
I seriously hope I am being stupid and am missing something simple either that or this change gets reverted in the next release.
Color me confused as well. Everything else in Ansible, as far as I can see, uses Jinja delimeters. What's the difference between "changed_when" and the rest? Speaking as someone who is learning Ansible, it makes things harder to understand.
Please see above PR. I will probably get fish slapped pretty hard but if it is affecting enough people please show your support and maybe the warnings will get removed (either by this way or another).
Instead of saying what not to do it should say WHAT TO DO! We are not magicians. Thanks.
I get this warning all over the place now. I have a generic role that is 'extended' in specialized roles by specifying some variables when defining this generic as a dependency like this in the meta/main.yml
:
dependencies:
- role: generic_role
_configuration_needed: "{{custom_configuration_needed}}"
The custom_configuration_needed
is then a default or can be overridden per-host or per-group when including the specialized role.
Then, in the generic role I have steps like this:
- name: "configure package if necessary"
include: configure.yml
when: _configuration_needed
I now however, in every single step in the configure.yml
in the 'base' generic role executed for that specialized role, get warnings like this:
[WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or {% %}. Found: {{custom_configuration_needed}}
```
This is due to the implicit 'when' clause that's added to every step in that included file, but I'm not sure how to solve this-one. The `_configuration_needed` isn't the only case, it's just the one spamming most warnings right now. Now for this `_configuration_needed` I tried defining the dependency like this:
dependencies:
This however doesn't work, since when I debug print that _configuration_needed variable, I see this "custom_configuration_needed" as (a non-empty) string, which always evaluates to "True". This is certainly not expected or wanted behavior and I have no idea how to remove these warnings.
If there is a working solution for preventing these warnings in this case, which also have the expected behavior, please share - bur right now, I can't find any way to do this.
Also, for ansible 3, please consider making jinja templating consistent across the board. Everywhere or nowhere {{}}
, but this is plain silly.
I can't eveluate a dynamic variable without the {{}}, I can't get this working witout the curly brackets:
vars:
host_name: ['foo', 'bar']
foo_wwn_2: "This exist"
tasks:
- debug:
var: "{{item.1}}_wwn_{{item.0}}"
when: ({{item.1 + '_wwn_' + item.0}}) is defined
with_nested:
- ['1', '2']
- "{{host_name}}"
Without the brackets it's just a string which will be evaluated as TRUE.
It's really dissapointing to see that you want to remove the only way to evaluate variable within the when
.
@bartmeuris in your example, that warning will no longer show up in ansible v2.4 which is soon to be released
@MichalTaratuta you should be using the following instead:
when: vars[item.1 ~ '_wnn_' ~ item.0] is defined
The fact that your example worked before was unintentional, and is not best practice for building a variable name to check.
What about when testing for the presence of a string, part of which contains a variable?
vars:
acct:
name: example_name
tasks:
- name: Emergency Account | Gather list of usernames
ios_command:
commands: show run | i ^username
register: ios_usernames
- name: Emergency Account | Remove non-emergency account users
ios_config:
lines:
- no {{ item }}
with_flattened:
- "{{ ios_usernames.stdout_lines }}"
when: '"username {{ acct.name }} privilege 0 secret" not in item'
no_log: True
It's very possible I'm just missing a better or more appropriate way to write that but so far the only method that works seems to be using the brackets within the quoted string.
EDIT
Sorry for cluttering the thread. After re-reading a few of the examples and further testing was able to get it work by breaking apart the quote and using concatenation. Makes it a little longer but does the job.
when: '"username " ~ localauth.emergency.name ~ " privilege 0 secret" not in item'
I see that the warning is useful, but can e.g. longer expressions like the following one can be written without any templating delimiters:
when: |-
{%- set certs = {'sync': False} -%}
{% if gen_node_certs[inventory_hostname] or
(not etcdcert_node.results[0].stat.exists|default(False)) or
(not etcdcert_node.results[1].stat.exists|default(False)) or
(etcdcert_node.results[1].stat.checksum|default('') != etcdcert_master.files|selectattr("path", "equalto", etcdcert_node.results[1].stat.path)|map(attribute="checksum")|first|default('')) -%}
{%- set _ = certs.update({'sync': True}) -%}
{% endif %}
{{ certs.sync }}
This may help new people,
We can not use variables inside when condition because it has some restrictions and below warning will be displayed
WARNING:when statements should not include jinja2 templating delimiters such as {{ }} or {% %}
so to avoid such things while checking the condition by passing variable, first we need to register that particular variable and then use that.Below is the small example
VERSION is already defined or passed explicitely while running a play book
- name: Check the java version
shell: java -version 2>&1 | grep version | awk '{print $3}' | sed 's/"//g' | cut -d "_" -f1
register: java_versios
- name: testing senario
shell: echo '{{ VERSION }}'
register: r
- name: testing
file:
path: /root/Karthik/JAVATEST
state: directory
owner: root
group: root
mode: 0755
recurse: yes
when: java_version.stdout >= r.stdout
Hello,
What about the case when I am passing a inventory group name based on the predefined variable?
In this scenario based on the variable "sync_source", I invoke to inventory group which is passed as a variable by the user.
- debug:
msg:
- "source instance: {{ inventory_hostname }}"
- "{{ dir }} size is {{ result_dir_size }} GB"
when: "inventory_hostname in groups.{{ sync_source }}"
@linlinas
when: "inventory_hostname in groups[sync_source]"
Most helpful comment
I honestly don't see how you can write a meaningful playbook without triggering this new warning message. The whole point of Ansible is that things can be modularised into roles. If you want to stop this warning from being triggered you have no chance unless you are writing flat playbooks with ugly when expressions.
Examples that are seemingly not able to be worked around:
defaults
meta
throws warnings....
And finally (this is really difficult to work around!)
Parent Role - defaults
Parent Role - meta
Child Role - tasks
I seriously hope I am being stupid and am missing something simple either that or this change gets reverted in the next release.