Repository: ansible/ansible

Issue:
iosxr_command module - Commands that prompt are not sending an answer
<!---
Verify first that your issue/request is not already reported on GitHub.
THIS FORM WILL BE READ BY A MACHINE, COMPLETE ALL SECTIONS AS DESCRIBED.
Also test if the latest release, and devel branch are affected too.
ALWAYS add information AFTER (OUTSIDE) these html comments.
Otherwise it may end up being automatically closed by our bot. -->

##### ISSUE TYPE
 - Bug Report

##### COMPONENT NAME
<!--- Insert, BELOW THIS COMMENT, the name of the module, plugin, task or feature.
Do not include extra details here, e.g. "vyos_command" not "the network module vyos_command" or the full path-->
iosxr_command

##### ANSIBLE VERSION
<!--- Paste, BELOW THIS COMMENT, verbatim output from "ansible --version" between quotes below -->
```
ansible 2.5.2
  config file = /etc/ansible/ansible.cfg
  configured module search path = [u'/home/asmith/.ansible/plugins/modules', u'/usr/share/ansible/plugins/modules']
  ansible python module location = /usr/local/lib/python2.7/dist-packages/ansible
  executable location = /usr/local/bin/ansible
  python version = 2.7.12 (default, Dec  4 2017, 14:50:18) [GCC 5.4.0 20160609]
```

