Repository: ansible/ansible

Issue:
aireos_config fails to handle prompt when sending config command
<!---
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 or feature
-->
aireos_config
##### ANSIBLE VERSION
<!--- Paste verbatim output from "ansible --version" between quotes below -->
```
Ansible 2.4.3.0
```

##### CONFIGURATION
<!---
DEFAULT_LOG_PATH enabled, and PARAMIKO_HOST_KEY_AUTO_ADD = True
-->

##### 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.

-- | --




-->
Host OS: Ubuntu 16.04.3 LTS

managing Cisco 2500 series wireless controller
Software Version | 8.3.133.0

##### SUMMARY
<!--- Explain the problem briefly -->
While attempting to send a config command: "config ap group-name {{NewGroupName}} {{AccessPointName}}", the module times out. 

I believe this is because there is a prompt after issuing the command. Verified there is a prompt after testing in cli.

##### 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: Move renamed access points to new group
    aireos_config:
        provider: "{{ provider }}"
        timeout: 60
        lines: "ap group-name {{ variables.group_name }} {{ item }}"
    with_items:
        - "{{ new_names }}"

```

<!--- You can also paste gist.github.com links for larger files -->

##### EXPECTED RESULTS
<!--- What did you expect to happen when running the steps above? -->
Expecting the access point to accept the new name and reboot.
##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->

<!--- Paste verbatim command output between quotes below -->
```
TASK [Move renamed access points to new group. ] **********************************************************************************************************
task path: /home/ubuntu/Documents/Ansible/network-proj/roles/ap_regroup/tasks/main.yml:67
File lookup using /home/ubuntu/Documents/Ansible/network-proj/roles/ap_regroup/tasks/../../../files/reports/rename_ap.json as file
<10.10.96.55> using connection plugin network_cli
<10.10.96.55> socket_path: /home/ubuntu/.ansible/pc/c376d8a97a
Using module file /
![wireless_controller_prompt](https://user-images.githubusercontent.com/24993132/35697868-453a9668-0740-11e8-953d-b7637ad6dd57.png)
usr/lib/python2.7/dist-packages/ansible/modules/network/aireos/aireos_config.py
<10.10.96.55> ESTABLISH LOCAL CONNECTION FOR USER: root
<10.10.96.55> EXEC /bin/sh -c 'echo ~ && sleep 0'
<10.10.96.55> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo /home/ubuntu/.ansible/tmp/ansible-tmp-1517508914.73-230928761008767 `" && echo ansible-tmp-1517508914.73-230928761008767="` echo /home/ubuntu/.ansible/tmp/ansible-tmp-1517508914.73-230928761008767 `" ) && sleep 0'
<10.10.96.55> PUT /tmp/tmpQ5Y1FC TO /home/ubuntu/.ansible/tmp/ansible-tmp-1517508914.73-230928761008767/aireos_config.py
<10.10.96.55> EXEC /bin/sh -c 'chmod u+x /home/ubuntu/.ansible/tmp/ansible-tmp-1517508914.73-230928761008767/ /home/ubuntu/.ansible/tmp/ansible-tmp-1517508914.73-230928761008767/aireos_config.py && sleep 0'
![wireless_controller_prompt](https://user-images.githubusercontent.com/24993132/35697879-4a36ce84-0740-11e8-9d97-79f67e6f8e93.png)

<10.10.96.55> EXEC /bin/sh -c '/usr/bin/python /home/ubuntu/.ansible/tmp/ansible-tmp-1517508914.73-230928761008767/aireos_config.py; rm -rf "/home/ubuntu/.ansible/tmp/ansible-tmp-1517508914.73-230928761008767/" > /dev/null 2>&1 && sleep 0'
failed: [10.10.96.55] (item=test-ap-name) => {
    "changed": false, 
    "command": "ap group-name new-group test-ap-name", 
    "invocation": {
        "module_args": {
            "after": null, 
            "backup": false, 
            "before": null, 
            "diff_against": null, 
            "diff_ignore_lines": null, 
            "host": null, 
            "intended_config": null, 
            "lines": [
                "ap group-name new-group test-ap-name"
            ], 
            "match": "line", 
            "password": null, 
            "port": null, 
            "provider": {
                "host": "10.10.96.55", 
                "password": "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER", 
                "port": null, 
                "ssh_keyfile": null, 
                "timeout": 60, 
                "username": "admin"
            }, 
            "running_config": null, 
            "save": false, 
            "src": null, 
            "ssh_keyfile": null, 
            "timeout": 60, 
            "username": null
        }
    }, 
    "item": "test-ap-name", 
    "msg": "timeout trying to send command: ap group-name new-group test-ap-name", 
    "rc": 1
}

```


![wireless_controller_prompt](https://user-images.githubusercontent.com/24993132/35698002-aa3d9a88-0740-11e8-8cb7-d964c467520d.png)



Discussion:
Files identified in the description:
* [lib/ansible/modules/network/aireos/aireos_config.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/network/aireos/aireos_config.py)

If these files are inaccurate, please update the `component name` section of the description or use the `!component` bot command.

[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: components_banner --->
cc @jmighion
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Try sending `\r` or `\n` in with the command if you need to pass yes/no prompts.

`ap group-name new-group test-ap-name\r`
If that doesnt work, try the suggestion here : https://github.com/ansible/ansible/issues/32989#issuecomment-346378943
Thanks for the quick response. Gave both of those methods a test, \r and \n give the same timeout error. also tested double slashes before n  and r, and it ran through without giving an error but didn't actually change the access point group. The suggestion 32989 gives me an unsupported parameters error.
Some further testing has shown that this is only partially fixed by #41522. 

Prompts now work for "before" and "after" parameters (I had my AP group change configured to happen after all other config) as aireos_config pulls their value directly from module.params:

```
            if module.params['before']:
                commands[:0] = module.params['before']

            if module.params['after']:
                commands.extend(module.params['after'])
```

Whereas commands passed in via "lines" or "src" are pulled as:

```
        if configobjs:
            commands = dumps(configobjs, 'commands').split('\n')
```

Which leads to commands being compressed like this (full output below):
```
{\"answer\": null, \"command\": \"{'answer': 'y', 'command': 'ap group-name group_a wap_001', 'prompt': 'Are you sure you want to continue'}\", \"prompt\": null}
```

To resolve this completely without affecting the functionality of the "src" parameter, aireos_config could be changed from:
```
        if configobjs:
            commands = dumps(configobjs, 'commands').split('\n')
```
To:
```
        if configobjs:
            if module.params['src']:
                commands = dumps(configobjs, 'commands').split('\n')
            else:
                commands = module.params['lines']
```

I'll submit a further PR with this change for review.

Full output:
```
PLAY [Initial WAP Configuration] ***************************************************************************************

TASK [Execute Config] **************************************************************************************************
fatal: [wlc_001]: FAILED! => {"changed": false, "command": "{\"command\": \"{'command': 'ap group-name group_a wap_001', 'prompt': 'Are you sure you want to continue', 'answer': 'y'}\", \"prompt\": null, \"answer\": null}", "msg": "{'command': 'ap group-name group_a wap_001', 'prompt': 'Are you sure you want to continue', 'answer': 'y'}\r\n\r\nIncorrect usage.  Use the '?' or <TAB> key to list commands.\r\n\r\n(Cisco Controller) config>", "rc": -32603}
        to retry, use: --limit @/Users/james/PycharmProjects/ansible/testmod.retry

PLAY RECAP *************************************************************************************************************
wlc_001              : ok=0    changed=0    unreachable=0    failed=1
```

Resolving patch:
diff --git a/lib/ansible/module_utils/network/aireos/aireos.py b/lib/ansible/module_utils/network/aireos/aireos.py
--- a/lib/ansible/module_utils/network/aireos/aireos.py
+++ b/lib/ansible/module_utils/network/aireos/aireos.py
@@ -114,14 +114,13 @@ def run_commands(module, commands, check_rc=True):
 
 
 def load_config(module, commands):
+
     rc, out, err = exec_command(module, 'config')
     if rc != 0:
         module.fail_json(msg='unable to enter configuration mode', err=to_text(out, errors='surrogate_then_replace'))
 
-    commands = to_commands(module, to_list(commands))
-    for command in commands:
-        command = module.jsonify(command)
-        if "\"command\": \"end\"" in command:
+    for command in to_list(commands):
+        if command == 'end':
             continue
         rc, out, err = exec_command(module, command)
         if rc != 0:


Test patch: