]> Frank Brehm's Git Trees - pixelpark/admin-tools.git/commitdiff
Adding reading file in pp_lib/test_home_app.py
authorFrank Brehm <frank.brehm@pixelpark.com>
Tue, 21 Mar 2017 15:56:23 +0000 (16:56 +0100)
committerFrank Brehm <frank.brehm@pixelpark.com>
Tue, 21 Mar 2017 15:56:23 +0000 (16:56 +0100)
pp_lib/test_home_app.py

index 8fc25c23af8be15f4319cbe9bf92688088177505..63ed6525c3ad32f210c679f10b216ec3ef5ab3fe 100644 (file)
@@ -31,7 +31,7 @@ from .common import pp, terminal_can_colors, to_bytes, to_bool
 
 from .cfg_app import PpCfgAppError, PpConfigApplication
 
-__version__ = '0.1.1'
+__version__ = '0.2.1'
 LOG = logging.getLogger(__name__)
 
 
@@ -52,7 +52,7 @@ class PpTestHomeApp(PpConfigApplication):
     default_home_root = os.sep + 'home'
 
     # /etc/pixelpark/exclude_homes
-    default_exlude_file = os.sep + os.path.join('etc', 'pixelpark', 'exclude_homes')
+    default_exclude_file = os.sep + os.path.join('etc', 'pixelpark', 'exclude_homes')
 
     default_mail_recipients = [
         'frank.brehm@pixelpark.com'
@@ -63,6 +63,9 @@ class PpTestHomeApp(PpConfigApplication):
 
     default_reply_to = 'frank.brehm@pixelpark.com'
 
+    comment_re = re.compile(r'\s*#.*')
+    whitespace_re = re.compile(r'(?:[,;]+|\s*[,;]*\s+)')
+
     # -------------------------------------------------------------------------
     def __init__(self, appname=None, version=__version__):
 
@@ -70,6 +73,8 @@ class PpTestHomeApp(PpConfigApplication):
         self.home_root_abs = self.default_home_root
         self.home_root_rel = os.path.relpath(self.home_root_abs, os.sep)
 
+        self.exclude_file = self.default_exclude_file
+
         self.mail_recipients = copy.copy(self.default_mail_recipients)
         self.mail_cc = copy.copy(self.default_mail_cc)
         self.reply_to = self.default_reply_to
@@ -81,7 +86,7 @@ class PpTestHomeApp(PpConfigApplication):
             This scripts detects unnecessary home directories - without an
             appropriate home directory in the passwd database and not excluded
             in {!r}.
-            ''').strip().format(self.default_exlude_file)
+            ''').strip().format(self.default_exclude_file)
 
         super(PpTestHomeApp, self).__init__(
             appname=appname, version=version, description=description,
@@ -90,10 +95,123 @@ class PpTestHomeApp(PpConfigApplication):
 
         self.initialized = True
 
+    # -------------------------------------------------------------------------
+    def perform_config(self):
+
+        super(PpTestHomeApp, self).perform_config()
+
+        for section_name in self.cfg.keys():
+
+            if self.verbose > 2:
+                LOG.debug("Checking config section {!r} ...".format(section_name))
+
+            if section_name.lower() not in ('test-home', 'test_home', 'testhome') :
+                continue
+
+            section = self.cfg[section_name]
+            if self.verbose > 2:
+                LOG.debug("Evaluating config section {n!r}:\n{s}".format(
+                    n=section_name, s=pp(section)))
+
+            if 'chroot_homedir' in section:
+                v = section['chroot_homedir']
+                if not os.path.isabs(v):
+                    msg = (
+                        "The chrooted path of the home directories must be an "
+                        "absolute pathname (found [{s}]/chroot_homedir "
+                        "=> {v!r} in configuration.").format(s=section_name, v=v)
+                    raise PpMkHomeError(msg)
+                self.chroot_homedir = v
+
+            if 'home_root' in section:
+                v = section['home_root']
+                if not os.path.isabs(v):
+                    msg = (
+                        "The root path of the home directories must be an "
+                        "absolute pathname (found [{s}]/home_root "
+                        "=> {v!r} in configuration.").format(s=section_name, v=v)
+                    raise PpMkHomeError(msg)
+                self.home_root_abs = v
+
+            if 'exclude_file' in section:
+                v = section['exclude_file']
+                if not os.path.isabs(v):
+                    msg = (
+                        "The path of file of excluded directories must be an "
+                        "absolute pathname (found [{s}]/exclude_file "
+                        "=> {v!r} in configuration.").format(s=section_name, v=v)
+                    raise PpMkHomeError(msg)
+                self.exclude_file = v
+
+        self.home_root_rel = os.path.relpath(self.home_root_abs, os.sep)
+        self.home_root_real = os.path.join(self.chroot_homedir, self.home_root_rel)
+
     # -------------------------------------------------------------------------
     def _run(self):
 
-        LOG.info("Jetzt geht's los ...")
+        self.read_exclude_dirs()
+
+    # -------------------------------------------------------------------------
+    def read_exclude_dirs(self):
+
+        LOG.info("Reading exclude file {!r} ...".format(self.exclude_file))
+        upper_dir = os.pardir + os.sep
+
+        if not os.path.exists(self.exclude_file):
+            msg = "Exclude file {!r} does not exists.".format(self.exclude_file)
+            LOG.error(msg)
+            return
+
+        if not os.path.isfile(self.exclude_file):
+            msg = "Exclude file {!r} is not a regular file.".format(self.exclude_file)
+            LOG.error(msg)
+            return
+
+        if not os.access(self.exclude_file, os.R_OK):
+            msg = "No read access to exclude file {!r}.".format(self.exclude_file)
+            LOG.error(msg)
+            return
+
+        open_args = {}
+        if six.PY3:
+            open_args['encoding'] = 'utf-8'
+            open_args['errors'] = 'surrogateescape'
+
+        with open(self.exclude_file, 'r', **open_args) as fh:
+            lnr = 0
+            for line in fh.readlines():
+                lnr += 1
+                line = line.strip()
+                if not line:
+                    continue
+                line = self.comment_re.sub('', line)
+                if not line:
+                    continue
+                if self.verbose > 3:
+                    LOG.debug("Evaluating line {l!r} (file {f!r}, line {lnr}).".format(
+                        l=line, f=self.exclude_file, lnr=lnr))
+                tokens = self.whitespace_re.split(line)
+                for token in tokens:
+                    if not os.path.isabs(token):
+                        LOG.warn((
+                            "Entry {e!r} in file {f!r}, line {l}, "
+                            "is not an absolute path.").format(
+                            e=token, f=self.exclude_file, l=lnr))
+                        continue
+                    home_relative = os.path.relpath(token, self.home_root_abs)
+                    if home_relative.startswith(upper_dir):
+                        LOG.warn((
+                            "Entry {e!r} in file {f!r}, line {l}, "
+                            "is outside home root {h!r}.").format(
+                            e=token, f=self.exclude_file, l=lnr, h=self.home_root_abs))
+                        continue
+                    if not token in self.exclude_dirs:
+                        self.exclude_dirs.append(token)
+
+        self.exclude_dirs.sort(key=str.lower)
+
+        if self.verbose > 2:
+            LOG.debug("Found directories to exclude:\n{}".format(pp(self.exclude_dirs)))
 
 # =============================================================================