From 2aaabc77c46432df380b1364af415f22e9a58398 Mon Sep 17 00:00:00 2001 From: Rafael Guterres Jeffman <rjeffman@redhat.com> Date: Fri, 9 Oct 2020 15:34:35 -0300 Subject: [PATCH] Add FreeIPA version check to module_utils.ansible_freeipa_module. Some attribute values are only accepted for specific FreeIPA versions, for example `self` for permission's `bindtype`. Although there are options to check for command and parameter availability, there is no check for verifying if a value should be accepted. This patch add a function to evaluate the target FreeIPA host version, by comparing a giver version to the current installed one. The version evaluation uses Python packaging's version comparision, which is compatible with PEP 440, if available. If not available, it falls back to a string split, that will work for the most common cases, but might fail for versions including strings with `rc` or `dev`, for example. --- .../module_utils/ansible_freeipa_module.py | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py index 43f96eb6..03cfe1f1 100644 --- a/plugins/module_utils/ansible_freeipa_module.py +++ b/plugins/module_utils/ansible_freeipa_module.py @@ -23,6 +23,7 @@ import sys +import operator import os import uuid import tempfile @@ -30,6 +31,25 @@ import shutil import gssapi from datetime import datetime from pprint import pformat + +try: + from packaging import version +except ImportError: + # If `packaging` not found, split version string for creating version + # object. Although it is not PEP 440 compliant, it will work for stable + # FreeIPA releases. + import re + + class version: + @staticmethod + def parse(version_str): + """ + Split a version string A.B.C, into a tuple. + + This will not work for `rc`, `dev` or similar version string. + """ + return tuple(re.split("[-_\.]", version_str)) # noqa: W605 + from ipalib import api from ipalib import errors as ipalib_errors # noqa from ipalib.config import Env @@ -41,6 +61,7 @@ except ImportError: from ipapython.ipautil import kinit_password, kinit_keytab from ipapython.ipautil import run from ipapython.dn import DN +from ipapython.version import VERSION from ipaplatform.paths import paths from ipalib.krb_utils import get_credentials_if_valid from ansible.module_utils.basic import AnsibleModule @@ -187,6 +208,26 @@ def api_check_param(command, name): return name in api.Command[command].params +def api_check_ipa_version(oper, requested_version): + """ + Compare the installed IPA version against a requested version. + + The valid operators are: <, <=, >, >=, ==, != + """ + oper_map = { + "<": operator.lt, + "<=": operator.le, + ">": operator.gt, + ">=": operator.ge, + "==": operator.eq, + "!=": operator.ne, + } + operation = oper_map.get(oper) + if not(operation): + raise NotImplementedError("Invalid operator: %s" % oper) + return operation(version.parse(VERSION), version.parse(requested_version)) + + def execute_api_command(module, principal, password, command, name, args): """ Execute an API command. -- GitLab