diff options
Diffstat (limited to 'reconfigure/includers')
-rw-r--r-- | reconfigure/includers/__init__.py | 14 | ||||
-rw-r--r-- | reconfigure/includers/auto.py | 68 | ||||
-rw-r--r-- | reconfigure/includers/base.py | 21 | ||||
-rw-r--r-- | reconfigure/includers/bind9.py | 11 | ||||
-rw-r--r-- | reconfigure/includers/nginx.py | 11 | ||||
-rw-r--r-- | reconfigure/includers/supervisor.py | 11 |
6 files changed, 136 insertions, 0 deletions
diff --git a/reconfigure/includers/__init__.py b/reconfigure/includers/__init__.py new file mode 100644 index 0000000..1128588 --- /dev/null +++ b/reconfigure/includers/__init__.py @@ -0,0 +1,14 @@ +from base import BaseIncluder +from auto import AutoIncluder +from bind9 import BIND9Includer +from nginx import NginxIncluder +from supervisor import SupervisorIncluder + + +__all__ = [ + 'BaseIncluder', + 'AutoIncluder', + 'BIND9Includer', + 'NginxIncluder', + 'SupervisorIncluder', +] diff --git a/reconfigure/includers/auto.py b/reconfigure/includers/auto.py new file mode 100644 index 0000000..16844ca --- /dev/null +++ b/reconfigure/includers/auto.py @@ -0,0 +1,68 @@ +from base import BaseIncluder +from reconfigure.nodes import * +import glob +import os + + +class AutoIncluder (BaseIncluder): + """ + This base includer automatically walks the node tree and loads the include files from ``IncludeNode.files`` properties. ``files`` is supposed to contain absolute path, relative path or a shell wildcard. + """ + + def compose(self, origin, tree): + self.compose_rec(origin, origin, tree) + return tree + + def compose_rec(self, root, origin, node): + if not node.origin: + node.origin = origin + for child in node.children: + self.compose_rec(root, origin, child) + for child in node.children: + spec = self.is_include(child) + if spec: + files = spec + if node.origin and not files.startswith('/'): + files = os.path.join(os.path.split(root)[0], files) + if '*' in files or '.' in files: + files = glob.glob(files) + else: + files = [files] + for file in files: + if file in self.content_map: + content = self.content_map[file] + else: + content = open(file, 'r').read() + subtree = self.parser.parse(content) + node.children.extend(subtree.children) + self.compose_rec(root, file, subtree) + node.children[node.children.index(child)] = IncludeNode(spec) + + def decompose(self, tree): + result = {} + result[tree.origin] = self.decompose_rec(tree, result) + return result + + def decompose_rec(self, node, result): + for child in node.children: + if child.__class__ == IncludeNode: + replacement = self.remove_include(child) + if replacement: + node.children[node.children.index(child)] = replacement + else: + if child.origin != node.origin: + node.children.remove(child) + result.setdefault(child.origin, RootNode()).children.append(self.decompose_rec(child, result)) + else: + self.decompose_rec(child, result) + return node + + def is_include(self, node): + """ + Should return whether the node is an include node and return file pattern glob if it is + """ + + def remove_include(self, node): + """ + Shoud transform :class:`reconfigure.nodes.IncludeNode` into a normal Node to be stringified into the file + """ diff --git a/reconfigure/includers/base.py b/reconfigure/includers/base.py new file mode 100644 index 0000000..e0512bf --- /dev/null +++ b/reconfigure/includers/base.py @@ -0,0 +1,21 @@ +class BaseIncluder (object): # pragma: no cover + """ + A base includer class + + :param parser: Parser instance that was used to parse the root config file + :param content_map: a dict that overrides config content for specific paths + """ + + def __init__(self, parser=None, content_map={}): + self.parser = parser + self.content_map = content_map + + def compose(self, origin, tree): + """ + Should locate the include nodes in the Node tree, replace them with :class:`reconfigure.nodes.IncludeNode`, parse the specified include files and append them to tree, with correct node ``origin`` attributes + """ + + def decompose(self, origin, tree): + """ + Should detach the included subtrees from the Node tree and return a ``{ origin: content-node-tree }`` dict. + """ diff --git a/reconfigure/includers/bind9.py b/reconfigure/includers/bind9.py new file mode 100644 index 0000000..6a1e08c --- /dev/null +++ b/reconfigure/includers/bind9.py @@ -0,0 +1,11 @@ +from reconfigure.includers.auto import AutoIncluder +from reconfigure.nodes import PropertyNode + + +class BIND9Includer (AutoIncluder): + def is_include(self, node): + if isinstance(node, PropertyNode) and node.name == 'include': + return node.value.strip('"') + + def remove_include(self, node): + return PropertyNode('include', '"%s"' % node.files) diff --git a/reconfigure/includers/nginx.py b/reconfigure/includers/nginx.py new file mode 100644 index 0000000..f9c1c9b --- /dev/null +++ b/reconfigure/includers/nginx.py @@ -0,0 +1,11 @@ +from reconfigure.includers.auto import AutoIncluder +from reconfigure.nodes import PropertyNode + + +class NginxIncluder (AutoIncluder): + def is_include(self, node): + if isinstance(node, PropertyNode) and node.name == 'include': + return node.value + + def remove_include(self, node): + return PropertyNode('include', node.files) diff --git a/reconfigure/includers/supervisor.py b/reconfigure/includers/supervisor.py new file mode 100644 index 0000000..2314cd9 --- /dev/null +++ b/reconfigure/includers/supervisor.py @@ -0,0 +1,11 @@ +from reconfigure.includers.auto import AutoIncluder +from reconfigure.nodes import Node, PropertyNode + + +class SupervisorIncluder (AutoIncluder): + def is_include(self, node): + if node.name == 'include': + return node.get('files').value + + def remove_include(self, node): + return Node('include', children=[PropertyNode('files', node.files)]) |