summaryrefslogtreecommitdiff
path: root/lib/ansible/inventory/script.py
diff options
context:
space:
mode:
Diffstat (limited to 'lib/ansible/inventory/script.py')
-rw-r--r--lib/ansible/inventory/script.py27
1 files changed, 16 insertions, 11 deletions
diff --git a/lib/ansible/inventory/script.py b/lib/ansible/inventory/script.py
index 6dfb1d2af0..95e48eff58 100644
--- a/lib/ansible/inventory/script.py
+++ b/lib/ansible/inventory/script.py
@@ -31,6 +31,7 @@ from ansible.errors import AnsibleError
from ansible.inventory.host import Host
from ansible.inventory.group import Group
from ansible.module_utils.basic import json_dict_bytes_to_unicode
+from ansible.utils.unicode import to_str, to_unicode
class InventoryScript:
@@ -57,12 +58,17 @@ class InventoryScript:
if sp.returncode != 0:
raise AnsibleError("Inventory script (%s) had an execution error: %s " % (filename,stderr))
- self.data = stdout
+ # make sure script output is unicode so that json loader will output
+ # unicode strings itself
+ try:
+ self.data = to_unicode(stdout, errors="strict")
+ except Exception as e:
+ raise AnsibleError("inventory data from {0} contained characters that cannot be interpreted as UTF-8: {1}".format(to_str(self.filename), to_str(e)))
+
# see comment about _meta below
self.host_vars_from_top = None
self._parse(stderr)
-
def _parse(self, err):
all_hosts = {}
@@ -72,13 +78,11 @@ class InventoryScript:
self.raw = self._loader.load(self.data)
except Exception as e:
sys.stderr.write(err + "\n")
- raise AnsibleError("failed to parse executable inventory script results from {0}: {1}".format(self.filename, str(e)))
+ raise AnsibleError("failed to parse executable inventory script results from {0}: {1}".format(to_str(self.filename), to_str(e)))
if not isinstance(self.raw, Mapping):
sys.stderr.write(err + "\n")
- raise AnsibleError("failed to parse executable inventory script results from {0}: data needs to be formatted as a json dict".format(self.filename))
-
- self.raw = json_dict_bytes_to_unicode(self.raw)
+ raise AnsibleError("failed to parse executable inventory script results from {0}: data needs to be formatted as a json dict".format(to_str(self.filename)))
group = None
for (group_name, data) in self.raw.items():
@@ -103,7 +107,7 @@ class InventoryScript:
if not isinstance(data, dict):
data = {'hosts': data}
# is not those subkeys, then simplified syntax, host with vars
- elif not any(k in data for k in ('hosts','vars')):
+ elif not any(k in data for k in ('hosts','vars','children')):
data = {'hosts': [group_name], 'vars': data}
if 'hosts' in data:
@@ -112,7 +116,7 @@ class InventoryScript:
"data for the host list:\n %s" % (group_name, data))
for hostname in data['hosts']:
- if not hostname in all_hosts:
+ if hostname not in all_hosts:
all_hosts[hostname] = Host(hostname)
host = all_hosts[hostname]
group.add_host(host)
@@ -145,10 +149,12 @@ class InventoryScript:
def get_host_variables(self, host):
""" Runs <script> --host <hostname> to determine additional host variables """
if self.host_vars_from_top is not None:
- got = self.host_vars_from_top.get(host.name, {})
+ try:
+ got = self.host_vars_from_top.get(host.name, {})
+ except AttributeError as e:
+ raise AnsibleError("Improperly formated host information for %s: %s" % (host.name,to_str(e)))
return got
-
cmd = [self.filename, "--host", host.name]
try:
sp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
@@ -161,4 +167,3 @@ class InventoryScript:
return json_dict_bytes_to_unicode(self._loader.load(out))
except ValueError:
raise AnsibleError("could not parse post variable response: %s, %s" % (cmd, out))
-