]> Frank Brehm's Git Trees - pixelpark/pp-admin-tools.git/commitdiff
Adding Ansible info module ds389_plugins_info
authorFrank Brehm <frank.brehm@pixelpark.com>
Thu, 19 Dec 2024 17:28:48 +0000 (18:28 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Thu, 19 Dec 2024 17:28:48 +0000 (18:28 +0100)
lib/ansible/ds389_plugins_info.py [new file with mode: 0644]

diff --git a/lib/ansible/ds389_plugins_info.py b/lib/ansible/ds389_plugins_info.py
new file mode 100644 (file)
index 0000000..1b7bbff
--- /dev/null
@@ -0,0 +1,309 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+"""
+@summary: Ansible info module for retrieving configuration of all plugins of a 389ds instance.
+
+@author: Frank Brehm
+@contact: frank.brehm@pixelpark.com
+@copyright: © 2024 by Frank Brehm, Berlin
+"""
+
+# Copyright (c) 2024, Frank Brehm <frank.brehm@pixelpark.com>
+# GNU General Public License v3.0+
+# SPDX-License-Identifier: GPL-3.0-or-later
+
+from __future__ import absolute_import, division, print_function
+__metaclass__ = type
+
+
+DOCUMENTATION = r"""
+---
+module: ds389_logging_info
+short_description: Retrieve all plugins configuration of a 389ds instance
+description:
+  - Get the configuration of all plugims of an instance of a 389ds directory server
+author: "Frank Brehm <frank.brehm@pixelpark.com>"
+extends_documentation_fragment:
+  - community.general.attributes
+  - community.general.attributes.info_module
+options:
+  instance:
+    type: str
+    description:
+      - The name of the instance, where the plugins configuration should be retrieved.
+    required: true
+
+"""
+
+EXAMPLES = r"""
+- name: Get plugin configuration of the 389ds directory server
+  ds389_plugins_info:
+    instance: slapd-dev-ds21
+  register: ds389_plugin_config
+
+"""
+
+RETURN = r"""
+---
+changed: false
+failed: false
+config:
+  memberof:
+    enabled: true
+
+"""
+
+# Standard modules
+import re
+import warnings
+from subprocess import CalledProcessError
+from subprocess import run
+
+# Third party modules
+from ansible.module_utils.basic import AnsibleModule
+# from ansible.module_utils.common.text.converters import to_text
+from ansible.module_utils.common.process import get_bin_path
+
+
+# ##############################################################################
+class Ds389PluginsInfo(object):
+    """Class for retrieving configuration of all plugins of a 389ds directory server instance."""
+
+    encoding = 'utf-8'
+
+    re_int = re.compile(r'^[+-]?\d+$')
+    re_float = re.compile(r'^[+-]?\d+\.\d*$')
+    re_cn = re.compile(r'^cn:\s+(.*)', re.IGNORECASE)
+    re_plugin_version = re.compile(r'^nsslapd-pluginVersion:\s+(.*)', re.IGNORECASE)
+    re_enabled = re.compile(r'^nsslapd-pluginEnabled:\s+(.*)', re.IGNORECASE)
+
+    # --------------------------------------------------------------------------
+    def __init__(self):
+        """Initialize the Ds389LoggingInfo object."""
+        self.instance = module.params.get('instance')
+
+        self.result = {}
+        self.cmd = None
+
+    # --------------------------------------------------------------------------
+    def run(self):
+        """Retrieve the plugins comfig anyhow ..."""
+        try:
+            self.cmd = get_bin_path('dsconf')
+        except ValueError:
+            return {}
+
+        if not self.cmd:
+            return {}
+
+        self.get_memberof()
+        self.get_referint()
+
+        return self.result
+
+    # ------------------
+    def mangle_value(self, value):
+        """Tape cast the given value to a boolean, integer of float value, if it is looking so."""
+        if self.re_int.match(value):
+            return int(value)
+        if self.re_float.match(value):
+            return float(value)
+        if value.lower() == 'on':
+            return True
+        if value.lower() == 'yes':
+            return True
+        if value.lower() == 'off':
+            return False
+        if value.lower() == 'no':
+            return False
+
+        return value
+
+    # --------------------------------------------------------------------------
+    def get_memberof(self):
+        """Get config of memberof plugin."""
+        proc = run(
+            [self.cmd, self.instance, 'plugin', 'memberof', 'show'],
+            capture_output=True, encoding=self.encoding)
+        if proc.stderr:
+            warnings.warn(proc.stderr)
+        try:
+            proc.check_returncode()
+        except CalledProcessError:
+            return
+
+        re_attr = re.compile(r'^memberOfAttr:\s+(.*)', re.IGNORECASE)
+        re_groupattr = re.compile(r'^memberOfGroupAttr:\s+(.*)', re.IGNORECASE)
+        re_allbackends = re.compile(r'^memberOfAllBackends:\s+(.*)', re.IGNORECASE)
+        re_skipnested = re.compile(r'^memberOfSkipNested:\s+(.*)', re.IGNORECASE)
+        re_scope = re.compile(r'^memberOfEntryScope:\s+(.*)', re.IGNORECASE)
+        re_exclude = re.compile(r'^memberOfEntryScopeExcludeSubtree:\s+(.*)', re.IGNORECASE)
+        re_autoaddoc = re.compile(r'^memberOfAutoAddOC:\s+(.*)', re.IGNORECASE)
+
+        if 'memberof' not in self.result:
+            self.result['memberof'] = {}
+
+        for line in proc.stdout.splitlines():
+            line = line.strip()
+            if not line:
+                continue
+
+            m = self.re_cn.match(line)
+            if m:
+                self.result['memberof']['cn'] = m.group(1)
+                continue
+
+            m = self.re_plugin_version.match(line)
+            if m:
+                self.result['memberof']['plugin_version'] = m.group(1)
+                continue
+
+            m = self.re_enabled.match(line)
+            if m:
+                self.result['memberof']['enabled'] = self.mangle_value(m.group(1))
+                continue
+
+            m = re_attr.match(line)
+            if m:
+                self.result['memberof']['attr'] = m.group(1)
+                continue
+
+            m = re_groupattr.match(line)
+            if m:
+                if 'groupattr' not in self.result['memberof']:
+                    self.result['memberof']['groupattr'] = []
+                self.result['memberof']['groupattr'].append(m.group(1))
+                continue
+
+            m = re_allbackends.match(line)
+            if m:
+                self.result['memberof']['allbackends'] = self.mangle_value(m.group(1))
+                continue
+
+            m = re_skipnested.match(line)
+            if m:
+                self.result['memberof']['skipnested'] = self.mangle_value(m.group(1))
+                continue
+
+            m = re_scope.match(line)
+            if m:
+                if 'scope' not in self.result['memberof']:
+                    self.result['memberof']['scope'] = []
+                self.result['memberof']['scope'].append(m.group(1))
+                continue
+
+            m = re_exclude.match(line)
+            if m:
+                if 'exclude' not in self.result['memberof']:
+                    self.result['memberof']['exclude'] = []
+                self.result['memberof']['exclude'].append(m.group(1))
+                continue
+
+            m = re_autoaddoc.match(line)
+            if m:
+                self.result['memberof']['auto_add_oc'] = m.group(1)
+                continue
+
+    # --------------------------------------------------------------------------
+    def get_referint(self):
+        """Get config of mreferential-integrity plugin."""
+        proc = run(
+            [self.cmd, self.instance, 'plugin', 'referential-integrity', 'show'],
+            capture_output=True, encoding=self.encoding)
+        if proc.stderr:
+            warnings.warn(proc.stderr)
+        try:
+            proc.check_returncode()
+        except CalledProcessError:
+            return
+
+        re_upate_delay = re.compile(r'^referint-update-delay:\s+(.*)', re.IGNORECASE)
+        re_membership_attr = re.compile(r'^referint-membership-attr:\s+(.*)', re.IGNORECASE)
+        re_entry_scope = re.compile(r'^nsslapd-pluginEntryScope:\s+(.*)', re.IGNORECASE)
+        re_exclude_entry_scope = re.compile(
+            r'^nsslapd-pluginExcludeEntryScope:\s+(.*)', re.IGNORECASE)
+        re_container_scope = re.compile(r'^mnsslapd-pluginContainerScope:\s+(.*)', re.IGNORECASE)
+        re_logfile = re.compile(r'^referint-logfile:\s+(.*)', re.IGNORECASE)
+
+        if 'referint' not in self.result:
+            self.result['referint'] = {}
+
+        for line in proc.stdout.splitlines():
+            line = line.strip()
+            if not line:
+                continue
+
+            m = self.re_cn.match(line)
+            if m:
+                self.result['referint']['cn'] = m.group(1)
+                continue
+
+            m = self.re_plugin_version.match(line)
+            if m:
+                self.result['referint']['plugin_version'] = m.group(1)
+                continue
+
+            m = self.re_enabled.match(line)
+            if m:
+                self.result['referint']['enabled'] = self.mangle_value(m.group(1))
+                continue
+
+            m = re_membership_attr.match(line)
+            if m:
+                if 'membership_attr' not in self.result['referint']:
+                    self.result['referint']['membership_attr'] = []
+                self.result['referint']['membership_attr'].append(m.group(1))
+                continue
+
+            m = re_upate_delay.match(line)
+            if m:
+                self.result['referint']['update_delay'] = self.mangle_value(m.group(1))
+                continue
+
+            m = re_entry_scope.match(line)
+            if m:
+                self.result['referint']['entry_scope'] = m.group(1)
+                continue
+
+            m = re_exclude_entry_scope.match(line)
+            if m:
+                self.result['referint']['exclude_entry_scope'] = m.group(1)
+                continue
+
+            m = re_container_scope.match(line)
+            if m:
+                self.result['referint']['container_scope'] = m.group(1)
+                continue
+
+            m = re_logfile.match(line)
+            if m:
+                self.result['referint']['logfile'] = m.group(1)
+                continue
+
+
+# ##############################################################################
+def main():
+    """Execute main entry function of this module."""
+    global module
+
+    module = AnsibleModule(
+        argument_spec={
+            'instance': {
+                'type': 'str',
+                'required': True,
+            },
+        },
+        supports_check_mode=True,
+    )
+
+    config = Ds389PluginsInfo().run()
+    module.exit_json(changed=False, config=config)
+
+
+# ##############################################################################
+if __name__ == '__main__':
+    main()
+
+# =============================================================================
+
+# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list