Repository: ansible/ansible

Issue:
diff directive does not behave the same as '--diff' on the command line
<!---
Verify first that your issue/request is not already reported on GitHub.
Also test if the latest release, and master branch are affected too.
-->

##### ISSUE TYPE
<!--- Pick one below and delete the rest: -->
 - Feature Idea

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
Shows in nxos/ios_config modules but probably a Core issue.

- [ ] nxos

- [ ] ios

##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
scarter@ansible-2.4:~/projects/ansible-netops.ismc$ ansible --version
ansible 2.4.0.0
  config file = /Users/scarter/.ansible.cfg
  configured module search path = [u'/Users/scarter/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/lib/python2.7/site-packages/ansible
  executable location = /usr/bin/ansible
  python version = 2.7.5 (default, Nov  6 2016, 00:28:07) [GCC 4.8.5 20150623 (Red Hat 4.8.5-11)]
```

##### CONFIGURATION
<!---
If using Ansible 2.4 or above, paste the results of "ansible-config dump --only-changed"

Otherwise, mention any settings you have changed/added/removed in ansible.cfg
(or using the ANSIBLE_* environment variables).

-->
```
scarter@ansible-2.4:~/projects/ansible-netops.ismc$ ansible-config dump --only-changed
ANSIBLE_SSH_CONTROL_PATH(/Users/scarter/.ansible.cfg) = /tmp/%%h<E2><80><90>%%r
```
##### OS / ENVIRONMENT
<!---
Mention the OS you are running Ansible from, and the OS you are
managing, or say "N/A" for anything that is not platform-specific.
Also mention the specific version of what you are trying to control,
e.g. if this is a network bug the version of firmware on the network device.
-->
CentOS 7 Docker container on OSX

##### SUMMARY
<!--- Explain the problem briefly -->
The 'diff' directive shows that there was a change but not what the change was.  The '--diff' option on the command line shows both.  The behaviors should match.

##### STEPS TO REPRODUCE
<!---
For bugs, show exactly how to reproduce the problem, using a minimal test-case.
For new features, show how the feature would be used.
-->

<!--- Paste example playbooks or commands between quotes below -->
```yaml
- name: diff the running-config against a provided config
  nxos_config:
    diff_against: intended
    intended_config: "{{ lookup('file', net_backup_file) }}"
  diff: true
  register: diff_results
```

<!--- 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 expect to see the actually difference in the configuration

##### ACTUAL RESULTS
I only see that there was a change, not what that change was

<!--- Paste verbatim command output between quotes below -->
```
ansible-playbook --diff -u stevenca -i inventory/cil --limit csn-sjc18-n9k2.ciscolabs.net net-backup.yml

TASK [net-backup : diff the running-config against a provided config] **************************************************************************************************************************
--- before
+++ after
@@ -131,7 +131,7 @@
   switchport monitor
   speed 1000
 interface Ethernet1/10
-  description bar
+  description foo
 interface Ethernet1/11
   description csn-sjc18-fs8k1:s1p1
   switchport access vlan 200

changed: [csn-sjc18-n9k2.ciscolabs.net]

ansible-playbook -u stevenca -i inventory/cil --limit csn-sjc18-n9k2.ciscolabs.net net-backup.yml
TASK [net-backup : diff the running-config against a provided config] **************************************************************************************************************************
changed: [csn-sjc18-n9k2.ciscolabs.net]
```



Discussion:
cc @dharmabumstead
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
cc @kedarX @privateip @rcarrillocruz
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Making `diff: yes` always display diff for a specific task, even if `--diff` is not passed would be an awesome addition. Currently it only allows you to disable diff of specific tasks setting `diff: no`.

This parameter also isn't documented anywhere, or at least I couldn't find it.
The modules `nxos_config`, `ios_config` support `diff`.
With `diff: true` option in the task, it displays the `after` and `before` diff in the response.
It doesn't display diff for every line with `+`, `-` like `--diff` does.
```
changed: [nxos] => {
    "attempts": 1, 
    "changed": true, 
    "diff": {
        "after": "",
        "before": ""
    },
```
but when run the playbook with command line option `--diff`, it displays diff for the specific task in the playbook result:
```
--- before
+++ after
@@ -1,9 +1,7 @@
 interface Ethernet1/2
-  switchport access vlan 100
-  lldp transmit
-  lldp receive
+  no lldp transmit
+  no lldp receive
```

This is more like a **feature idea** to me and core issue.
/cc @abadger @bcoca 
@trishnaguha
So is it possible to get only diff results from the ansible playbook output, for example like this:
 interface Ethernet1/2
-  switchport access vlan 100
-  lldp transmit
-  lldp receive
?
@kustodian  http://docs.ansible.com/ansible/latest/reference_appendices/playbooks_keywords.html

bug was that we only called the callback event when the global diff was set, but not the task level one, fix incoming.

Resolving patch:
diff --git a/lib/ansible/plugins/strategy/__init__.py b/lib/ansible/plugins/strategy/__init__.py
--- a/lib/ansible/plugins/strategy/__init__.py
+++ b/lib/ansible/plugins/strategy/__init__.py
@@ -439,12 +439,6 @@ def parent_handler_match(target_handler, handler_name):
             task_result._host = original_host
             task_result._task = original_task
 
-            # get the correct loop var for use later
-            if original_task.loop_control:
-                loop_var = original_task.loop_control.loop_var
-            else:
-                loop_var = 'item'
-
             # send callbacks for 'non final' results
             if '_ansible_retry' in task_result._result:
                 self._tqm.send_callback('v2_runner_retry', task_result)
@@ -456,7 +450,7 @@ def parent_handler_match(target_handler, handler_name):
                     self._tqm.send_callback('v2_runner_item_on_skipped', task_result)
                 else:
                     if 'diff' in task_result._result:
-                        if self._diff:
+                        if self._diff or getattr(original_task, 'diff', False):
                             self._tqm.send_callback('v2_on_file_diff', task_result)
                     self._tqm.send_callback('v2_runner_item_on_ok', task_result)
                 continue
@@ -630,7 +624,7 @@ def parent_handler_match(target_handler, handler_name):
                                     self._tqm._stats.set_custom_stats(k, data[k], myhost)
 
                 if 'diff' in task_result._result:
-                    if self._diff:
+                    if self._diff or getattr(original_task, 'diff', False):
                         self._tqm.send_callback('v2_on_file_diff', task_result)
 
                 if not isinstance(original_task, TaskInclude):


Test patch: