Repository: ansible/ansible

Issue:
warnings messages not reported when using lists
##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
Bug Report

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
modules with "warning messages"

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.2.0.0
  config file = /etc/ansible/ansible.cfg
  configured module search path = Default w/o overrides
```

##### CONFIGURATION
<!---
no changes in ansible.cfg
-->

##### OS / ENVIRONMENT
<!---
Linux version 3.10.0-514.16.1.el7.x86_64 (Redhat 7)
-->

##### SUMMARY
<!--- Explain the problem briefly -->
A task which using with_items don't report warning messages


##### STEPS TO REPRODUCE
<!---
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
---
create module: test.py
#-----------------------------------------------------------
#! /usr/bin/env python2
from ansible.module_utils.basic import *
module.exit_json(changed=False, warnings=['test'])
#-----------------------------------------------------------
create playbook: test.yml
#-----------------------------------------------------------
---
  - name: test
    hosts: 127.0.0.1

    tasks:
      - name: test 
        test:
#-----------------------------------------------------------
run: playbook:
ansible-playbook  test.yml
 [WARNING]: provided hosts list is empty, only localhost is available


PLAY [test] ********************************************************************

TASK [setup] *******************************************************************
ok: [127.0.0.1]

TASK [test user:pijpe00] *******************************************************
ok: [127.0.0.1]
 [WARNING]: test


PLAY RECAP *********************************************************************
127.0.0.1                  : ok=2    changed=0    unreachable=0    failed=0

Change: playbook in (test.yml):
#-----------------------------------------------------------
---
  - name: test
    hosts: 127.0.0.1

    tasks:
      - name: test
        test:
        with_items:
          - edwin
          - henk
#-----------------------------------------------------------

Run module again:
ansible-playbook  test.yml
 [WARNING]: provided hosts list is empty, only localhost is available


PLAY [test] ********************************************************************

TASK [setup] *******************************************************************
ok: [127.0.0.1]

TASK [test] ********************************************************************
ok: [127.0.0.1] => (item=edwin)
ok: [127.0.0.1] => (item=henk)

PLAY RECAP *********************************************************************
127.0.0.1                  : ok=2    changed=0    unreachable=0    failed=0

The warnings are not reported!

```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
I expected two warnings, like:
ok: [127.0.0.1] => (item=edwin)
 [WARNING]: test
ok: [127.0.0.1] => (item=henk)
 [WARNING]: test
##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
I did not get any warning message. I got:
ok: [127.0.0.1] => (item=edwin)
ok: [127.0.0.1] => (item=henk)


<!--- Paste verbatim command output between quotes below -->
```

```



Discussion:

Resolving patch:
diff --git a/lib/ansible/executor/task_executor.py b/lib/ansible/executor/task_executor.py
--- a/lib/ansible/executor/task_executor.py
+++ b/lib/ansible/executor/task_executor.py
@@ -34,7 +34,6 @@
 from ansible.template import Templar
 from ansible.utils.encrypt import key_for_hostname
 from ansible.utils.listify import listify_lookup_plugin_terms
-from ansible.utils.ssh_functions import check_for_controlpersist
 from ansible.utils.unsafe_proxy import UnsafeProxy, wrap_var
 
 try:
@@ -96,27 +95,28 @@ def run(self):
                 if len(items) > 0:
                     item_results = self._run_loop(items)
 
-                    # loop through the item results, and remember the changed/failed
-                    # result flags based on any item there.
-                    changed = False
-                    failed = False
-                    for item in item_results:
-                        if 'changed' in item and item['changed']:
-                            changed = True
-                        if 'failed' in item and item['failed']:
-                            failed = True
-
-                    # create the overall result item, and set the changed/failed
-                    # flags there to reflect the overall result of the loop
+                    # create the overall result item
                     res = dict(results=item_results)
 
-                    if changed:
-                        res['changed'] = True
-
-                    if failed:
-                        res['failed'] = True
-                        res['msg'] = 'One or more items failed'
-                    else:
+                    # loop through the item results, and set the global changed/failed result flags based on any item.
+                    for item in item_results:
+                        if 'changed' in item and item['changed'] and not res.get('changed'):
+                            res['changed'] = True
+                        if 'failed' in item and item['failed'] and not res.get('failed'):
+                            res['failed'] = True
+                            res['msg'] = 'One or more items failed'
+
+                        # ensure to accumulate these
+                        for array in ['warnings', 'deprecations']:
+                            if array in item and item[array]:
+                                if array not in res:
+                                    res[array] = []
+                                if not isinstance(item[array], list):
+                                    item[array] = [item[array]]
+                                res[array] = res[array] + item[array]
+                                del item[array]
+
+                    if not res.get('Failed', False):
                         res['msg'] = 'All items completed'
                 else:
                     res = dict(changed=False, skipped=True, skipped_reason='No items in the list', results=[])


Test patch: