Skip to content

Commit

Permalink
ipagroup: Add support for renaming groups
Browse files Browse the repository at this point in the history
FreeIPA suports renaming groupobjects with the CLI parameter "rename",
and this parameter was missing in ansible-freeipa ipagroup module.

This patch adds support for a new state 'renamed' and the 'rename'
parameter.

Tests were updated to cope with the changes.
  • Loading branch information
rjeffman committed Dec 20, 2023
1 parent 3fe41a5 commit 1ecdbd3
Show file tree
Hide file tree
Showing 4 changed files with 167 additions and 21 deletions.
45 changes: 43 additions & 2 deletions README-group.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,45 @@ And ensure the presence of the groups with this example playbook:
groups: "{{ groups }}"
```

Example playbook to rename a group:

```yaml
---
- name: Playbook to rename a single group
hosts: ipaserver
become: false
gather_facts: false
tasks:
- name: Rename group appops to webops
ipagroup:
ipaadmin_password: SomeADMINpassword
name: appops
rename: webops
state: renamed
```

Several groups can also be renamed with a single task, as in the example playbook:

```yaml
---
- name: Playbook to rename multiple groups
hosts: ipaserver
become: false
gather_facts: false
tasks:
- name Rename group1 to newgroup1 and group2 to newgroup2
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: group1
rename: newgroup1
- name: group2
rename: newgroup2
state: renamed
```

Example playbook to add users to a group:

```yaml
Expand Down Expand Up @@ -262,11 +301,13 @@ Variable | Description | Required
`membermanager_group` | List of member manager groups assigned to this group. Only usable with IPA versions 4.8.4 and up. | no
`externalmember` \| `ipaexternalmember` \| `external_member`| List of members of a trusted domain in DOM\\name or name@domain form. | no
`idoverrideuser` | List of user ID overrides to manage. Only usable with IPA versions 4.8.7 and up.| no
`rename` \| `new_name` | Rename the user object to the new name string. Only usable with `state: renamed`. | no
`action` | Work on group or member level. It can be on of `member` or `group` and defaults to `group`. | no
`state` | The state to ensure. It can be one of `present` or `absent`, default: `present`. | yes
`state` | The state to ensure. It can be one of `present`, `absent` or `renamed`, default: `present`. | yes


Authors
=======

