mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-03-26 21:33:05 +00:00
ipauser: Add support for renaming users
FreeIPA suports renaming user objects with the CLI parameter "rename", and this parameter was missing in ansible-freeipa ipauser module. This patch adds support for a new state 'renamed' and the 'rename' parameter. Tests were updated to cope with the changes. Related to RHBZ#2234379, RHBZ#2234380 Fixes #1103
This commit is contained in:
@@ -279,7 +279,6 @@ Example playbook to disable a user:
|
||||
|
||||
This can also be done as an alternative with the `users` variable containing only names.
|
||||
|
||||
|
||||
Example playbook to enable users:
|
||||
|
||||
```yaml
|
||||
@@ -298,6 +297,22 @@ Example playbook to enable users:
|
||||
|
||||
This can also be done as an alternative with the `users` variable containing only names.
|
||||
|
||||
Example playbook to rename users:
|
||||
|
||||
```yaml
|
||||
---
|
||||
- name: Playbook to handle users
|
||||
hosts: ipaserver
|
||||
become: true
|
||||
|
||||
tasks:
|
||||
# Rename user pinky to reddy
|
||||
- ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: pinky
|
||||
rename: reddy
|
||||
state: enabled
|
||||
```
|
||||
|
||||
Example playbook to unlock users:
|
||||
|
||||
@@ -401,7 +416,7 @@ Variable | Description | Required
|
||||
`update_password` | Set password for a user in present state only on creation or always. It can be one of `always` or `on_create` and defaults to `always`. | no
|
||||
`preserve` | Delete a user, keeping the entry available for future use. (bool) | no
|
||||
`action` | Work on user or member level. It can be on of `member` or `user` and defaults to `user`. | no
|
||||
`state` | The state to ensure. It can be one of `present`, `absent`, `enabled`, `disabled`, `unlocked` or `undeleted`, default: `present`. Only `names` or `users` with only `name` set are allowed if state is not `present`. | yes
|
||||
`state` | The state to ensure. It can be one of `present`, `absent`, `enabled`, `disabled`, `renamed`, `unlocked` or `undeleted`, default: `present`. Only `names` or `users` with only `name` set are allowed if state is not `present`. | yes
|
||||
|
||||
|
||||
|
||||
@@ -458,10 +473,10 @@ Variable | Description | Required
|
||||
`smb_profile_path:` \| `ipantprofilepath` | SMB profile path, in UNC format. Requires FreeIPA version 4.8.0+. | no
|
||||
`smb_home_dir` \| `ipanthomedirectory` | SMB Home Directory, in UNC format. Requires FreeIPA version 4.8.0+. | no
|
||||
`smb_home_drive` \| `ipanthomedirectorydrive` | SMB Home Directory Drive, a single upercase letter (A-Z) followed by a colon (:), for example "U:". Requires FreeIPA version 4.8.0+. | no
|
||||
`rename` \| `new_name` | Rename the user object to the new name string. Only usable with `state: renamed`. | no
|
||||
`nomembers` | Suppress processing of membership attributes. (bool) | no
|
||||
|
||||
|
||||
|
||||
Return Values
|
||||
=============
|
||||
|
||||
@@ -477,5 +492,5 @@ Variable | Description | Returned When
|
||||
Authors
|
||||
=======
|
||||
|
||||
Thomas Woerner
|
||||
Rafael Jeffman
|
||||
- Thomas Woerner
|
||||
- Rafael Jeffman
|
||||
|
||||
@@ -319,6 +319,11 @@ options:
|
||||
description: Suppress processing of membership attributes
|
||||
required: false
|
||||
type: bool
|
||||
rename:
|
||||
description: Rename the user object
|
||||
required: false
|
||||
type: str
|
||||
aliases: ["new_name"]
|
||||
required: false
|
||||
first:
|
||||
description: The first name. Required if user does not exist.
|
||||
@@ -586,6 +591,11 @@ options:
|
||||
description: Suppress processing of membership attributes
|
||||
required: false
|
||||
type: bool
|
||||
rename:
|
||||
description: Rename the user object
|
||||
required: false
|
||||
type: str
|
||||
aliases: ["new_name"]
|
||||
preserve:
|
||||
description: Delete a user, keeping the entry available for future use
|
||||
required: false
|
||||
@@ -607,7 +617,8 @@ options:
|
||||
default: present
|
||||
choices: ["present", "absent",
|
||||
"enabled", "disabled",
|
||||
"unlocked", "undeleted"]
|
||||
"unlocked", "undeleted",
|
||||
"renamed"]
|
||||
author:
|
||||
- Thomas Woerner (@t-woerner)
|
||||
"""
|
||||
@@ -694,6 +705,13 @@ EXAMPLES = """
|
||||
smb_profile_path: \\\\server\\profiles\\some_profile
|
||||
smb_home_dir: \\\\users\\home\\smbuser
|
||||
smb_home_drive: "U:"
|
||||
|
||||
# Rename an existing user
|
||||
- ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: someuser
|
||||
rename: anotheruser
|
||||
state: renamed
|
||||
"""
|
||||
|
||||
RETURN = """
|
||||
@@ -857,7 +875,7 @@ def check_parameters( # pylint: disable=unused-argument
|
||||
employeenumber, employeetype, preferredlanguage, certificate,
|
||||
certmapdata, noprivate, nomembers, preserve, update_password,
|
||||
smb_logon_script, smb_profile_path, smb_home_dir, smb_home_drive,
|
||||
idp, ipa_user_id,
|
||||
idp, ipa_user_id, rename
|
||||
):
|
||||
if state == "present" and action == "user":
|
||||
invalid = ["preserve"]
|
||||
@@ -885,6 +903,19 @@ def check_parameters( # pylint: disable=unused-argument
|
||||
module.fail_json(
|
||||
msg="Preserve is only possible for state=absent")
|
||||
|
||||
if state != "renamed":
|
||||
invalid.append("rename")
|
||||
else:
|
||||
invalid.extend([
|
||||
"preserve", "principal", "manager", "certificate", "certmapdata",
|
||||
])
|
||||
if not rename:
|
||||
module.fail_json(
|
||||
msg="A value for attribute 'rename' must be provided.")
|
||||
if action == "member":
|
||||
module.fail_json(
|
||||
msg="Action member can not be used with state: renamed.")
|
||||
|
||||
module.params_fail_used_invalid(invalid, state, action)
|
||||
|
||||
if certmapdata is not None:
|
||||
@@ -1097,6 +1128,8 @@ def main():
|
||||
idp=dict(type="str", default=None, aliases=['ipaidpconfiglink']),
|
||||
idp_user_id=dict(type="str", default=None,
|
||||
aliases=['ipaidpconfiglink']),
|
||||
rename=dict(type="str", required=False, default=None,
|
||||
aliases=["new_name"]),
|
||||
)
|
||||
|
||||
ansible_module = IPAAnsibleModule(
|
||||
@@ -1128,7 +1161,7 @@ def main():
|
||||
choices=["member", "user"]),
|
||||
state=dict(type="str", default="present",
|
||||
choices=["present", "absent", "enabled", "disabled",
|
||||
"unlocked", "undeleted"]),
|
||||
"unlocked", "undeleted", "renamed"]),
|
||||
|
||||
# Add user specific parameters for simple use case
|
||||
**user_spec
|
||||
@@ -1209,6 +1242,8 @@ def main():
|
||||
preserve = ansible_module.params_get("preserve")
|
||||
# mod
|
||||
update_password = ansible_module.params_get("update_password")
|
||||
# rename
|
||||
rename = ansible_module.params_get("rename")
|
||||
# general
|
||||
action = ansible_module.params_get("action")
|
||||
state = ansible_module.params_get("state")
|
||||
@@ -1219,27 +1254,30 @@ def main():
|
||||
(users is None or len(users) < 1):
|
||||
ansible_module.fail_json(msg="One of name and users is required")
|
||||
|
||||
if state == "present":
|
||||
if state in ["present", "renamed"]:
|
||||
if names is not None and len(names) != 1:
|
||||
act = "renamed" if state == "renamed" else "added"
|
||||
ansible_module.fail_json(
|
||||
msg="Only one user can be added at a time using name.")
|
||||
|
||||
check_parameters(
|
||||
ansible_module, state, action,
|
||||
first, last, fullname, displayname, initials, homedir, gecos, shell,
|
||||
email,
|
||||
principal, principalexpiration, passwordexpiration, password, random,
|
||||
uid, gid, street, city, phone, mobile, pager, fax, orgunit, title,
|
||||
manager, carlicense, sshpubkey, userauthtype, userclass, radius,
|
||||
radiususer, departmentnumber, employeenumber, employeetype,
|
||||
preferredlanguage, certificate, certmapdata, noprivate, nomembers,
|
||||
preserve, update_password, smb_logon_script, smb_profile_path,
|
||||
smb_home_dir, smb_home_drive, idp, idp_user_id)
|
||||
certmapdata = convert_certmapdata(certmapdata)
|
||||
msg="Only one user can be %s at a time using name." % (act))
|
||||
|
||||
# Use users if names is None
|
||||
if users is not None:
|
||||
names = users
|
||||
else:
|
||||
check_parameters(
|
||||
ansible_module, state, action,
|
||||
first, last, fullname, displayname, initials, homedir, gecos,
|
||||
shell, email,
|
||||
principal, principalexpiration, passwordexpiration, password,
|
||||
random,
|
||||
uid, gid, street, city, phone, mobile, pager, fax, orgunit, title,
|
||||
manager, carlicense, sshpubkey, userauthtype, userclass, radius,
|
||||
radiususer, departmentnumber, employeenumber, employeetype,
|
||||
preferredlanguage, certificate, certmapdata, noprivate, nomembers,
|
||||
preserve, update_password, smb_logon_script, smb_profile_path,
|
||||
smb_home_dir, smb_home_drive, idp, idp_user_id, rename,
|
||||
)
|
||||
certmapdata = convert_certmapdata(certmapdata)
|
||||
|
||||
# Init
|
||||
|
||||
@@ -1330,6 +1368,7 @@ def main():
|
||||
smb_home_drive = user.get("smb_home_drive")
|
||||
idp = user.get("idp")
|
||||
idp_user_id = user.get("idp_user_id")
|
||||
rename = user.get("rename")
|
||||
certificate = user.get("certificate")
|
||||
certmapdata = user.get("certmapdata")
|
||||
noprivate = user.get("noprivate")
|
||||
@@ -1346,7 +1385,8 @@ def main():
|
||||
employeetype, preferredlanguage, certificate,
|
||||
certmapdata, noprivate, nomembers, preserve,
|
||||
update_password, smb_logon_script, smb_profile_path,
|
||||
smb_home_dir, smb_home_drive, idp, idp_user_id)
|
||||
smb_home_dir, smb_home_drive, idp, idp_user_id, rename,
|
||||
)
|
||||
certmapdata = convert_certmapdata(certmapdata)
|
||||
|
||||
# Check API specific parameters
|
||||
@@ -1737,6 +1777,12 @@ def main():
|
||||
else:
|
||||
raise ValueError("No user '%s'" % name)
|
||||
|
||||
elif state == "renamed":
|
||||
if res_find is None:
|
||||
ansible_module.fail_json(msg="No user '%s'" % name)
|
||||
else:
|
||||
if rename != name:
|
||||
commands.append([name, 'user_mod', {"rename": rename}])
|
||||
else:
|
||||
ansible_module.fail_json(msg="Unkown state '%s'" % state)
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: manager1,manager2,manager3,pinky,pinky2,igagarin
|
||||
name: manager1,manager2,manager3,pinky,pinky2,igagarin,reddy
|
||||
state: absent
|
||||
|
||||
- name: User manager1 present
|
||||
@@ -352,6 +352,46 @@
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Rename user pinky to reddy
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: pinky
|
||||
rename: reddy
|
||||
state: renamed
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Rename user pinky to reddy, again
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: pinky
|
||||
rename: reddy
|
||||
state: renamed
|
||||
register: result
|
||||
failed_when: not result.failed or "No user 'pinky'" not in result.msg
|
||||
|
||||
- name: Rename user reddy to reddy
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: reddy
|
||||
rename: reddy
|
||||
state: renamed
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Rename user reddy back to pinky
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||
name: reddy
|
||||
rename: pinky
|
||||
state: renamed
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: User pinky absent and preserved for future exclusion.
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
|
||||
@@ -5,6 +5,12 @@
|
||||
gather_facts: false
|
||||
|
||||
tasks:
|
||||
- name: Remove test users
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
name: manager1,manager2,manager3,pinky,pinky2,mod1,mod2
|
||||
state: absent
|
||||
|
||||
- name: Remove test users
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
@@ -48,7 +54,7 @@
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Users user1..10 present
|
||||
- name: Users user1..10 present, again
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
users:
|
||||
@@ -85,6 +91,42 @@
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Rename users user1 and user2 to mod1 and mod1
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
users:
|
||||
- name: user1
|
||||
rename: mod1
|
||||
- name: user2
|
||||
rename: mod2
|
||||
state: renamed
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
- name: Rename users mod1 and mod2 to the same name
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
users:
|
||||
- name: mod1
|
||||
rename: mod1
|
||||
- name: mod2
|
||||
rename: mod2
|
||||
state: renamed
|
||||
register: result
|
||||
failed_when: result.changed or result.failed
|
||||
|
||||
- name: Rename users mod1 and mod2 back to user1 and user2
|
||||
ipauser:
|
||||
ipaadmin_password: SomeADMINpassword
|
||||
users:
|
||||
- name: mod1
|
||||
rename: user1
|
||||
- name: mod2
|
||||
rename: user2
|
||||
state: renamed
|
||||
register: result
|
||||
failed_when: not result.changed or result.failed
|
||||
|
||||
# failed_when: not result.failed has been added as this test needs to
|
||||
# fail because two users with the same name should be added in the same
|
||||
# task.
|
||||
|
||||
Reference in New Issue
Block a user