cluster_configure: Remove files for "None" template substitutions
authorMartin Schwenke <martin@meltin.net>
Tue, 25 Nov 2014 00:26:32 +0000 (11:26 +1100)
committerMartin Schwenke <martin@meltin.net>
Tue, 25 Nov 2014 01:37:48 +0000 (12:37 +1100)
This is a hack that assume any substitution that returns None must
cause the template containing it to produce no output file at all.

Signed-off-by: Martin Schwenke <martin@meltin.net>
base/all/root/scripts/cluster_configure/cluster-configure.py

index 217f3b5..e94579e 100755 (executable)
@@ -207,19 +207,11 @@ class Package(object):
                 logger.debug("_find_template_files: add template file %s" % frel)
                 self.files.append(frel)
 
-    def _expand_template(self, fdir, file):
+    def _substitute_template(self, contents):
         """Expand the given template fdir/file into the staging area."""
 
-        global options
-
         logger.debug("_expand_template: subsitute variables into %s", file)
 
-        # Read input file.
-        src = os.path.join(fdir, file)
-        f = open(src)
-        contents = f.read()
-        f.close()
-
         # Find variables in template and substitute values.
         variables = sorted(set(re.findall("!!((\w+)((=)([^!]*))?)!!",
                                           contents)))
@@ -240,14 +232,33 @@ class Package(object):
             (m, f, rest) = re.split("[:(]", e, 2)
             foo = 'plugins["%s"].%s(config, "%s", %s' % (m, f, self.name, rest)
             r = eval(foo)
+            if r is None:
+                return None
             contents = contents.replace("!!%%%s!!" % e, r)
 
         # Find general python expressions in template and subsitute values.
         exprs = re.findall("!!\|([^!]+)!!", contents)
         for e in exprs:
             r = eval(e)
+            if r is None:
+                return None
             contents = contents.replace("!!|%s!!" % e, r)
 
+        return contents
+
+    def _expand_template(self, fdir, file):
+        """Expand the given template fdir/file into the staging area."""
+
+        logger.debug("_expand_template: subsitute variables into %s", file)
+
+        # Read input file.
+        src = os.path.join(fdir, file)
+        f = open(src)
+        contents = f.read()
+        f.close()
+
+        contents = self._substitute_template(contents)
+
         # Ensure output directory exists in staging area.
         dst = os.path.join(self.stage, file)
         try:
@@ -257,10 +268,19 @@ class Package(object):
                 pass
             else: raise
 
-        # Write output file into staging area.
-        f = open(dst, "w")
-        f.write(contents)
-        f.close()
+        # Write output file into staging area, unless it is None,
+        # which means to remove the file if it exists.
+        if contents is not None:
+            f = open(dst, "w")
+            f.write(contents)
+            f.close()
+        else:
+            try:
+                os.remove(dst)
+            except OSError, exc:
+                if exc.errno == errno.ENOENT:
+                    pass
+                else: raise
 
     def _would_install_file(self, file):
         """Check if a file should be installed from the staging area
@@ -269,6 +289,11 @@ class Package(object):
 
         src = os.path.join(self.stage, file)
         dst = os.path.join("/", file)
+
+        if not os.path.exists(src) and not os.path.exists(dst):
+            logger.debug("_would_install_file: skip install of %s (missing)", dst)
+            return False
+
         try: 
             if not options.force and filecmp.cmp(src, dst, shallow=False):
                 logger.debug("_would_install_file: skip install of %s (unchanged)", dst)
@@ -307,8 +332,17 @@ class Package(object):
         src = os.path.join(self.stage, file)
         dst = os.path.join("/", file)
 
-        logger.info("_install_file: install file %s", dst)
-        shutil.copy2(src, dst)
+        if os.path.exists(src):
+            logger.info("_install_file: install file %s", dst)
+            shutil.copy2(src, dst)
+        else:
+            logger.info("_install_file: remove file %s", dst)
+            try:
+                os.remove(dst)
+            except OSError, exc:
+                if exc.errno == errno.ENOENT:
+                    pass
+                else: raise
 
     def install_files(self):
         """Install the list of files from self.files_to_install."""