Merge ~afreiberger/charm-local-users:bug/1964807 into charm-local-users:main

Proposed by Drew Freiberger
Status: Merged
Approved by: Xav Paice
Approved revision: ef0ea618e0012d508331e784b89e7c71d40362fe
Merged at revision: 84de21ec629938836f80a110ea235509ab00157f
Proposed branch: ~afreiberger/charm-local-users:bug/1964807
Merge into: charm-local-users:main
Diff against target: 144 lines (+65/-13)
4 files modified
charmcraft.yaml (+13/-7)
requirements.txt (+0/-1)
src/charm.py (+4/-4)
src/lib/local_users.py (+48/-1)
Reviewer Review Type Date Requested Status
Xav Paice (community) Approve
BootStack Reviewers Pending
Review via email: mp+416830@code.launchpad.net

Commit message

Remove charmhelpers requirement and import group add functions

To post a comment you must log in.
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

This merge proposal is being monitored by mergebot. Change the status to Approved to merge.

Revision history for this message
Xav Paice (xavpaice) wrote :

lgtm, we really really need this charm to have proper test coverage

review: Approve
Revision history for this message
🤖 Canonical IS Merge Bot (canonical-is-mergebot) wrote :

Change successfully merged at revision 84de21ec629938836f80a110ea235509ab00157f

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1diff --git a/charmcraft.yaml b/charmcraft.yaml
2index fd5e934..663c211 100644
3--- a/charmcraft.yaml
4+++ b/charmcraft.yaml
5@@ -1,9 +1,15 @@
6 type: "charm"
7 bases:
8- - name: "ubuntu"
9- channel: "20.04"
10- - name: "ubuntu"
11- channel: "18.04"
12-parts:
13- charm:
14- charm-python-packages: [setuptools < 58]
15+ - build-on:
16+ - name: ubuntu
17+ channel: "20.04"
18+ architectures: ["amd64"]
19+ run-on:
20+ - name: ubuntu
21+ channel: "20.04"
22+ architectures:
23+ - amd64
24+ - name: ubuntu
25+ channel: "18.04"
26+ architectures:
27+ - amd64
28diff --git a/requirements.txt b/requirements.txt
29index 7d3a551..5d6fa96 100644
30--- a/requirements.txt
31+++ b/requirements.txt
32@@ -1,2 +1 @@
33 ops >= 1.2.0
34-charmhelpers >= 0.20.24
35\ No newline at end of file
36diff --git a/src/charm.py b/src/charm.py
37index f71608d..e9875e5 100755
38--- a/src/charm.py
39+++ b/src/charm.py
40@@ -23,13 +23,13 @@ from ops.framework import StoredState
41 from ops.main import main
42 from ops.model import ActiveStatus, BlockedStatus
43
44-from charmhelpers.core import host
45-
46 from lib.local_users import (
47+ add_group,
48 configure_user,
49 check_sudoers_file,
50 delete_user,
51 get_group_users,
52+ group_exists,
53 is_unmanaged_user,
54 parse_gecos,
55 remove_group,
56@@ -76,7 +76,7 @@ class CharmLocalUsersCharm(CharmBase):
57 self.unit.status = BlockedStatus("'group' config option value is required")
58 return
59
60- if not host.group_exists(group):
61+ if not group_exists(group):
62 if self._stored.group and self._stored.group != group:
63 log.debug(
64 "renaming charm managed group: '%s' to '%s'",
65@@ -85,7 +85,7 @@ class CharmLocalUsersCharm(CharmBase):
66 )
67 rename_group(self._stored.group, group)
68 else:
69- host.add_group(group)
70+ add_group(group)
71
72 # save the current managed group name in StoredState so that the charm can detect if rename
73 # is needed on future config_changed events
74diff --git a/src/lib/local_users.py b/src/lib/local_users.py
75index 531458f..dba53e7 100755
76--- a/src/lib/local_users.py
77+++ b/src/lib/local_users.py
78@@ -20,6 +20,7 @@ import re
79 import subprocess
80 import logging
81 import tempfile
82+import grp
83 from collections import namedtuple
84
85 from charmhelpers.core import host
86@@ -179,7 +180,7 @@ def update_gecos(user):
87
88
89 def parse_gecos(raw):
90- """Helper to convert a raw GECOS string into a 5 elements list."""
91+ """Convert a raw GECOS string into a 5 elements list."""
92 gecos = [""] * 5
93 fields = raw.split(",")
94 for i in range(5):
95@@ -220,3 +221,49 @@ def write_sudoers_file(sudoers):
96 sudoers_file.close()
97 os.chmod(NEW_FILE, 0o440)
98 os.replace(NEW_FILE, SUDOERS_FILE)
99+
100+
101+def group_exists(groupname):
102+ """Check if a group exists."""
103+ try:
104+ grp.getgrnam(groupname)
105+ group_exists = True
106+ except KeyError:
107+ group_exists = False
108+ return group_exists
109+
110+
111+def add_group(group_name, system_group=False, gid=None):
112+ """Add a group to the system.
113+
114+ Will log but otherwise succeed if the group already exists.
115+ :param str group_name: group to create
116+ :param bool system_group: Create system group
117+ :param int gid: GID for user being created
118+ :returns: The password database entry struct, as returned by `grp.getgrnam`
119+ """
120+ try:
121+ group_info = grp.getgrnam(group_name)
122+ log('group {0} already exists!'.format(group_name))
123+ if gid:
124+ group_info = grp.getgrgid(gid)
125+ log('group with gid {0} already exists!'.format(gid))
126+ except KeyError:
127+ log('creating group {0}'.format(group_name))
128+ add_new_group(group_name, system_group, gid)
129+ group_info = grp.getgrnam(group_name)
130+ return group_info
131+
132+
133+def add_new_group(group_name, system_group=False, gid=None):
134+ cmd = ['addgroup']
135+ if gid:
136+ cmd.extend(['--gid', str(gid)])
137+ if system_group:
138+ cmd.append('--system')
139+ else:
140+ cmd.extend([
141+ '--group',
142+ ])
143+ cmd.append(group_name)
144+ subprocess.check_call(cmd)

Subscribers

People subscribed via source and target branches

to all changes: