diff --git a/plugins/module_utils/ansible_freeipa_module.py b/plugins/module_utils/ansible_freeipa_module.py
index 7c60eb28497d1d1514532746c6bce426728ba303..0b50720c865ae2de72e448aec47b30cbdd501180 100644
--- a/plugins/module_utils/ansible_freeipa_module.py
+++ b/plugins/module_utils/ansible_freeipa_module.py
@@ -44,7 +44,6 @@ else:
     import netaddr
     import gssapi
     from datetime import datetime
-    from pprint import pformat
     from contextlib import contextmanager
 
     # ansible-freeipa requires locale to be C, IPA requires utf-8.
@@ -569,7 +568,192 @@ else:
         def __getattr__(self, name):
             return self.get(name)
 
-    class FreeIPABaseModule(AnsibleModule):
+    class IPAAnsibleModule(AnsibleModule):
+        """
+        IPA Ansible Module.
+
+        This class is an extended version of the Ansible Module that provides
+        IPA specific methods to simplify module generation.
+
+        Simple example:
+
+        from ansible.module_utils.ansible_freeipa_module import \
+            IPAAnsibleModule
+
+        def main():
+            ansible_module = IPAAnsibleModule(
+                argument_spec=dict(
+                      name=dict(type="str", aliases=["cn"], default=None),
+                      state=dict(type="str", default="present",
+                                 choices=["present", "absent"]),
+                ),
+            )
+
+            # Get parameters
+            name = ansible_module.params_get("name")
+            state = ansible_module.params_get("state")
+
+            # Connect to IPA API
+            with ansible_module.ipa_connect():
+
+                # Execute command
+                if state == "present":
+                    ansible_module.ipa_command(["command_add", name, {}])
+                else:
+                    ansible_module.ipa_command(["command_del", name, {}])
+
+            # Done
+
+            ansible_module.exit_json(changed=True)
+
+        if __name__ == "__main__":
+            main()
+
+        """
+
+        def __init__(self, *args, **kwargs):
+            # Extend argument_spec with ipamodule_base_spec
+            if "argument_spec" in kwargs:
+                _spec = kwargs["argument_spec"]
+                _spec.update(ipamodule_base_spec)
+                kwargs["argument_spec"] = _spec
+
+            # pylint: disable=super-with-arguments
+            super(IPAAnsibleModule, self).__init__(*args, **kwargs)
+
+            # ipaadmin vars
+            self.ipaadmin_principal = self.params_get("ipaadmin_principal")
+            self.ipaadmin_password = self.params_get("ipaadmin_password")
+
+            # Attributes to store kerberos credentials (if needed)
+            self.ccache_dir = None
+            self.ccache_name = None
+
+        @contextmanager
+        def ipa_connect(self, context=None):
+            """
+            Create a context with a connection to IPA API.
+
+            Parameters
+            ----------
+            context: string
+                An optional parameter defining which context API
+                commands will be executed.
+
+            """
+            ccache_dir = None
+            ccache_name = None
+            try:
+                if not valid_creds(self, self.ipaadmin_principal):
+                    ccache_dir, ccache_name = temp_kinit(
+                        self.ipaadmin_principal, self.ipaadmin_password)
+                api_connect(context)
+            except Exception as e:
+                self.fail_json(msg=str(e))
+            else:
+                try:
+                    yield ccache_name
+                except Exception as e:
+                    self.fail_json(msg=str(e))
+                finally:
+                    temp_kdestroy(ccache_dir, ccache_name)
+
+        def params_get(self, name):
+            """
+            Retrieve value set for module parameter.
+
+            Parameters
+            ----------
+            name: string
+                The name of the parameter to retrieve.
+
+            """
+            return module_params_get(self, name)
+
+        def ipa_command(self, command, name, args):
+            """
+            Execute an IPA API command with a required `name` argument.
+
+            Parameters
+            ----------
+            command: string
+                The IPA API command to execute.
+            name: string
+                The name parameter to pass to the command.
+            args: dict
+                The parameters to pass to the command.
+
+            """
+            return api_command(self, command, name, args)
+
+        def ipa_command_no_name(self, command, args):
+            """
+            Execute an IPA API command requiring no `name` argument.
+
+            Parameters
+            ----------
+            command: string
+                The IPA API command to execute.
+            args: dict
+                The parameters to pass to the command.
+
+            """
+            return api_command_no_name(self, command, args)
+
+        @staticmethod
+        def ipa_get_domain():
+            """Retrieve IPA API domain."""
+            return api_get_domain()
+
+        @staticmethod
+        def ipa_get_realm():
+            """Retrieve IPA API realm."""
+            return api_get_realm()
+
+        @staticmethod
+        def ipa_command_exists(command):
+            """
+            Check if IPA command is supported.
+
+            Parameters
+            ----------
+            command: string
+                The IPA API command to verify.
+
+            """
+            return api_check_command(command)
+
+        @staticmethod
+        def ipa_command_param_exists(command, name):
+            """
+            Check if IPA command support a specific parameter.
+
+            Parameters
+            ----------
+            command: string
+                The IPA API command to test.
+            name: string
+                The parameter name to verify.
+
+            """
+            return api_check_param(command, name)
+
+        @staticmethod
+        def ipa_check_version(oper, requested_version):
+            """
+            Compare available IPA version.
+
+            Parameters
+            ----------
+            oper: string
+                The relational operator to use.
+            requested_version: string
+                The version to compare to.
+
+            """
+            return api_check_ipa_version(oper, requested_version)
+
+    class FreeIPABaseModule(IPAAnsibleModule):
         """
         Base class for FreeIPA Ansible modules.
 
@@ -642,10 +826,6 @@ else:
             # pylint: disable=super-with-arguments
             super(FreeIPABaseModule, self).__init__(*args, **kwargs)
 
-            # Attributes to store kerberos credentials (if needed)
-            self.ccache_dir = None
-            self.ccache_name = None
-
             # Status of an execution. Will be changed to True
             #   if something is actually peformed.
             self.changed = False
@@ -724,64 +904,6 @@ else:
             """Define commands that will be run in IPA server."""
             raise NotImplementedError
 
-        def api_command(self, command, name=None, args=None):
-            """Execute a single command in IPA server."""
-            if args is None:
-                args = {}
-
-            if name is None:
-                return api_command_no_name(self, command, args)
-
-            return api_command(self, command, name, args)
-
-        def __enter__(self):
-            """
-            Connect to IPA server.
-
-            Check the there are working Kerberos credentials to connect to
-            IPA server. If there are not we perform a temporary kinit
-            that will be terminated when exiting the context.
-
-            If the connection fails ``ipa_connected`` attribute will be set
-            to False.
-            """
-            principal = self.ipa_params.ipaadmin_principal
-            password = self.ipa_params.ipaadmin_password
-
-            try:
-                if not valid_creds(self, principal):
-                    self.ccache_dir, self.ccache_name = temp_kinit(
-                        principal, password,
-                    )
-
-                api_connect()
-
-            except Exception as excpt:
-                self.fail_json(msg=str(excpt))
-            else:
-                self.ipa_connected = True
-
-            return self
-
-        def __exit__(self, exc_type, exc_val, exc_tb):
-            """
-            Terminate a connection with the IPA server.
-
-            Deal with exceptions, destroy temporary kinit credentials and
-            exit the module with proper arguments.
-
-            """
-            # TODO: shouldn't we also disconnect from api backend?
-            temp_kdestroy(self.ccache_dir, self.ccache_name)
-
-            if exc_type == SystemExit:
-                raise
-
-            if exc_val:
-                self.fail_json(msg=str(exc_val))
-
-            self.exit_json(changed=self.changed, **self.exit_args)
-
         def get_command_errors(self, command, result):
             """Look for erros into command results."""
             # Get all errors
@@ -815,7 +937,7 @@ else:
 
             for name, command, args in self.ipa_commands:
                 try:
-                    result = self.api_command(command, name, args)
+                    result = self.ipa_command(command, name, args)
                 except Exception as excpt:
                     self.fail_json(msg="%s: %s: %s" % (command, name,
                                                        str(excpt)))
@@ -847,122 +969,10 @@ else:
             equal = compare_args_ipa(self, command_args, ipa_attrs)
             return not equal
 
-        def pdebug(self, value):
-            """Debug with pretty formatting."""
-            self.debug(pformat(value))
-
         def ipa_run(self):
             """Execute module actions."""
-            with self:
-                if not self.ipa_connected:
-                    return
-
+            with self.ipa_connect():
                 self.check_ipa_params()
                 self.define_ipa_commands()
                 self._run_ipa_commands()
-
-    class IPAAnsibleModule(AnsibleModule):
-        """
-        IPA Ansible Module.
-
-        This class is an extended version of the Ansible Module that provides
-        IPA specific methods to simplify module generation.
-
-        Simple example:
-
-        from ansible.module_utils.ansible_freeipa_module import \
-            IPAAnsibleModule
-
-        def main():
-            ansible_module = IPAAnsibleModule(
-                argument_spec=dict(
-                      name=dict(type="str", aliases=["cn"], default=None),
-                      state=dict(type="str", default="present",
-                                 choices=["present", "absent"]),
-                ),
-            )
-
-            # Get parameters
-            name = ansible_module.params_get("name")
-            state = ansible_module.params_get("state")
-
-            # Connect to IPA API
-            with ansible_module.ipa_connect():
-
-                # Execute command
-                if state == "present":
-                    ansible_module.ipa_command(["command_add", name, {}])
-                else:
-                    ansible_module.ipa_command(["command_del", name, {}])
-
-            # Done
-
-            ansible_module.exit_json(changed=True)
-
-        if __name__ == "__main__":
-            main()
-
-        """
-
-        def __init__(self, *args, **kwargs):
-            # Extend argument_spec with ipamodule_base_spec
-            if "argument_spec" in kwargs:
-                _spec = kwargs["argument_spec"]
-                _spec.update(ipamodule_base_spec)
-                kwargs["argument_spec"] = _spec
-
-            # pylint: disable=super-with-arguments
-            super(IPAAnsibleModule, self).__init__(*args, **kwargs)
-
-            # ipaadmin vars
-            self.ipaadmin_principal = self.params_get("ipaadmin_principal")
-            self.ipaadmin_password = self.params_get("ipaadmin_password")
-
-            # Attributes to store kerberos credentials (if needed)
-            self.ccache_dir = None
-            self.ccache_name = None
-
-        @contextmanager
-        def ipa_connect(self, context=None):
-            ccache_dir = None
-            ccache_name = None
-            try:
-                if not valid_creds(self, self.ipaadmin_principal):
-                    ccache_dir, ccache_name = temp_kinit(
-                        self.ipaadmin_principal, self.ipaadmin_password)
-                api_connect(context)
-            except Exception as e:
-                self.fail_json(msg=str(e))
-            else:
-                try:
-                    yield ccache_name
-                except Exception as e:
-                    self.fail_json(msg=str(e))
-                finally:
-                    temp_kdestroy(ccache_dir, ccache_name)
-
-        def params_get(self, name):
-            return module_params_get(self, name)
-
-        def ipa_command(self, command, name, args):
-            return api_command(self, command, name, args)
-
-        def ipa_command_no_name(self, command, args):
-            return api_command_no_name(self, command, args)
-
-        def ipa_get_domain(self):  # pylint: disable=R0201
-            return api_get_domain()
-
-        def ipa_get_realm(self):  # pylint: disable=R0201
-            return api_get_realm()
-
-        def ipa_command_exists(self, command):  # pylint: disable=R0201
-            return api_check_command(command)
-
-        # pylint: disable=R0201
-        def ipa_command_param_exists(self, command, name):
-            return api_check_param(command, name)
-
-        # pylint: disable=R0201
-        def ipa_check_version(self, oper, requested_version):
-            return api_check_ipa_version(oper, requested_version)
+            self.exit_json(changed=self.changed, **self.exit_args)