Added recursiv dependency resolution

This commit is contained in:
Kevin Veen-Birkenbach 2025-05-17 10:48:58 +02:00
parent 06238343df
commit d51be05d83
No known key found for this signature in database
GPG Key ID: 44D8F11FD62F878E

View File

@ -1,8 +1,15 @@
import os
import yaml
from ansible.errors import AnsibleFilterError from ansible.errors import AnsibleFilterError
class FilterModule(object): class FilterModule(object):
""" """
Custom filters for conditional domain assignments Custom filters for conditional domain assignments, handling both direct group matches
and recursive role dependency resolution.
Determines if a given application_id (domain_key) should have its domain added by checking:
- If domain_key is explicitly listed in group_names, or
- If domain_key matches any application_id of roles reachable from active groups via dependencies.
""" """
def filters(self): def filters(self):
@ -13,17 +20,67 @@ class FilterModule(object):
@staticmethod @staticmethod
def add_domain_if_group(domains_dict, domain_key, domain_value, group_names): def add_domain_if_group(domains_dict, domain_key, domain_value, group_names):
""" """
Add {domain_key: domain_value} to domains_dict Add {domain_key: domain_value} to domains_dict if either:
only if domain_key is in group_names. 1) domain_key is in group_names (direct inclusion), or
2) domain_key is among collected application_id values of roles
reachable from any group in group_names via recursive dependencies.
Usage in Jinja: Parameters:
{{ {} domains_dict: existing dict of domains
| add_domain_if_group('akaunting', 'akaunting.' ~ primary_domain, group_names) }} domain_key: name of the application to check
domain_value: domain or dict/list of domains to assign
group_names: list of active group (role/application) names
""" """
try: try:
result = dict(domains_dict) result = dict(domains_dict)
# Direct group match: if the application name itself is in group_names
if domain_key in group_names: if domain_key in group_names:
result[domain_key] = domain_value result[domain_key] = domain_value
return result
# Setup roles directory path
plugin_dir = os.path.dirname(__file__)
project_root = os.path.abspath(os.path.join(plugin_dir, '..'))
roles_dir = os.path.join(project_root, 'roles')
# Collect all roles reachable from the active groups
def collect_roles(role_name, collected):
if role_name in collected:
return
collected.add(role_name)
meta_path = os.path.join(roles_dir, role_name, 'meta', 'main.yml')
if os.path.isfile(meta_path):
with open(meta_path) as f:
meta = yaml.safe_load(f) or {}
for dep in meta.get('dependencies', []):
if isinstance(dep, str):
dep_name = dep
elif isinstance(dep, dict):
dep_name = dep.get('role') or dep.get('name')
else:
continue
collect_roles(dep_name, collected)
included_roles = set()
for grp in group_names:
collect_roles(grp, included_roles)
# Gather application_ids from each included role
app_ids = set()
for role in included_roles:
vars_main = os.path.join(roles_dir, role, 'vars', 'main.yml')
if os.path.isfile(vars_main):
with open(vars_main) as f:
vars_data = yaml.safe_load(f) or {}
app_id = vars_data.get('application_id')
if app_id:
app_ids.add(app_id)
# Indirect inclusion: match by application_id
if domain_key in app_ids:
result[domain_key] = domain_value
return result return result
except Exception as exc: except Exception as exc:
raise AnsibleFilterError(f"add_domain_if_group failed: {exc}") raise AnsibleFilterError(f"add_domain_if_group failed: {exc}")