From 23c333e2d3eec7e94d1a2ab113730daefcd29cae Mon Sep 17 00:00:00 2001
From: Honza Mach <honza.mach.ml@gmail.com>
Date: Tue, 14 Mar 2017 20:11:27 +0100
Subject: [PATCH] Improved the uid/gid daemon options.

Daemon can now take user/group options, which can contain either user/group name as string, or uid/gid as integer. Anything else fails with exception.
---
 pyzenkit/zendaemon.py | 57 +++++++++++++++++++++++++++++++++++--------
 setup.py              |  2 +-
 2 files changed, 48 insertions(+), 11 deletions(-)

diff --git a/pyzenkit/zendaemon.py b/pyzenkit/zendaemon.py
index 839d20e..39a269a 100644
--- a/pyzenkit/zendaemon.py
+++ b/pyzenkit/zendaemon.py
@@ -12,6 +12,8 @@ Base implementation of generic daemon.
 import os
 import re
 import sys
+import pwd
+import grp
 import json
 import time
 import copy
@@ -250,8 +252,8 @@ class ZenDaemon(pyzenkit.baseapp.BaseApp):
     CONFIG_PID_FILE       = 'pid_file'
     CONFIG_STATE_FILE     = 'state_file'
     CONFIG_UMASK          = 'umask'
-    CONFIG_UID            = 'uid'
-    CONFIG_GID            = 'gid'
+    CONFIG_USER           = 'user'
+    CONFIG_GROUP          = 'group'
     CONFIG_STATS_INTERVAL = 'stats_interval'
     CONFIG_PARALEL        = 'paralel'
 
@@ -282,8 +284,8 @@ class ZenDaemon(pyzenkit.baseapp.BaseApp):
             (self.CONFIG_PID_FILE,       os.path.join(self.paths.get(self.PATH_RUN), "{}.pid".format(self.name))),
             (self.CONFIG_STATE_FILE,     os.path.join(self.paths.get(self.PATH_RUN), "{}.state".format(self.name))),
             (self.CONFIG_UMASK,          None),
-            (self.CONFIG_UID,            None),
-            (self.CONFIG_GID,            None),
+            (self.CONFIG_USER,           None),
+            (self.CONFIG_GROUP,          None),
             (self.CONFIG_STATS_INTERVAL, 300),
             (self.CONFIG_PARALEL,        False),
         )
@@ -317,10 +319,10 @@ class ZenDaemon(pyzenkit.baseapp.BaseApp):
         argparser.add_argument('--umask', help = 'default file umask')
 
         # Option for overriding the process UID.
-        argparser.add_argument('--uid', help = 'process UID')
+        argparser.add_argument('--user', help = 'process UID or user name')
 
         # Option for overriding the process GID.
-        argparser.add_argument('--gid', help = 'process GID')
+        argparser.add_argument('--group', help = 'process GID or group name')
 
         # Option for defining processing statistics display interval.
         argparser.add_argument('--stats-interval', help = 'define processing statistics display interval')
@@ -398,6 +400,41 @@ class ZenDaemon(pyzenkit.baseapp.BaseApp):
         self.config[self.CORE][self.CORE_RUNLOG][self.CORE_RUNLOG_SAVE] = True
         self.config[self.CORE][self.CORE_PSTATE][self.CORE_PSTATE_SAVE] = True
 
+        if self.config[self.CONFIG_USER]:
+            u = self.config[self.CONFIG_USER]
+            res = None
+            if not res:
+                try:
+                    res = pwd.getpwnam(u)
+                    self.config[self.CONFIG_USER] = res[2]
+                except:
+                    pass
+            if not res:
+                try:
+                    res = pwd.getpwuid(int(u))
+                    self.config[self.CONFIG_USER] = res[2]
+                except:
+                    pass
+            if not res:
+                raise ZenDaemonException("Unknown user '{}'".format(u))
+
+        if self.config[self.CONFIG_GROUP]:
+            g = self.config[self.CONFIG_GROUP]
+            res = None
+            if not res:
+                try:
+                    res = grp.getgrnam(g)
+                    self.config[self.CONFIG_GROUP] = res[2]
+                except:
+                    pass
+            if not res:
+                try:
+                    res = grp.getgruid(int(g))
+                    self.config[self.CONFIG_GROUP] = res[2]
+                except:
+                    pass
+            if not res:
+                raise ZenDaemonException("Unknown group '{}'".format(g))
 
 
     def _stage_setup_custom(self):
@@ -705,8 +742,8 @@ class ZenDaemon(pyzenkit.baseapp.BaseApp):
                 work_dir       = self.c(self.CONFIG_WORK_DIR),
                 pidfile        = self.get_fn_pidfile(),
                 umask          = self.c(self.CONFIG_UMASK),
-                uid            = self.c(self.CONFIG_UID),
-                gid            = self.c(self.CONFIG_GID),
+                uid            = self.c(self.CONFIG_USER),
+                gid            = self.c(self.CONFIG_GROUP),
                 files_preserve = logs,
                 signals        = {
                     signal.SIGHUP:  self._hnd_signal_hup,
@@ -728,8 +765,8 @@ class ZenDaemon(pyzenkit.baseapp.BaseApp):
                 work_dir       = self.c(self.CONFIG_WORK_DIR),
                 pidfile        = self.get_fn_pidfile(),
                 umask          = self.c(self.CONFIG_UMASK),
-                uid            = self.c(self.CONFIG_UID),
-                gid            = self.c(self.CONFIG_GID),
+                uid            = self.c(self.CONFIG_USER),
+                gid            = self.c(self.CONFIG_GROUP),
                 signals        = {
                     signal.SIGHUP:  self._hnd_signal_hup,
                     signal.SIGUSR1: self._hnd_signal_usr1,
diff --git a/setup.py b/setup.py
index c04bb04..c4ac641 100644
--- a/setup.py
+++ b/setup.py
@@ -23,7 +23,7 @@ with open(path.join(here, 'README.rst'), encoding='utf-8') as f:
 
 setup(
     name = 'pyzenkit',
-    version = '0.12',
+    version = '0.13',
     description = 'Python 3 script and daemon toolkit',
     long_description = long_description,
     classifiers = [
-- 
GitLab