diff --git a/README-hostgroup.md b/README-hostgroup.md
index e021d89a444af71119b4abcf468f5a50b491eb59..cedca7e2729b0fcb0b00b65450bd107e47133570 100644
--- a/README-hostgroup.md
+++ b/README-hostgroup.md
@@ -19,6 +19,8 @@ Supported FreeIPA Versions
 
 FreeIPA versions 4.4.0 and up are supported by the ipahostgroup module.
 
+Some variables are only supported on newer versions of FreeIPA. Check `Variables` section for details.
+
 
 Requirements
 ------------
@@ -105,6 +107,23 @@ Example playbook to make sure hosts and hostgroups are absent in databases hostg
       state: absent
 ```
 
+Example playbook to rename an existing playbook:
+
+```yaml
+---
+- name: Playbook to handle hostgroups
+  hosts: ipaserver
+  become: true
+
+  tasks:
+  # Ensure host-group databases is absent
+  - ipahostgroup:
+      ipaadmin_password: SomeADMINpassword
+      name: databases
+      rename: datalake
+      state: renamed
+```
+
 Example playbook to make sure host-group databases is absent:
 
 ```yaml
@@ -121,7 +140,6 @@ Example playbook to make sure host-group databases is absent:
       state: absent
 ```
 
-
 Variables
 =========
 
@@ -139,8 +157,9 @@ Variable | Description | Required
 `hostgroup` | List of hostgroup name strings assigned to this hostgroup. | no
 `membermanager_user` | List of member manager users assigned to this hostgroup. Only usable with IPA versions 4.8.4 and up. | no
 `membermanager_group` | List of member manager groups assigned to this hostgroup. Only usable with IPA versions 4.8.4 and up. | no
+`rename` \| `new_name` | Rename hostgroup to the provided name. Only usable with IPA versions 4.8.7 and up. | no
 `action` | Work on hostgroup or member level. It can be on of `member` or `hostgroup` and defaults to `hostgroup`. | no
-`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | no
+`state` | The state to ensure. It can be one of `present`, `absent` or `renamed`, default: `present`. | no
 
 
 Authors
diff --git a/playbooks/hostgroup/rename-hostgroup.yml b/playbooks/hostgroup/rename-hostgroup.yml
new file mode 100644
index 0000000000000000000000000000000000000000..53937aa150c2f83a56691e7955c89f6ce991e51b
--- /dev/null
+++ b/playbooks/hostgroup/rename-hostgroup.yml
@@ -0,0 +1,12 @@
+---
+- name: Playbook to handle hostgroups
+  hosts: ipaserver
+  become: yes
+
+  tasks:
+  - name : Rename host-group from `databases` to `datalake`
+    ipahostgroup:
+      ipaadmin_password: SomeADMINpassword
+      name: databases
+      rename: datalake
+      state: renamed
diff --git a/plugins/modules/ipahostgroup.py b/plugins/modules/ipahostgroup.py
index 4c18e940e61d481a2ac990f739178a19eaddc0c1..8616fbaac0ce1e85d95cca15844e15252e9098a0 100644
--- a/plugins/modules/ipahostgroup.py
+++ b/plugins/modules/ipahostgroup.py
@@ -70,6 +70,12 @@ options:
     - Only usable with IPA versions 4.8.4 and up.
     required: false
     type: list
+  rename:
+    description:
+    - Rename hostgroup to the given name.
+    - Only usable with IPA versions 4.8.7 and up.
+    required: false
+    aliases: ["new_name"]
   action:
     description: Work on hostgroup or member level
     default: hostgroup
@@ -77,7 +83,7 @@ options:
   state:
     description: State to ensure
     default: present
-    choices: ["present", "absent"]
+    choices: ["present", "absent", "renamed"]
 author:
     - Thomas Woerner
 """
@@ -116,6 +122,12 @@ EXAMPLES = """
     action: member
     state: absent
 
+# Rename hostgroup
+- ipahostgroup:
+    ipaadmin_password: SomeADMINpassword
+    name: databases
+    rename: datalake
+
 # Ensure host-group databases is absent
 - ipahostgroup:
     ipaadmin_password: SomeADMINpassword
