From bce0bd401ea4ef71279d28e436e81ed96d9e550a Mon Sep 17 00:00:00 2001 From: Peter Sprygada Date: Thu, 2 Feb 2017 18:32:36 -0500 Subject: [PATCH] bug fixes for shell exec command (#20988) * fixes up eos_local to call appropriate method * fixes up ios_cli to call appropriate method * moves json conversion to eos --- lib/ansible/module_utils/eos.py | 1 + lib/ansible/module_utils/eos_local.py | 24 +++++---- lib/ansible/module_utils/ios_cli.py | 3 +- lib/ansible/module_utils/shell.py | 74 +++++++++------------------ 4 files changed, 41 insertions(+), 61 deletions(-) diff --git a/lib/ansible/module_utils/eos.py b/lib/ansible/module_utils/eos.py index 7a44720f803..be9dbfefb6e 100644 --- a/lib/ansible/module_utils/eos.py +++ b/lib/ansible/module_utils/eos.py @@ -62,6 +62,7 @@ def run_commands(module, commands): responses = list() for cmd in to_list(commands): + cmd = module.jsonify(cmd) rc, out, err = module.exec_command(cmd) if rc != 0: diff --git a/lib/ansible/module_utils/eos_local.py b/lib/ansible/module_utils/eos_local.py index 9b9de794229..0b45c8c6bd8 100644 --- a/lib/ansible/module_utils/eos_local.py +++ b/lib/ansible/module_utils/eos_local.py @@ -118,13 +118,13 @@ class Cli(CliBase): def connect(self): super(Cli, self).connect(self._module.params, kickstart=False) - self.shell.send('terminal length 0') + self.exec_command('terminal length 0') def authorize(self): passwd = self._module.params['auth_pass'] if passwd: prompt = r"[\r\n]?Password: $" - self.execute(dict(command='enable', prompt=prompt, response=passwd)) + self.exec_command(dict(command='enable', prompt=prompt, response=passwd)) else: self.exec_command('enable') @@ -334,23 +334,27 @@ class Eapi: return response['result'] for item in to_list(commands): - if all((output == 'json', is_text(item))) or all((output =='text', is_json(item))): + if item['output'] == 'json' and not is_json(item['command']): + item['command'] = '%s | json' % item['command'] + + if item['output'] == 'text' and is_json(item['command']): + item['command'] = str(item['command']).split('|')[0] + + if all((output == 'json', is_text(item['command']))) or all((output =='text', is_json(item['command']))): responses.extend(_send(queue, output)) queue = list() - if is_json(item): - output = 'json' - else: - output = 'text' - - queue.append(item) + output = item['output'] or 'json' + queue.append(item['command']) if queue: responses.extend(_send(queue, output)) for index, item in enumerate(commands): - if is_text(item): + try: responses[index] = responses[index]['output'].strip() + except KeyError: + pass return responses diff --git a/lib/ansible/module_utils/ios_cli.py b/lib/ansible/module_utils/ios_cli.py index 16b8ec4ca30..377a9de576d 100644 --- a/lib/ansible/module_utils/ios_cli.py +++ b/lib/ansible/module_utils/ios_cli.py @@ -97,7 +97,7 @@ class Cli(CliBase): def connect(self): super(Cli, self).connect(self._module.params, kickstart=False) - self.shell.send('terminal length 0') + self.exec_command('terminal length 0') def authorize(self): passwd = self._module.params['auth_pass'] @@ -108,7 +108,6 @@ class Cli(CliBase): self.exec_command('enable') - def connection(module): global _DEVICE_CONNECTION if not _DEVICE_CONNECTION: diff --git a/lib/ansible/module_utils/shell.py b/lib/ansible/module_utils/shell.py index ffae396c930..d0f9619260d 100644 --- a/lib/ansible/module_utils/shell.py +++ b/lib/ansible/module_utils/shell.py @@ -35,6 +35,7 @@ from ansible.module_utils.network import NetworkError from ansible.module_utils.six import BytesIO from ansible.module_utils._text import to_native from ansible.module_utils.network_common import to_list, ComplexDict +from ansible.module_utils.netcli import Command ANSI_RE = [ re.compile(r'(\x1b\[\?1h\x1b=)'), @@ -121,15 +122,6 @@ class Shell(object): data = regex.sub('', data) return data - def to_command(self, obj): - cast = ComplexDict({ - 'command': dict(key=True), - 'output': dict(), - 'prompt': dict(), - 'response': dict() - }) - return cast(obj) - def alarm_handler(self, signum, frame): self.shell.close() raise ShellError('timeout trying to send command: %s' % self._history[-1]) @@ -161,10 +153,8 @@ class Shell(object): exc.command = cmd['command'] raise - def send_command(self, command): + def send(self, obj): try: - obj = self.to_command(command) - self._history.append(str(obj['command'])) cmd = '%s\r' % str(obj['command']) @@ -182,15 +172,6 @@ class Shell(object): exc = get_exception() return (1, '', to_native(exc)) - def send(self, commands): - responses = list() - for command in to_list(commands): - rc, out, err = self.send_command(command) - if rc != 0: - raise ShellError(err) - responses.append(out) - return responses - def close(self): self.shell.close() @@ -234,7 +215,6 @@ class CliBase(object): self.shell = None self._connected = False - self.default_output = 'text' def connect(self, params, kickstart=True): host = params['host'] @@ -267,42 +247,38 @@ class CliBase(object): self.shell.close() self._connected = False - def authorize(self, params, **kwargs): - pass - def to_command(self, obj): - if isinstance(command, Command): + if isinstance(obj, Command): cmdobj = dict() cmdobj['command'] = obj.command cmdobj['response'] = obj.response cmdobj['prompt'] = [p.pattern for p in to_list(obj.prompt)] return cmdobj - return obj + + elif not isinstance(obj, dict): + transform = ComplexDict(dict( + command=dict(key=True), + prompt=dict(), + response=dict() + )) + return transform(obj) + + else: + return obj def execute(self, commands): try: - for index, item in enumerate(commands): - commands[index] = to_command(item) - return self.shell.send(commands) + responses = list() + for item in to_list(commands): + item = self.to_command(item) + rc, out, err = self.shell.send(item) + if rc != 0: + raise ShellError(err) + responses.append(out) + return responses except ShellError: exc = get_exception() - commands = [str(c) for c in commands] - raise NetworkError(to_native(exc), commands=commands) + raise NetworkError(to_native(exc)) - def exec_command(self, command): - - transform = ComplexDict(dict( - command=dict(key=True), - prompt=dict(), - response=dict() - )) - - if not isinstance(command, dict): - command = transform(command) - - rc, out, err = self.shell.send_command(command) - - return rc, out, err - - def run_commands(self, commands): - return self.execute(to_list(commands)) + run_commands = lambda self, x: self.execute(to_list(x)) + exec_command = lambda self, x: self.shell.send(self.to_command(x))