Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[WARNING]: when statements should not include jinja2 templating delimiters such as {{ }} or {% %}. #22397

Closed
basictheprogram opened this issue Mar 8, 2017 · 31 comments
Labels
affects_2.3 This issue/PR affects Ansible v2.3 bug This issue/PR relates to a bug.

Comments

@basictheprogram
Copy link

ISSUE TYPE
  • Bug Report
COMPONENT NAME
ANSIBLE VERSION
$ 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)]
CONFIGURATION

Stock ansible.cfg

OS / ENVIRONMENT

Management host macOS 10.12.3

SUMMARY

Task I've been using for over 7 months started throwing a warning.

STEPS TO REPRODUCE
- 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
EXPECTED RESULTS

Task would run without a warning

ACTUAL RESULTS
TASK [win_powershell : install powershell] *************************************
 [WARNING]: when statements should not include jinja2 templating delimiters
such as {{ }} or {% %}. Found: {{ ansible_PSVersionTable.Major|int < 5 }}
@ansibot ansibot added affects_2.3 This issue/PR affects Ansible v2.3 bug_report needs_triage Needs a first human triage before being processed. labels Mar 8, 2017
@sivel
Copy link
Member

sivel commented Mar 8, 2017

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.

@sivel sivel closed this as completed Mar 8, 2017
@bcoca bcoca removed the needs_triage Needs a first human triage before being processed. label Mar 13, 2017
@rawbertp
Copy link

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.

@basictheprogram
Copy link
Author

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)]

@rawbertp
Copy link

That works for me too. But now move the condition to a variable and try to use the variable instead.

@basictheprogram
Copy link
Author

ansible_PSVersionTable is a variable from a custom fact I have installed on all Window computers.

@rawbertp
Copy link

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

@jhawkesworth
Copy link
Contributor

In that case you would need the "{{ ... }}" - its only the 'when' conditional where the "{{ .... }}" is implied, I think.

@jhawkesworth
Copy link
Contributor

also might want to make use of | bool filter to ensure var is stored as a boolean.

@rawbertp
Copy link

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.

@AnthonyWC
Copy link

You can use something like:

- set_fact: content1="{{ var1.stdout }}" content2="{{ var2.stdout }}" and compare that.

@djmitche
Copy link

possibly a dup of #23578

@anavarre
Copy link

anavarre commented Apr 20, 2017

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?

@PhilEv
Copy link

PhilEv commented Apr 26, 2017

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

- name: Make sure the following users are removed
 user: 
   name: "{{ item.name }}"
   state: absent 
   remove: "{{item.remove}}"
 with_items: '{{ to_be_removed_users }}'
 when: getent_passwd.{{ item.name }} is defined
 tags:
   - userdel

@mkst
Copy link

mkst commented May 3, 2017

@PhilEv , you can do something like this to avoid that problem (note you dont need the true check):

- hosts:
    - localhost
  tasks:
    - set_fact:
        COLOURS:
          RED:  True
          BLUE: True
          YELLOW: False

    - 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"```

@jsuter
Copy link

jsuter commented May 3, 2017

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?

@sivel
Copy link
Member

sivel commented May 3, 2017

@jsuter

when: "redis_is_installed.stdout.find('v=' ~ redis_version) == -1"

@jsuter
Copy link

jsuter commented May 3, 2017

@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.

@sivel
Copy link
Member

sivel commented May 3, 2017

@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!.

@PhilEv
Copy link

PhilEv commented May 3, 2017

Thanks @streetster as posted in ansible group (thanks @sivel and Josh)

when: getent_passwd[item['name']] is defined
was all good for my case

@rlees85
Copy link

rlees85 commented May 9, 2017

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.

@h4ckninja
Copy link

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.

@rlees85
Copy link

rlees85 commented May 24, 2017

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).

#24974

kskmori pushed a commit to kskmori/ansible-pacemaker that referenced this issue Jul 5, 2017
wangsha added a commit to wangsha/ansible-role-clamav that referenced this issue Jul 17, 2017
@erikbgithub
Copy link

Instead of saying what not to do it should say WHAT TO DO! We are not magicians. Thanks.

openstack-gerrit pushed a commit to openstack/kolla-ansible that referenced this issue Sep 6, 2017
Ansible 2.3.0 does not like delimiters in when statement.

Related link: ansible/ansible#22397

Closes-Bug: #1714349
Change-Id: I973cc6537c4c1374546b5cddb4ce713a553b92f4
@bartmeuris
Copy link

bartmeuris commented Sep 19, 2017

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:
  - role: generic_role
    _configuration_needed: custom_configuration_needed

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.

@MichalTaratuta
Copy link

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 .

@sivel
Copy link
Member

sivel commented Sep 19, 2017

@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.

@garpadev
Copy link

garpadev commented Sep 29, 2017

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'

@guenhter
Copy link

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 }}

mattymo pushed a commit to kubernetes-sigs/kubespray that referenced this issue Nov 3, 2017
… var (#1911)

* Change deprecated vagrant ansible flag 'sudo' to 'become'

* Emphasize, that the name of the pip_pyton_modules is only considered in coreos

* Remove useless unused variable

* Fix warning when jinja2 template-delimiters used in when statement

There is no need for jinja2 template-delimiters like {{ }} or {% %}
any more. They can just be omitted as described in ansible/ansible#22397

* Fix broken link in getting-started guide
cackharot pushed a commit to cackharot/kubespray that referenced this issue Nov 15, 2017
… var (kubernetes-sigs#1911)

* Change deprecated vagrant ansible flag 'sudo' to 'become'

* Emphasize, that the name of the pip_pyton_modules is only considered in coreos

* Remove useless unused variable

* Fix warning when jinja2 template-delimiters used in when statement

There is no need for jinja2 template-delimiters like {{ }} or {% %}
any more. They can just be omitted as described in ansible/ansible#22397

* Fix broken link in getting-started guide
OnlyLoveOleg pushed a commit to globeandmail/ansible-role-java-jce that referenced this issue Mar 6, 2018
@ansibot ansibot added bug This issue/PR relates to a bug. and removed bug_report labels Mar 7, 2018
@karthikm57
Copy link

karthikm57 commented Mar 27, 2018

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

@linlinas
Copy link

linlinas commented May 23, 2018

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 }}"

@sivel
Copy link
Member

sivel commented May 23, 2018

@linlinas

when: "inventory_hostname in groups[sync_source]"

@ansible ansible locked as resolved and limited conversation to collaborators May 23, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
affects_2.3 This issue/PR affects Ansible v2.3 bug This issue/PR relates to a bug.
Projects
None yet
Development

No branches or pull requests