diff --git a/.github/workflows/docs.yml b/.github/workflows/docs.yml
index 6212cfa4600b605ac29aba292b8321153b19449e..4f4db6b35d6a91373f66aa0c940f6e43bbdaaa3d 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 cb33ca71dc19a23476ea5f3ca29e3d86440218b2..a8e56b87fb809325066f54f34a6527c7838a8f34 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 ea9bf8587dc54536cb2d29a255f1841e11b80796..c4705358fb76056744fb6b9f087e399b6f3412ff 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 0000000000000000000000000000000000000000..22f2a1d1c8fbc2240326fb533b61cc8b48eedd66
--- /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 c31f30af4db2558ac33ba79ca7dcd6b0c913c1fb..4b3884a9af1211df3839232d312c42952907744a 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 140662967520bae371f2de7f189e24868dcd230c..6c7579449d60c6d8b0b7f9d6b9c8000fb5bc8303 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 1c9095c0cde94e84f0ebd6e87bbdab52f4623d8a..41afb63584c6b7d2fb26237fcdd91664395ef4ab 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",