Starting to add additional unit tests for VariableManager

Required some rewiring in inventory code to make sure we're using
the DataLoader class for some data file operations, which makes mocking
them much easier.

Also identified two corner cases not currently handled by the code, related
to inventory variable sources and which one "wins". Also noticed we weren't
properly merging variables from multiple group/host_var file locations
(inventory directory vs. playbook directory locations) so fixed as well.
This commit is contained in:
James Cammarata
2015-09-04 16:41:38 -04:00
parent 87f75a50ad
commit ff9f5d7dc8
13 changed files with 233 additions and 54 deletions

View File

@@ -104,9 +104,9 @@ class Inventory(object):
all.add_host(Host(tokens[0], tokens[1]))
else:
all.add_host(Host(x))
elif os.path.exists(host_list):
elif self._loader.path_exists(host_list):
#TODO: switch this to a plugin loader and a 'condition' per plugin on which it should be tried, restoring 'inventory pllugins'
if os.path.isdir(host_list):
if self._loader.is_directory(host_list):
# Ensure basedir is inside the directory
host_list = os.path.join(self.host_list, "")
self.parser = InventoryDirectory(loader=self._loader, filename=host_list)
@@ -595,14 +595,14 @@ class Inventory(object):
""" did inventory come from a file? """
if not isinstance(self.host_list, basestring):
return False
return os.path.exists(self.host_list)
return self._loader.path_exists(self.host_list)
def basedir(self):
""" if inventory came from a file, what's the directory? """
dname = self.host_list
if not self.is_file():
dname = None
elif os.path.isdir(self.host_list):
elif self._loader.is_directory(self.host_list):
dname = self.host_list
else:
dname = os.path.dirname(self.host_list)

View File

@@ -29,7 +29,6 @@ from ansible.inventory.host import Host
from ansible.inventory.group import Group
from ansible.utils.vars import combine_vars
from ansible.utils.path import is_executable
from ansible.inventory.ini import InventoryParser as InventoryINIParser
from ansible.inventory.script import InventoryScript
@@ -54,7 +53,7 @@ def get_file_parser(hostsfile, loader):
except:
pass
if is_executable(hostsfile):
if loader.is_executable(hostsfile):
try:
parser = InventoryScript(loader=loader, filename=hostsfile)
processed = True
@@ -65,10 +64,10 @@ def get_file_parser(hostsfile, loader):
if not processed:
try:
parser = InventoryINIParser(filename=hostsfile)
parser = InventoryINIParser(loader=loader, filename=hostsfile)
processed = True
except Exception as e:
if shebang_present and not is_executable(hostsfile):
if shebang_present and not loader.is_executable(hostsfile):
myerr.append("The file %s looks like it should be an executable inventory script, but is not marked executable. " % hostsfile + \
"Perhaps you want to correct this with `chmod +x %s`?" % hostsfile)
else:

View File

@@ -114,12 +114,15 @@ class Host:
def get_vars(self):
results = {}
groups = self.get_groups()
for group in sorted(groups, key=lambda g: g.depth):
results = combine_vars(results, group.get_vars())
results = combine_vars(results, self.vars)
results['inventory_hostname'] = self.name
results['inventory_hostname_short'] = self.name.split('.')[0]
results['group_names'] = sorted([ g.name for g in groups if g.name != 'all'])
results['group_names'] = sorted([ g.name for g in self.get_groups() if g.name != 'all'])
return results
def get_group_vars(self):
results = {}
groups = self.get_groups()
for group in sorted(groups, key=lambda g: g.depth):
results = combine_vars(results, group.get_vars())
return results

View File

@@ -37,7 +37,8 @@ class InventoryParser(object):
with their associated hosts and variable settings.
"""
def __init__(self, filename=C.DEFAULT_HOST_LIST):
def __init__(self, loader, filename=C.DEFAULT_HOST_LIST):
self._loader = loader
self.filename = filename
# Start with an empty host list and the default 'all' and
@@ -53,8 +54,14 @@ class InventoryParser(object):
# Read in the hosts, groups, and variables defined in the
# inventory file.
with open(filename) as fh:
self._parse(fh.readlines())
if loader:
(data, private) = loader._get_file_contents(filename)
data = data.split('\n')
else:
with open(filename) as fh:
data = fh.readlines()
self._parse(data)
# Finally, add all top-level groups (including 'ungrouped') as
# children of 'all'.