Allow inventory to be a directory containing other inventories

This commit is contained in:
Daniel Hokka Zakrisson 2013-02-27 21:24:45 +01:00
parent 647cd0141c
commit d9c6b60b24
3 changed files with 79 additions and 1 deletions

View file

@ -16,6 +16,7 @@ Core Features
* a new chroot connection type * a new chroot connection type
* module common code now has basic type checking (and casting) capability * module common code now has basic type checking (and casting) capability
* module common now supports a 'no_log' attribute to mark a field as not to be syslogged * module common now supports a 'no_log' attribute to mark a field as not to be syslogged
* inventory can now point to a directory containing multiple scripts/hosts files
Modules Added: Modules Added:

View file

@ -25,6 +25,7 @@ import subprocess
import ansible.constants as C import ansible.constants as C
from ansible.inventory.ini import InventoryParser from ansible.inventory.ini import InventoryParser
from ansible.inventory.script import InventoryScript from ansible.inventory.script import InventoryScript
from ansible.inventory.dir import InventoryDirectory
from ansible.inventory.group import Group from ansible.inventory.group import Group
from ansible.inventory.host import Host from ansible.inventory.host import Host
from ansible import errors from ansible import errors
@ -78,7 +79,10 @@ class Inventory(object):
else: else:
all.add_host(Host(x)) all.add_host(Host(x))
elif os.path.exists(host_list): elif os.path.exists(host_list):
if utils.is_executable(host_list): if os.path.isdir(host_list):
self.parser = InventoryDirectory(filename=host_list)
self.groups = self.parser.groups.values()
elif utils.is_executable(host_list):
self.parser = InventoryScript(filename=host_list) self.parser = InventoryScript(filename=host_list)
self.groups = self.parser.groups.values() self.groups = self.parser.groups.values()
else: else:

View file

@ -0,0 +1,73 @@
# (c) 2013, Daniel Hokka Zakrisson <daniel@hozac.com>
#
# This file is part of Ansible
#
# Ansible is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Ansible is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Ansible. If not, see <http://www.gnu.org/licenses/>.
#############################################
import os
import ansible.constants as C
from ansible.inventory.host import Host
from ansible.inventory.group import Group
from ansible.inventory.ini import InventoryParser
from ansible.inventory.script import InventoryScript
from ansible import utils
from ansible import errors
class InventoryDirectory(object):
''' Host inventory parser for ansible using a directory of inventories. '''
def __init__(self, filename=C.DEFAULT_HOST_LIST):
self.names = os.listdir(filename)
self.names.sort()
self.directory = filename
self.parsers = []
self.hosts = {}
self.groups = {}
for i in self.names:
if i.endswith("~") or i.endswith(".orig") or i.endswith(".bak"):
continue
fullpath = os.path.join(self.directory, i)
if os.path.isdir(fullpath):
parser = InventoryDirectory(filename=fullpath)
elif utils.is_executable(fullpath):
parser = InventoryScript(filename=fullpath)
else:
parser = InventoryParser(filename=fullpath)
self.parsers.append(parser)
# This takes a lot of code because we can't directly use any of the objects, as they have to blend
for name, group in parser.groups.iteritems():
if name not in self.groups:
self.groups[name] = Group(name)
for k, v in group.get_variables().iteritems():
self.groups[name].set_variable(k, v)
for host in group.get_hosts():
if host.name not in self.hosts:
self.hosts[host.name] = Host(host.name)
for k, v in host.get_variables().iteritems():
self.hosts[host.name].set_variable(k, v)
self.groups[name].add_host(self.hosts[host.name])
# This needs to be a second loop to ensure all the parent groups exist
for name, group in parser.groups.iteritems():
for ancestor in group.get_ancestors():
self.groups[ancestor.name].add_child_group(self.groups[name])
def get_host_variables(self, host):
""" Gets additional host variables from all inventories """
vars = {}
for i in self.parsers:
vars.update(i.get_host_variables(host))
return vars