mirror of
https://github.com/ansible-collections/community.general.git
synced 2026-04-24 23:46:32 +00:00
./group_vars/groupname.yml (for all groups the host is in) ./host_vars/hostname.yml (for the hostname given in the inventory) This requires an actual inventory file, not script and the paths are relative to the directory of the inventory file.
191 lines
6.7 KiB
Python
191 lines
6.7 KiB
Python
# (c) 2012, 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 fnmatch
|
|
import os
|
|
|
|
import subprocess
|
|
import ansible.constants as C
|
|
from ansible.inventory.ini import InventoryParser
|
|
from ansible.inventory.yaml import InventoryParserYaml
|
|
from ansible.inventory.script import InventoryScript
|
|
from ansible.inventory.group import Group
|
|
from ansible.inventory.host import Host
|
|
from ansible import errors
|
|
from ansible import utils
|
|
|
|
class Inventory(object):
|
|
"""
|
|
Host inventory for ansible.
|
|
"""
|
|
|
|
def __init__(self, host_list=C.DEFAULT_HOST_LIST):
|
|
|
|
# the host file file, or script path, or list of hosts
|
|
# if a list, inventory data will NOT be loaded
|
|
self.host_list = host_list
|
|
|
|
# the inventory object holds a list of groups
|
|
self.groups = []
|
|
|
|
# a list of host(names) to contain current inquiries to
|
|
self._restriction = None
|
|
|
|
# whether the inventory file is a script
|
|
self._is_script = False
|
|
|
|
if type(host_list) in [ str, unicode ]:
|
|
if host_list.find(",") != -1:
|
|
host_list = host_list.split(",")
|
|
host_list = [ h for h in host_list if h and h.strip() ]
|
|
|
|
if type(host_list) == list:
|
|
all = Group('all')
|
|
self.groups = [ all ]
|
|
for x in host_list:
|
|
if x.find(":") != -1:
|
|
tokens = x.split(":",1)
|
|
all.add_host(Host(tokens[0], tokens[1]))
|
|
else:
|
|
all.add_host(Host(x))
|
|
elif os.access(host_list, os.X_OK):
|
|
self._is_script = True
|
|
self.parser = InventoryScript(filename=host_list)
|
|
self.groups = self.parser.groups.values()
|
|
else:
|
|
data = file(host_list).read()
|
|
if not data.startswith("---"):
|
|
self.parser = InventoryParser(filename=host_list)
|
|
self.groups = self.parser.groups.values()
|
|
else:
|
|
self.parser = InventoryParserYaml(filename=host_list)
|
|
self.groups = self.parser.groups.values()
|
|
|
|
def _match(self, str, pattern_str):
|
|
return fnmatch.fnmatch(str, pattern_str)
|
|
|
|
# TODO: cache this logic so if called a second time the result is not recalculated
|
|
def get_hosts(self, pattern="all"):
|
|
""" Get all host objects matching the pattern """
|
|
hosts = {}
|
|
patterns = pattern.replace(";",":").split(":")
|
|
|
|
groups = self.get_groups()
|
|
for pat in patterns:
|
|
if pat.startswith("!"):
|
|
pat = pat[1:]
|
|
inverted = True
|
|
else:
|
|
inverted = False
|
|
for group in groups:
|
|
for host in group.get_hosts():
|
|
if group.name == pat or pat == 'all' or self._match(host.name, pat):
|
|
# must test explicitly for None because [] means no hosts allowed
|
|
if self._restriction==None or host.name in self._restriction:
|
|
if inverted:
|
|
if host.name in hosts:
|
|
del hosts[host.name]
|
|
else:
|
|
hosts[host.name] = host
|
|
return sorted(hosts.values(), key=lambda x: x.name)
|
|
|
|
def get_groups(self):
|
|
return self.groups
|
|
|
|
# TODO: cache this logic so if called a second time the result is not recalculated
|
|
# if using inventory scripts
|
|
def get_host(self, hostname):
|
|
for group in self.groups:
|
|
for host in group.get_hosts():
|
|
if hostname == host.name:
|
|
return host
|
|
return None
|
|
|
|
def get_group(self, groupname):
|
|
for group in self.groups:
|
|
if group.name == groupname:
|
|
return group
|
|
return None
|
|
|
|
# TODO: cache this logic so if called a second time the result is not recalculated
|
|
# if using inventory scripts
|
|
def get_group_variables(self, groupname):
|
|
group = self.get_group(groupname)
|
|
if group is None:
|
|
raise Exception("group not found: %s" % groupname)
|
|
return group.get_variables()
|
|
|
|
# TODO: cache this logic so if called a second time the result is not recalculated
|
|
# if using inventory scripts
|
|
def get_variables(self, hostname):
|
|
|
|
if self._is_script:
|
|
host = self.get_host(hostname)
|
|
cmd = subprocess.Popen(
|
|
[self.host_list,"--host",hostname],
|
|
stdout=subprocess.PIPE,
|
|
stderr=subprocess.PIPE
|
|
)
|
|
(out, err) = cmd.communicate()
|
|
results = utils.parse_json(out)
|
|
results['inventory_hostname'] = hostname
|
|
groups = [ g.name for g in host.get_groups() if g.name != 'all' ]
|
|
results['group_names'] = sorted(groups)
|
|
return results
|
|
|
|
host = self.get_host(hostname)
|
|
if host is None:
|
|
raise Exception("host not found: %s" % hostname)
|
|
return host.get_variables()
|
|
|
|
def add_group(self, group):
|
|
self.groups.append(group)
|
|
|
|
def list_hosts(self, pattern="all"):
|
|
return [ h.name for h in self.get_hosts(pattern) ]
|
|
|
|
def list_groups(self):
|
|
return [ g.name for g in self.groups ]
|
|
|
|
def get_restriction(self):
|
|
return self._restriction
|
|
|
|
def restrict_to(self, restriction, append_missing=False):
|
|
""" Restrict list operations to the hosts given in restriction """
|
|
if type(restriction) != list:
|
|
restriction = [ restriction ]
|
|
self._restriction = restriction
|
|
|
|
def lift_restriction(self):
|
|
""" Do not restrict list operations """
|
|
|
|
self._restriction = None
|
|
|
|
def is_file(self):
|
|
""" did inventory come from a file? """
|
|
if not isinstance(self.host_list, basestring):
|
|
return False
|
|
return os.path.exists(self.host_list)
|
|
|
|
def basedir(self):
|
|
""" if inventory came from a file, what's the directory? """
|
|
if not self.is_file():
|
|
return None
|
|
return os.path.dirname(self.host_list)
|