@@ -129,7 +141,7 @@ 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, gen_add_del_lists, api_check_command
+    module_params_get, gen_add_del_lists, api_check_command, api_check_param
 
 
 def find_hostgroup(module, name):
@@ -149,12 +161,14 @@ def find_hostgroup(module, name):
         return None
 
 
-def gen_args(description, nomembers):
+def gen_args(description, nomembers, rename):
     _args = {}
     if description is not None:
         _args["description"] = description
     if nomembers is not None:
         _args["nomembers"] = nomembers
+    if rename is not None:
+        _args["rename"] = rename
 
     return _args
 
@@ -186,11 +200,13 @@ def main():
             membermanager_user=dict(required=False, type='list', default=None),
             membermanager_group=dict(required=False, type='list',
                                      default=None),
+            rename=dict(required=False, type='str', default=None,
+                        aliases=["new_name"]),
             action=dict(type="str", default="hostgroup",
                         choices=["member", "hostgroup"]),
             # state
             state=dict(type="str", default="present",
-                       choices=["present", "absent"]),
+                       choices=["present", "absent", "renamed"]),
         ),
         supports_check_mode=True,
     )
@@ -215,6 +231,7 @@ def main():
                                            "membermanager_user")
     membermanager_group = module_params_get(ansible_module,
                                             "membermanager_group")
+    rename = module_params_get(ansible_module, "rename")
     action = module_params_get(ansible_module, "action")
     # state
     state = module_params_get(ansible_module, "state")
@@ -222,22 +239,41 @@ def main():
     # Check parameters
 
     if state == "present":
+        if len(names) != 1:
+            ansible_module.fail_json(
+                msg="Only one hostgroup can be added at a time.")
+        invalid = ["rename"]
+        if action == "member":
+            invalid.extend(["description", "nomembers"])
+        for x in invalid:
+            if vars()[x] is not None:
+                ansible_module.fail_json(
+                    msg="Argument '%s' can not be used with action "
+                    "'%s'" % (x, action))
+
+    if state == "renamed":
         if len(names) != 1:
             ansible_module.fail_json(
                 msg="Only one hostgroup can be added at a time.")
         if action == "member":
-            invalid = ["description", "nomembers"]
-            for x in invalid:
-                if vars()[x] is not None:
-                    ansible_module.fail_json(
-                        msg="Argument '%s' can not be used with action "
-                        "'%s'" % (x, action))
+            ansible_module.fail_json(
+                msg="Action '%s' can not be used with state '%s'" %
+                (action, state))
+        invalid = [
+            "description", "nomembers", "host", "hostgroup",
+            "membermanager_user", "membermanager_group"
+        ]
+        for x in invalid:
+            if vars()[x] is not None:
+                ansible_module.fail_json(
+                    msg="Argument '%s' can not be used with state '%s'" %
+                    (x, state))
 
     if state == "absent":
         if len(names) < 1:
             ansible_module.fail_json(
                 msg="No name given.")
-        invalid = ["description", "nomembers"]
+        invalid = ["description", "nomembers", "rename"]
         if action == "hostgroup":
             invalid.extend(["host", "hostgroup"])
         for x in invalid:
@@ -266,6 +302,10 @@ def main():
                 msg="Managing a membermanager user or group is not supported "
                 "by your IPA version"
             )
+        has_mod_rename = api_check_param("hostgroup_mod", "rename")
+        if not has_mod_rename and rename is not None:
+            ansible_module.fail_json(
+                msg="Renaming hostgroups is not supported by your IPA version")
 
         commands = []
 
@@ -276,7 +316,7 @@ def main():
             # Create command
             if state == "present":
                 # Generate args
-                args = gen_args(description, nomembers)
+                args = gen_args(description, nomembers, rename)
 
                 if action == "hostgroup":
                     # Found the hostgroup
@@ -375,6 +415,22 @@ def main():
                                  }]
                             )
 
