If the inventory file is EXECUTABLE, treat it as a file returning JSON, if called directly, return the host

and groups list.  If called with an argument of a host name, return the key=value data for that particular
host.
This commit is contained in:
Michael DeHaan 2012-03-30 19:06:14 -04:00
parent f200a467e7
commit 9f6d98844e
2 changed files with 60 additions and 19 deletions

View file

@ -200,8 +200,6 @@ if __name__ == '__main__':
# Generic handler for ansible specific errors
print "ERROR: %s" % str(e)
sys.exit(1)
except Exception as e2:
print e2.__class__
else:
cli.output(runner, results, options, args)

View file

@ -29,6 +29,7 @@ import random
import jinja2
import traceback
import tempfile
import subprocess
# FIXME: stop importing *, use as utils/errors
from ansible.utils import *
@ -135,24 +136,41 @@ class Runner(object):
if not os.path.exists(host_list):
raise AnsibleFileNotFound("inventory file not found: %s" % host_list)
lines = file(host_list).read().split("\n")
groups = {}
groups['ungrouped'] = []
group_name = 'ungrouped'
results = []
for item in lines:
item = item.lstrip().rstrip()
if item.startswith("#"):
# ignore commented out lines
continue
if item.startswith("["):
# looks like a group
group_name = item.replace("[","").replace("]","").lstrip().rstrip()
groups[group_name] = []
else:
# looks like a regular host
groups[group_name].append(item)
results.append(item)
groups = { 'ungrouped' : [] }
if not os.access(host_list, os.X_OK):
# it's a regular file
lines = file(host_list).read().split("\n")
group_name = 'ungrouped'
results = []
for item in lines:
item = item.lstrip().rstrip()
if item.startswith("#"):
# ignore commented out lines
continue
if item.startswith("["):
# looks like a group
group_name = item.replace("[","").replace("]","").lstrip().rstrip()
groups[group_name] = []
else:
# looks like a regular host
groups[group_name].append(item)
results.append(item)
else:
host_list = os.path.abspath(host_list)
cls._external_variable_script = host_list
# it's a script -- expect a return of a JSON hash with group names keyed
# to lists of hosts
cmd = subprocess.Popen([host_list], stdout=subprocess.PIPE, stderr=subprocess.PIPE, shell=False)
out, err = cmd.communicate()
try:
groups = json.loads(out)
except:
raise AnsibleError("invalid JSON response from script: %s" % host_list)
for (groupname, hostlist) in groups.iteritems():
for host in hostlist:
if host not in results:
results.append(host)
return (results, groups)
@ -272,6 +290,31 @@ class Runner(object):
args = " ".join(args)
inject_vars = self.setup_cache.get(conn.host,{})
# if the host file was an external script, execute it with the hostname
# as a first parameter to get the variables to use for the host
if Runner._external_variable_script is not None:
host = conn.host
cmd = subprocess.Popen([Runner._external_variable_script, host],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
shell=False
)
out, err = cmd.communicate()
inject2 = {}
try:
inject2 = json.loads(out)
except:
raise AnsibleError("%s returned invalid result when called with hostname %s" % (
Runner._external_variable_script,
host
))
inject_vars.update(inject2)
# store injected variables in the templates
if self.module_name == 'setup':
for (k,v) in inject2.iteritems():
args = "%s %s=%s" % (args, k, v)
# the metadata location for the setup module is transparently managed
# since it's an 'internals' module, kind of a black box. See playbook
# other modules are not allowed to have this kind of handling