diff --git a/changelogs/fragments/95-api-encoding.yml b/changelogs/fragments/95-api-encoding.yml new file mode 100644 index 0000000..d3e0ea3 --- /dev/null +++ b/changelogs/fragments/95-api-encoding.yml @@ -0,0 +1,2 @@ +minor_changes: + - "api* modules - allow to set an encoding other than the default ASCII for communicating with the API (https://github.com/ansible-collections/community.routeros/pull/95)." diff --git a/plugins/doc_fragments/api.py b/plugins/doc_fragments/api.py index f436d64..6995c5c 100644 --- a/plugins/doc_fragments/api.py +++ b/plugins/doc_fragments/api.py @@ -63,6 +63,13 @@ options: - See also I(validate_cert_hostname). Only used when I(tls=true) and I(validate_certs=true). type: path version_added: 1.2.0 + encoding: + description: + - Use the specified encoding when communicating with the RouterOS device. + - Default is C(ASCII). Note that C(UTF-8) requires librouteros 3.2.1 or newer. + type: str + default: ASCII + version_added: 2.1.0 requirements: - librouteros - Python >= 3.6 (for librouteros) diff --git a/plugins/module_utils/api.py b/plugins/module_utils/api.py index f8b839f..7150dcc 100644 --- a/plugins/module_utils/api.py +++ b/plugins/module_utils/api.py @@ -43,10 +43,11 @@ def api_argument_spec(): validate_certs=dict(type='bool', default=True), validate_cert_hostname=dict(type='bool', default=False), ca_path=dict(type='path'), + encoding=dict(type='str', default='ASCII') ) -def _ros_api_connect(module, username, password, host, port, use_tls, validate_certs, validate_cert_hostname, ca_path): +def _ros_api_connect(module, username, password, host, port, use_tls, validate_certs, validate_cert_hostname, ca_path, encoding): '''Connect to RouterOS API.''' if not port: if use_tls: @@ -54,6 +55,13 @@ def _ros_api_connect(module, username, password, host, port, use_tls, validate_c else: port = 8728 try: + params = dict( + username=username, + password=password, + host=host, + port=port, + encoding=encoding, + ) if use_tls: ctx = ssl.create_default_context(cafile=ca_path) wrap_context = ctx.wrap_socket @@ -68,20 +76,8 @@ def _ros_api_connect(module, username, password, host, port, use_tls, validate_c def wrap_context(*args, **kwargs): kwargs.pop('server_hostname', None) return ctx.wrap_socket(*args, server_hostname=host, **kwargs) - api = connect( - username=username, - password=password, - host=host, - ssl_wrapper=wrap_context, - port=port, - ) - else: - api = connect( - username=username, - password=password, - host=host, - port=port, - ) + params['ssl_wrapper'] = wrap_context + api = connect(**params) except Exception as e: connection = { 'username': username, @@ -105,4 +101,5 @@ def create_api(module): module.params['validate_certs'], module.params['validate_cert_hostname'], module.params['ca_path'], + module.params['encoding'], ) diff --git a/plugins/modules/api.py b/plugins/modules/api.py index 85dc704..ddd026c 100644 --- a/plugins/modules/api.py +++ b/plugins/modules/api.py @@ -329,23 +329,26 @@ class ROS_api_module: # create api base path self.api_path = self.api_add_path(self.api, self.path) - # api call's - if self.add: - self.api_add() - elif self.remove: - self.api_remove() - elif self.update: - self.api_update() - elif self.query: - self.check_query() - self.api_query() - elif self.extended_query: - self.check_extended_query() - self.api_extended_query() - elif self.arbitrary: - self.api_arbitrary() - else: - self.api_get_all() + # api calls + try: + if self.add: + self.api_add() + elif self.remove: + self.api_remove() + elif self.update: + self.api_update() + elif self.query: + self.check_query() + self.api_query() + elif self.extended_query: + self.check_extended_query() + self.api_extended_query() + elif self.arbitrary: + self.api_arbitrary() + else: + self.api_get_all() + except UnicodeEncodeError as exc: + self.module.fail_json(msg='Error while encoding text: {error}'.format(error=exc)) def check_query(self): where_index = self.query.find(' WHERE ') diff --git a/plugins/modules/api_find_and_modify.py b/plugins/modules/api_find_and_modify.py index 0d4a282..e1265a0 100644 --- a/plugins/modules/api_find_and_modify.py +++ b/plugins/modules/api_find_and_modify.py @@ -277,7 +277,7 @@ def main(): for modification in modifications: try: api_path.update(**modification) - except LibRouterosError as e: + except (LibRouterosError, UnicodeEncodeError) as e: module.fail_json( msg='Error while modifying for .id={id}: {error}'.format( id=modification['.id'],