Skip to content

Instantly share code, notes, and snippets.

@atomatt
Created May 19, 2012 22:21
Show Gist options
  • Save atomatt/2732574 to your computer and use it in GitHub Desktop.
Save atomatt/2732574 to your computer and use it in GitHub Desktop.
Simplified/generic ini-style inventory parser for Ansible
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