From 579e72573a32073e6c438915178e055ccdfb4ef4 Mon Sep 17 00:00:00 2001 From: Sam Doran Date: Tue, 2 Apr 2019 09:58:04 -0400 Subject: [PATCH] Add BusyBox support to group module (#54689) * Add BusyBox support to group module * Use bytes when reading/writing to file --- lib/ansible/modules/system/group.py | 59 +++++++++++++++++++ .../integration/targets/group/tasks/tests.yml | 8 +-- 2 files changed, 63 insertions(+), 4 deletions(-) diff --git a/lib/ansible/modules/system/group.py b/lib/ansible/modules/system/group.py index d7c2596a30..ba32247289 100644 --- a/lib/ansible/modules/system/group.py +++ b/lib/ansible/modules/system/group.py @@ -56,6 +56,7 @@ options: non_unique: description: - This option allows to change the group ID to a non-unique value. Requires C(gid). + - Not supported on macOS or BusyBox distributions. type: bool default: no version_added: "2.8" @@ -75,6 +76,7 @@ EXAMPLES = ''' import grp +from ansible.module_utils._text import to_bytes from ansible.module_utils.basic import AnsibleModule, load_platform_subclass @@ -463,6 +465,63 @@ class NetBsdGroup(Group): # =========================================== + +class BusyBoxGroup(Group): + """ + BusyBox group manipulation class for systems that have addgroup and delgroup. + + It overrides the following methods: + - group_add() + - group_del() + - group_mod() + """ + + def group_add(self, **kwargs): + cmd = [self.module.get_bin_path('addgroup', True)] + if self.gid is not None: + cmd.extend(['-g', str(self.gid)]) + + if self.system: + cmd.append('-S') + + cmd.append(self.name) + + return self.execute_command(cmd) + + def group_del(self): + cmd = [self.module.get_bin_path('delgroup', True), self.name] + return self.execute_command(cmd) + + def group_mod(self, **kwargs): + # Since there is no groupmod command, modify /etc/group directly + info = self.group_info() + if self.gid is not None and self.gid != info[2]: + with open('/etc/group', 'rb') as f: + b_groups = f.read() + + b_name = to_bytes(self.name) + b_current_group_string = b'%s:x:%d:' % (b_name, info[2]) + b_new_group_string = b'%s:x:%d:' % (b_name, self.gid) + + if b':%d:' % self.gid in b_groups: + self.module.fail_json(msg="gid '{gid}' in use".format(gid=self.gid)) + + if self.module.check_mode: + return 0, '', '' + b_new_groups = b_groups.replace(b_current_group_string, b_new_group_string) + with open('/etc/group', 'wb') as f: + f.write(b_new_groups) + return 0, '', '' + + return None, '', '' + + +class AlpineGroup(BusyBoxGroup): + + platform = 'Linux' + distribution = 'Alpine' + + def main(): module = AnsibleModule( argument_spec=dict( diff --git a/test/integration/targets/group/tasks/tests.yml b/test/integration/targets/group/tasks/tests.yml index 86a7702330..2c625c12a4 100644 --- a/test/integration/targets/group/tasks/tests.yml +++ b/test/integration/targets/group/tasks/tests.yml @@ -11,7 +11,7 @@ check_mode: True - name: get result of create group (check mode) - script: grouplist.sh "{{ ansible_distribution }}" + script: 'grouplist.sh "{{ ansible_distribution }}"' register: create_group_actual_check - name: assert create group (check mode) @@ -27,7 +27,7 @@ register: create_group - name: get result of create group - script: grouplist.sh "{{ ansible_distribution }}" + script: 'grouplist.sh "{{ ansible_distribution }}"' register: create_group_actual - name: assert create group @@ -89,7 +89,7 @@ check_mode: True - name: get result of create a group with a gid (check mode) - script: grouplist.sh "{{ ansible_distribution }}" + script: 'grouplist.sh "{{ ansible_distribution }}"' register: create_group_gid_actual_check - name: assert create group with a gid (check mode) @@ -143,7 +143,7 @@ that: - create_group_gid_non_unique is changed - create_group_gid_non_unique.gid | int == gid.stdout_lines[0] | int - when: ansible_facts.system != 'Darwin' + when: ansible_facts.distribution not in ['MacOSX', 'Alpine'] ## ## group remove