diff --git a/filter_plugins/generate_all_domains.py b/filter_plugins/generate_all_domains.py new file mode 100644 index 00000000..b9084352 --- /dev/null +++ b/filter_plugins/generate_all_domains.py @@ -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}") \ No newline at end of file diff --git a/tasks/constructor.yml b/tasks/constructor.yml index 2ece37bf..9964d5ea 100644 --- a/tasks/constructor.yml +++ b/tasks/constructor.yml @@ -75,18 +75,13 @@ set_fact: base_sld_domains: "{{ base_domains | map('regex_replace', '^(?:.*\\.)?([^.]+\\.[^.]+)$', '\\1') | list | unique | sort }}" - - name: Initialise all_domains as empty list - set_fact: - all_domains: [] - - - name: Build all_domains with base + www via loop - 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 }}" + - set_fact: + all_domains: >- + {{ domains + | generate_all_domains( + ('www_redirect' in group_names) + ) + }} - name: "Merged Variables" # Add new merged variables here diff --git a/tests/unit/test_generate_all_domains.py b/tests/unit/test_generate_all_domains.py new file mode 100644 index 00000000..64d9c382 --- /dev/null +++ b/tests/unit/test_generate_all_domains.py @@ -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()