Repository: ansible/ansible

Issue:
nxos_config : play fails when using 'save_when' always
<!---
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: -->
 - Bug Report

##### COMPONENT NAME
<!--- Name of the module/plugin/task/feature -->
- nxos_config

##### ANSIBLE VERSION
<!--- Paste verbatim output from “ansible --version” between quotes below -->
```
ansible 2.4.0 (devel ddbdf0fd5d) last updated 2017/08/29 14:13:40 (GMT -400)
  config file = None
  configured module search path = [u'/root/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  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
<!---
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.
-->
Ubuntu 14.04

##### SUMMARY
<!--- Explain the problem briefly -->
using `save_when` property and setting it to `always` generates a failure as `startup-config` is not a valid command.

##### 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: save config
  nxos_config:
    save_when: always
    timeout: 300
    provider: "{{ cli }}"
```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
play to save config.

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
TASK [nxos_config : save config] ***************************************************************************************************************************************************
task path: /root/agents-ci/ansible/test/integration/targets/nxos_config/tests/cli/save.yaml:17
<n9k-xxx.example.com> connection transport is cli 
<n9k-xxx.example.com> using connection plugin network_cli
<n9k-xxx.example.com> socket_path: /root/.ansible/pc/eb89154fe6
Using module file /root/agents-ci/ansible/lib/ansible/modules/network/nxos/nxos_config.py
<n9k-xxx.example.com> ESTABLISH LOCAL CONNECTION FOR USER: root
<n9k-xxx.example.com> EXEC /bin/sh -c 'echo ~ && sleep 0'
<n9k-xxx.example.com> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /root/.ansible/tmp/ansible-tmp-1504037302.74-194581850162318 `" && echo ansible-tmp-1504037302.74-194581850162318="` echo /root/.ansible/tmp/ansible-tmp-1504037302.74-194581850162318 `" ) && sleep 0'
<n9k-xxx.example.com> PUT /tmp/tmpIvRgcx TO /root/.ansible/tmp/ansible-tmp-1504037302.74-194581850162318/nxos_config.py
<n9k-xxx.example.com> EXEC /bin/sh -c 'chmod u+x /root/.ansible/tmp/ansible-tmp-1504037302.74-194581850162318/ /root/.ansible/tmp/ansible-tmp-1504037302.74-194581850162318/nxos_config.py && sleep 0'
<n9k-xxx.example.com> EXEC /bin/sh -c '/usr/bin/python /root/.ansible/tmp/ansible-tmp-1504037302.74-194581850162318/nxos_config.py; rm -rf "/root/.ansible/tmp/ansible-tmp-1504037302.74-194581850162318/" > /dev/null 2>&1 && sleep 0'
The full traceback is: 
  File "/tmp/ansible_alURUK/ansible_modlib.zip/ansible/module_utils/nxos.py", line 158, in run_commands
    out = self._module.from_json(out)
  File "/tmp/ansible_alURUK/ansible_modlib.zip/ansible/module_utils/basic.py", line 2215, in from_json
    return json.loads(data)
  File "/usr/lib/python2.7/json/__init__.py", line 338, in loads
    return _default_decoder.decode(s)
  File "/usr/lib/python2.7/json/decoder.py", line 366, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
  File "/usr/lib/python2.7/json/decoder.py", line 384, in raw_decode
    raise ValueError("No JSON object could be decoded")
FAILED! => {
    "changed": false, 
    "failed": true, 
    "invocation": {
        "module_args": {
            "after": null, 
            "backup": false, 
            "before": null, 
            "defaults": false, 
            "diff_against": null, 
            "diff_ignore_lines": null, 
            "force": false, 
            "host": null, 
            "intended_config": null, 
            "lines": null, 
            "match": "line", 
            "parents": null, 
            "password": null, 
            "port": null, 
            "provider": null, 
            "replace": "line", 
            "running_config": null, 
            "save": false, 
            "save_when": "always", 
            "src": null, 
            "ssh_keyfile": null, 
            "timeout": 300, 
            "transport": "cli", 
            "use_ssl": null, 
            "username": null, 
            "validate_certs": null
        }   
    },  
    "msg": "startup-config\r\r\n          ^\r\n% Invalid command at '^' marker.\r\n\rn9k-xxx.example.com# "

```



Discussion:
cc @GGabriele @jedelman8 @mikewiebe @privateip @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_config.py b/lib/ansible/modules/network/nxos/nxos_config.py
--- a/lib/ansible/modules/network/nxos/nxos_config.py
+++ b/lib/ansible/modules/network/nxos/nxos_config.py
@@ -392,8 +392,11 @@ def main():
 
     diff_ignore_lines = module.params['diff_ignore_lines']
 
+    if module.params['save']:
+        module.params['save_when'] = 'always'
+
     if module.params['save_when'] != 'never':
-        output = run_commands(module, ['show running-config', 'startup-config'])
+        output = run_commands(module, ['show running-config', 'show startup-config'])
 
         running_config = NetworkConfig(indent=1, contents=output[0], ignore_lines=diff_ignore_lines)
         startup_config = NetworkConfig(indent=1, contents=output[1], ignore_lines=diff_ignore_lines)


Test patch: