From a1517234f661de58dd146f479e1ceac489e50b78 Mon Sep 17 00:00:00 2001 From: Nathaniel Case Date: Tue, 14 Nov 2017 15:51:14 -0500 Subject: [PATCH] Fix `authorize: yes` and `become_method: enable` (#32864) * Update connection play_context when socket exists * Don't fail on connections other than network_cli * Fix enable prompt detection on ios & eos * Check against "Module not found" error code, defined in modules/jsonrpc.py --- bin/ansible-connection | 17 +++++++++++++++-- lib/ansible/plugins/connection/network_cli.py | 19 +++++++++++++++---- lib/ansible/plugins/terminal/eos.py | 2 +- lib/ansible/plugins/terminal/ios.py | 2 +- 4 files changed, 32 insertions(+), 8 deletions(-) diff --git a/bin/ansible-connection b/bin/ansible-connection index 7fbceedbd94..eed348f4310 100755 --- a/bin/ansible-connection +++ b/bin/ansible-connection @@ -26,12 +26,11 @@ from ansible import constants as C from ansible.module_utils._text import to_bytes, to_native, to_text from ansible.module_utils.six import PY3 from ansible.module_utils.six.moves import cPickle -from ansible.module_utils.connection import send_data, recv_data +from ansible.module_utils.connection import Connection, ConnectionError, send_data, recv_data from ansible.module_utils.service import fork_process from ansible.playbook.play_context import PlayContext from ansible.plugins.loader import connection_loader from ansible.utils.path import unfrackpath, makedirs_safe -from ansible.errors import AnsibleError from ansible.utils.display import Display from ansible.utils.jsonrpc import JsonRpcServer @@ -293,6 +292,20 @@ def main(): else: messages.append('found existing local domain socket, using it!') + conn = Connection(socket_path) + pc_data = to_text(init_data) + try: + messages.extend(conn.update_play_context(pc_data)) + except Exception as exc: + # Only network_cli has update_play context, so missing this is + # not fatal e.g. netconf + if isinstance(exc, ConnectionError) and getattr(exc, 'code') == -32601: + pass + else: + result.update({ + 'error': to_text(exc), + 'exception': traceback.format_exc() + }) result.update({ 'messages': messages, diff --git a/lib/ansible/plugins/connection/network_cli.py b/lib/ansible/plugins/connection/network_cli.py index 0a20a42dd69..3939ed799ef 100644 --- a/lib/ansible/plugins/connection/network_cli.py +++ b/lib/ansible/plugins/connection/network_cli.py @@ -56,8 +56,10 @@ from collections import Sequence from ansible import constants as C from ansible.errors import AnsibleConnectionFailure -from ansible.module_utils.six import BytesIO, binary_type +from ansible.module_utils.six import PY3, BytesIO, binary_type +from ansible.module_utils.six.moves import cPickle from ansible.module_utils._text import to_bytes, to_text +from ansible.playbook.play_context import PlayContext from ansible.plugins.loader import cliconf_loader, terminal_loader, connection_loader from ansible.plugins.connection import ConnectionBase from ansible.plugins.connection.local import Connection as LocalConnection @@ -134,19 +136,28 @@ class Connection(ConnectionBase): def fetch_file(self, in_path, out_path): return self._local.fetch_file(in_path, out_path) - def update_play_context(self, play_context): + def update_play_context(self, pc_data): """Updates the play context information for the connection""" + pc_data = to_bytes(pc_data) + if PY3: + pc_data = cPickle.loads(pc_data, encoding='bytes') + else: + pc_data = cPickle.loads(pc_data) + play_context = PlayContext() + play_context.deserialize(pc_data) - display.vvvv('updating play_context for connection', host=self._play_context.remote_addr) - + messages = ['updating play_context for connection'] if self._play_context.become is False and play_context.become is True: auth_pass = play_context.become_pass self._terminal.on_authorize(passwd=auth_pass) + messages.append('authorizing connection') elif self._play_context.become is True and not play_context.become: self._terminal.on_deauthorize() + messages.append('deauthorizing connection') self._play_context = play_context + return messages def _connect(self): ''' diff --git a/lib/ansible/plugins/terminal/eos.py b/lib/ansible/plugins/terminal/eos.py index 40fc01038ee..3f3077c0bc4 100644 --- a/lib/ansible/plugins/terminal/eos.py +++ b/lib/ansible/plugins/terminal/eos.py @@ -61,7 +61,7 @@ class TerminalModule(TerminalBase): cmd = {u'command': u'enable'} if passwd: - cmd[u'prompt'] = to_text(r"[\r\n]?password: $", errors='surrogate_or_strict') + cmd[u'prompts'] = to_text(r"[\r\n]?password: $", errors='surrogate_or_strict') cmd[u'answer'] = passwd try: diff --git a/lib/ansible/plugins/terminal/ios.py b/lib/ansible/plugins/terminal/ios.py index 4df746084c3..4de74a21652 100644 --- a/lib/ansible/plugins/terminal/ios.py +++ b/lib/ansible/plugins/terminal/ios.py @@ -60,7 +60,7 @@ class TerminalModule(TerminalBase): if passwd: # Note: python-3.5 cannot combine u"" and r"" together. Thus make # an r string and use to_text to ensure it's text on both py2 and py3. - cmd[u'prompt'] = to_text(r"[\r\n]?password: $", errors='surrogate_or_strict') + cmd[u'prompts'] = to_text(r"[\r\n]?password: $", errors='surrogate_or_strict') cmd[u'answer'] = passwd try: