Issue 1:
ISSUE TYPE

Bug Report

ANSIBLE VERSION

ansible 2.1.1.0
config file = /etc/ansible/ansible.cfg
configured module search path = Default w/o overrides

OS / ENVIRONMENT

RHEL 7

SUMMARY

When with_items is used on the yum module and it fails, the detailed information normally emitted during a task failure is missing.

This is particularly confusing because the task does abort the run, or trigger block/rescue logic, but is logged as success.

Note, if I modify the yum module's module.fail_json to include an rc= parameter, this fails correctly. It is my guess the ansible logic handling faliure logging or with_items munging is not checking the module's returncode and only evaluating the json object.

STEPS TO REPRODUCE

# on (or modify to have a remote target) a RHEL 7 machine
# as this needs to execute the yum module to demo
git clone https://gist.github.com/2cc7844d3994e98bdb8b5410212d268b.git

ansible-playbook -i localhost, with_items-doesnt-show-as-failed.yaml

EXPECTED RESULTS

Normal output

fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "msg": "No Package matching 'foobar' found available, installed or updated", "rc": 0, "results": ["ansible-2.1.1.0-0.1.rc1.el7.centos.noarch providing ansible is already installed"]}

Snipped debugging details

{"changed": false, "results": ["ansible-2.1.1.0-0.1.rc1.el7.centos.noarch providing ansible is already installed"], "failed": true, "rc": 0, "invocation": {"module_args": {"name": ["ansible", "foobar"], "list": null, "disable_gpg_check": false, "conf_file": null, "install_repoquery": true, "state": "installed", "disablerepo": null, "update_cache": false, "enablerepo": null, "exclude": null, "validate_certs": true}}, "msg": "No Package matching 'foobar' found available, installed or updated"}
, stderr=
38409 1468349672.93083: done with _execute_module (yum, {'_ansible_version': '2.1.1.0', '_ansible_selinux_special_fs': ['fuse', 'nfs', 'vboxsf', 'ramfs'], u'name': u'ansible,foobar', '_ansible_verbosity': 5, '_ansible_syslog_facility': 'LOG_USER', '_ansible_diff': False, '_ansible_debug': True, '_ansible_check_mode': False, '_ansible_no_log': False})
38409 1468349672.93096: handler run complete
38409 1468349672.93114: attempt loop complete, returning result
38409 1468349672.93119: _execute() done
38409 1468349672.93123: dumping result to json
38409 1468349672.93137: done dumping result, returning
38409 1468349672.93149: done running TaskExecutor() for localhost/TASK: yum
38409 1468349672.93154: sending task result
38409 1468349672.93199: done sending task result
38409 1468349672.93337: WORKER PROCESS EXITING
38353 1468349672.93346: worker 0 has data to read
38353 1468349672.93417: got a result from worker 0: <ansible.executor.task_result.TaskResult object at 0x22f3f90>
#### This result object is correctly identified as a failure.
38353 1468349672.93430: sending result: [u'host_task_failed', u'<ansible.executor.task_result.TaskResult object at 0x22f3f90>']
38353 1468349672.93436: done sending result
38348 1468349672.93694: got result from result worker: [u'host_task_failed', u'<ansible.executor.task_result.TaskResult object at 0x263e950>']
38348 1468349672.93702: marking localhost as failed
38348 1468349672.93709: marking host localhost failed, current state: HOST STATE: block=3, task=1, rescue=0, always=0, role=None, run_state=ITERATING_TASKS, fail_state=FAILED_NONE, pending_setup=False, tasks child state? None, rescue child state? None, always child state? None, did start at task? False
38348 1468349672.93714: ^ failed state is now: HOST STATE: block=3, task=1, rescue=0, always=0, role=None, run_state=ITERATING_RESCUE, fail_state=FAILED_TASKS, pending_setup=False, tasks child state? None, rescue child state? None, always child state? None, did start at task? False
38348 1468349672.93718: getting the next task for host localhost
38348 1468349672.93722: done getting next task for host localhost
38348 1468349672.93726: ^ task is: TASK: Installing multiple packages (csv) dies OK
38348 1468349672.93730: ^ state is: HOST STATE: block=3, task=1, rescue=1, always=0, role=None, run_state=ITERATING_RESCUE, fail_state=FAILED_TASKS, pending_setup=False, tasks child state? None, rescue child state? None, always child state? None, did start at task? False
fatal: [localhost]: FAILED! => {"changed": false, "failed": true, "invocation": {"module_args": {"conf_file": null, "disable_gpg_check": false, "disablerepo": null, "enablerepo": null, "exclude": null, "install_repoquery": true, "list": null, "name": ["ansible", "foobar"], "state": "installed", "update_cache": false, "validate_certs": true}, "module_name": "yum"}, "msg": "No Package matching 'foobar' found available, installed or updated", "rc": 0, "results": ["ansible-2.1.1.0-0.1.rc1.el7.centos.noarch providing ansible is already installed"]}
38348 1468349672.93824: no more pending results, returning what we have
38348 1468349672.93831: results queue empty
38348 1468349672.93833: checking for any_errors_fatal
38348 1468349672.93839: done checking for any_errors_fatal
38348 1468349672.93842: checking for max_fail_percentage
38348 1468349672.93844: done checking for max_fail_percentage
38348 1468349672.93846: getting the remaining hosts for this loop
38348 1468349672.93851: done getting the remaining hosts for this loop
38348 1468349672.93870: building list of next tasks for hosts
38348 1468349672.93874: getting the next task for host localhost

