Add module_utils and filters for quoting and unquoting (#53)

* Move splitting code to own file.

* Move list to dictionary code to quoting as well.

* Add quoting functionality.

* Add quoting filters.

* Add integration tests to CI.

* Fix bugs, increase coverage.

* Make parsing more strict.

* Extract function parse_argument_value from split_routeros_command to make proper parsing of WHERE possible.

* Adjust expected error message in integration tests.

* Simplify code and improve coverage.

* Add changelog fragment for WHERE strictness in api module.

* Add documenation.

* Fix typo.

* Add documentation references.

* Add example to api module which uses quote_argument_value.

* Fix bug, and add tests which prevent this in the future.

* Add more escape sequence tests.

* Make sure all control characters are quoted.
This commit is contained in:
Felix Fontein 2021-10-11 23:44:40 +02:00 committed by GitHub
parent f9d246cd7a
commit d73eb1c144
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
14 changed files with 803 additions and 145 deletions

113
plugins/filter/quoting.py Normal file
View file

@ -0,0 +1,113 @@
# -*- coding: utf-8 -*-
# Copyright: (c) 2021, Felix Fontein <felix@fontein.de>
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
from __future__ import absolute_import, division, print_function
__metaclass__ = type
from ansible.errors import AnsibleFilterError
from ansible.module_utils.common.text.converters import to_text
from ansible_collections.community.routeros.plugins.module_utils.quoting import (
ParseError,
convert_list_to_dictionary,
join_routeros_command,
quote_routeros_argument,
quote_routeros_argument_value,
split_routeros_command,
)
def wrap_exception(fn, *args, **kwargs):
try:
return fn(*args, **kwargs)
except ParseError as e:
raise AnsibleFilterError(to_text(e))
def split(line):
'''
Split a command into arguments.
Example:
'add name=wrap comment="with space"'
is converted to:
['add', 'name=wrap', 'comment=with space']
'''
return wrap_exception(split_routeros_command, line)
def quote_argument_value(argument):
'''
Quote an argument value.
Example:
'with "space"'
is converted to:
r'"with \"space\""'
'''
return wrap_exception(quote_routeros_argument_value, argument)
def quote_argument(argument):
'''
Quote an argument.
Example:
'comment=with "space"'
is converted to:
r'comment="with \"space\""'
'''
return wrap_exception(quote_routeros_argument, argument)
def join(arguments):
'''
Join a list of arguments to a command.
Example:
['add', 'name=wrap', 'comment=with space']
is converted to:
'add name=wrap comment="with space"'
'''
return wrap_exception(join_routeros_command, arguments)
def list_to_dict(string_list, require_assignment=True, skip_empty_values=False):
'''
Convert a list of arguments to a list of dictionary.
Example:
['foo=bar', 'comment=with space', 'additional=']
is converted to:
{'foo': 'bar', 'comment': 'with space', 'additional': ''}
If require_assignment is True (default), arguments without assignments are
rejected. (Example: in ['add', 'name=foo'], 'add' is an argument without
assignment.) If it is False, these are given value None.
If skip_empty_values is True, arguments with empty value are removed from
the result. (Example: in ['name='], 'name' has an empty value.)
If it is False (default), these are kept.
'''
return wrap_exception(
convert_list_to_dictionary,
string_list,
require_assignment=require_assignment,
skip_empty_values=skip_empty_values,
)
class FilterModule(object):
'''Ansible jinja2 filters for RouterOS command quoting and unquoting'''
def filters(self):
return {
'split': split,
'quote_argument': quote_argument,
'quote_argument_value': quote_argument_value,
'join': join,
'list_to_dict': list_to_dict,
}