Fix use of bytes in cliconf plugins for Python 3 (#37715)

* Remove raw byte-strings from cliconf plugins of supported platforms + edgeos

Remove uses of to_bytes, too

* Update CliConfBase docstring to reflect current position on byte strings
pull/38888/head
Nathaniel Case 7 years ago committed by GitHub
parent be6628cd3d
commit 3b3c72f3e5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -55,13 +55,11 @@ class CliconfBase(with_metaclass(ABCMeta, object)):
""" """
A base class for implementing cli connections A base class for implementing cli connections
.. note:: Unlike most of Ansible, nearly all strings in .. note:: String inputs to :meth:`send_command` will be cast to byte strings
:class:`CliconfBase` plugins are byte strings. This is because of within this method and as such are not required to be made byte strings
how close to the underlying platform these plugins operate. Remember beforehand. Please avoid using literal byte strings (``b'string'``) in
to mark literal strings as byte string (``b"string"``) and to use :class:`CliConfBase` plugins as this can lead to unexpected errors when
:func:`~ansible.module_utils._text.to_bytes` and running on Python 3
:func:`~ansible.module_utils._text.to_text` to avoid unexpected
problems.
List of supported rpc's: List of supported rpc's:
:get_config: Retrieves the specified configuration from the device :get_config: Retrieves the specified configuration from the device

@ -10,7 +10,7 @@ import json
from itertools import chain from itertools import chain
from ansible.module_utils._text import to_bytes, to_text from ansible.module_utils._text import to_text
from ansible.module_utils.network.common.utils import to_list from ansible.module_utils.network.common.utils import to_list
from ansible.plugins.cliconf import CliconfBase from ansible.plugins.cliconf import CliconfBase
@ -21,7 +21,7 @@ class Cliconf(CliconfBase):
device_info = {} device_info = {}
device_info['network_os'] = 'edgeos' device_info['network_os'] = 'edgeos'
reply = self.get(b'show version') reply = self.get('show version')
data = to_text(reply, errors='surrogate_or_strict').strip() data = to_text(reply, errors='surrogate_or_strict').strip()
match = re.search(r'Version:\s*v?(\S+)', data) match = re.search(r'Version:\s*v?(\S+)', data)
@ -32,24 +32,21 @@ class Cliconf(CliconfBase):
if match: if match:
device_info['network_os_model'] = match.group(1) device_info['network_os_model'] = match.group(1)
reply = self.get(b'show host name') reply = self.get('show host name')
reply = to_text(reply, errors='surrogate_or_strict').strip() reply = to_text(reply, errors='surrogate_or_strict').strip()
device_info['network_os_hostname'] = reply device_info['network_os_hostname'] = reply
return device_info return device_info
def get_config(self, source='running', format='text'): def get_config(self, source='running', format='text'):
return self.send_command(b'show configuration commands') return self.send_command('show configuration commands')
def edit_config(self, command): def edit_config(self, command):
for cmd in chain([b'configure'], to_list(command)): for cmd in chain(['configure'], to_list(command)):
self.send_command(cmd) self.send_command(cmd)
def get(self, command, prompt=None, answer=None, sendonly=False): def get(self, command, prompt=None, answer=None, sendonly=False):
return self.send_command(to_bytes(command), return self.send_command(command, prompt=prompt, answer=answer, sendonly=sendonly)
prompt=to_bytes(prompt),
answer=to_bytes(answer),
sendonly=sendonly)
def commit(self, comment=None): def commit(self, comment=None):
if comment: if comment:
@ -59,7 +56,7 @@ class Cliconf(CliconfBase):
self.send_command(command) self.send_command(command)
def discard_changes(self, *args, **kwargs): def discard_changes(self, *args, **kwargs):
self.send_command(b'discard') self.send_command('discard')
def get_capabilities(self): def get_capabilities(self):
result = {} result = {}

@ -33,13 +33,13 @@ class Cliconf(CliconfBase):
device_info = {} device_info = {}
device_info['network_os'] = 'eos' device_info['network_os'] = 'eos'
reply = self.get(b'show version | json') reply = self.get('show version | json')
data = json.loads(reply) data = json.loads(reply)
device_info['network_os_version'] = data['version'] device_info['network_os_version'] = data['version']
device_info['network_os_model'] = data['modelName'] device_info['network_os_model'] = data['modelName']
reply = self.get(b'show hostname | json') reply = self.get('show hostname | json')
data = json.loads(reply) data = json.loads(reply)
device_info['network_os_hostname'] = data['hostname'] device_info['network_os_hostname'] = data['hostname']
@ -52,9 +52,9 @@ class Cliconf(CliconfBase):
if source not in lookup: if source not in lookup:
return self.invalid_params("fetching configuration from %s is not supported" % source) return self.invalid_params("fetching configuration from %s is not supported" % source)
cmd = b'show %s ' % lookup[source] cmd = 'show %s ' % lookup[source]
if format and format is not 'text': if format and format is not 'text':
cmd += b'| %s ' % format cmd += '| %s ' % format
cmd += ' '.join(to_list(flags)) cmd += ' '.join(to_list(flags))
cmd = cmd.strip() cmd = cmd.strip()
@ -62,7 +62,7 @@ class Cliconf(CliconfBase):
@enable_mode @enable_mode
def edit_config(self, command): def edit_config(self, command):
for cmd in chain([b'configure'], to_list(command), [b'end']): for cmd in chain(['configure'], to_list(command), ['end']):
self.send_command(cmd) self.send_command(cmd)
def get(self, command, prompt=None, answer=None, sendonly=False): def get(self, command, prompt=None, answer=None, sendonly=False):

@ -24,7 +24,7 @@ import json
from itertools import chain from itertools import chain
from ansible.module_utils._text import to_bytes, to_text from ansible.module_utils._text import to_text
from ansible.module_utils.network.common.utils import to_list from ansible.module_utils.network.common.utils import to_list
from ansible.plugins.cliconf import CliconfBase, enable_mode from ansible.plugins.cliconf import CliconfBase, enable_mode
@ -35,7 +35,7 @@ class Cliconf(CliconfBase):
device_info = {} device_info = {}
device_info['network_os'] = 'ios' device_info['network_os'] = 'ios'
reply = self.get(b'show version') reply = self.get('show version')
data = to_text(reply, errors='surrogate_or_strict').strip() data = to_text(reply, errors='surrogate_or_strict').strip()
match = re.search(r'Version (\S+),', data) match = re.search(r'Version (\S+),', data)

@ -24,7 +24,7 @@ import json
from itertools import chain from itertools import chain
from ansible.module_utils._text import to_bytes, to_text from ansible.module_utils._text import to_text
from ansible.module_utils.network.common.utils import to_list from ansible.module_utils.network.common.utils import to_list
from ansible.plugins.cliconf import CliconfBase from ansible.plugins.cliconf import CliconfBase
@ -35,7 +35,7 @@ class Cliconf(CliconfBase):
device_info = {} device_info = {}
device_info['network_os'] = 'iosxr' device_info['network_os'] = 'iosxr'
reply = self.get(b'show version | utility head -n 20') reply = self.get('show version | utility head -n 20')
data = to_text(reply, errors='surrogate_or_strict').strip() data = to_text(reply, errors='surrogate_or_strict').strip()
match = re.search(r'Version (\S+)$', data, re.M) match = re.search(r'Version (\S+)$', data, re.M)
@ -61,9 +61,9 @@ class Cliconf(CliconfBase):
if source not in lookup: if source not in lookup:
return self.invalid_params("fetching configuration from %s is not supported" % source) return self.invalid_params("fetching configuration from %s is not supported" % source)
if filter: if filter:
cmd = to_bytes('show {0} {1}'.format(lookup[source], filter), errors='surrogate_or_strict') cmd = 'show {0} {1}'.format(lookup[source], filter)
else: else:
cmd = to_bytes('show {0}'.format(lookup[source]), errors='surrogate_or_strict') cmd = 'show {0}'.format(lookup[source])
return self.send_command(cmd) return self.send_command(cmd)
@ -94,10 +94,10 @@ class Cliconf(CliconfBase):
command = 'commit comment {0}'.format(comment) command = 'commit comment {0}'.format(comment)
else: else:
command = 'commit' command = 'commit'
self.send_command(to_bytes(command)) self.send_command(command)
def discard_changes(self): def discard_changes(self):
self.send_command(b'abort') self.send_command('abort')
def get_capabilities(self): def get_capabilities(self):
result = {} result = {}

@ -23,7 +23,7 @@ import json
import re import re
from itertools import chain from itertools import chain
from ansible.module_utils._text import to_bytes, to_text from ansible.module_utils._text import to_text
from ansible.module_utils.network.common.utils import to_list from ansible.module_utils.network.common.utils import to_list
from ansible.plugins.cliconf import CliconfBase from ansible.plugins.cliconf import CliconfBase
@ -78,15 +78,15 @@ class Cliconf(CliconfBase):
comment: Optional commit description. comment: Optional commit description.
""" """
comment = kwargs.get('comment', None) comment = kwargs.get('comment', None)
command = b'commit' command = 'commit'
if comment: if comment:
command += b' comment {0}'.format(comment) command += ' comment {0}'.format(comment)
command += b' and-quit' command += ' and-quit'
return self.send_command(command) return self.send_command(command)
def discard_changes(self): def discard_changes(self):
command = b'rollback 0' command = 'rollback 0'
for cmd in chain(to_list(command), b'exit'): for cmd in chain(to_list(command), 'exit'):
self.send_command(cmd) self.send_command(cmd)
def get_capabilities(self): def get_capabilities(self):
@ -97,7 +97,7 @@ class Cliconf(CliconfBase):
return json.dumps(result) return json.dumps(result)
def compare_configuration(self, rollback_id=None): def compare_configuration(self, rollback_id=None):
command = b'show | compare' command = 'show | compare'
if rollback_id is not None: if rollback_id is not None:
command += b' rollback %s' % int(rollback_id) command += ' rollback %s' % int(rollback_id)
return self.send_command(command) return self.send_command(command)

@ -53,7 +53,7 @@ class Cliconf(CliconfBase):
def get_config(self, source='running', format='text', flags=None): def get_config(self, source='running', format='text', flags=None):
lookup = {'running': 'running-config', 'startup': 'startup-config'} lookup = {'running': 'running-config', 'startup': 'startup-config'}
cmd = 'show {} '.format(lookup[source]) cmd = 'show {0} '.format(lookup[source])
if flags: if flags:
cmd += ' '.join(flags) cmd += ' '.join(flags)
cmd = cmd.strip() cmd = cmd.strip()

@ -24,7 +24,7 @@ import json
from itertools import chain from itertools import chain
from ansible.module_utils._text import to_bytes, to_text from ansible.module_utils._text import to_text
from ansible.module_utils.network.common.utils import to_list from ansible.module_utils.network.common.utils import to_list
from ansible.plugins.cliconf import CliconfBase from ansible.plugins.cliconf import CliconfBase
@ -35,7 +35,7 @@ class Cliconf(CliconfBase):
device_info = {} device_info = {}
device_info['network_os'] = 'vyos' device_info['network_os'] = 'vyos'
reply = self.get(b'show version') reply = self.get('show version')
data = to_text(reply, errors='surrogate_or_strict').strip() data = to_text(reply, errors='surrogate_or_strict').strip()
match = re.search(r'Version:\s*(\S+)', data) match = re.search(r'Version:\s*(\S+)', data)
@ -46,17 +46,17 @@ class Cliconf(CliconfBase):
if match: if match:
device_info['network_os_model'] = match.group(1) device_info['network_os_model'] = match.group(1)
reply = self.get(b'show host name') reply = self.get('show host name')
device_info['network_os_hostname'] = to_text(reply, errors='surrogate_or_strict').strip() device_info['network_os_hostname'] = to_text(reply, errors='surrogate_or_strict').strip()
return device_info return device_info
def get_config(self, source='running', format='text'): def get_config(self, source='running', format='text'):
return self.send_command(b'show configuration commands') return self.send_command('show configuration commands')
def edit_config(self, command): def edit_config(self, command):
for cmd in chain(['configure'], to_list(command)): for cmd in chain(['configure'], to_list(command)):
self.send_command(to_bytes(cmd)) self.send_command(cmd)
def get(self, command, prompt=None, answer=None, sendonly=False): def get(self, command, prompt=None, answer=None, sendonly=False):
return self.send_command(command, prompt=prompt, answer=answer, sendonly=sendonly) return self.send_command(command, prompt=prompt, answer=answer, sendonly=sendonly)
@ -66,10 +66,10 @@ class Cliconf(CliconfBase):
command = 'commit comment "{0}"'.format(comment) command = 'commit comment "{0}"'.format(comment)
else: else:
command = 'commit' command = 'commit'
self.send_command(to_bytes(command)) self.send_command(command)
def discard_changes(self, *args, **kwargs): def discard_changes(self, *args, **kwargs):
self.send_command(b'exit discard') self.send_command('exit discard')
def get_capabilities(self): def get_capabilities(self):
result = {} result = {}

@ -67,8 +67,6 @@ lib/ansible/modules/storage/infinidat/infini_vol.py ansible-format-automatic-spe
lib/ansible/modules/storage/purestorage/purefa_host.py ansible-format-automatic-specification lib/ansible/modules/storage/purestorage/purefa_host.py ansible-format-automatic-specification
lib/ansible/modules/storage/purestorage/purefa_pg.py ansible-format-automatic-specification lib/ansible/modules/storage/purestorage/purefa_pg.py ansible-format-automatic-specification
lib/ansible/modules/system/firewalld.py ansible-format-automatic-specification lib/ansible/modules/system/firewalld.py ansible-format-automatic-specification
lib/ansible/plugins/cliconf/junos.py ansible-no-format-on-bytestring 3
lib/ansible/plugins/cliconf/nxos.py ansible-format-automatic-specification
test/runner/injector/importer.py missing-docstring 3.7 test/runner/injector/importer.py missing-docstring 3.7
test/runner/injector/injector.py missing-docstring 3.7 test/runner/injector/injector.py missing-docstring 3.7
test/runner/lib/ansible_util.py missing-docstring 3.7 test/runner/lib/ansible_util.py missing-docstring 3.7

Loading…
Cancel
Save