ACTUAL RESULTS

Instead I see the following and then an immediate abort.

Normal output

ok: [localhost] => (item=[u'ansible', u'foobar'])

Snipped debugging details

{"changed": false, "results": ["ansible-2.1.1.0-0.1.rc1.el7.centos.noarch providing ansible is already installed"], "failed": true, "rc": 0, "invocation": {"module_args": {"name": ["ansible", "foobar"], "list": null, "disable_gpg_check": false, "conf_file": null, "install_repoquery": true, "state": "installed", "disablerepo": null, "update_cache": false, "enablerepo": null, "exclude": null, "validate_certs": true}}, "msg": "No Package matching 'foobar' found available, installed or updated"}
, stderr=
38448 1468349674.12175: done with _execute_module (yum, {'_ansible_version': '2.1.1.0', '_ansible_selinux_special_fs': ['fuse', 'nfs', 'vboxsf', 'ramfs'], 'name': [u'ansible', u'foobar'], '_ansible_verbosity': 5, '_ansible_syslog_facility': 'LOG_USER', u'state': u'installed', '_ansible_diff': False, '_ansible_debug': True, '_ansible_check_mode': False, '_ansible_no_log': False})
38448 1468349674.12186: handler run complete
38448 1468349674.12200: attempt loop complete, returning result
38448 1468349674.12248: dumping result to json
38448 1468349674.12260: done dumping result, returning
38448 1468349674.12274: done running TaskExecutor() for localhost/TASK: yum
38448 1468349674.12281: sending task result
38353 1468349674.12396: worker 0 has data to read
38353 1468349674.12463: got a result from worker 0: <ansible.executor.task_result.TaskResult object at 0x22f0410>
#### This result object should be a failure, not ok.
38353 1468349674.12473: sending result: [u'v2_runner_item_on_ok', u'<ansible.executor.task_result.TaskResult object at 0x22f0410>']
38353 1468349674.12479: done sending result
38448 1468349674.12486: done sending task result
38448 1468349674.12493: WORKER PROCESS EXITING
38348 1468349674.12615: got result from result worker: [u'v2_runner_item_on_ok', u'<ansible.executor.task_result.TaskResult object at 0x264b150>']
ok: [localhost] => (item=[u'ansible', u'foobar'])
38353 1468349674.12668: worker 0 has data to read
38353 1468349674.12723: got a result from worker 0: <ansible.executor.task_result.TaskResult object at 0x22f3f50>
38353 1468349674.12732: sending result: [u'host_task_failed', u'<ansible.executor.task_result.TaskResult object at 0x22f3f50>']
38353 1468349674.12736: done sending result
38348 1468349674.12841: got result from result worker: [u'host_task_failed', u'<ansible.executor.task_result.TaskResult object at 0x2649e90>']
38348 1468349674.12849: marking localhost as failed
38348 1468349674.12857: marking host localhost failed, current state: HOST STATE: block=4, task=1, rescue=0, always=0, role=None, run_state=ITERATING_TASKS, fail_state=FAILED_NONE, pending_setup=False, tasks child state? None, rescue child state? None, always child state? None, did start at task? False
38348 1468349674.12862: ^ failed state is now: HOST STATE: block=4, task=1, rescue=0, always=0, role=None, run_state=ITERATING_RESCUE, fail_state=FAILED_TASKS, pending_setup=False, tasks child state? None, rescue child state? None, always child state? None, did start at task? False
38348 1468349674.12866: getting the next task for host localhost

Issue 2:
I looked but couldn't see an obvious issue for this

ISSUE TYPE

Bug Report

ANSIBLE VERSION

ansible-playbook 2.1.0.0
config file = /Users/g.lynch/git/tos/ansible_pulp/ansible.cfg
configured module search path = Default w/o overrides

CONFIGURATION

[defaults]
inventory = hosts
roles_path = roles
retry_files_enabled = False

