mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Fixing some v2 inventory bugs
This commit is contained in:
parent
b6a34518ad
commit
4d9bf37afa
6 changed files with 63 additions and 40 deletions
|
@ -32,15 +32,9 @@ from ansible.inventory.dir import InventoryDirectory
|
|||
from ansible.inventory.group import Group
|
||||
from ansible.inventory.host import Host
|
||||
from ansible.plugins import vars_loader
|
||||
from ansible.utils.path import is_executable
|
||||
from ansible.utils.vars import combine_vars
|
||||
|
||||
# FIXME: these defs need to be somewhere else
|
||||
def is_executable(path):
|
||||
'''is the given path executable?'''
|
||||
return (stat.S_IXUSR & os.stat(path)[stat.ST_MODE]
|
||||
or stat.S_IXGRP & os.stat(path)[stat.ST_MODE]
|
||||
or stat.S_IXOTH & os.stat(path)[stat.ST_MODE])
|
||||
|
||||
class Inventory(object):
|
||||
"""
|
||||
Host inventory for ansible.
|
||||
|
@ -108,7 +102,7 @@ class Inventory(object):
|
|||
if os.path.isdir(host_list):
|
||||
# Ensure basedir is inside the directory
|
||||
self.host_list = os.path.join(self.host_list, "")
|
||||
self.parser = InventoryDirectory(filename=host_list)
|
||||
self.parser = InventoryDirectory(loader=self._loader, filename=host_list)
|
||||
self.groups = self.parser.groups.values()
|
||||
else:
|
||||
# check to see if the specified file starts with a
|
||||
|
@ -124,10 +118,9 @@ class Inventory(object):
|
|||
except:
|
||||
pass
|
||||
|
||||
# FIXME: utils is_executable
|
||||
if is_executable(host_list):
|
||||
try:
|
||||
self.parser = InventoryScript(filename=host_list)
|
||||
self.parser = InventoryScript(loader=self._loader, filename=host_list)
|
||||
self.groups = self.parser.groups.values()
|
||||
except:
|
||||
if not shebang_present:
|
||||
|
|
|
@ -19,18 +19,21 @@
|
|||
#############################################
|
||||
|
||||
import os
|
||||
import ansible.constants as C
|
||||
|
||||
from ansible import constants as C
|
||||
from ansible.errors import *
|
||||
|
||||
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
|
||||
from ansible.utils.path import is_executable
|
||||
from ansible.utils.vars import combine_vars
|
||||
|
||||
class InventoryDirectory(object):
|
||||
''' Host inventory parser for ansible using a directory of inventories. '''
|
||||
|
||||
def __init__(self, filename=C.DEFAULT_HOST_LIST):
|
||||
def __init__(self, loader, filename=C.DEFAULT_HOST_LIST):
|
||||
self.names = os.listdir(filename)
|
||||
self.names.sort()
|
||||
self.directory = filename
|
||||
|
@ -38,10 +41,12 @@ class InventoryDirectory(object):
|
|||
self.hosts = {}
|
||||
self.groups = {}
|
||||
|
||||
self._loader = loader
|
||||
|
||||
for i in self.names:
|
||||
|
||||
# Skip files that end with certain extensions or characters
|
||||
if any(i.endswith(ext) for ext in ("~", ".orig", ".bak", ".ini", ".retry", ".pyc", ".pyo")):
|
||||
if any(i.endswith(ext) for ext in ("~", ".orig", ".bak", ".ini", ".cfg", ".retry", ".pyc", ".pyo")):
|
||||
continue
|
||||
# Skip hidden files
|
||||
if i.startswith('.') and not i.startswith('./'):
|
||||
|
@ -51,9 +56,9 @@ class InventoryDirectory(object):
|
|||
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)
|
||||
parser = InventoryDirectory(loader=loader, filename=fullpath)
|
||||
elif is_executable(fullpath):
|
||||
parser = InventoryScript(loader=loader, filename=fullpath)
|
||||
else:
|
||||
parser = InventoryParser(filename=fullpath)
|
||||
self.parsers.append(parser)
|
||||
|
@ -196,7 +201,7 @@ class InventoryDirectory(object):
|
|||
self.groups[newparent.name].add_child_group(group)
|
||||
|
||||
# variables
|
||||
group.vars = utils.combine_vars(group.vars, newgroup.vars)
|
||||
group.vars = combine_vars(group.vars, newgroup.vars)
|
||||
|
||||
def _merge_hosts(self,host, newhost):
|
||||
""" Merge all of instance newhost into host """
|
||||
|
@ -218,7 +223,7 @@ class InventoryDirectory(object):
|
|||
self.groups[newgroup.name].add_host(host)
|
||||
|
||||
# variables
|
||||
host.vars = utils.combine_vars(host.vars, newhost.vars)
|
||||
host.vars = combine_vars(host.vars, newhost.vars)
|
||||
|
||||
def get_host_variables(self, host):
|
||||
""" Gets additional host variables from all inventories """
|
||||
|
|
|
@ -34,7 +34,7 @@ class InventoryParser(object):
|
|||
"""
|
||||
|
||||
def __init__(self, filename=C.DEFAULT_HOST_LIST):
|
||||
|
||||
self.filename = filename
|
||||
with open(filename) as fh:
|
||||
self.lines = fh.readlines()
|
||||
self.groups = {}
|
||||
|
@ -142,7 +142,7 @@ class InventoryParser(object):
|
|||
try:
|
||||
(k,v) = t.split("=", 1)
|
||||
except ValueError, e:
|
||||
raise AnsibleError("Invalid ini entry: %s - %s" % (t, str(e)))
|
||||
raise AnsibleError("Invalid ini entry in %s: %s - %s" % (self.filename, t, str(e)))
|
||||
if k == 'ansible_ssh_host':
|
||||
host.ipv4_address = self._parse_value(v)
|
||||
else:
|
||||
|
|
|
@ -19,19 +19,21 @@
|
|||
|
||||
import os
|
||||
import subprocess
|
||||
import ansible.constants as C
|
||||
import sys
|
||||
|
||||
from ansible import constants as C
|
||||
from ansible.errors import *
|
||||
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 import utils
|
||||
from ansible import errors
|
||||
import sys
|
||||
|
||||
|
||||
class InventoryScript(object):
|
||||
class InventoryScript:
|
||||
''' Host inventory parser for ansible using external inventory scripts. '''
|
||||
|
||||
def __init__(self, filename=C.DEFAULT_HOST_LIST):
|
||||
def __init__(self, loader, filename=C.DEFAULT_HOST_LIST):
|
||||
|
||||
self._loader = loader
|
||||
|
||||
# Support inventory scripts that are not prefixed with some
|
||||
# path information but happen to be in the current working
|
||||
|
@ -41,11 +43,11 @@ class InventoryScript(object):
|
|||
try:
|
||||
sp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except OSError, e:
|
||||
raise errors.AnsibleError("problem running %s (%s)" % (' '.join(cmd), e))
|
||||
raise AnsibleError("problem running %s (%s)" % (' '.join(cmd), e))
|
||||
(stdout, stderr) = sp.communicate()
|
||||
|
||||
if sp.returncode != 0:
|
||||
raise errors.AnsibleError("Inventory script (%s) had an execution error: %s " % (filename,stderr))
|
||||
raise AnsibleError("Inventory script (%s) had an execution error: %s " % (filename,stderr))
|
||||
|
||||
self.data = stdout
|
||||
# see comment about _meta below
|
||||
|
@ -58,7 +60,7 @@ class InventoryScript(object):
|
|||
all_hosts = {}
|
||||
|
||||
# not passing from_remote because data from CMDB is trusted
|
||||
self.raw = utils.parse_json(self.data)
|
||||
self.raw = self._loader.load(self.data)
|
||||
self.raw = json_dict_bytes_to_unicode(self.raw)
|
||||
|
||||
all = Group('all')
|
||||
|
@ -68,7 +70,7 @@ class InventoryScript(object):
|
|||
|
||||
if 'failed' in self.raw:
|
||||
sys.stderr.write(err + "\n")
|
||||
raise errors.AnsibleError("failed to parse executable inventory script results: %s" % self.raw)
|
||||
raise AnsibleError("failed to parse executable inventory script results: %s" % self.raw)
|
||||
|
||||
for (group_name, data) in self.raw.items():
|
||||
|
||||
|
@ -97,7 +99,7 @@ class InventoryScript(object):
|
|||
|
||||
if 'hosts' in data:
|
||||
if not isinstance(data['hosts'], list):
|
||||
raise errors.AnsibleError("You defined a group \"%s\" with bad "
|
||||
raise AnsibleError("You defined a group \"%s\" with bad "
|
||||
"data for the host list:\n %s" % (group_name, data))
|
||||
|
||||
for hostname in data['hosts']:
|
||||
|
@ -108,7 +110,7 @@ class InventoryScript(object):
|
|||
|
||||
if 'vars' in data:
|
||||
if not isinstance(data['vars'], dict):
|
||||
raise errors.AnsibleError("You defined a group \"%s\" with bad "
|
||||
raise AnsibleError("You defined a group \"%s\" with bad "
|
||||
"data for variables:\n %s" % (group_name, data))
|
||||
|
||||
for k, v in data['vars'].iteritems():
|
||||
|
@ -143,12 +145,12 @@ class InventoryScript(object):
|
|||
try:
|
||||
sp = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
|
||||
except OSError, e:
|
||||
raise errors.AnsibleError("problem running %s (%s)" % (' '.join(cmd), e))
|
||||
raise AnsibleError("problem running %s (%s)" % (' '.join(cmd), e))
|
||||
(out, err) = sp.communicate()
|
||||
if out.strip() == '':
|
||||
return dict()
|
||||
try:
|
||||
return json_dict_bytes_to_unicode(utils.parse_json(out))
|
||||
return json_dict_bytes_to_unicode(self._loader.load(out))
|
||||
except ValueError:
|
||||
raise errors.AnsibleError("could not parse post variable response: %s, %s" % (cmd, out))
|
||||
raise AnsibleError("could not parse post variable response: %s, %s" % (cmd, out))
|
||||
|
||||
|
|
|
@ -66,7 +66,6 @@ class DataLoader():
|
|||
a JSON or YAML string.
|
||||
'''
|
||||
|
||||
#print("in load, data is: %s (%s)" % (data, type(data)))
|
||||
try:
|
||||
# we first try to load this data as JSON
|
||||
return json.loads(data)
|
||||
|
@ -109,8 +108,6 @@ class DataLoader():
|
|||
def _safe_load(self, stream, file_name=None):
|
||||
''' Implements yaml.safe_load(), except using our custom loader class. '''
|
||||
|
||||
#print("stream is: %s" % stream)
|
||||
#print("file name is: %s" % file_name)
|
||||
loader = AnsibleLoader(stream, file_name)
|
||||
try:
|
||||
return loader.get_single_data()
|
||||
|
|
26
v2/ansible/utils/path.py
Normal file
26
v2/ansible/utils/path.py
Normal file
|
@ -0,0 +1,26 @@
|
|||
# (c) 2012-2014, Michael DeHaan <michael.dehaan@gmail.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 stat
|
||||
|
||||
__all__ = ['is_executable']
|
||||
|
||||
def is_executable(path):
|
||||
'''is the given path executable?'''
|
||||
return (stat.S_IXUSR & os.stat(path)[stat.ST_MODE] or stat.S_IXGRP & os.stat(path)[stat.ST_MODE] or stat.S_IXOTH & os.stat(path)[stat.ST_MODE])
|
||||
|
Loading…
Reference in a new issue