From 534b0688f7f619ca26163067631eb6d58c4b09ed Mon Sep 17 00:00:00 2001 From: Alexander Sulfrian Date: Wed, 5 Dec 2012 15:23:23 +0100 Subject: Server/Plugin: backported XMLMatch from bcfg2-1.3 --- src/lib/Server/Plugin.py | 83 +++++++++++++++++++++++++++++++++--------------- 1 file changed, 58 insertions(+), 25 deletions(-) (limited to 'src/lib') diff --git a/src/lib/Server/Plugin.py b/src/lib/Server/Plugin.py index 28299d8c7..7298bc552 100644 --- a/src/lib/Server/Plugin.py +++ b/src/lib/Server/Plugin.py @@ -647,36 +647,37 @@ class StructFile(XMLFileBacked): def __init__(self, name): XMLFileBacked.__init__(self, name) + def _include_element(self, item, metadata): + """ determine if an XML element matches the metadata """ + if isinstance(item, lxml.etree._Comment): # pylint: disable=W0212 + return False + negate = item.get('negate', 'false').lower() == 'true' + if item.tag == 'Group': + return negate == (item.get('name') not in metadata.groups) + elif item.tag == 'Client': + return negate == (item.get('name') != metadata.hostname) + else: + return True + def _match(self, item, metadata): """ recursive helper for Match() """ - if isinstance(item, lxml.etree._Comment): - return [] - elif item.tag == 'Group': - rv = [] - if ((item.get('negate', 'false').lower() == 'true' and - item.get('name') not in metadata.groups) or - (item.get('negate', 'false').lower() == 'false' and - item.get('name') in metadata.groups)): - for child in item.iterchildren(): - rv.extend(self._match(child, metadata)) - return rv - elif item.tag == 'Client': - rv = [] - if ((item.get('negate', 'false').lower() == 'true' and - item.get('name') != metadata.hostname) or - (item.get('negate', 'false').lower() == 'false' and - item.get('name') == metadata.hostname)): + if self._include_element(item, metadata): + if item.tag == 'Group' or item.tag == 'Client': + rv = [] + if self._include_element(item, metadata): + for child in item.iterchildren(): + rv.extend(self._match(child, metadata)) + return rv + else: + rv = copy.deepcopy(item) + for child in rv.iterchildren(): + rv.remove(child) for child in item.iterchildren(): rv.extend(self._match(child, metadata)) - return rv + return [rv] else: - rv = copy.copy(item) - for child in rv.iterchildren(): - rv.remove(child) - for child in item.iterchildren(): - rv.extend(self._match(child, metadata)) - return [rv] - + return [] + def Match(self, metadata): """Return matching fragments of independent.""" rv = [] @@ -684,6 +685,38 @@ class StructFile(XMLFileBacked): rv.extend(self._match(child, metadata)) return rv + def _xml_match(self, item, metadata): + """ recursive helper for XMLMatch """ + if self._include_element(item, metadata): + if item.tag == 'Group' or item.tag == 'Client': + for child in item.iterchildren(): + item.remove(child) + item.getparent().append(child) + self._xml_match(child, metadata) + item.getparent().remove(item) + else: + for child in item.iterchildren(): + self._xml_match(child, metadata) + else: + item.getparent().remove(item) + + def XMLMatch(self, metadata): + """ Return a rebuilt XML document that only contains the + matching portions of the original file. A tag is considered + to match if all ```` and ```` tags that are its + ancestors match the metadata given. Unlike :func:`Match`, the + document returned by XMLMatch will only contain matching data. + All ```` and ```` tags will have been stripped + out. + + :param metadata: Client metadata to match against. + :type metadata: Bcfg2.Server.Plugins.Metadata.ClientMetadata + :returns: lxml.etree._Element """ + rv = copy.deepcopy(self.xdata) + for child in rv.iterchildren(): + self._xml_match(child, metadata) + return rv + class INode: """ -- cgit v1.2.3-1-g7c22