Repository: ansible/ansible
Pull request: Fix network_cli exec_command connection init


##### SUMMARY
<!--- Describe the change below, including rationale and design decisions -->
Fixes https://github.com/ansible/ansible/issues/61596

*  Ensure connection is established before executing
   exec_command network_cli connection method which is
   invoked from the module code.
<!--- HINT: Include "Fixes #nnn" if you are fixing an existing issue -->

##### ISSUE TYPE
<!--- Pick one below and delete the rest -->
- Bugfix Pull Request


##### COMPONENT NAME
<!--- Write the short name of the module, plugin, task or feature below -->
ansible/plugins/connection/network_cli.py

##### ADDITIONAL INFORMATION
<!--- Include additional information to help people understand the change here -->
<!--- A step-by-step reproduction of the problem is helpful if there is no related issue -->

<!--- Paste verbatim command output below, e.g. before and after your change -->
```paste below

```


Problem statement:
playbooks using icx_modules that require enable mode  fail in stable 2.9 branch but work in 2.8
##### SUMMARY
playbook that require enable mode work in Ansible 2.8 but fail in stable 2.9 


##### ISSUE TYPE
When attached playbook is run using ansible-playbook binary in devel branch it fails. But when run with /usr/bin/ansible-playbook (2.8 version) it works fine.

##### COMPONENT NAME
ansible-playbook

##### ANSIBLE VERSION
2.9 devel 

