Ansible: Using with_dict and when does not skip task when undefined

Created on 11 Aug 2014  ·  3Comments  ·  Source: ansible/ansible

Issue Type:

Bug Report

Ansible Version:

ansible 1.7

Environment:

Running OS from : OSX 10.9
Managing: Ubuntu 14.04

Summary:

When a task is used with "with_dict" and "when" and the value of when evaluates to false, ansible tries to check for a dict value and fails when it should skip the task.

Steps To Reproduce:

hosts:

[test]
testhost

playbook.yml:

- hosts: all
  tasks:
   - name: Delete a user
     user: name="{{item}}" state=absent
     when: users_deleted is defined
     with_dict: users_deleted

command: ansible-playbook -i hosts playbook.yml
I have not defined users_deleted so this task should be skipped.
In playbook.yml if you change "with_dict" to "with_items" the task is skipped correctly.

Expected Results:

Results from running the task using "with_items" instead of "with_dict":

PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [testhost]

TASK: [Delete a user] *********************************************************
skipping: [testhost] => (item=users_deleted)

PLAY RECAP ********************************************************************
testhost             : ok=2    changed=0    unreachable=0    failed=0
Actual Results:
PLAY [all] ********************************************************************

GATHERING FACTS ***************************************************************
ok: [testhost]

TASK: [Delete a user] *********************************************************
fatal: [testhost] => with_dict expects a dict

FATAL: all hosts have already failed -- aborting

PLAY RECAP ********************************************************************

testhost            : ok=1    changed=0    unreachable=1    failed=0

Most helpful comment

Hi!

This is a bit of a misunderstanding, but the conditional here is evaluated for each and every item, which is a needed feature. In order to evaluate it for each item, it must start with something for which it can iterate.

As such, you might wish to do something like:

with_dict: "{{ users_deleted | default({}) }}"

Which should help resolve this.

It would also allow you to remove the when clause because the list would be of zero length instead of undefined.

Feel free to stop by ansible-project if you have further questions and we'd be glad to help with this one.

Thanks!

All 3 comments

Hi!

This is a bit of a misunderstanding, but the conditional here is evaluated for each and every item, which is a needed feature. In order to evaluate it for each item, it must start with something for which it can iterate.

As such, you might wish to do something like:

with_dict: "{{ users_deleted | default({}) }}"

Which should help resolve this.

It would also allow you to remove the when clause because the list would be of zero length instead of undefined.

Feel free to stop by ansible-project if you have further questions and we'd be glad to help with this one.

Thanks!

I ended up using:
with_dict: users_deleted | default({})

This works as expected and skips the task. As a user this was a little confusing as I would expect to be able to use "when:" consistently when I need a conditional for a task. Thanks for clarifying this!

I still got this error in version 2.0.1.0

[DEPRECATION WARNING]: Skipping task due to undefined Error, in the future this will be a fatal error.. This feature will be removed in a future
release. Deprecation warnings can be disabled by setting deprecation_warnings=False in ansible.cfg.
fatal: [xxx.xxx.xxx.xxx]: FAILED! => {"failed": true, "msg": "with_dict expects a dict"}

I have to use ignore_errors to bypass it.

Was this page helpful?
0 / 5 - 0 ratings