From 52b7d4d092359e776da0b79db9752bfc6ca91969 Mon Sep 17 00:00:00 2001 From: Varun Chawla <34209028+veeceey@users.noreply.github.com> Date: Fri, 20 Feb 2026 06:40:55 -0800 Subject: [PATCH] user: return actual system groups instead of input parameter (#86553) The user module's 'groups' return value was returning the groups specified in the module input rather than the actual groups the user belongs to on the system. When using append=true, this meant pre-existing groups were missing from the output. Now queries the system for the user's actual group membership after modification, which matches the documented behavior of "List of groups of which the user is a member." Fixes #80669 Co-Authored-By: Claude Opus 4.6 --- .../80669-user-return-actual-groups.yml | 3 + lib/ansible/modules/user.py | 7 +-- test/integration/targets/user/tasks/main.yml | 1 + .../user/tasks/test_returned_groups.yml | 57 +++++++++++++++++++ 4 files changed, 64 insertions(+), 4 deletions(-) create mode 100644 changelogs/fragments/80669-user-return-actual-groups.yml create mode 100644 test/integration/targets/user/tasks/test_returned_groups.yml diff --git a/changelogs/fragments/80669-user-return-actual-groups.yml b/changelogs/fragments/80669-user-return-actual-groups.yml new file mode 100644 index 00000000000..22f6d7e8249 --- /dev/null +++ b/changelogs/fragments/80669-user-return-actual-groups.yml @@ -0,0 +1,3 @@ +bugfixes: + - user - return the actual system groups the user belongs to instead of only the + groups specified in the module input (https://github.com/ansible/ansible/issues/80669). diff --git a/lib/ansible/modules/user.py b/lib/ansible/modules/user.py index 849014a5205..8df45f00a26 100644 --- a/lib/ansible/modules/user.py +++ b/lib/ansible/modules/user.py @@ -422,8 +422,8 @@ group: type: int sample: 1001 groups: - description: List of groups of which the user is a member. - returned: When O(groups) is not empty and O(state) is V(present) + description: Comma-separated list of groups of which the user is a member. + returned: When user exists and O(state) is V(present) type: str sample: 'chrony,apache' home: @@ -3502,8 +3502,7 @@ def main(): result['comment'] = info[4] result['home'] = info[5] result['shell'] = info[6] - if user.groups is not None: - result['groups'] = user.groups + result['groups'] = ','.join(user.user_group_membership()) # handle missing homedirs info = user.user_info() diff --git a/test/integration/targets/user/tasks/main.yml b/test/integration/targets/user/tasks/main.yml index 85462e4e92d..7d9831bd17b 100644 --- a/test/integration/targets/user/tasks/main.yml +++ b/test/integration/targets/user/tasks/main.yml @@ -18,6 +18,7 @@ - import_tasks: test_expires_min_max.yml - import_tasks: test_expires_warn.yml - import_tasks: test_ssh_key_passphrase.yml +- import_tasks: test_returned_groups.yml - include_tasks: test_password_lock.yml - include_tasks: test_password_lock_new_user.yml - include_tasks: test_local.yml diff --git a/test/integration/targets/user/tasks/test_returned_groups.yml b/test/integration/targets/user/tasks/test_returned_groups.yml new file mode 100644 index 00000000000..9c4e8da3ea0 --- /dev/null +++ b/test/integration/targets/user/tasks/test_returned_groups.yml @@ -0,0 +1,57 @@ +# Test that the user module returns the actual groups a user belongs to +# See: https://github.com/ansible/ansible/issues/80669 + +- name: remove test user for groups return test + user: + name: ansibulluser_groups + state: absent + +- name: create test user with initial groups + user: + name: ansibulluser_groups + groups: + - daemon + - bin + state: present + register: user_groups_create + +- name: validate groups on initial creation + assert: + that: + - "'bin' in user_groups_create.groups" + - "'daemon' in user_groups_create.groups" + +- name: append a group to the test user + user: + name: ansibulluser_groups + groups: + - sys + append: true + state: present + register: user_groups_append + +- name: validate groups after append includes all groups + assert: + that: + - "'bin' in user_groups_append.groups" + - "'daemon' in user_groups_append.groups" + - "'sys' in user_groups_append.groups" + +- name: run user module with no groups param + user: + name: ansibulluser_groups + state: present + register: user_groups_noarg + +- name: validate groups returned even when groups param is not set + assert: + that: + - user_groups_noarg.groups is defined + - "'bin' in user_groups_noarg.groups" + - "'daemon' in user_groups_noarg.groups" + - "'sys' in user_groups_noarg.groups" + +- name: clean up test user + user: + name: ansibulluser_groups + state: absent