Mini Shell
"""
Manage groups on Mac OS 10.7+
"""
import logging
import salt.utils.functools
import salt.utils.itertools
import salt.utils.stringutils
from salt.exceptions import CommandExecutionError, SaltInvocationError
from salt.modules.mac_user import _dscl, _flush_dscl_cache
try:
import grp
except ImportError:
pass
log = logging.getLogger(__name__)
# Define the module's virtual name
__virtualname__ = "group"
def __virtual__():
global _dscl, _flush_dscl_cache
if __grains__.get("kernel") != "Darwin" or __grains__["osrelease_info"] < (10, 7):
return (
False,
"The mac_group execution module cannot be loaded: only available on"
" Darwin-based systems >= 10.7",
)
_dscl = salt.utils.functools.namespaced_function(_dscl, globals())
_flush_dscl_cache = salt.utils.functools.namespaced_function(
_flush_dscl_cache, globals()
)
return __virtualname__
def add(name, gid=None, **kwargs):
"""
.. versionchanged:: 3006.0
Add the specified group
name
Name of the new group
gid
Use GID for the new group
CLI Example:
.. code-block:: bash
salt '*' group.add foo 3456
"""
### NOTE: **kwargs isn't used here but needs to be included in this
### function for compatibility with the group.present state
if info(name):
raise CommandExecutionError(f"Group '{name}' already exists")
if salt.utils.stringutils.contains_whitespace(name):
raise SaltInvocationError("Group name cannot contain whitespace")
if name.startswith("_"):
raise SaltInvocationError(
"Salt will not create groups beginning with underscores"
)
if gid is not None and not isinstance(gid, int):
raise SaltInvocationError("gid must be an integer")
if "non_unique" in kwargs:
log.warning("The non_unique parameter is not supported on this platform.")
# check if gid is already in use
gid_list = _list_gids()
if str(gid) in gid_list:
raise CommandExecutionError(f"gid '{gid}' already exists")
cmd = ["dseditgroup", "-o", "create"]
if gid:
cmd.extend(["-i", gid])
cmd.append(name)
return __salt__["cmd.retcode"](cmd, python_shell=False) == 0
def _list_gids():
"""
Return a list of gids in use
"""
output = __salt__["cmd.run"](
["dscacheutil", "-q", "group"], output_loglevel="quiet", python_shell=False
)
ret = set()
for line in salt.utils.itertools.split(output, "\n"):
if line.startswith("gid:"):
ret.update(line.split()[1:])
return sorted(ret)
def delete(name):
"""
Remove the named group
CLI Example:
.. code-block:: bash
salt '*' group.delete foo
"""
if salt.utils.stringutils.contains_whitespace(name):
raise SaltInvocationError("Group name cannot contain whitespace")
if name.startswith("_"):
raise SaltInvocationError(
"Salt will not remove groups beginning with underscores"
)
if not info(name):
return True
cmd = ["dseditgroup", "-o", "delete", name]
return __salt__["cmd.retcode"](cmd, python_shell=False) == 0
def adduser(group, name):
"""
Add a user in the group.
CLI Example:
.. code-block:: bash
salt '*' group.adduser foo bar
Verifies if a valid username 'bar' as a member of an existing group 'foo',
if not then adds it.
"""
cmd = f"dscl . -merge /Groups/{group} GroupMembership {name}"
return __salt__["cmd.retcode"](cmd) == 0
def deluser(group, name):
"""
Remove a user from the group
.. versionadded:: 2016.3.0
CLI Example:
.. code-block:: bash
salt '*' group.deluser foo bar
Removes a member user 'bar' from a group 'foo'. If group is not present
then returns True.
"""
cmd = f"dscl . -delete /Groups/{group} GroupMembership {name}"
return __salt__["cmd.retcode"](cmd) == 0
def members(name, members_list):
"""
Replaces members of the group with a provided list.
.. versionadded:: 2016.3.0
CLI Example:
.. code-block:: bash
salt '*' group.members foo 'user1,user2,user3,...'
Replaces a membership list for a local group 'foo'.
"""
retcode = 1
grp_info = __salt__["group.info"](name)
if grp_info and name in grp_info["name"]:
cmd = f"/usr/bin/dscl . -delete /Groups/{name} GroupMembership"
retcode = __salt__["cmd.retcode"](cmd) == 0
for user in members_list.split(","):
cmd = "/usr/bin/dscl . -merge /Groups/{} GroupMembership {}".format(
name, user
)
retcode = __salt__["cmd.retcode"](cmd)
if not retcode == 0:
break
# provided list is '': users previously deleted from group
else:
retcode = 0
return retcode == 0
def info(name):
"""
Return information about a group
CLI Example:
.. code-block:: bash
salt '*' group.info foo
"""
if salt.utils.stringutils.contains_whitespace(name):
raise SaltInvocationError("Group name cannot contain whitespace")
try:
# getgrnam seems to cache weirdly, so don't use it
grinfo = next(iter(x for x in grp.getgrall() if x.gr_name == name))
except StopIteration:
return {}
else:
return _format_info(grinfo)
def _format_info(data):
"""
Return formatted information in a pretty way.
"""
return {
"name": data.gr_name,
"gid": data.gr_gid,
"passwd": data.gr_passwd,
"members": data.gr_mem,
}
def getent(refresh=False):
"""
Return info on all groups
CLI Example:
.. code-block:: bash
salt '*' group.getent
"""
if "group.getent" in __context__ and not refresh:
return __context__["group.getent"]
ret = []
for grinfo in grp.getgrall():
if not grinfo.gr_name.startswith("_"):
ret.append(_format_info(grinfo))
__context__["group.getent"] = ret
return ret
def chgid(name, gid):
"""
Change the gid for a named group
CLI Example:
.. code-block:: bash
salt '*' group.chgid foo 4376
"""
if not isinstance(gid, int):
raise SaltInvocationError("gid must be an integer")
pre_gid = __salt__["file.group_to_gid"](name)
pre_info = info(name)
if not pre_info:
raise CommandExecutionError(f"Group '{name}' does not exist")
if gid == pre_info["gid"]:
return True
cmd = ["dseditgroup", "-o", "edit", "-i", gid, name]
return __salt__["cmd.retcode"](cmd, python_shell=False) == 0
Zerion Mini Shell 1.0