Thomas Woerner
- Thomas Woerner
- Rafael Jeffman
62 changes: 46 additions & 16 deletions plugins/modules/ipagroup.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@
required: false
type: list
elements: str
rename:
description: Rename the group object
required: false
type: str
aliases: ["new_name"]
description:
description: The group description
type: str
Expand Down Expand Up @@ -198,11 +203,16 @@
type: str
default: group
choices: ["member", "group"]
rename:
description: Rename the group object
required: false
type: str
aliases: ["new_name"]
state:
description: State to ensure
type: str
default: present
choices: ["present", "absent"]
choices: ["present", "absent", "renamed"]
author:
- Thomas Woerner (@t-woerner)
"""
Expand Down Expand Up @@ -267,6 +277,13 @@
group:
- group2
# Rename a group
- ipagroup:
ipaadmin_password: SomeADMINpassword
name: oldname
rename: newestname
state: renamed
# Create a non-POSIX group
- ipagroup:
ipaadmin_password: SomeADMINpassword
Expand Down Expand Up @@ -380,18 +397,20 @@ def gen_member_args(user, group, service, externalmember, idoverrideuser):


def check_parameters(module, state, action):
invalid = []
if state == "present":
invalid = ["description", "gid", "posix", "nonposix", "external",
"nomembers"]
if action == "group":
if state == "present":
invalid = []
elif state == "absent":
invalid.extend(["user", "group", "service", "externalmember"])
if state == "renamed":
if action == "member":
invalid = ["description", "gid", "posix", "nonposix", "external",
"nomembers"]

module.fail_json(
msg="Action member can not be used with state: renamed.")
invalid.extend(["user", "group", "service", "externalmember"])
else:
invalid = ["description", "gid", "posix", "nonposix", "external",
"nomembers"]
if action == "group":
invalid.extend(["user", "group", "service", "externalmember"])

invalid.append("rename")
module.params_fail_used_invalid(invalid, state, action)


Expand Down Expand Up @@ -448,7 +467,9 @@ def main():
aliases=[
"ipaexternalmember",
"external_member"
])
]),
rename=dict(type="str", required=False, default=None,
aliases=["new_name"]),
)
ansible_module = IPAAnsibleModule(
argument_spec=dict(
Expand All @@ -470,7 +491,7 @@ def main():
action=dict(type="str", default="group",
choices=["member", "group"]),
state=dict(type="str", default="present",
choices=["present", "absent"]),
choices=["present", "absent", "renamed"]),

# Add group specific parameters for simple use case
**group_spec
Expand Down Expand Up @@ -506,8 +527,10 @@ def main():
membermanager_user = ansible_module.params_get("membermanager_user")
membermanager_group = ansible_module.params_get("membermanager_group")
externalmember = ansible_module.params_get("externalmember")
# rename
rename = ansible_module.params_get("rename")
# state and action
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")

# Check parameters
Expand All @@ -516,10 +539,11 @@ def main():
(groups is None or len(groups) < 1):
ansible_module.fail_json(msg="At least one name or groups is required")

if state == "present":
if state in ["present", "renamed"]:
if names is not None and len(names) != 1:
what = "renamed" if state == "renamed" else "added"
ansible_module.fail_json(
msg="Only one group can be added at a time using 'name'.")
msg="Only one group can be %s at a time using 'name'." % what)

check_parameters(ansible_module, state, action)

Expand Down Expand Up @@ -633,6 +657,7 @@ def main():
membermanager_group = group_name.get("membermanager_group")
externalmember = group_name.get("externalmember")
nomembers = group_name.get("nomembers")
rename = group_name.get("rename")

check_parameters(ansible_module, state, action)

Expand Down Expand Up @@ -794,6 +819,11 @@ def main():
membermanager_group,
res_find.get("membermanager_group")
)
elif state == "renamed":
if res_find is None:
ansible_module.fail_json(msg="No group '%s'" % name)
elif rename != name:
commands.append([name, 'group_mod', {"rename": rename}])
else:
ansible_module.fail_json(msg="Unkown state '%s'" % state)

Expand Down
34 changes: 33 additions & 1 deletion tests/group/test_group.yml
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@

- name: Ensure group group3, group2 and group1 are absent
ipagroup:
name: group3,group2,group1
name: groupren,group3,group2,group1
state: absent

# CREATE TEST ITEMS
Expand Down Expand Up @@ -65,6 +65,38 @@
register: result
failed_when: result.changed or result.failed

- name: Rename group1 to groupren
ipagroup:
name: group1
rename: groupren
state: renamed
register: result
failed_when: not result.changed or result.failed

- name: Rename group1 to groupren
ipagroup:
name: group1
rename: groupren
state: renamed
register: result
failed_when: not result.failed or "No group 'group1'" not in result.msg

- name: Rename group groupren to groupren
ipagroup:
name: groupren
rename: groupren
state: renamed
register: result
failed_when: result.changed or result.failed

- name: Rename group groupren back to group1
ipagroup:
name: groupren
rename: group1
state: renamed
register: result
failed_when: not result.changed or result.failed

- name: Ensure group2 is present
ipagroup:
name: group2
Expand Down
47 changes: 45 additions & 2 deletions tests/group/test_groups.yml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
- name: Remove test groups
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group1,group2,group3,group4,group5,group6,group7,group8,group9,group10
name: group1,group2,group3,group4,group5,group6,group7,group8,group9,group10,newgroup1,newgroup2
state: absent

- name: Remove test users
Expand Down Expand Up @@ -130,10 +130,53 @@
register: result
failed_when: result.changed or not result.failed or "Only one group can be added at a time using 'name'." not in result.msg

- name: Ensure group1 and group2 exist
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: group1
- name: group2

- name: Rename group1 and group2 to newgroup1 and newgroup2, respectively
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: group1
rename: newgroup1
- name: group2
rename: newgroup2
state: renamed
register: result
failed_when: not result.changed or result.failed

- name: Rename newgroup1 and newgroup2 to the same name
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: newgroup1
rename: newgroup1
- name: newgroup2
rename: newgroup2
state: renamed
register: result
failed_when: result.changed or result.failed

- name: Rename newgroup1 and newgroup2 back to group1 and group2, respectively
ipagroup:
ipaadmin_password: SomeADMINpassword
groups:
- name: newgroup1
rename: group1
- name: newgroup2
rename: group2
state: renamed
register: result
failed_when: not result.changed or result.failed

- name: Remove test groups
ipagroup:
ipaadmin_password: SomeADMINpassword
name: group1,group2,group3,group4,group5,group6,group7,group8,group9,group10
name: group1,group2,group3,group4,group5,group6,group7,group8,group9,group10,newgroup1,newgroup2
state: absent

- name: Remove test users
Expand Down

0 comments on commit 1ecdbd3

Please sign in to comment.