Repository: ansible/ansible

Issue:
(P1) nxos_smu structured output not supported transport nxapi
##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
 - nxos_smu

##### NXOS VERSION
7.0(3)I5(3)
##### ANSIBLE VERSION
```
ansible 2.4.0 (devel aa19563388) last updated 2017/08/01 09:45:40 (GMT -400)
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/usr/share/ansible']
  ansible python module location = /root/agents-ci/ansible/lib/ansible
  executable location = /root/agents-ci/ansible/bin/ansible
  python version = 2.7.6 (default, Oct 26 2016, 20:30:19) [GCC 4.8.4]
```

##### OS / ENVIRONMENT
Ubuntu 14.04

##### SUMMARY
The following playbook fails to apply properly indicating that structured output is not supported.

This is only a problem for the `nxapi` transport.

```yaml
---
- debug: msg="START TRANSPORT:{{ connection.transport }} nxos_smu sanity test"

- name: Test SMUs
  nxos_smu:
    pkg: "nxos.sample-n9k_ALL-1.0.0-7.0.3.I5.3.lib32_n9000"
    timeout: 300
    provider: "{{ connection }}"

- debug: msg="END TRANSPORT:{{ connection.transport }} nxos_smu sanity test"

```

```shell
TASK [nxos_smu : debug] ***************************************************************************************************************************************************************************************************************
task path: /root/agents-ci/ansible/test/integration/targets/nxos_smu/tests/common/sanity.yaml:2
ok: [n9k.example.com] => {
    "msg": "START TRANSPORT:nxapi nxos_smu sanity test"
}

TASK [nxos_smu : Test SMUs] ***********************************************************************************************************************************************************************************************************
task path: /root/agents-ci/ansible/test/integration/targets/nxos_smu/tests/common/sanity.yaml:4
<n9k.example.com> connection transport is nxapi
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/basic.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/nxos.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/_text.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/parsing/convert_bool.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/parsing/__init__.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/pycompat24.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/six/__init__.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/connection.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/network_common.py
Using module_utils file /root/agents-ci/ansible/lib/ansible/module_utils/urls.py
Using module file /root/agents-ci/ansible/lib/ansible/modules/network/nxos/nxos_smu.py
<n9k.example.com> ESTABLISH LOCAL CONNECTION FOR USER: root
<n9k.example.com> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1501595633.02-214170940236146 `" && echo ansible-tmp-1501595633.02-214170940236146="` echo $HOME/.ansible/tmp/ansible-tmp-1501595633.02-214170940236146 `" ) && sleep 0'
<n9k.example.com> PUT /tmp/tmpLwXK4c TO /root/.ansible/tmp/ansible-tmp-1501595633.02-214170940236146/nxos_smu.py
<n9k.example.com> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1501595633.02-214170940236146/ /root/.ansible/tmp/ansible-tmp-1501595633.02-214170940236146/nxos_smu.py && sleep 0'
<n9k.example.com> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1501595633.02-214170940236146/nxos_smu.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1501595633.02-214170940236146/" > /dev/null 2>&1 && sleep 0'
fatal: [n9k.example.com]: FAILED! => {
    "changed": false, 
    "clierror": "No such file or directory\n", 
    "code": "501", 
    "failed": true, 
    "input": "dir bootflash:/nxos.sample-n9k_ALL-1.0.0-7.0.3.I5.3.lib32_n9000", 
    "invocation": {
        "module_args": {
            "config": null, 
            "file_system": "bootflash:", 
            "host": "n9k.example.com", 
            "include_defaults": "False", 
            "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", 
            "pkg": "nxos.sample-n9k_ALL-1.0.0-7.0.3.I5.3.lib32_n9000", 
            "port": 80, 
            "provider": {
                "host": "n9k.example.com", 
                "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", 
                "port": 80, 
                "ssh_keyfile": null, 
                "timeout": 300, 
                "transport": "nxapi", 
                "use_ssl": false, 
                "username": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", 
                "validate_certs": true
            }, 
            "save": false, 
            "ssh_keyfile": null, 
            "timeout": 300, 
            "transport": "nxapi", 
            "url_password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", 
            "url_username": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", 
            "use_ssl": false, 
            "username": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", 
            "validate_certs": true
        }
    }, 
    "msg": "Structured output unsupported", 
    "output": {
        "clierror": "No such file or directory\n", 
        "code": "501", 
        "input": "dir bootflash:/nxos.sample-n9k_ALL-1.0.0-7.0.3.I5.3.lib32_n9000", 
        "msg": "Structured output unsupported"
    }, 
    "url": "http://n9k.example.com:80/ins"
}
	to retry, use: --limit @/root/agents-ci/ansible/test/integration/nxos.retry

PLAY RECAP ****************************************************************************************************************************************************************************************************************************
n9k.example.com          : ok=18   changed=2    unreachable=0    failed=1   

```


Discussion:
cc @GGabriele @jedelman8 @privateip @rahushen @rcarrillocruz @trishnaguha
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->

Resolving patch:
diff --git a/lib/ansible/modules/network/nxos/nxos_smu.py b/lib/ansible/modules/network/nxos/nxos_smu.py
--- a/lib/ansible/modules/network/nxos/nxos_smu.py
+++ b/lib/ansible/modules/network/nxos/nxos_smu.py
@@ -88,18 +88,18 @@
 import time
 import collections
 
-import re
 import re
 
 def execute_show_command(command, module, command_type='cli_show'):
-    if module.params['transport'] == 'cli':
-        cmds = [command]
-        body = run_commands(module, cmds)
-    elif module.params['transport'] == 'nxapi':
+    if command_type == 'cli_show_ascii':
+        cmds = [{
+            'command': command,
+            'output': 'text',
+        }]
+    else:
         cmds = [command]
-        body = run_commands(module, cmds)
 
-    return body
+    return run_commands(module, cmds)
 
 
 def remote_file_exists(module, dst, file_system='bootflash:'):
@@ -122,11 +122,18 @@ def get_commands(module, pkg, file_system):
     fixed_pkg = '.'.join(splitted_pkg[0:-1])
 
     command = 'show install inactive'
-    inactive_body = execute_show_command(command, module,
-                                                command_type='cli_show_ascii')
+    inactive_body = execute_show_command(
+        command,
+        module,
+        command_type='cli_show_ascii'
+    )
+
     command = 'show install active'
-    active_body = execute_show_command(command, module,
-                                                command_type='cli_show_ascii')
+    active_body = execute_show_command(
+        command,
+        module,
+        command_type='cli_show_ascii'
+    )
 
     if fixed_pkg not in inactive_body[0] and fixed_pkg not in active_body[0]:
         commands.append('install add {0}{1}'.format(file_system, pkg))
@@ -167,8 +174,9 @@ def main():
     remote_exists = remote_file_exists(module, pkg, file_system=file_system)
 
     if not remote_exists:
-        module.fail_json(msg="The requested package doesn't exist "
-                             "on the device")
+        module.fail_json(
+            msg="The requested package doesn't exist on the device"
+        )
 
     commands = get_commands(module, pkg, file_system)
     if not module.check_mode and commands:
@@ -178,12 +186,13 @@ def main():
     if 'configure' in commands:
         commands.pop(0)
 
-    module.exit_json(changed=changed,
-                     pkg=pkg,
-                     file_system=file_system,
-                     updates=commands)
+    module.exit_json(
+        changed=changed,
+        pkg=pkg,
+        file_system=file_system,
+        updates=commands
+    )
 
 
 if __name__ == '__main__':
     main()
-


Test patch: