diff --git a/README-user.md b/README-user.md index 9a75ea5310cfbfa2c3b60115202132c59be17779..e7402610638e40224c7c42f7bd33aa38106f130e 100644 --- a/README-user.md +++ b/README-user.md @@ -58,6 +58,7 @@ Example playbook to ensure a user is present: last: Acme uid: 10001 gid: 100 + gecos: "The Pinky" phone: "+555123457" email: pinky@acme.com passwordexpiration: "2023-01-19 23:59:59" @@ -395,6 +396,7 @@ Variable | Description | Required `random` | Generate a random user password | no `uid` \| `uidnumber` | User ID Number (system will assign one if not provided). | no `gid` \| `gidnumber` | Group ID Number. | no +`gecos` | GECOS | no `city` | City | no `userstate` \| `st` | State/Province | no `postalcode` \| `zip` | Postalcode/ZIP | no diff --git a/plugins/modules/ipauser.py b/plugins/modules/ipauser.py index a0a596ebb0a4a4323a62c24037b280fa04776c8b..b703b09f54c9a970a365f5d0861aec3ccf61da2a 100644 --- a/plugins/modules/ipauser.py +++ b/plugins/modules/ipauser.py @@ -80,6 +80,10 @@ options: description: The home directory type: str required: false + gecos: + description: The GECOS + type: str + required: false shell: description: The login shell type: str @@ -304,6 +308,10 @@ options: description: The home directory type: str required: false + gecos: + description: The GECOS + type: str + required: false shell: description: The login shell type: str @@ -652,8 +660,8 @@ def find_user(module, name): return _result -def gen_args(first, last, fullname, displayname, initials, homedir, shell, - email, principalexpiration, passwordexpiration, password, +def gen_args(first, last, fullname, displayname, initials, homedir, gecos, + shell, email, principalexpiration, passwordexpiration, password, random, uid, gid, city, userstate, postalcode, phone, mobile, pager, fax, orgunit, title, carlicense, sshpubkey, userauthtype, userclass, radius, radiususer, departmentnumber, employeenumber, @@ -672,6 +680,8 @@ def gen_args(first, last, fullname, displayname, initials, homedir, shell, _args["initials"] = initials if homedir is not None: _args["homedirectory"] = homedir + if gecos is not None: + _args["gecos"] = gecos if shell is not None: _args["loginshell"] = shell if email is not None and len(email) > 0: @@ -735,7 +745,7 @@ def gen_args(first, last, fullname, displayname, initials, homedir, shell, def check_parameters( # pylint: disable=unused-argument module, state, action, first, last, fullname, displayname, initials, - homedir, shell, email, principal, principalexpiration, + homedir, gecos, shell, email, principal, principalexpiration, passwordexpiration, password, random, uid, gid, city, phone, mobile, pager, fax, orgunit, title, manager, carlicense, sshpubkey, userauthtype, userclass, radius, radiususer, departmentnumber, @@ -745,7 +755,8 @@ def check_parameters( # pylint: disable=unused-argument if state == "present": if action == "member": invalid = ["first", "last", "fullname", "displayname", "initials", - "homedir", "shell", "email", "principalexpiration", + "homedir", "gecos", "shell", "email", + "principalexpiration", "passwordexpiration", "password", "random", "uid", "gid", "city", "phone", "mobile", "pager", "fax", "orgunit", "title", "carlicense", "sshpubkey", @@ -756,7 +767,7 @@ def check_parameters( # pylint: disable=unused-argument else: invalid = ["first", "last", "fullname", "displayname", "initials", - "homedir", "shell", "email", "principalexpiration", + "homedir", "gecos", "shell", "email", "principalexpiration", "passwordexpiration", "password", "random", "uid", "gid", "city", "phone", "mobile", "pager", "fax", "orgunit", "title", "carlicense", "sshpubkey", @@ -902,6 +913,7 @@ def main(): displayname=dict(type="str", default=None), initials=dict(type="str", default=None), homedir=dict(type="str", default=None), + gecos=dict(type="str", default=None), shell=dict(type="str", aliases=["loginshell"], default=None), email=dict(type="list", elements="str", default=None), principal=dict(type="list", elements="str", @@ -1015,6 +1027,7 @@ def main(): displayname = ansible_module.params_get("displayname") initials = ansible_module.params_get("initials") homedir = ansible_module.params_get("homedir") + gecos = ansible_module.params_get("gecos") shell = ansible_module.params_get("shell") email = ansible_module.params_get("email") principal = ansible_module.params_get("principal") @@ -1080,7 +1093,8 @@ def main(): check_parameters( ansible_module, state, action, - first, last, fullname, displayname, initials, homedir, shell, email, + first, last, fullname, displayname, initials, homedir, gecos, shell, + email, principal, principalexpiration, passwordexpiration, password, random, uid, gid, city, phone, mobile, pager, fax, orgunit, title, manager, carlicense, sshpubkey, userauthtype, userclass, radius, radiususer, @@ -1133,6 +1147,7 @@ def main(): displayname = user.get("displayname") initials = user.get("initials") homedir = user.get("homedir") + gecos = user.get("gecos") shell = user.get("shell") email = user.get("email") principal = user.get("principal") @@ -1178,7 +1193,7 @@ def main(): check_parameters( ansible_module, state, action, first, last, fullname, displayname, initials, homedir, - shell, email, principal, principalexpiration, + gecos, shell, email, principal, principalexpiration, passwordexpiration, password, random, uid, gid, city, phone, mobile, pager, fax, orgunit, title, manager, carlicense, sshpubkey, userauthtype, userclass, radius, @@ -1235,6 +1250,7 @@ def main(): # Generate args args = gen_args( first, last, fullname, displayname, initials, homedir, + gecos, shell, email, principalexpiration, passwordexpiration, password, random, uid, gid, city, userstate, postalcode, phone, mobile, pager, fax, orgunit, title, carlicense, diff --git a/tests/user/test_user.yml b/tests/user/test_user.yml index 4583fd72af009173c6d7eaf400c8ec2783252765..46a7de9923837e25cbb60da4a0c023506330c669 100644 --- a/tests/user/test_user.yml +++ b/tests/user/test_user.yml @@ -9,7 +9,7 @@ ipauser: ipaadmin_password: SomeADMINpassword ipaapi_context: "{{ ipa_context | default(omit) }}" - name: manager1,manager2,manager3,pinky,pinky2 + name: manager1,manager2,manager3,pinky,pinky2,igagarin state: absent - name: User manager1 present @@ -342,9 +342,107 @@ register: result failed_when: result.changed or result.failed + - name: Ensure user with GECOS information exists. + ipauser: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: igagarin + first: Iuri + last: Gagarin + gecos: Юрий Алексеевич Гагарин + register: result + failed_when: not result.changed or result.failed + + - name: Ensure user with GECOS information exists, again. + ipauser: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: igagarin + first: Iuri + last: Gagarin + gecos: Юрий Алексеевич Гагарин + register: result + failed_when: result.changed or result.failed + + - name: Modify GECOS information. + ipauser: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: igagarin + gecos: Юрий Гагарин + register: result + failed_when: not result.changed or result.failed + + - name: Updating with existent data, should not change user. + ipauser: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: igagarin + first: Iuri + last: Gagarin + gecos: Юрий Гагарин + register: result + failed_when: result.changed or result.failed + + - name: Ensure GECOS parameter is cleared. + ipauser: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: igagarin + gecos: "" + register: result + failed_when: not result.changed or result.failed + + - name: Ensure GECOS parameter is cleared, again + ipauser: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: igagarin + gecos: "" + register: result + failed_when: result.changed or result.failed + + - name: Ensure GECOS parameter cannot be used with state absent. + ipauser: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: igagarin + gecos: Юрий Гагарин + state: absent + register: result + failed_when: not result.failed or "Argument 'gecos' can not be used with action 'user' and state 'absent'" not in result.msg + + - name: Ensure user igagarin is absent. + ipauser: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: igagarin + state: absent + register: result + failed_when: not result.changed or result.failed + + - name: Ensure user with non-ascii name exists. + ipauser: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: igagarin + first: Юрий + last: Гагарин + register: result + failed_when: not result.changed or result.failed + + - name: Ensure user with non-ascii name exists has proper GECOS value. + ipauser: + ipaadmin_password: SomeADMINpassword + ipaapi_context: "{{ ipa_context | default(omit) }}" + name: igagarin + gecos: Юрий Гагарин + register: result + failed_when: result.changed or result.failed + - name: Remove test users ipauser: ipaadmin_password: SomeADMINpassword ipaapi_context: "{{ ipa_context | default(omit) }}" - name: manager1,manager2,manager3,pinky,pinky2 + name: manager1,manager2,manager3,pinky,pinky2,igagarin state: absent