Last active
December 17, 2020 17:19
-
-
Save Timoses/17c39a100350eeedb10d77ab39b9eceb to your computer and use it in GitHub Desktop.
Ansible vars_plugin to load r_group_vars recursively from
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from __future__ import (absolute_import, division, print_function) | |
__metaclass__ = type | |
DOCUMENTATION = ''' | |
vars: recursive_group_vars | |
version_added: "?" | |
short_description: Loads group_vars recursively | |
description: | |
- In comparision to host_group_vars plugin, this plugin traverses the `r_group_vars` directory and instead of matching all files and directories within the first matching directory it traverses the directoy tree and recursively matches directories and files during directory traversal to groups | |
- If a file matching the group is found during traversal of a directory it is applied | |
- The deepest found matching file is applied last | |
- If several matching directories are found on the same level they are traversed consecutively (depth-first). This means that on the same level, the existing priorities apply (see [How variables are merged](https://docs.ansible.com/ansible/latest/user_guide/intro_inventory.html#how-variables-are-merged)) | |
- On the same directory level, a matching file will be applied first and then matching directories are traversed | |
- Only files that match a group are applied. Any other files are ignored. | |
- The following points are identical to host_group_vars plugin: | |
- Files are restricted by extension to one of .yaml, .json, .yml or no extension. | |
- Hidden (starting with '.') and backup (ending with '~') files and directories are ignored. | |
- Only applies to inventory sources that are existing paths. | |
options: | |
_valid_extensions: | |
default: [".yml", ".yaml", ".json"] | |
description: | |
- "Check all of these extensions when looking for 'variable' files which should be YAML or JSON or vaulted versions of these." | |
- 'This affects vars_files, include_vars, inventory and vars plugins among others.' | |
env: | |
- name: ANSIBLE_YAML_FILENAME_EXT | |
ini: | |
- section: yaml_valid_extensions | |
key: defaults | |
type: list | |
''' | |
import os | |
from ansible.module_utils._text import to_bytes, to_native, to_text | |
from ansible.errors import AnsibleParserError | |
from ansible.plugins.vars import BaseVarsPlugin | |
from ansible.inventory.group import Group | |
from ansible.utils.vars import combine_vars | |
FOUND = {} | |
class VarsModule(BaseVarsPlugin): | |
def find_vars_recurse(self, loader, groups, path): | |
data = {} | |
found_files = [] | |
for group in groups: | |
b_opath = os.path.realpath(to_bytes(os.path.join(path, group.name))) | |
if os.path.exists(b_opath): | |
try: | |
found_files = loader.find_vars_files(path, group.name, allow_dir=False) | |
for found in found_files: | |
new_data = loader.load_from_file(found, cache=True, unsafe=True) | |
if new_data: | |
data = combine_vars(data, new_data) | |
except Exception as e: | |
raise AnsibleParserError(to_native(e)) | |
if os.path.isdir(b_opath): | |
data = combine_vars(data, | |
self.find_vars_recurse(loader, groups, to_text(b_opath))) | |
return data | |
def get_vars(self, loader, path, entities, cache=True): | |
if not isinstance(entities, list): | |
entities = [entities] | |
groups = list(filter(lambda ent : isinstance(ent, Group), entities)) | |
if not groups: | |
return dict() | |
super(VarsModule, self).get_vars(loader, path, entities) | |
b_opath = os.path.realpath(to_bytes(os.path.join(self._basedir, 'r_group_vars'))) | |
data = {} | |
if os.path.exists(b_opath): | |
key = '.'.join(list(map(lambda group : group.name, groups)) + [to_text(b_opath)]) | |
if cache and key in FOUND: | |
data = FOUND[key] | |
else: | |
data = self.find_vars_recurse(loader, groups, to_text(b_opath)) | |
FOUND[key] = data | |
return data |
Hi, glad you're interested.
I've created a PR: ansible/ansible#60593 (review)
Would this suffice?
Otherwise let me know and I see what I can do (never dealt with copyright headers before; so a pointer is welcome).
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Hello! I relay want to use yours code. Can you insert copyright header into this code please.