##### CONFIGURATION
<!--- If using Ansible 2.4 or above, paste, BELOW THIS COMMENT, 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).-->
ANSIBLE_PIPELINING(/home/asmith/SMInetinfra/ansible.cfg) = True
ANSIBLE_SSH_ARGS(/home/asmith/SMInetinfra/ansible.cfg) = -o UserKnownHostsFile=/dev/null
DEFAULT_CALLBACK_WHITELIST(/home/asmith/SMInetinfra/ansible.cfg) = ['syslog_boss', 'profile_tasks']
DEFAULT_HOST_LIST(/home/asmith/SMInetinfra/ansible.cfg) = [u'/home/asmith/SMInetinfra/hosts']
DEFAULT_JINJA2_EXTENSIONS(/home/asmith/SMInetinfra/ansible.cfg) = jinja2.ext.do,jinja2.ext.i18n
DEFAULT_LOG_PATH(/home/asmith/SMInetinfra/ansible.cfg) = /dev/null
DEFAULT_MODULE_PATH(/home/asmith/SMInetinfra/ansible.cfg) = [u'/home/asmith/SMInetinfra/library', u'/usr/share/my_modules/smi-n
DEFAULT_REMOTE_USER(/home/asmith/SMInetinfra/ansible.cfg) = ansible
HOST_KEY_CHECKING(/home/asmith/SMInetinfra/ansible.cfg) = False
RETRY_FILES_ENABLED(/home/asmith/SMInetinfra/ansible.cfg) = False

##### OS / ENVIRONMENT
<!--- Mention, BELOW THIS COMMENT, 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.-->
N/A

##### SUMMARY
<!--- Explain the problem briefly -->
When using the iosxr_command module to send commands that prompt, the answer never gets sent.

##### 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. -->
Run one of the following playbooks. The command will not be run past the prompt since the answer never gets sent.

<!--- Paste example playbooks or commands between quotes below -->
**First example playbook:**
```yaml
- name: "Reboot equipment"
  iosxr_command:
    provider:
      host: "{{ ansible_host }}"
      username: "{{ ansible_user }}"
      password: "{{ ansible_ssh_pass }}"
      timeout: 120
    commands:
      - command: "reload location all"
        prompt: '[confirm]'
        answer: 'y'
```

**Second example playbook:**
```yaml
- name: "Install base image file"
  iosxr_command:
    provider:
      host: "{{ ansible_host }}"
      username: "{{ ansible_user }}"
      password: "{{ ansible_ssh_pass }}"
      timeout: 120
    commands:
      - command: "install add source sftp://ansible@10.199.255.220/usr/local/packages-cisco/6.3.2/packages/ ncs5500-mpls-te-rsvp-2.2.0.0-r632.x86_64.rpm"
        prompt: 'password:'
        answer: 'MyPassword'
  when: base_image_file is defined
  register: result
  changed_when: result is succeeded
```

<!--- 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 am expecting the commands to run as if I had entered the prompt answer manually.

##### ACTUAL RESULTS
<!--- What actually happened? If possible run with extra verbosity (-vvvv) -->
The command hangs while waiting for user input.

For instance, when running the first playbook from the example playbooks, the reboot never happens because the command is waiting for the answer to get sent. 

When running the second playbook from the example playbooks, we can see in the log that the command times out.

Here is the log on the equipment when running the following command after the second playbook has timed out: 

> show install log [install_id]

```
May 08 05:55:39 Install operation 131 started by ansible:
 install add source sftp://ansible@10.199.255.220/usr/local/packages-cisco/6.3.2/packages/ ncs5500-mpls-te-rsvp-2.2.0.0-r632.x86_64.rpm 
May 08 05:55:41 Action 1: install add action started
May 08 05:55:41 password:******
May 08 05:56:41 Timeout while waiting for password from user
May 08 05:56:42 
May 08 05:56:44 Install operation 131 aborted
May 08 05:56:44 Ending operation 131
```

<!--- Paste verbatim command output between quotes below -->
```
reload location all
Tue May  8 14:04:53.444 UTC

Standby card not present or not Ready for failover. Proceed? [confirm]
```
```
install add source sftp://ansible@10.199.255.220/usr/local/packages-cisco/6.3.2/packages/ ncs5500-mpls-te-rsvp-2.2.0.0-r632.x86_64.rpm 
Tue May  8 14:03:54.018 UTC
May 08 14:03:55 Install operation 133 started by ansible:
 install add source sftp://ansible@10.199.255.220/usr/local/packages-cisco/6.3.2/packages/ ncs5500-mpls-te-rsvp-2.2.0.0-r632.x86_64.rpm 
password:
```

I included what is shown when running the playbook commands manually on the equipment for reference purposes in case the "prompt" line is what is causing the problem.


Discussion:
Files identified in the description:
* [lib/ansible/modules/network/iosxr/iosxr_command.py](https://github.com/ansible/ansible/blob/devel/lib/ansible/modules/network/iosxr/iosxr_command.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 @gdpak @privateip @rcarrillocruz
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Do you need additional information to look into this issue? We really need this feature so if there is anything I can do to help it will be my pleasure.
Hello @AdamSmith-Mtl  I am able to reproduce this error so no further info is required from your side. I shall start work on it soon.

Resolving patch:
diff --git a/lib/ansible/module_utils/network/iosxr/iosxr.py b/lib/ansible/module_utils/network/iosxr/iosxr.py
--- a/lib/ansible/module_utils/network/iosxr/iosxr.py
+++ b/lib/ansible/module_utils/network/iosxr/iosxr.py
@@ -454,7 +454,7 @@ def run_command(module, commands):
             sendonly = False
             newline = True
 
-        out = conn.get(command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline)
+        out = conn.get(command=command, prompt=prompt, answer=answer, sendonly=sendonly, newline=newline)
 
         try:
             responses.append(to_text(out, errors='surrogate_or_strict'))


Test patch:
diff --git a/test/integration/targets/iosxr_command/tests/cli/prompt.yaml b/test/integration/targets/iosxr_command/tests/cli/prompt.yaml
new file mode 100644
--- /dev/null
+++ b/test/integration/targets/iosxr_command/tests/cli/prompt.yaml
@@ -0,0 +1,25 @@
+---
+- debug: msg="START cli/prompt.yaml on connection={{ ansible_connection }}"
+
+- name: delete config file on disk to prevent failure of copy task for duplicate
+  iosxr_command:
+    commands:
+        - command: 'delete harddisk:ansible_tmp.txt'
+          prompt: 'Delete harddisk\:ansible_tmp\.txt\[confirm\]'
+          answer: "\r\n"
+  ignore_errors: yes
+
+- name: copy
+  iosxr_command:
+    commands:
+        - command: 'copy running-config harddisk:ansible_tmp.txt'
+          prompt: 'Destination file name \(control-c to abort\)\: \[\/ansible_tmp.txt\]\?'
+          answer: 'ansible_tmp.txt'
+  register: result
+
+- assert:
+    that:
+      - "result.stdout is defined"
+      - "'ansible_tmp' in result.stdout[0]"
+
+- debug: msg="END cli/prompt.yaml on connection={{ ansible_connection }}"