From 80e8c83e49f8c4829cacf254fe0a343bf0840602 Mon Sep 17 00:00:00 2001 From: Andrew Klychkov Date: Mon, 12 Feb 2024 15:25:01 +0100 Subject: [PATCH] community_client: Add handling of types not supported by ansible-core --- changelogs/fragments/1-clickhouse_client.yml | 2 + plugins/modules/clickhouse_client.py | 52 +++++++++++++++++++ .../clickhouse_client/tasks/initial.yml | 11 ++++ 3 files changed, 65 insertions(+) create mode 100644 changelogs/fragments/1-clickhouse_client.yml diff --git a/changelogs/fragments/1-clickhouse_client.yml b/changelogs/fragments/1-clickhouse_client.yml new file mode 100644 index 0000000..e5ea06b --- /dev/null +++ b/changelogs/fragments/1-clickhouse_client.yml @@ -0,0 +1,2 @@ +bugfixes: +- clickhouse_client - Add support for returning values of types ``UUID``, ``timedelta``, and ``decimal``. diff --git a/plugins/modules/clickhouse_client.py b/plugins/modules/clickhouse_client.py index a6a24c8..5dd73f0 100644 --- a/plugins/modules/clickhouse_client.py +++ b/plugins/modules/clickhouse_client.py @@ -114,6 +114,9 @@ returned: on success type: dict ''' +from datetime import timedelta +from decimal import Decimal +from uuid import UUID from ansible.module_utils.basic import AnsibleModule from ansible.module_utils._text import to_native @@ -131,6 +134,51 @@ HAS_DB_DRIVER = False +def is_uuid(value): + """Checks if the value is valid UUID. + + Returns True if yes, False otherwise. + """ + try: + UUID(str(value)) + return True + except ValueError: + return False + + +def vals_to_supported(result): + """Converts values of types unsupported by Ansible Core + to supported. + + Ansible Core has a limited set of supported values. + This is intentional, and the docs says such values + have to be converted on the module's side. + + Add more values here if needed. + """ + for idx_row, row in enumerate(result): + for idx_val, val in enumerate(row): + if is_uuid(val) or isinstance(val, timedelta): + # As tuple does not support change, + # we need some conversion here + result[idx_row] = replace_val_in_tuple(row, idx_val, str(val)) + + elif isinstance(val, Decimal): + result[idx_row] = replace_val_in_tuple(row, idx_val, float(val)) + + return result + + +def replace_val_in_tuple(tup, idx, val): + """Creates another tuple from a tuple substituting a value. + + Returns a new tuple. + """ + tmp = list(tup) + tmp[idx] = val + return tuple(tmp) + + def get_main_conn_kwargs(module): """Retrieves main connection arguments values and translates them into corresponding clickhouse_driver.Client() arguments. @@ -269,6 +317,10 @@ def main(): # Execute query result = execute_query(module, client, query, execute_kwargs) + # Convert values not supported by ansible-core + if result: + result = vals_to_supported(result) + # Retreive statistics statistics = get_query_statistics(module, client) diff --git a/tests/integration/targets/clickhouse_client/tasks/initial.yml b/tests/integration/targets/clickhouse_client/tasks/initial.yml index aee4110..ee4d0d1 100644 --- a/tests/integration/targets/clickhouse_client/tasks/initial.yml +++ b/tests/integration/targets/clickhouse_client/tasks/initial.yml @@ -71,3 +71,14 @@ ansible.builtin.assert: that: - result.result == [["one"], ["two"], ["three"]] + + +- name: The system.users table contain UUID value + register: result + community.clickhouse.clickhouse_client: + execute: SELECT id FROM system.users LIMIT 1 + +- name: Print the result + ansible.builtin.assert: + that: + - result.result[0] != []