From 7a665bdb6322bf39464875e3949a4bb11e7b0aca Mon Sep 17 00:00:00 2001
From: Thomas Woerner <twoerner@redhat.com>
Date: Tue, 24 Aug 2021 14:04:14 +0200
Subject: [PATCH] New ipamodule_base_vars

There are common parameters in all modules like ipaadmin_principal and
ipaadmin_password. As this list of common parameters will be extended
soon, there is a need to reduce the code and documentation duplicates.

A ModuleDocFragment is added to provide the module documentation for the
common parameters. This is used in the modules with
extends_documentation_fragment.

ansible_freeipa_module has additional ipamodule_base_spec and
get_ipamodule_base_vars. ipamodule_base_spec extends argument_spec in
the module and get_ipamodule_base_vars is used to return a dict
containing the common parameters.
---
 .github/workflows/docs.yml                    |  4 +-
 .github/workflows/lint.yml                    |  1 +
 .pre-commit-config.yaml                       |  2 +-
 plugins/doc_fragments/ipamodule_base_docs.py  | 33 +++++++++++++
 .../module_utils/ansible_freeipa_module.py    | 16 +++++++
 plugins/modules/ipalocation.py                | 48 +++++++++----------
 utils/ansible-doc-test                        |  2 +
 7 files changed, 77 insertions(+), 29 deletions(-)
 create mode 100644 plugins/doc_fragments/ipamodule_base_docs.py

diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 6212cfa4..4f4db6b3 100644
--- a/.github/workflows/docs.yml
+++ b/.github/workflows/docs.yml
@@ -15,7 +15,7 @@ jobs:
       - name: Run ansible-doc-test
         run: |
           python -m pip install "ansible < 2.10"
-          ANSIBLE_LIBRARY="." python utils/ansible-doc-test -v roles plugins
+          ANSIBLE_LIBRARY="." ANSIBLE_DOC_FRAGMENT_PLUGINS="." python utils/ansible-doc-test -v roles plugins
   
   check_docs_latest:
     name: Check Ansible Documentation with latest Ansible.
@@ -28,5 +28,5 @@ jobs:
       - name: Run ansible-doc-test
         run: |
           python -m pip install ansible
-          ANSIBLE_LIBRARY="." python utils/ansible-doc-test -v roles plugins
+          ANSIBLE_LIBRARY="." ANSIBLE_DOC_FRAGMENT_PLUGINS="." python utils/ansible-doc-test -v roles plugins
 
diff --git a/.github/workflows/lint.yml b/.github/workflows/lint.yml
index cb33ca71..a8e56b87 100644
--- a/.github/workflows/lint.yml
+++ b/.github/workflows/lint.yml
@@ -24,6 +24,7 @@ jobs:
         env:
           ANSIBLE_MODULE_UTILS: plugins/module_utils
           ANSIBLE_LIBRARY: plugins/modules
+          ANSIBLE_DOC_FRAGMENT_PLUGINS: plugins/doc_fragments
 
   yamllint:
     name: Verify yamllint
diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml
index ea9bf858..c4705358 100644
--- a/.pre-commit-config.yaml
+++ b/.pre-commit-config.yaml
@@ -7,7 +7,7 @@ repos:
     always_run: false
     pass_filenames: true
     files: \.(yaml|yml)$
-    entry: env ANSIBLE_LIBRARY=./plugins/modules ANSIBLE_MODULE_UTILS=./plugins/module_utils ansible-lint --force-color
+    entry: env ANSIBLE_LIBRARY=./plugins/modules ANSIBLE_MODULE_UTILS=./plugins/module_utils ANSIBLE_DOC_FRAGMENT_PLUGINS=./plugins/doc_fragments ansible-lint --force-color
 - repo: https://github.com/adrienverge/yamllint.git
   rev: v1.26.1
   hooks:
diff --git a/plugins/doc_fragments/ipamodule_base_docs.py b/plugins/doc_fragments/ipamodule_base_docs.py
new file mode 100644
index 00000000..22f2a1d1
--- /dev/null
+++ b/plugins/doc_fragments/ipamodule_base_docs.py
@@ -0,0 +1,33 @@
+#!/usr/bin/python
+# -*- coding: utf-8 -*-
+
+# Authors:
+#   Thomas Woerner <twoerner@redhat.com>
+#
+# Copyright (C) 2021  Red Hat
+# see file 'COPYING' for use and warranty information
+#
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with this program.  If not, see <http://www.gnu.org/licenses/>.
+
+
+class ModuleDocFragment(object):  # pylint: disable=R0205,R0903
+    DOCUMENTATION = r"""
+options:
+  ipaadmin_principal:
+    description: The admin principal.
+    default: admin
+  ipaadmin_password:
+    description: The admin password.
+    required: false
+"""
diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py
index c31f30af..4b3884a9 100644
--- a/plugins/module_utils/ansible_freeipa_module.py
+++ b/plugins/module_utils/ansible_freeipa_module.py
@@ -109,6 +109,22 @@ else:
     if six.PY3:
         unicode = str
 
