Optimized filter logic for all domains

This commit is contained in:
Kevin Veen-Birkenbach 2025-05-17 11:54:23 +02:00
parent ca5c3c6e8a
commit 76f303da27
No known key found for this signature in database
GPG Key ID: 44D8F11FD62F878E
3 changed files with 106 additions and 12 deletions

View File

@ -0,0 +1,47 @@
import os
from ansible.errors import AnsibleFilterError
class FilterModule(object):
"""
Custom Ansible filter to generate a flattened, deduplicated,
and sorted list of domains, with optional 'www.' prefixes.
"""
def filters(self):
return {
'generate_all_domains': self.generate_all_domains,
}
@staticmethod
def generate_all_domains(domains_dict, include_www=True):
"""
Transform a dict of domains into a flat list of domain strings.
Values in domains_dict may be strings, lists, or dicts.
If include_www is True, also generate "www." variants.
The final list is deduplicated and sorted alphabetically.
:param domains_dict: dict where each value is str, list, or dict of domains
:param include_www: bool indicating if 'www.' prefixes should be added
:return: sorted list of unique domain names
"""
try:
flat = []
for val in domains_dict.values():
if isinstance(val, str):
flat.append(val)
elif isinstance(val, list):
flat.extend(val)
elif isinstance(val, dict):
flat.extend(val.values())
else:
# skip unsupported types
continue
if include_www:
flat.extend(['www.' + d for d in flat])
# dedupe and sort
return sorted(set(flat))
except Exception as exc:
raise AnsibleFilterError(f"generate_all_domains failed: {exc}")

View File

@ -75,18 +75,13 @@
set_fact: set_fact:
base_sld_domains: "{{ base_domains | map('regex_replace', '^(?:.*\\.)?([^.]+\\.[^.]+)$', '\\1') | list | unique | sort }}" base_sld_domains: "{{ base_domains | map('regex_replace', '^(?:.*\\.)?([^.]+\\.[^.]+)$', '\\1') | list | unique | sort }}"
- name: Initialise all_domains as empty list - set_fact:
set_fact: all_domains: >-
all_domains: [] {{ domains
| generate_all_domains(
- name: Build all_domains with base + www via loop ('www_redirect' in group_names)
set_fact: )
all_domains: "{{ all_domains + [ item, 'www.' ~ item ] }}" }}
loop: "{{ base_domains }}"
- name: Deduplicate and sort all_domains
set_fact:
all_domains: "{{ all_domains | unique | sort }}"
- name: "Merged Variables" - name: "Merged Variables"
# Add new merged variables here # Add new merged variables here

View File

@ -0,0 +1,52 @@
import sys
import os
import pytest
from filter_plugins.generate_all_domains import FilterModule
@pytest.fixture
def generate_filter():
"""
Fixture to return the generate_all_domains filter function.
"""
fm = FilterModule()
return fm.generate_all_domains
def test_simple_string_values(generate_filter):
domains = {'app': 'example.com'}
result = generate_filter(domains)
# Expect original and www-prefixed, deduped and sorted
expected = ['example.com', 'www.example.com']
assert result == expected
def test_list_and_dict_values(generate_filter):
domains = {
'app1': ['one.com', 'two.com'],
'app2': {'x': 'x.com', 'y': 'y.com'}
}
result = generate_filter(domains)
expected = sorted([
'one.com', 'two.com', 'x.com', 'y.com',
'www.one.com', 'www.two.com', 'www.x.com', 'www.y.com'
])
assert result == expected
def test_include_www_false(generate_filter):
domains = {'app': 'no-www.com'}
result = generate_filter(domains, include_www=False)
# Only the original domain
assert result == ['no-www.com']
def test_deduplicate_and_sort(generate_filter):
domains = {
'a': 'dup.com',
'b': 'dup.com',
'c': ['b.com', 'a.com'],
}
result = generate_filter(domains)
# Should contain unique domains sorted alphabetically
expected = ['a.com', 'b.com', 'dup.com', 'www.a.com', 'www.b.com', 'www.dup.com']
assert result == expected
if __name__ == '__main__':
pytest.main()