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

@ -10,7 +10,7 @@ import json
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.plugins.cliconf import CliconfBase
@ -21,7 +21,7 @@ class Cliconf(CliconfBase):
device_info = {}
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()
match = re.search(r'Version:\s*v?(\S+)', data)
@ -32,24 +32,21 @@ class Cliconf(CliconfBase):
if match:
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()
device_info['network_os_hostname'] = reply
return device_info
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):
for cmd in chain([b'configure'], to_list(command)):
for cmd in chain(['configure'], to_list(command)):
self.send_command(cmd)
def get(self, command, prompt=None, answer=None, sendonly=False):
return self.send_command(to_bytes(command),
prompt=to_bytes(prompt),
answer=to_bytes(answer),
sendonly=sendonly)
return self.send_command(command, prompt=prompt, answer=answer, sendonly=sendonly)
def commit(self, comment=None):
if comment:
@ -59,7 +56,7 @@ class Cliconf(CliconfBase):
self.send_command(command)
def discard_changes(self, *args, **kwargs):
self.send_command(b'discard')
self.send_command('discard')
def get_capabilities(self):
result = {}

@ -33,13 +33,13 @@ class Cliconf(CliconfBase):
device_info = {}
device_info['network_os'] = 'eos'
reply = self.get(b'show version | json')
reply = self.get('show version | json')
data = json.loads(reply)
device_info['network_os_version'] = data['version']
device_info['network_os_model'] = data['modelName']
reply = self.get(b'show hostname | json')
reply = self.get('show hostname | json')
data = json.loads(reply)
device_info['network_os_hostname'] = data['hostname']
@ -52,9 +52,9 @@ class Cliconf(CliconfBase):
if source not in lookup:
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':
cmd += b'| %s ' % format
cmd += '| %s ' % format
cmd += ' '.join(to_list(flags))
cmd = cmd.strip()
@ -62,7 +62,7 @@ class Cliconf(CliconfBase):
@enable_mode
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)
def get(self, command, prompt=None, answer=None, sendonly=False):

@ -24,7 +24,7 @@ import json
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.plugins.cliconf import CliconfBase, enable_mode
@ -35,7 +35,7 @@ class Cliconf(CliconfBase):
device_info = {}
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()
match = re.search(r'Version (\S+),', data)

@ -24,7 +24,7 @@ import json
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.plugins.cliconf import CliconfBase
@ -35,7 +35,7 @@ class Cliconf(CliconfBase):
device_info = {}
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()
match = re.search(r'Version (\S+)$', data, re.M)
@ -61,9 +61,9 @@ class Cliconf(CliconfBase):
if source not in lookup:
return self.invalid_params("fetching configuration from %s is not supported" % source)
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:
cmd = to_bytes('show {0}'.format(lookup[source]), errors='surrogate_or_strict')
cmd = 'show {0}'.format(lookup[source])
return self.send_command(cmd)
@ -94,10 +94,10 @@ class Cliconf(CliconfBase):
command = 'commit comment {0}'.format(comment)
else:
command = 'commit'
self.send_command(to_bytes(command))
self.send_command(command)
def discard_changes(self):
self.send_command(b'abort')
self.send_command('abort')
def get_capabilities(self):
result = {}

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

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

@ -24,7 +24,7 @@ import json
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.plugins.cliconf import CliconfBase
@ -35,7 +35,7 @@ class Cliconf(CliconfBase):
device_info = {}
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()
match = re.search(r'Version:\s*(\S+)', data)
@ -46,17 +46,17 @@ class Cliconf(CliconfBase):
if match:
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()
return device_info
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):
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):
return self.send_command(command, prompt=prompt, answer=answer, sendonly=sendonly)
@ -66,10 +66,10 @@ class Cliconf(CliconfBase):
command = 'commit comment "{0}"'.format(comment)
else:
command = 'commit'
self.send_command(to_bytes(command))
self.send_command(command)
def discard_changes(self, *args, **kwargs):
self.send_command(b'exit discard')
self.send_command('exit discard')
def get_capabilities(self):
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_pg.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/injector.py missing-docstring 3.7
test/runner/lib/ansible_util.py missing-docstring 3.7

Loading…
Cancel
Save