+    # AnsibleModule argument specs for all modules
+    ipamodule_base_spec = dict(
+        ipaadmin_principal=dict(type="str", default="admin"),
+        ipaadmin_password=dict(type="str", required=False, no_log=True),
+    )
+
+    # Get ipamodule common vars as nonlocal
+    def get_ipamodule_base_vars(module):
+        ipaadmin_principal = module_params_get(module, "ipaadmin_principal")
+        ipaadmin_password = module_params_get(module, "ipaadmin_password")
+
+        return dict(
+            ipaadmin_principal=ipaadmin_principal,
+            ipaadmin_password=ipaadmin_password,
+        )
+
     def valid_creds(module, principal):  # noqa
         """Get valid credentials matching the princial, try GSSAPI first."""
         if "KRB5CCNAME" in os.environ:
diff --git a/plugins/modules/ipalocation.py b/plugins/modules/ipalocation.py
index 14066296..6c757944 100644
--- a/plugins/modules/ipalocation.py
+++ b/plugins/modules/ipalocation.py
@@ -31,13 +31,9 @@ DOCUMENTATION = """
 module: ipalocation
 short description: Manage FreeIPA location
 description: Manage FreeIPA location
+extends_documentation_fragment:
+  - ipamodule_base_docs
 options:
-  ipaadmin_principal:
-    description: The admin principal.
-    default: admin
-  ipaadmin_password:
-    description: The admin password.
-    required: false
   name:
     description: The list of location name strings.
     required: true
@@ -73,7 +69,8 @@ RETURN = """
 from ansible.module_utils.basic import AnsibleModule
 from ansible.module_utils.ansible_freeipa_module import \
     temp_kinit, temp_kdestroy, valid_creds, api_connect, api_command, \
-    compare_args_ipa, module_params_get
+    compare_args_ipa, module_params_get, ipamodule_base_spec, \
+    get_ipamodule_base_vars
 import six
 
 if six.PY3:
@@ -99,20 +96,20 @@ def gen_args(description):
 
 
 def main():
+    # Arguments
+    argument_spec = dict(
+        name=dict(type="list", aliases=["idnsname"],
+                  default=None, required=True),
+        # present
+        description=dict(required=False, type='str', default=None),
+        # state
+        state=dict(type="str", default="present",
+                   choices=["present", "absent"]),
+    )
+    argument_spec.update(ipamodule_base_spec)
+
     ansible_module = AnsibleModule(
-        argument_spec=dict(
-            # general
-            ipaadmin_principal=dict(type="str", default="admin"),
-            ipaadmin_password=dict(type="str", required=False, no_log=True),
-
-            name=dict(type="list", aliases=["idnsname"],
-                      default=None, required=True),
-            # present
-            description=dict(required=False, type='str', default=None),
-            # state
-            state=dict(type="str", default="present",
-                       choices=["present", "absent"]),
-        ),
+        argument_spec=argument_spec,
         supports_check_mode=True,
     )
 
@@ -121,9 +118,7 @@ def main():
     # Get parameters
 
     # general
-    ipaadmin_principal = module_params_get(ansible_module,
-                                           "ipaadmin_principal")
-    ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password")
+    base_vars = get_ipamodule_base_vars(ansible_module)
     names = module_params_get(ansible_module, "name")
 
     # present
@@ -156,9 +151,10 @@ def main():
     ccache_dir = None
     ccache_name = None
     try:
-        if not valid_creds(ansible_module, ipaadmin_principal):
-            ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
-                                                 ipaadmin_password)
+        if not valid_creds(ansible_module, base_vars["ipaadmin_principal"]):
+            ccache_dir, ccache_name = temp_kinit(
+                base_vars["ipaadmin_principal"],
+                base_vars["ipaadmin_password"])
         api_connect()
 
         commands = []
diff --git a/utils/ansible-doc-test b/utils/ansible-doc-test
index 1c9095c0..41afb635 100755
--- a/utils/ansible-doc-test
+++ b/utils/ansible-doc-test
@@ -30,9 +30,11 @@ import subprocess
 def run_ansible_doc(role, module, verbose=False):
     playbook_dir, module_path = get_playbook_dir(role, module)
     module_dir = os.path.dirname(module_path)
+    doc_fragments = os.path.dirname(module_path)+"/../doc_fragments/"
 
     command = ["env",
                "ANSIBLE_LIBRARY=%s" % module_dir,
+               "ANSIBLE_DOC_FRAGMENT_PLUGINS=%s" % doc_fragments,
                "ansible-doc",
                "--playbook-dir=%s" % playbook_dir,
                "--type=module",
-- 
GitLab