Files
computer-playbook/tests/unit/python/plugins/lookup/test_canonical_url.py
T
kevinveenbirkenbachandClaude Opus 5 e8e89d293d refactor(seaweedfs): split the object store from its browser consoles
web-app-seaweedfs becomes two roles. web-svc-seaweedfs keeps the storage
engine: the container, the seaweedfs_data volume, the per-consumer S3
identities and the single canonical domain api. web-app-seaweedfs-console
takes the filer and master web UIs into its own compose stack behind the
admin-only oauth2 proxy, reaching the engine over the shared object-store
network. A node can now run the store without the consoles.

The console needs a distinct role name because get_entity_name strips the
category prefix: both halves would have resolved to the entity seaweedfs and
collided on the compose project, the instance directory and the container
name.

The filer and master ports move into the engine's services.seaweedfs.ports
.internal as their single owner; 01_init_consumer.yml consumes the master
port and would otherwise have resolved it only by role-var leakage from the
console, breaking bucket provisioning on exactly the console-less node the
split makes possible.

The engine's api vhost gains the prometheus locations. It never had them: the
override satisfied the cross-cutting-include lint only because the strings sat
in the SSO branch that the api domain never took.

Consumers, the objstore lookup and the catalogs follow the role id.

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-01 02:20:12 +02:00

177 lines
5.8 KiB
Python

import unittest
from unittest.mock import MagicMock, patch
from ansible.errors import AnsibleError
from plugins.lookup.canonical_url import LookupModule
class TestCanonicalUrlLookup(unittest.TestCase):
def setUp(self):
self.lookup = LookupModule()
self.base_vars = {"TLS_ENABLED": True}
def _get(name, *args, **kwargs):
plugin = MagicMock()
def _run(terms, variables=None, **_kwargs):
key = "domains" if name == "domains" else "applications"
return [(variables or {}).get(key, {})]
plugin.run.side_effect = _run
return plugin
patcher = patch(
"plugins.lookup.canonical_url.lookup_loader.get",
side_effect=_get,
)
patcher.start()
self.addCleanup(patcher.stop)
def _run(self, terms, domains, applications=None, extra_vars=None, **kwargs):
v = dict(self.base_vars)
v["domains"] = domains
v["applications"] = applications or {}
if extra_vars:
v.update(extra_vars)
return self.lookup.run(terms, variables=v, **kwargs)[0]
def test_primary_clearnet_is_https(self):
out = self._run(["web-app-a"], {"web-app-a": ["a.example"]})
self.assertEqual(out, "https://a.example")
def test_primary_onion_is_http(self):
out = self._run(["web-app-a"], {"web-app-a": ["a.abc.onion"]})
self.assertEqual(out, "http://a.abc.onion")
def test_named_canonical_clearnet(self):
out = self._run(
["web-app-matrix", "element"],
{
"web-app-matrix": {
"synapse": "matrix.example",
"element": "element.example",
}
},
)
self.assertEqual(out, "https://element.example")
def test_named_canonical_onion(self):
out = self._run(
["web-app-matrix", "synapse"],
{
"web-app-matrix": {
"synapse": "matrix.abc.onion",
"element": "element.abc.onion",
}
},
)
self.assertEqual(out, "http://matrix.abc.onion")
def test_missing_key_raises(self):
with self.assertRaises(AnsibleError):
self._run(
["web-app-matrix", "nope"],
{"web-app-matrix": {"element": "element.example"}},
)
def test_key_on_list_domain_raises(self):
with self.assertRaises(AnsibleError):
self._run(["web-app-a", "element"], {"web-app-a": ["a.example"]})
def test_bad_arity_raises(self):
with self.assertRaises(AnsibleError):
self.lookup.run([], variables=self.base_vars)
def test_primary_aligns_to_clearnet_consumer(self):
out = self._run(
["web-svc-cdn"],
{
"web-svc-cdn": ["cdn.abc.onion", "cdn.example"],
"web-app-bigbluebutton": ["bbb.example"],
},
extra_vars={"application_id": "web-app-bigbluebutton"},
)
self.assertEqual(out, "https://cdn.example")
def test_primary_stays_onion_for_onion_consumer(self):
out = self._run(
["web-svc-cdn"],
{
"web-svc-cdn": ["cdn.abc.onion", "cdn.example"],
"web-app-dashboard": ["dash.abc.onion"],
},
extra_vars={"application_id": "web-app-dashboard"},
)
self.assertEqual(out, "http://cdn.abc.onion")
def test_primary_onion_only_falls_back_for_clearnet_consumer(self):
out = self._run(
["web-svc-cdn"],
{
"web-svc-cdn": ["cdn.abc.onion"],
"web-app-bigbluebutton": ["bbb.example"],
},
extra_vars={"application_id": "web-app-bigbluebutton"},
)
self.assertEqual(out, "http://cdn.abc.onion")
def test_primary_unchanged_without_consumer_context(self):
out = self._run(
["web-svc-cdn"],
{
"web-svc-cdn": ["cdn.abc.onion", "cdn.example"],
"web-app-bigbluebutton": ["bbb.example"],
},
)
self.assertEqual(out, "http://cdn.abc.onion")
def test_consumer_kwarg_drives_alignment(self):
out = self._run(
["web-svc-cdn"],
{
"web-svc-cdn": ["cdn.abc.onion", "cdn.example"],
"web-app-bigbluebutton": ["bbb.example"],
},
applications={
"web-app-bigbluebutton": {"services": {"cdn": {"enabled": True}}}
},
consumer="web-app-bigbluebutton",
)
self.assertEqual(out, "https://cdn.example")
def test_consumer_with_enabled_binding_resolves(self):
out = self._run(
["web-svc-seaweedfs", "filer"],
{"web-svc-seaweedfs": {"filer": "filer.example"}},
applications={
"web-app-nextcloud": {"services": {"seaweedfs": {"enabled": True}}}
},
consumer="web-app-nextcloud",
)
self.assertEqual(out, "https://filer.example")
def test_consumer_with_disabled_binding_is_empty(self):
out = self._run(
["web-svc-seaweedfs", "filer"],
{"web-svc-seaweedfs": {"filer": "filer.example"}},
applications={
"web-app-nextcloud": {"services": {"seaweedfs": {"enabled": False}}}
},
consumer="web-app-nextcloud",
)
self.assertEqual(out, "")
def test_consumer_without_binding_is_empty(self):
out = self._run(
["web-svc-seaweedfs", "filer"],
{"web-svc-seaweedfs": {"filer": "filer.example"}},
applications={"web-app-nextcloud": {"services": {}}},
consumer="web-app-nextcloud",
)
self.assertEqual(out, "")
if __name__ == "__main__":
unittest.main()