+            elif state == "renamed":
+                if res_find is not None:
+                    if rename != name:
+                        commands.append(
+                            [name, "hostgroup_mod", {"rename": rename}]
+                        )
+                else:
+                    # If a hostgroup with the desired name exists, do nothing.
+                    new_find = find_hostgroup(ansible_module, rename)
+                    if new_find is None:
+                        # Fail only if the either hostsgroups do not exist.
+                        ansible_module.fail_json(
+                            msg="Attribute `rename` can not be used, unless "
+                                "hostgroup exists."
+                        )
+
             elif state == "absent":
                 if action == "hostgroup":
                     if res_find is not None:
diff --git a/tests/hostgroup/test_hostgroup_rename.yml b/tests/hostgroup/test_hostgroup_rename.yml
new file mode 100644
index 0000000000000000000000000000000000000000..8d13338fa5a907f6738518d1af741e3f0c9b70cd
--- /dev/null
+++ b/tests/hostgroup/test_hostgroup_rename.yml
@@ -0,0 +1,105 @@
+---
+- name: Test hostgroup
+  hosts: ipaserver
+  become: true
+  gather_facts: false
+
+  tasks:
+  - name: Ensure testing host-group are absent
+    ipahostgroup:
+      ipaadmin_password: SomeADMINpassword
+      name:
+      - databases
+      - datalake
+      - inexistenthostgroup
+      state: absent
+
+  - name: Ensure host-group databases is present
+    ipahostgroup:
+      ipaadmin_password: SomeADMINpassword
+      name: databases
+      state: present
+    register: result
+    failed_when: not result.changed
+
+  - name: Rename host-group from `databases` to `datalake`
+    ipahostgroup:
+      ipaadmin_password: SomeADMINpassword
+      name: databases
+      rename: datalake
+      state: renamed
+    register: result
+    failed_when: not result.changed
+
+  - name: Ensure host-group database was already absent
+    ipahostgroup:
+      ipaadmin_password: SomeADMINpassword
+      name: database
+      state: absent
+    register: result
+    failed_when: result.changed
+
+  - name: Rename host-group from `databases` to `datalake`, again
+    ipahostgroup:
+      ipaadmin_password: SomeADMINpassword
+      name: databases
+      rename: datalake
+      state: renamed
+    register: result
+    failed_when: result.changed or result.failed
+
+  - name: Rename host-group with same name.
+    ipahostgroup:
+      ipaadmin_password: SomeADMINpassword
+      name: datalake
+      rename: datalake
+      state: renamed
+    register: result
+    failed_when: result.changed
+
+  - name: Ensure testing hostgroups do not exist.
+    ipahostgroup:
+      ipaadmin_password: SomeADMINpassword
+      name: inexistenthostgroup,alsoinexistent
+      state: absent
+
+  - name: Rename inexistent host-group to an existing one.
+    ipahostgroup:
+      ipaadmin_password: SomeADMINpassword
+      name: inexistenthostgroup
+      rename: datalake
+      state: renamed
+    register: result
+    failed_when: result.changed or result.failed
+
+  - name: Rename inexistent host-group to a non-existing one.
+    ipahostgroup:
+      ipaadmin_password: SomeADMINpassword
+      name: inexistenthostgroup
+      rename: alsoinexistent
+      state: renamed
+    register: result
+    failed_when: not result.failed or "Attribute `rename` can not be used, unless hostgroup exists." not in result.msg
+
+  - name: Ensure host-group databases is present
+    ipahostgroup:
+      ipaadmin_password: SomeADMINpassword
+      name: databases
+      state: present
+
+  - name: Rename host-group to an existing one.
+    ipahostgroup:
+      ipaadmin_password: SomeADMINpassword
+      name: databases
+      rename: datalake
+      state: renamed
+    register: result
+    failed_when: not result.failed or "This entry already exists" not in result.msg
+
+  - name: Ensure host-group databases and datalake are absent
+    ipahostgroup:
+      ipaadmin_password: SomeADMINpassword
+      name:
+      - databases
+      - datalake
+      state: absent