diff --git a/changelogs/fragments/user-local-mode-group-append.yaml b/changelogs/fragments/user-local-mode-group-append.yaml new file mode 100644 index 00000000000..fef7d581e16 --- /dev/null +++ b/changelogs/fragments/user-local-mode-group-append.yaml @@ -0,0 +1,2 @@ +bugfixes: + - user - omit incompatible options when operating in local mode (https://github.com/ansible/ansible/issues/48722) diff --git a/lib/ansible/modules/system/user.py b/lib/ansible/modules/system/user.py index cc1ab81190c..7dfbcdb5d02 100644 --- a/lib/ansible/modules/system/user.py +++ b/lib/ansible/modules/system/user.py @@ -60,12 +60,14 @@ options: C(null), or C(~), the user is removed from all groups except the primary group. (C(~) means C(null) in YAML) - Before Ansible 2.3, the only input format allowed was a comma separated string. + - Mutually exclusive with C(local) type: list append: description: - If C(yes), add the user to the groups specified in C(groups). - If C(no), user will only be added to the groups specified in C(groups), removing them from all other groups. + - Mutually exclusive with C(local) type: bool default: no shell: @@ -209,6 +211,7 @@ options: - This will check C(/etc/passwd) for an existing account before invoking commands. If the local account database exists somewhere other than C(/etc/passwd), this setting will not work properly. - This requires that the above commands as well as C(/etc/passwd) must exist on the target host, otherwise it will be a fatal error. + - Mutually exclusive with C(groups) and C(append) type: bool default: no version_added: "2.4" @@ -616,7 +619,7 @@ class User(object): else: cmd.append('-N') - if self.groups is not None and len(self.groups): + if self.groups is not None and not self.local and len(self.groups): groups = self.get_groups_set() cmd.append('-G') cmd.append(','.join(groups)) @@ -737,7 +740,7 @@ class User(object): else: groups_need_mod = True - if groups_need_mod: + if groups_need_mod and not self.local: if self.append and not has_append: cmd.append('-A') cmd.append(','.join(group_diff)) @@ -2852,7 +2855,11 @@ def main(): authorization=dict(type='str'), role=dict(type='str'), ), - supports_check_mode=True + supports_check_mode=True, + mutually_exclusive=[ + ('local', 'groups'), + ('local', 'append') + ] ) user = User(module) diff --git a/test/integration/targets/user/tasks/main.yml b/test/integration/targets/user/tasks/main.yml index fe5e931afa8..798f3aa80d2 100644 --- a/test/integration/targets/user/tasks/main.yml +++ b/test/integration/targets/user/tasks/main.yml @@ -853,7 +853,7 @@ state: absent remove: yes local: yes - register: local_user_test_3 + register: local_user_test_remove_1 tags: - user_test_local_mode @@ -863,16 +863,56 @@ state: absent remove: yes local: yes - register: local_user_test_4 + register: local_user_test_remove_2 tags: - user_test_local_mode -- name: Ensure local user accounts were created +- name: Create test group + group: + name: testgroup + tags: + - user_test_local_mode + +- name: Create local_ansibulluser with groups + user: + name: local_ansibulluser + state: present + local: yes + groups: testgroup + register: local_user_test_3 + ignore_errors: yes + tags: + - user_test_local_mode + +- name: Append groups for local_ansibulluser + user: + name: local_ansibulluser + state: present + local: yes + append: yes + register: local_user_test_4 + ignore_errors: yes + tags: + - user_test_local_mode + +- name: Ensure local user accounts were created and removed properly assert: that: - local_user_test_1 is changed - local_user_test_2 is not changed - - local_user_test_3 is changed - - local_user_test_4 is not changed + - local_user_test_3 is failed + - "local_user_test_3['msg'] is search('parameters are mutually exclusive: groups|local')" + - local_user_test_4 is failed + - "local_user_test_4['msg'] is search('parameters are mutually exclusive: groups|append')" + - local_user_test_remove_1 is changed + - local_user_test_remove_2 is not changed tags: - user_test_local_mode + +- name: Ensure warnings were displayed + assert: + that: + - local_user_test_1['warnings'] | length > 0 + - "'user was not found in /etc/passwd. The local user account may already exist if the local account + database exists somewhere other than /etc/passwd.' in local_user_test_1['warnings'][0]" + when: ansible_facts.system in ['Linux']