OS / ENVIRONMENT

Docker container FROM: centos:6.8

SUMMARY

Using yum and with_items returns OK instead of FATAL in the task, followed by NO MORE HOSTS LEFT, when an item fails.

STEPS TO REPRODUCE

# foo.yml

---
- hosts: all
vars:
mongodb_packages:
- name: mongodb-server
tasks:
- name: configure the packages
yum:
name: "{{ item.name }}"
state: "{{ item.state|default('present') }}"
with_items: "{{ mongodb_packages }}"

docker run -dt --name centos68 centos:6.8 /sbin/init
ansible-playbook -i 'centos68,' foo.yml -c docker -vvv

EXPECTED RESULTS

The task should output an obvious fatal message

fatal: [centos68]: FAILED! => {"changed": false, "failed": true, "invocation": {"module_args": {"conf_file": null, "disable_gpg_check": false, "disablerepo": null, "enablerepo": null, "exclude": null, "install_repoquery": true, "list": null, "name": ["mongodb-server"], "state": "present", "update_cache": false, "validate_certs": true}, "module_name": "yum"}, "msg": "No Package matching 'mongodb-server' found available, installed or updated", "rc": 0, "results": []}

Note I get the fatal message if I remove the with_items.

ACTUAL RESULTS

I get an OK response followed by an initially confusing NO MORE HOSTS LEFT message

$ ansible-playbook -i 'centos68,' foo.yml -c docker -vvv
Using /tmp/ansible.cfg as config file

PLAYBOOK: foo.yml **************************************************************
1 plays in foo.yml

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

TASK [setup] *******************************************************************
<centos68> ESTABLISH DOCKER CONNECTION FOR USER: root
<centos68> EXEC ['/usr/local/bin/docker', 'exec', '-i', 'centos68', u'/bin/sh', '-c', u'/bin/sh -c \'( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1467802796.84-176847019920783 `" && echo ansible-tmp-1467802796.84-176847019920783="` echo $HOME/.ansible/tmp/ansible-tmp-1467802796.84-176847019920783 `" ) && sleep 0\'']
<centos68> PUT /var/folders/_j/pvqg__g512v5jgc3kl9vnlvd_6vfxx/T/tmpEkhN1i TO /root/.ansible/tmp/ansible-tmp-1467802796.84-176847019920783/setup
<centos68> EXEC ['/usr/local/bin/docker', 'exec', '-i', 'centos68', u'/bin/sh', '-c', u'/bin/sh -c \'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /root/.ansible/tmp/ansible-tmp-1467802796.84-176847019920783/setup; rm -rf "/root/.ansible/tmp/ansible-tmp-1467802796.84-176847019920783/" > /dev/null 2>&1 && sleep 0\'']
ok: [centos68]

TASK [configure the packages] **************************************************
task path: /tmp/foo.yml:7
<centos68> ESTABLISH DOCKER CONNECTION FOR USER: root
<centos68> EXEC ['/usr/local/bin/docker', 'exec', '-i', 'centos68', u'/bin/sh', '-c', u'/bin/sh -c \'( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1467802797.72-8724224930718 `" && echo ansible-tmp-1467802797.72-8724224930718="` echo $HOME/.ansible/tmp/ansible-tmp-1467802797.72-8724224930718 `" ) && sleep 0\'']
<centos68> PUT /var/folders/_j/pvqg__g512v5jgc3kl9vnlvd_6vfxx/T/tmpytRzHJ TO /root/.ansible/tmp/ansible-tmp-1467802797.72-8724224930718/yum
<centos68> EXEC ['/usr/local/bin/docker', 'exec', '-i', 'centos68', u'/bin/sh', '-c', u'/bin/sh -c \'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /root/.ansible/tmp/ansible-tmp-1467802797.72-8724224930718/yum; rm -rf "/root/.ansible/tmp/ansible-tmp-1467802797.72-8724224930718/" > /dev/null 2>&1 && sleep 0\'']
ok: [centos68] => (item={u'name': u'mongodb-server'}) => {"changed": false, "failed": true, "invocation": {"module_args": {"conf_file": null, "disable_gpg_check": false, "disablerepo": null, "enablerepo": null, "exclude": null, "install_repoquery": true, "list": null, "name": ["mongodb-server"], "state": "present", "update_cache": false, "validate_certs": true}, "module_name": "yum"}, "item": {"name": "mongodb-server"}, "msg": "No Package matching 'mongodb-server' found available, installed or updated", "rc": 0, "results": []}

NO MORE HOSTS LEFT *************************************************************

PLAY RECAP *********************************************************************
centos68 : ok=1 changed=0 unreachable=0 failed=1