Created
May 19, 2012 22:21
-
-
Save atomatt/2732574 to your computer and use it in GitHub Desktop.
Simplified/generic ini-style inventory parser for Ansible
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import codecs | |
class Parser(object): | |
def __init__(self): | |
self.nodes = {} | |
def node_with_name(self, name): | |
node = self.nodes.get(name) | |
if node is None: | |
node = Node(name) | |
self.nodes[name] = node | |
return node | |
def parse(self, filename): | |
# Iterate lines in the file. | |
lines = codecs.open(filename, encoding="utf-8") | |
lines = (line.rstrip() for line in lines) | |
current_group = None | |
section_type = None | |
for line in lines: | |
if line.strip()[:1] in ["", "#"]: | |
# Empty line or comment, ignore. | |
continue | |
if line.startswith("[") and line.endswith("]"): | |
# Start of group block. Make the group node the current node | |
# and record the group's section type (if any) so we know how | |
# to parse a normal line. | |
name, _, section_type = line[1:-1].partition(":") | |
node = self.node_with_name(name) | |
current_group = node | |
elif line.startswith("["): | |
raise Exception("Syntax error: %s" % line) | |
elif section_type == "vars": | |
# Line in a vars section. | |
name, val = line.split("=", 1) | |
current_group.add_variables({name: val}) | |
else: | |
# Line containing a host or group name | |
if " " in line: | |
name, variables = line.split(" ", 1) | |
variables = dict(i.split("=", 1) for i in variables.split()) | |
else: | |
name, variables = line, {} | |
name, _, port = name.partition(':') | |
if port: | |
variables["__port__"] = port | |
node = self.node_with_name(name) | |
node.add_variables(variables) | |
if current_group: | |
current_group.add_child(node) | |
node.add_parent(current_group) | |
else: | |
ungrouped = self.node_with_name("ungrouped") | |
ungrouped.add_child(node) | |
node.add_parent(ungrouped) | |
class Node(object): | |
def __init__(self, name): | |
self.name = name | |
self.variables = {} | |
self.children = {} | |
self.parents = {} | |
def add_variables(self, variables): | |
self.variables.update(variables) | |
def add_child(self, node): | |
self.children[node.name] = node | |
def add_parent(self, node): | |
self.parents[node.name] = node | |
def __unicode__(self): | |
return self.__repr__() | |
def __repr__(self): | |
return "%s %r children=%r parents=%r" % (self.name, self.variables, | |
list(self.children), | |
list(self.parents)) | |
def iter_hosts(nodes): | |
for node in nodes.itervalues(): | |
if not node.children: | |
yield node | |
def iter_groups(nodes): | |
for node in nodes.itervalues(): | |
if node.children: | |
yield node | |
def variables(node, _collector={}): | |
_collector.update(node.variables) | |
for parent in node.parents.itervalues(): | |
variables(parent, _collector) | |
return _collector | |
if __name__ == '__main__': | |
import sys | |
parser = Parser() | |
parser.parse(sys.argv[1]) | |
for node in parser.nodes.values(): | |
print node | |
print "=" * 78 | |
print "all:" | |
for node in iter_hosts(parser.nodes): | |
print node | |
print " ", variables(node) | |
print "=" * 78 | |
print "groups:" | |
for node in iter_groups(parser.nodes): | |
print node |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment