mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2025-09-20 01:06:03 +02:00
filter/domain_redirect_mappings: add auto_build_alias parameter
- Extend filter signature with auto_build_alias flag to control automatic default→canonical alias creation - group_vars/all: introduce AUTO_BUILD_ALIASES variable for global toggle - Update unit tests: adjust calls to new signature and add dedicated test cases for auto_build_aliases=False Ref: conversation https://chatgpt.com/share/68cd512c-c878-800f-bdf2-81737adf7e0e
This commit is contained in:
@@ -7,7 +7,7 @@ class FilterModule(object):
|
||||
def filters(self):
|
||||
return {'domain_mappings': self.domain_mappings}
|
||||
|
||||
def domain_mappings(self, apps, PRIMARY_DOMAIN):
|
||||
def domain_mappings(self, apps, primary_domain, auto_build_alias):
|
||||
"""
|
||||
Build a flat list of redirect mappings for all apps:
|
||||
- source: each alias domain
|
||||
@@ -43,7 +43,7 @@ class FilterModule(object):
|
||||
domains_cfg = cfg.get('server',{}).get('domains',{})
|
||||
entry = domains_cfg.get('canonical')
|
||||
if entry is None:
|
||||
canonical_map[app_id] = [default_domain(app_id, PRIMARY_DOMAIN)]
|
||||
canonical_map[app_id] = [default_domain(app_id, primary_domain)]
|
||||
elif isinstance(entry, dict):
|
||||
canonical_map[app_id] = list(entry.values())
|
||||
elif isinstance(entry, list):
|
||||
@@ -61,11 +61,11 @@ class FilterModule(object):
|
||||
alias_map[app_id] = []
|
||||
continue
|
||||
if isinstance(domains_cfg, dict) and not domains_cfg:
|
||||
alias_map[app_id] = [default_domain(app_id, PRIMARY_DOMAIN)]
|
||||
alias_map[app_id] = [default_domain(app_id, primary_domain)]
|
||||
continue
|
||||
|
||||
aliases = parse_entry(domains_cfg, 'aliases', app_id) or []
|
||||
default = default_domain(app_id, PRIMARY_DOMAIN)
|
||||
default = default_domain(app_id, primary_domain)
|
||||
has_aliases = 'aliases' in domains_cfg
|
||||
has_canonical = 'canonical' in domains_cfg
|
||||
|
||||
@@ -74,7 +74,7 @@ class FilterModule(object):
|
||||
aliases.append(default)
|
||||
elif has_canonical:
|
||||
canon = canonical_map.get(app_id, [])
|
||||
if default not in canon and default not in aliases:
|
||||
if default not in canon and default not in aliases and auto_build_alias:
|
||||
aliases.append(default)
|
||||
|
||||
alias_map[app_id] = aliases
|
||||
@@ -84,7 +84,7 @@ class FilterModule(object):
|
||||
mappings = []
|
||||
for app_id, sources in alias_map.items():
|
||||
canon_list = canonical_map.get(app_id, [])
|
||||
target = canon_list[0] if canon_list else default_domain(app_id, PRIMARY_DOMAIN)
|
||||
target = canon_list[0] if canon_list else default_domain(app_id, primary_domain)
|
||||
for src in sources:
|
||||
if src == target:
|
||||
# skip self-redirects
|
||||
|
@@ -32,8 +32,10 @@ WEBSOCKET_PROTOCOL: "{{ 'wss' if WEB_PROTOCOL == 'https' else 'ws' }}"
|
||||
# WWW-Redirect to None WWW-Domains enabled
|
||||
WWW_REDIRECT_ENABLED: "{{ ('web-opt-rdr-www' in group_names) | bool }}"
|
||||
|
||||
AUTO_BUILD_ALIASES: False # If enabled it creates an alias domain for each web application by the entity name, recommended to set to false to safge domain space
|
||||
|
||||
# Domain
|
||||
PRIMARY_DOMAIN: "localhost" # Primary Domain of the server
|
||||
PRIMARY_DOMAIN: "localhost" # Primary Domain of the server
|
||||
|
||||
DNS_PROVIDER: cloudflare # The DNS Provider\Registrar for the domain
|
||||
|
||||
|
@@ -18,20 +18,20 @@ class TestDomainMappings(unittest.TestCase):
|
||||
|
||||
def test_empty_apps(self):
|
||||
apps = {}
|
||||
result = self.filter.domain_mappings(apps, self.primary)
|
||||
result = self.filter.domain_mappings(apps, self.primary, True)
|
||||
self.assertEqual(result, [])
|
||||
|
||||
def test_app_without_domains(self):
|
||||
apps = {'web-app-desktop': {}}
|
||||
# no domains key → no mappings
|
||||
result = self.filter.domain_mappings(apps, self.primary)
|
||||
result = self.filter.domain_mappings(apps, self.primary, True)
|
||||
self.assertEqual(result, [])
|
||||
|
||||
def test_empty_domains_cfg(self):
|
||||
apps = {'web-app-desktop': {'domains': {}}}
|
||||
default = 'desktop.example.com'
|
||||
expected = []
|
||||
result = self.filter.domain_mappings(apps, self.primary)
|
||||
result = self.filter.domain_mappings(apps, self.primary, True)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_explicit_aliases(self):
|
||||
@@ -46,7 +46,7 @@ class TestDomainMappings(unittest.TestCase):
|
||||
expected = [
|
||||
{'source': 'alias.com', 'target': default},
|
||||
]
|
||||
result = self.filter.domain_mappings(apps, self.primary)
|
||||
result = self.filter.domain_mappings(apps, self.primary, True)
|
||||
# order not important
|
||||
self.assertCountEqual(result, expected)
|
||||
|
||||
@@ -61,7 +61,7 @@ class TestDomainMappings(unittest.TestCase):
|
||||
expected = [
|
||||
{'source': 'desktop.example.com', 'target': 'foo.com'}
|
||||
]
|
||||
result = self.filter.domain_mappings(apps, self.primary)
|
||||
result = self.filter.domain_mappings(apps, self.primary, True)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_canonical_dict(self):
|
||||
@@ -78,7 +78,7 @@ class TestDomainMappings(unittest.TestCase):
|
||||
expected = [
|
||||
{'source': 'desktop.example.com', 'target': 'one.com'}
|
||||
]
|
||||
result = self.filter.domain_mappings(apps, self.primary)
|
||||
result = self.filter.domain_mappings(apps, self.primary, True)
|
||||
self.assertEqual(result, expected)
|
||||
|
||||
def test_multiple_apps(self):
|
||||
@@ -94,7 +94,7 @@ class TestDomainMappings(unittest.TestCase):
|
||||
{'source': 'a1.com', 'target': 'desktop.example.com'},
|
||||
{'source': 'mastodon.example.com', 'target': 'c2.com'},
|
||||
]
|
||||
result = self.filter.domain_mappings(apps, self.primary)
|
||||
result = self.filter.domain_mappings(apps, self.primary, True)
|
||||
self.assertCountEqual(result, expected)
|
||||
|
||||
def test_multiple_aliases(self):
|
||||
@@ -108,7 +108,7 @@ class TestDomainMappings(unittest.TestCase):
|
||||
{'source': 'a1.com', 'target': 'desktop.example.com'},
|
||||
{'source': 'a2.com', 'target': 'desktop.example.com'}
|
||||
]
|
||||
result = self.filter.domain_mappings(apps, self.primary)
|
||||
result = self.filter.domain_mappings(apps, self.primary, True)
|
||||
self.assertCountEqual(result, expected)
|
||||
|
||||
def test_invalid_aliases_type(self):
|
||||
@@ -116,8 +116,77 @@ class TestDomainMappings(unittest.TestCase):
|
||||
'web-app-desktop': {'server':{'domains': {'aliases': 123}}}
|
||||
}
|
||||
with self.assertRaises(AnsibleFilterError):
|
||||
self.filter.domain_mappings(apps, self.primary)
|
||||
self.filter.domain_mappings(apps, self.primary, True)
|
||||
|
||||
def test_canonical_not_default_no_autobuild(self):
|
||||
"""
|
||||
When only a canonical different from the default exists and auto_build_aliases is False,
|
||||
we should NOT auto-generate a default alias -> canonical mapping.
|
||||
"""
|
||||
apps = {
|
||||
'web-app-desktop': {
|
||||
'server': {
|
||||
'domains': {'canonical': ['foo.com']}
|
||||
}
|
||||
}
|
||||
}
|
||||
result = self.filter.domain_mappings(apps, self.primary, False)
|
||||
self.assertEqual(result, []) # no auto-added default alias
|
||||
|
||||
def test_aliases_and_canonical_no_autobuild_still_adds_default(self):
|
||||
"""
|
||||
If explicit aliases are present, the filter always appends the default domain
|
||||
to the alias list (to cover 'www'/'root' style defaults), regardless of auto_build_aliases.
|
||||
With a canonical set, both the explicit alias and the default should point to the canonical.
|
||||
"""
|
||||
apps = {
|
||||
'web-app-desktop': {
|
||||
'server': {
|
||||
'domains': {
|
||||
'aliases': ['alias.com'],
|
||||
'canonical': ['foo.com']
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
expected = [
|
||||
{'source': 'alias.com', 'target': 'foo.com'},
|
||||
{'source': 'desktop.example.com', 'target': 'foo.com'},
|
||||
]
|
||||
result = self.filter.domain_mappings(apps, self.primary, False)
|
||||
self.assertCountEqual(result, expected)
|
||||
|
||||
def test_mixed_apps_no_autobuild(self):
|
||||
"""
|
||||
One app with only canonical (no aliases) and one app with only aliases:
|
||||
- The canonical-only app produces no mappings when auto_build_aliases is False.
|
||||
- The alias-only app maps its aliases to its default domain; default self-mapping is skipped.
|
||||
"""
|
||||
apps = {
|
||||
'web-app-desktop': {
|
||||
'server': {'domains': {'canonical': ['c1.com']}}
|
||||
},
|
||||
'web-app-mastodon': {
|
||||
'server': {'domains': {'aliases': ['m1.com']}}
|
||||
},
|
||||
}
|
||||
expected = [
|
||||
{'source': 'm1.com', 'target': 'mastodon.example.com'},
|
||||
]
|
||||
result = self.filter.domain_mappings(apps, self.primary, False)
|
||||
self.assertCountEqual(result, expected)
|
||||
|
||||
def test_no_domains_key_no_autobuild(self):
|
||||
"""
|
||||
App ohne 'server.domains' erzeugt keine Mappings, unabhängig von auto_build_aliases.
|
||||
"""
|
||||
apps = {
|
||||
'web-app-desktop': {
|
||||
# no 'server' or 'domains'
|
||||
}
|
||||
}
|
||||
result = self.filter.domain_mappings(apps, self.primary, False)
|
||||
self.assertEqual(result, [])
|
||||
|
||||
if __name__ == "__main__":
|
||||
unittest.main()
|
||||
|
Reference in New Issue
Block a user