```

##### CONFIGURATION

##### OS / ENVIRONMENT
linux

##### STEPS TO REPRODUCE
run below playbook using devel/bin/ansible-playbook
- hosts: 172.16.10.198
  connection: network_cli
  become_method: enable
  gather_facts: no
  vars:
    ansible_network_os: icx
    ansible_user: alethea
    ansible_become: yes
    ansible_password: alethea123
    ansible_become_method: enable
    ansible_become_pass: alethea123
    ansible_command_timeout: 80

  tasks:
   - name: set the motd on remote devices
     icx_banner:
       banner: motd
       text: |
         welcome motd
         multiline
         string


##### EXPECTED RESULTS
pass

##### ACTUAL RESULTS
{
    "ansible_facts": {
        "discovered_interpreter_python": "/usr/bin/python"
    }, 
    "changed": false, 
    "invocation": {
        "module_args": {
            "banner": "motd", 
            "check_running_config": true, 
            "enterkey": null, 
            "state": "present", 
            "text": "welcome motd\nmultiline\nstring\n"
        }
    }, 
    "msg": "operation requires privilege escalation"
}

Hints from issue discussion:
Files identified in the description:
* [`lib/ansible/plugins/connection/network_cli.py`](https://github.com/ansible/ansible/blob/devel/lib/ansible/plugins/connection/network_cli.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 @NilashishC @Qalthos @danielmellado @ganeshrn @justjais @trishnaguha
[click here for bot help](https://github.com/ansible/ansibullbot/blob/master/ISSUE_HELP.md)
<!--- boilerplate: notify --->
Files identified in the description:
* [`lib/ansible/playbook`](https://github.com/ansible/ansible/blob/devel/lib/ansible/playbook)

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 --->
@sushma-alethea Are you still seeing this issue in the latest devel branch. If yes can you please share the device interaction logs after redacting the sensitive information from log file. Refer https://docs.ansible.com/ansible/devel/network/user_guide/network_debug_troubleshooting.html#enabling-networking-device-interaction-logging for enabling device interaction logs.

needs_info
Will  take latest of devel, test and let you know.
________________________________
From: Ganesh Nalawade <notifications@github.com>
Sent: Wednesday, September 11, 2019 7:50 PM
To: ansible/ansible <ansible@noreply.github.com>
Cc: Pradeep, Sushma <sushma.pradeep@commscope.com>; Mention <mention@noreply.github.com>
Subject: Re: [ansible/ansible] playbooks using icx_modules that require enable mode fail in stable 2.9 branch but work in 2.8 (#61596)


Message received from external source. Exercise caution when opening attachments, clicking links, or exchanging information.



@sushma-alethea<https://secure-web.cisco.com/1hW4seDzt97Ii2t9jPo3EFtg_yhmAtUL8-CS-CTeXCMbPb4vNXHnA05srgetFUIRTysay_geE9jQvPXgwMniD82Gfbc-NggYu-VDz6RxIJNB9US1gBqzNEb1FbXX9eBI-flWeYbQuGT99fGtx9hRmSVeWquviVu1ypQrqM_mYAXgRHT4zFjTaVL12-Uey9RaawJY306gD61AMnClmz7MVt088vXrSHSiGDd2A1Xrc6DegmnpKrFYpwZl2GS_OJ8UOTgrPsyz7yDt7fthXvw2Ug_Scmm555PEPAFymlwcjfBWIOmNAYlZEXSuBI6pPWaXt/https%3A%2F%2Fgithub.com%2Fsushma-alethea> Are you still seeing this issue in the latest devel branch. If yes can you please share the device interaction logs after redacting the sensitive information from log file. Refer https://docs.ansible.com/ansible/devel/network/user_guide/network_debug_troubleshooting.html#enabling-networking-device-interaction-logging<https://secure-web.cisco.com/1lmjfZZshfveGAta2lkMlzdBqh5LgoiSoy0yZVVVrJKMLLTISyeHefElGoGJX9HMLC957wjXlt0uBK6KKDt6hG4NLSu86dM0P07O3-BpRiC3O9YHhhZrDNWHBpEA0Fn-Zjwex1W3vD_Mrvg-toAmjORbPW4sIv7FNWJsCmURCmF1L9RGc9u-3YdnRkqQN-LK87b18zs-Nl1gu9fmD4i39lFBqZ6OaDLbibiVUPQd2L24F23Yev3-_-44vNIrxgp0XyN2C7jI-8RQELbN5M6NL6BrBgVgJ9sWP26xqc8bd8CeNXYYAbZZGCNtYyMW9lVJdVPu4C_3M_mYj66_ErerTaw/https%3A%2F%2Fdocs.ansible.com%2Fansible%2Fdevel%2Fnetwork%2Fuser_guide%2Fnetwork_debug_troubleshooting.html%23enabling-networking-device-interaction-logging> for enabling device interaction logs.

needs_info

—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub<https://secure-web.cisco.com/1ufO4ndJqjvOogK64Asi6MypiP4ysSLv_u5TgiRWIwIYSd4vK0Cd0YQGkR3YTknGtZ_hBVbkgaRwgi3algJRM4oZrxIZE6IRFW3OSrrL0ehFPw7Wb8M8xfOSWNgu1KtCzYkTLBBSTuYRMbjTSPTgf3EoKmpt3vmSCGcf5mbAnnygbsVpmjT8Sg-rp4v0BIqJBYtg80lFllUwTOgW6885_GrQ4zNAajAEBkB6Xmg9ksDi17FEUHJewHZ31uxvi6TshoY0rqULZTNxDY22ExYzZf3Qz4ErJNQHulVX9aVmUyb4cjehsOvJuG6kNlTiIF6dW/https%3A%2F%2Fgithub.com%2Fansible%2Fansible%2Fissues%2F61596%3Femail_source%3Dnotifications%26email_token%3DAMQGKZP5FA2NYWZEUF3YWWLQJD5DHA5CNFSM4ISLLZ52YY3PNVWWK3TUL52HS4DFVREXG43VMVBW63LNMVXHJKTDN5WW2ZLOORPWSZGOD6OUWCI%23issuecomment-530402057>, or mute the thread<https://secure-web.cisco.com/173rtI_YM4B0bP3WUvW4jiF3L-bV0Ap9GXXYfF3tNsXbwtVZVJ74VTS_TPKDmLDpt_LzWQzqMMEVhxwD3Oohc7qyRMldcmd8QZ6_aMP4JN4WfFBEEST0diCdb1GcxMeYbtSHwA7h-hwuYgL3AwfnhikyQtg-32Ymu0naYSNgiJTb8ZPeBiWvyqymjk55N2PMSLxCH64OLrqKSRayVubaVgXu6GO17XLsbQcioWzBXYb3rFDh9LxPQPcJP38CUjbcXuhHSaqLSVEl7AQENoK7wInBUXy9Add8_Tlt2qvi5HsRKqnuuTR-rVEMkYD5yka4C/https%3A%2F%2Fgithub.com%2Fnotifications%2Funsubscribe-auth%2FAMQGKZOUARD3BWCDDEVZRUDQJD5DHANCNFSM4ISLLZ5Q>.


[ansible_2.8_working.log](https://github.com/ansible/ansible/files/3615439/ansible_2.8_working.log)
[ansible_2.9_not-working.log](https://github.com/ansible/ansible/files/3615443/ansible_2.9_not-working.log)

Commit message: Fix network_cli exec_command connection init

Fixes https://github.com/ansible/ansible/issues/61596

*  If `exec_command` method is invoked from module side
   on connection object to execute the command on target
   host check if connection is created if not create the
   connection.

Patch to review:
diff --git a/lib/ansible/cli/scripts/ansible_connection_cli_stub.py b/lib/ansible/cli/scripts/ansible_connection_cli_stub.py
index 5a61aa7167419f..50ec5a2a7484a7 100755
--- a/lib/ansible/cli/scripts/ansible_connection_cli_stub.py
+++ b/lib/ansible/cli/scripts/ansible_connection_cli_stub.py
@@ -138,6 +138,10 @@ def run(self):
                     if log_messages:
                         display.display("jsonrpc request: %s" % data, log_only=True)
 
+                    request = json.loads(to_text(data, errors='surrogate_then_replace'))
+                    if request.get('method') == "exec_command" and not self.connection.connected:
+                        self.connection._connect()
+
                     signal.alarm(self.connection.get_option('persistent_command_timeout'))
 
                     resp = self.srv.handle_request(data)


Code review comments:
diff_hunk: @@ -138,6 +138,10 @@ def run(self):
                     if log_messages:
                         display.display("jsonrpc request: %s" % data, log_only=True)
 
+                    request = json.loads(to_text(data, errors='surrogate_then_replace'))
path: lib/ansible/cli/scripts/ansible_connection_cli_stub.py
text: @user1:
Is `surrogate_then_replace`okay here?  It has the potential to mangle data but pass malformed data.

I see that you're only using `request['method'] == 'exec_command'` so maybe it's okay to do that but I thought I should check.  Typically we use `errors=surrogate_or_strict` when dealing with information that will be sent back to the computer.  (And then handle a traceback as malformed data).

@author:
The text data is the jsoncrpc request string which consists of information related to the method invoked from module side code on the connection object `(eg: Connection(module._socket_path).get())`. As you mentioned in the comment I now think that `surrogate_or_strict` is the right option here.