diff --git a/changelogs/fragments/1099-postgresql_ext_fix_failing_when_version_cannot_be_compared.yml b/changelogs/fragments/1099-postgresql_ext_fix_failing_when_version_cannot_be_compared.yml new file mode 100644 index 0000000000..bb102ecc82 --- /dev/null +++ b/changelogs/fragments/1099-postgresql_ext_fix_failing_when_version_cannot_be_compared.yml @@ -0,0 +1,2 @@ +bugfixes: +- postgresql_ext - fix the module crashes when available ext versions cannot be compared with current version (https://github.com/ansible-collections/community.general/issues/1095). diff --git a/plugins/modules/database/postgresql/postgresql_ext.py b/plugins/modules/database/postgresql/postgresql_ext.py index 6a3dfdae6c..2ca25f7ab0 100644 --- a/plugins/modules/database/postgresql/postgresql_ext.py +++ b/plugins/modules/database/postgresql/postgresql_ext.py @@ -106,6 +106,7 @@ notes: then PostgreSQL must also be installed on the remote host. - For Ubuntu-based systems, install the C(postgresql), C(libpq-dev), and C(python-psycopg2) packages on the remote host before using this module. +- Incomparable versions, for example PostGIS ``unpackaged``, cannot be installed. requirements: [ psycopg2 ] author: - Daniel Schep (@dschep) @@ -286,16 +287,40 @@ def ext_get_versions(cursor, ext): cursor.execute(query, {'ext': ext}) res = cursor.fetchall() - available_versions = [ - line['version'] - for line in res - if LooseVersion(line['version']) > LooseVersion(current_version) - ] + available_versions = parse_ext_versions(current_version, res) if current_version == '0': current_version = False - return (current_version, sorted(available_versions, key=LooseVersion)) + return (current_version, available_versions) + + +def parse_ext_versions(current_version, ext_ver_list): + """Parse ext versions. + + Args: + current_version (str) -- version to compare elements of ext_ver_list with + ext_ver_list (list) -- list containing dicts with versions + + Return a sorted list with versions that are higher than current_version. + + Note: Incomparable versions (e.g., postgis version "unpackaged") are skipped. + """ + available_versions = [] + + for line in ext_ver_list: + if line['version'] == 'unpackaged': + continue + + try: + if LooseVersion(line['version']) > LooseVersion(current_version): + available_versions.append(line['version']) + except Exception: + # When a version cannot be compared, skip it + # (there's a note in the documentation) + continue + + return sorted(available_versions, key=LooseVersion) # =========================================== # Module execution. diff --git a/tests/integration/targets/postgresql_ext/tasks/postgresql_ext_version_opt.yml b/tests/integration/targets/postgresql_ext/tasks/postgresql_ext_version_opt.yml index b459350533..f90340c597 100644 --- a/tests/integration/targets/postgresql_ext/tasks/postgresql_ext_version_opt.yml +++ b/tests/integration/targets/postgresql_ext/tasks/postgresql_ext_version_opt.yml @@ -330,6 +330,23 @@ - result.failed == true - result.msg == "Extension non_existent is not installed" + ###################################################################### + # https://github.com/ansible-collections/community.general/issues/1095 + - name: Install postgis + package: + name: postgis + + - name: Create postgis extension + <<: *task_parameters + postgresql_ext: + <<: *pg_parameters + name: postgis + version: latest + + - assert: + that: + - result is changed + # Cleanup: - name: postgresql_ext_version - drop the extension <<: *task_parameters diff --git a/tests/unit/plugins/modules/database/postgresql/test_postgresql_ext.py b/tests/unit/plugins/modules/database/postgresql/test_postgresql_ext.py new file mode 100644 index 0000000000..89417eaf8e --- /dev/null +++ b/tests/unit/plugins/modules/database/postgresql/test_postgresql_ext.py @@ -0,0 +1,35 @@ +# Copyright 2020, Andrew Klychkov @Andersson007 +# 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 + +import pytest + +from ansible_collections.community.general.plugins.modules.database.postgresql.postgresql_ext import ( + parse_ext_versions, +) + + +@pytest.mark.parametrize( + 'current,test_input,expected', + [ + ( + '2.0.0', + [{'version': '3.1.0dev'}, {'version': '3.1.0devnext'}, {'version': 'unpackaged'}], + ['3.1.0dev', '3.1.0devnext'], + ), + ( + '2.0.0', + [{'version': 'unpackaged'}, {'version': '3.1.0dev'}, {'version': '3.1.0devnext'}], + ['3.1.0dev', '3.1.0devnext'], + ), + ( + '2.0.1', + [{'version': 'unpackaged'}, {'version': '2.0.0'}, {'version': '2.1.0dev'}], + ['2.1.0dev'], + ), + ] +) +def test_parse_ext_versions(current, test_input, expected): + assert parse_ext_versions(current, test_input) == expected