diff options
author | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:55:42 +0000 |
---|---|---|
committer | Daniel Baumann <daniel.baumann@progress-linux.org> | 2024-04-19 00:55:42 +0000 |
commit | 62d9962ec7d01c95bf5732169320d3857a41446e (patch) | |
tree | f60d8fc63ff738e5f5afec48a84cf41480ee1315 /lib/ansible/plugins/vars | |
parent | Releasing progress-linux version 2.14.13-1~progress7.99u1. (diff) | |
download | ansible-core-62d9962ec7d01c95bf5732169320d3857a41446e.tar.xz ansible-core-62d9962ec7d01c95bf5732169320d3857a41446e.zip |
Merging upstream version 2.16.5.
Signed-off-by: Daniel Baumann <daniel.baumann@progress-linux.org>
Diffstat (limited to 'lib/ansible/plugins/vars')
-rw-r--r-- | lib/ansible/plugins/vars/__init__.py | 1 | ||||
-rw-r--r-- | lib/ansible/plugins/vars/host_group_vars.py | 95 |
2 files changed, 67 insertions, 29 deletions
diff --git a/lib/ansible/plugins/vars/__init__.py b/lib/ansible/plugins/vars/__init__.py index 2a7bafd..4f9045b 100644 --- a/lib/ansible/plugins/vars/__init__.py +++ b/lib/ansible/plugins/vars/__init__.py @@ -30,6 +30,7 @@ class BaseVarsPlugin(AnsiblePlugin): """ Loads variables for groups and/or hosts """ + is_stateless = False def __init__(self): """ constructor """ diff --git a/lib/ansible/plugins/vars/host_group_vars.py b/lib/ansible/plugins/vars/host_group_vars.py index 521b3b6..28b4213 100644 --- a/lib/ansible/plugins/vars/host_group_vars.py +++ b/lib/ansible/plugins/vars/host_group_vars.py @@ -54,20 +54,30 @@ DOCUMENTATION = ''' ''' import os -from ansible import constants as C from ansible.errors import AnsibleParserError -from ansible.module_utils._text import to_bytes, to_native, to_text +from ansible.module_utils.common.text.converters import to_native from ansible.plugins.vars import BaseVarsPlugin -from ansible.inventory.host import Host -from ansible.inventory.group import Group +from ansible.utils.path import basedir +from ansible.inventory.group import InventoryObjectType from ansible.utils.vars import combine_vars +CANONICAL_PATHS = {} # type: dict[str, str] FOUND = {} # type: dict[str, list[str]] +NAK = set() # type: set[str] +PATH_CACHE = {} # type: dict[tuple[str, str], str] class VarsModule(BaseVarsPlugin): REQUIRES_ENABLED = True + is_stateless = True + + def load_found_files(self, loader, data, found_files): + for found in found_files: + new_data = loader.load_from_file(found, cache=True, unsafe=True) + if new_data: # ignore empty files + data = combine_vars(data, new_data) + return data def get_vars(self, loader, path, entities, cache=True): ''' parses the inventory file ''' @@ -75,41 +85,68 @@ class VarsModule(BaseVarsPlugin): if not isinstance(entities, list): entities = [entities] - super(VarsModule, self).get_vars(loader, path, entities) + # realpath is expensive + try: + realpath_basedir = CANONICAL_PATHS[path] + except KeyError: + CANONICAL_PATHS[path] = realpath_basedir = os.path.realpath(basedir(path)) data = {} for entity in entities: - if isinstance(entity, Host): - subdir = 'host_vars' - elif isinstance(entity, Group): - subdir = 'group_vars' - else: + try: + entity_name = entity.name + except AttributeError: + raise AnsibleParserError("Supplied entity must be Host or Group, got %s instead" % (type(entity))) + + try: + first_char = entity_name[0] + except (TypeError, IndexError, KeyError): raise AnsibleParserError("Supplied entity must be Host or Group, got %s instead" % (type(entity))) # avoid 'chroot' type inventory hostnames /path/to/chroot - if not entity.name.startswith(os.path.sep): + if first_char != os.path.sep: try: found_files = [] # load vars - b_opath = os.path.realpath(to_bytes(os.path.join(self._basedir, subdir))) - opath = to_text(b_opath) - key = '%s.%s' % (entity.name, opath) - if cache and key in FOUND: - found_files = FOUND[key] + try: + entity_type = entity.base_type + except AttributeError: + raise AnsibleParserError("Supplied entity must be Host or Group, got %s instead" % (type(entity))) + + if entity_type is InventoryObjectType.HOST: + subdir = 'host_vars' + elif entity_type is InventoryObjectType.GROUP: + subdir = 'group_vars' else: - # no need to do much if path does not exist for basedir - if os.path.exists(b_opath): - if os.path.isdir(b_opath): - self._display.debug("\tprocessing dir %s" % opath) - found_files = loader.find_vars_files(opath, entity.name) - FOUND[key] = found_files - else: - self._display.warning("Found %s that is not a directory, skipping: %s" % (subdir, opath)) - - for found in found_files: - new_data = loader.load_from_file(found, cache=True, unsafe=True) - if new_data: # ignore empty files - data = combine_vars(data, new_data) + raise AnsibleParserError("Supplied entity must be Host or Group, got %s instead" % (type(entity))) + + if cache: + try: + opath = PATH_CACHE[(realpath_basedir, subdir)] + except KeyError: + opath = PATH_CACHE[(realpath_basedir, subdir)] = os.path.join(realpath_basedir, subdir) + + if opath in NAK: + continue + key = '%s.%s' % (entity_name, opath) + if key in FOUND: + data = self.load_found_files(loader, data, FOUND[key]) + continue + else: + opath = PATH_CACHE[(realpath_basedir, subdir)] = os.path.join(realpath_basedir, subdir) + + if os.path.isdir(opath): + self._display.debug("\tprocessing dir %s" % opath) + FOUND[key] = found_files = loader.find_vars_files(opath, entity_name) + elif not os.path.exists(opath): + # cache missing dirs so we don't have to keep looking for things beneath the + NAK.add(opath) + else: + self._display.warning("Found %s that is not a directory, skipping: %s" % (subdir, opath)) + # cache non-directory matches + NAK.add(opath) + + data = self.load_found_files(loader, data, found_files) except Exception as e: raise AnsibleParserError(to_native(e)) |