From dcf8fddddfa98f39549b57c89c5f79275b0c6b1c Mon Sep 17 00:00:00 2001 From: "Chris St. Pierre" Date: Tue, 24 Jul 2012 11:32:56 -0400 Subject: allow xinclude files to be missing if xi:fallback is provided --- src/lib/Bcfg2/Server/Lint/Comments.py | 5 +++-- src/lib/Bcfg2/Server/Lint/Duplicates.py | 5 +++-- src/lib/Bcfg2/Server/Lint/Validate.py | 24 +++++++++++++++--------- src/lib/Bcfg2/Server/Plugin.py | 18 +++++++++++++----- src/lib/Bcfg2/Server/__init__.py | 7 ++++++- 5 files changed, 40 insertions(+), 19 deletions(-) diff --git a/src/lib/Bcfg2/Server/Lint/Comments.py b/src/lib/Bcfg2/Server/Lint/Comments.py index f5d0e265f..59d18fc57 100644 --- a/src/lib/Bcfg2/Server/Lint/Comments.py +++ b/src/lib/Bcfg2/Server/Lint/Comments.py @@ -1,6 +1,7 @@ -import os.path +import os import lxml.etree import Bcfg2.Server.Lint +from Bcfg2.Server import XI, XI_NAMESPACE from Bcfg2.Server.Plugins.Cfg.CfgPlaintextGenerator import CfgPlaintextGenerator from Bcfg2.Server.Plugins.Cfg.CfgGenshiGenerator import CfgGenshiGenerator from Bcfg2.Server.Plugins.Cfg.CfgCheetahGenerator import CfgCheetahGenerator @@ -186,7 +187,7 @@ class Comments(Bcfg2.Server.Lint.ServerPlugin): path = os.path.join(self.metadata.data, mfile) if path in self.files: xdata = lxml.etree.parse(path) - for el in xdata.findall('./{http://www.w3.org/2001/XInclude}include'): + for el in xdata.findall('./%sinclude' % XI_NAMESPACE): if not self.has_all_xincludes(el.get('href')): self.LintError("broken-xinclude-chain", "Broken XInclude chain: could not include %s" % path) diff --git a/src/lib/Bcfg2/Server/Lint/Duplicates.py b/src/lib/Bcfg2/Server/Lint/Duplicates.py index ee6b7a2e6..60a02ffb9 100644 --- a/src/lib/Bcfg2/Server/Lint/Duplicates.py +++ b/src/lib/Bcfg2/Server/Lint/Duplicates.py @@ -1,6 +1,7 @@ -import os.path +import os import lxml.etree import Bcfg2.Server.Lint +from Bcfg2.Server import XI, XI_NAMESPACE class Duplicates(Bcfg2.Server.Lint.ServerPlugin): """ Find duplicate clients, groups, etc. """ @@ -80,7 +81,7 @@ class Duplicates(Bcfg2.Server.Lint.ServerPlugin): path = os.path.join(self.metadata.data, mfile) if path in self.files: xdata = lxml.etree.parse(path) - for el in xdata.findall('./{http://www.w3.org/2001/XInclude}include'): + for el in xdata.findall('./%sinclude' % XI_NAMESPACE): if not self.has_all_xincludes(el.get('href')): self.LintError("broken-xinclude-chain", "Broken XInclude chain: could not include %s" % path) diff --git a/src/lib/Bcfg2/Server/Lint/Validate.py b/src/lib/Bcfg2/Server/Lint/Validate.py index aa5cfe62c..5499e75c2 100644 --- a/src/lib/Bcfg2/Server/Lint/Validate.py +++ b/src/lib/Bcfg2/Server/Lint/Validate.py @@ -1,10 +1,10 @@ -import fnmatch +import os +import sys import glob +import fnmatch import lxml.etree -import os from subprocess import Popen, PIPE, STDOUT -import sys - +from Bcfg2.Server import XI, XI_NAMESPACE import Bcfg2.Server.Lint class Validate(Bcfg2.Server.Lint.ServerlessPlugin): @@ -174,23 +174,29 @@ class Validate(Bcfg2.Server.Lint.ServerlessPlugin): def follow_xinclude(self, xfile): """ follow xincludes in the given file """ xdata = lxml.etree.parse(xfile) - included = set([ent.get('href') for ent in - xdata.findall('./{http://www.w3.org/2001/XInclude}include')]) + included = set([el + for el in xdata.findall('./%sinclude' % XI_NAMESPACE)]) rv = [] while included: try: - filename = included.pop() + el = included.pop() except KeyError: continue + filename = el.get("href") path = os.path.join(os.path.dirname(xfile), filename) - if self.HandlesFile(path): + if not os.path.exists(path): + if not el.findall('./%sfallback' % XI_NAMESPACE): + self.LintError("broken-xinclude-chain", + "XInclude %s does not exist in %s: %s" % + (filename, xfile, self.RenderXML(el))) + elif self.HandlesFile(path): rv.append(path) groupdata = lxml.etree.parse(path) [included.add(el.get('href')) for el in - groupdata.findall('./{http://www.w3.org/2001/XInclude}include')] + groupdata.findall('./%sinclude' % XI_NAMESPACE)] included.discard(filename) return rv diff --git a/src/lib/Bcfg2/Server/Plugin.py b/src/lib/Bcfg2/Server/Plugin.py index d035b83d4..6b4276444 100644 --- a/src/lib/Bcfg2/Server/Plugin.py +++ b/src/lib/Bcfg2/Server/Plugin.py @@ -607,16 +607,24 @@ class XMLFileBacked(FileBacked): xdata = self.xdata.getroottree() else: xdata = lxml.etree.parse(fname) - included = [ent.get('href') - for ent in xdata.findall('//{http://www.w3.org/2001/XInclude}include')] - for name in included: + included = [el for el in xdata.findall('//%sinclude' % + Bcfg2.Server.XI_NAMESPACE)] + for el in included: + name = el.get("href") if name not in self.extras: if name.startswith("/"): fpath = name else: fpath = os.path.join(os.path.dirname(self.name), name) - self._follow_xincludes(fname=fpath) - self.add_monitor(fpath, name) + if os.path.exists(fpath): + self._follow_xincludes(fname=fpath) + self.add_monitor(fpath, name) + else: + msg = "%s: %s does not exist, skipping" % (self.name, name) + if el.findall('./%sfallback' % Bcfg2.Server.XI_NAMESPACE): + self.logger.debug(msg) + else: + self.logger.warning(msg) def Index(self): """Build local data structures.""" diff --git a/src/lib/Bcfg2/Server/__init__.py b/src/lib/Bcfg2/Server/__init__.py index 320371284..f79b51dd3 100644 --- a/src/lib/Bcfg2/Server/__init__.py +++ b/src/lib/Bcfg2/Server/__init__.py @@ -3,6 +3,11 @@ import lxml.etree __all__ = ["Admin", "Core", "FileMonitor", "Plugin", "Plugins", - "Hostbase", "Reports", "Snapshots", "XMLParser"] + "Hostbase", "Reports", "Snapshots", "XMLParser", + "XI", "XI_NAMESPACE"] XMLParser = lxml.etree.XMLParser(remove_blank_text=True) + +XI = 'http://www.w3.org/2001/XInclude' +XI_NAMESPACE = '{%s}' % XI + -- cgit v1.2.3-1-g7c22