Merge branch 'feature/ai-agent-employees' into feature/store-i18n

This commit is contained in:
kevinveenbirkenbach committed 2026-09-16 15:42:53 +02:00
commit 071884a35e
170 files changed
+4745 -566

No files matched your search

+12 -2
View File
@@ -90,9 +90,19 @@ class TestApiLookup(unittest.TestCase):
self.lookup.run(["cloudflare.api_token"], variables={"API": "nope"})
self.assertIn("mapping", str(ctx.exception))
def test_missing_api_global_raises_unknown_key(self):
def test_missing_api_global_falls_back_to_the_declaration(self):
self.assertEqual(self.lookup.run(["cloudflare.api_token"], variables={})[0], "")
def test_a_provider_the_scope_omits_still_resolves(self):
out = self.lookup.run(
["github.client_id"],
variables={"API": {"cloudflare": {"api_token": "cf"}}},
)
self.assertEqual(out, [""])
def test_an_undeclared_provider_still_raises(self):
with self.assertRaises(AnsibleError):
self.lookup.run(["cloudflare.api_token"], variables={})
self.lookup.run(["nope.api_key"], variables=self.vars)
def test_templar_resolves_jinja_values(self):
self.lookup._templar = _FakeTemplar(mapping={"{{ vault_cf }}": "secret-cf"})
@@ -119,5 +119,133 @@ class TestContainerPortsLookup(unittest.TestCase):
self.assertEqual(out, ['ports:\n - "10.0.0.1:8002:3000"'])
def _edge_apps():
return {
"web-svc-coturn": {
"services": {
"coturn": {
"ports": {
"public": {
"stun_turn": 3481,
"relay": {"start": 20000, "end": 39999},
}
}
},
"openresty": {
"ports": {
"internal": {"http": 80},
"public": {"http": 80},
}
},
"api": {"ports": {"internal": {"http": 5000}}},
}
}
}
def _run_edge(terms):
lookup = LookupModule()
lookup._loader = mock.MagicMock()
apps = _edge_apps()
with patch("plugins.lookup.container_ports.lookup_loader") as loader_mock:
loader_mock.get.return_value = mock.MagicMock(run=lambda *_a, **_k: [apps])
return lookup.run(terms, variables={"application_id": "web-svc-coturn"})[0]
class TestContainerPortsDictTerms(unittest.TestCase):
def test_one_list_item_per_transport(self):
out = _run_edge(
[
{
"service": "coturn",
"protocol": "stun_turn",
"transport": ["udp", "tcp"],
"container": "same",
}
]
)
self.assertEqual(out, 'ports:\n - "3481:3481/udp"\n - "3481:3481/tcp"')
def test_a_range_renders_on_both_sides(self):
out = _run_edge(
[
{
"service": "coturn",
"protocol": "relay",
"transport": "udp",
"container": "same",
}
]
)
self.assertEqual(out, 'ports:\n - "20000-39999:20000-39999/udp"')
def test_host_mode_emits_the_long_block(self):
out = _run_edge([{"service": "openresty", "protocol": "http", "mode": "host"}])
self.assertEqual(
out,
"ports:\n - target: 80\n published: 80\n"
" protocol: tcp\n mode: host",
)
def test_ephemeral_publishes_only_the_container_port(self):
out = _run_edge(
[{"service": "api", "protocol": "http", "publish": "ephemeral"}]
)
self.assertEqual(out, 'ports:\n - "5000"')
def test_host_mode_rejects_an_ip(self):
with self.assertRaises(AnsibleError):
_run_edge(
[
{
"service": "openresty",
"protocol": "http",
"mode": "host",
"ip": "10.0.0.1",
}
]
)
def test_an_unknown_term_key_is_rejected(self):
with self.assertRaises(AnsibleError):
_run_edge([{"service": "openresty", "protocol": "http", "protokol": "tcp"}])
def test_key_names_the_block(self):
lookup = LookupModule()
lookup._loader = mock.MagicMock()
with patch("plugins.lookup.container_ports.lookup_loader") as loader_mock:
loader_mock.get.return_value = mock.MagicMock(
run=lambda *_a, **_k: [_edge_apps()]
)
out = lookup.run(
[["openresty", "http"]],
variables={"application_id": "web-svc-coturn"},
key="expose",
)
self.assertEqual(out, ['expose:\n - "80:80"'])
def test_an_unknown_block_key_is_rejected(self):
lookup = LookupModule()
lookup._loader = mock.MagicMock()
with (
patch("plugins.lookup.container_ports.lookup_loader") as loader_mock,
self.assertRaises(AnsibleError),
):
loader_mock.get.return_value = mock.MagicMock(
run=lambda *_a, **_k: [_edge_apps()]
)
lookup.run(
[["openresty", "http"]],
variables={"application_id": "web-svc-coturn"},
key="publish",
)
def test_an_unknown_transport_is_rejected(self):
with self.assertRaises(AnsibleError):
_run_edge(
[{"service": "openresty", "protocol": "http", "transport": "sctp"}]
)
if __name__ == "__main__":
unittest.main()
@@ -66,9 +66,28 @@ class OidcFlavorLookupTests(unittest.TestCase):
self._patcher = mock.patch.object(self.mod, "lookup_loader")
self._loader_mock = self._patcher.start()
self._stub_payload = None
self._loader_mock.get.return_value = mock.MagicMock(
run=lambda *_a, **_k: [self._stub_payload]
)
self._loader_mock.get.side_effect = self._stub_lookup
def _stub_lookup(self, name, *_args, **_kwargs):
"""Stand in for the lookups the plugin consumes.
``config`` resolves a dotted path against the payload the way
``lookup('config', app, path, default)`` does with a default supplied;
anything else answers with the payload itself.
"""
if name == "config":
return mock.MagicMock(
run=lambda terms, **_kw: [self._stub_config(*terms)],
)
return mock.MagicMock(run=lambda *_a, **_kw: [self._stub_payload])
def _stub_config(self, application_id, config_path, default=None):
node = (self._stub_payload or {}).get(application_id)
for part in str(config_path).split("."):
if not isinstance(node, dict) or part not in node:
return default
node = node[part]
return node
def tearDown(self):
self._patcher.stop()
@@ -9,7 +9,7 @@ from ansible.errors import AnsibleError
from plugins.lookup.tor_ports import (
LookupModule,
collect_exposed_ports,
collect_public_ports,
collect_onion_ports,
)
from utils.cache import _reset_cache_for_tests
from utils.cache.yaml import dump_yaml_str
@@ -33,7 +33,15 @@ class TestTorPortsLookup(unittest.TestCase):
_write_services(
self.roles_dir,
"web-app-gitea",
{"gitea": {"ports": {"public": {"ssh": 2201}, "local": {"http": 8002}}}},
{
"gitea": {
"ports": {
"public": {"ssh": 2201},
"local": {"http": 8002},
"onion": {"ssh": True},
}
}
},
)
_write_services(
self.roles_dir,
@@ -68,40 +76,159 @@ class TestTorPortsLookup(unittest.TestCase):
_reset_cache_for_tests()
self._tmpdir.cleanup()
def test_collects_public_single_ints_sorted(self) -> None:
ports = collect_public_ports(
["web-app-gitea", "svc-db-openldap"], self.roles_dir
@staticmethod
def _apps(**roles: dict) -> dict:
"""The variant-merged applications view for the given roles.
Every entity keeps its own ``ports``; the top-level ``tor:`` block of
``meta/services.yml`` merges in as one more entity alongside them.
"""
return {role: {"services": dict(entities)} for role, entities in roles.items()}
def test_only_named_categories_are_forwarded_sorted(self) -> None:
apps = self._apps(
**{
"web-app-gitea": {
"gitea": {
"ports": {"public": {"ssh": 2201}, "onion": {"ssh": True}}
}
},
"web-app-mailu": {
"mailu": {
"ports": {
"public": {"smtp": 25, "smtps": 465, "imap": 143},
"onion": {"smtp": True},
}
}
},
}
)
self.assertEqual(ports, [636, 2201])
def test_relay_ranges_excluded(self) -> None:
ports = collect_public_ports(["web-svc-coturn"], self.roles_dir)
self.assertEqual(ports, [3481, 5351])
ports = collect_onion_ports(apps, ["web-app-gitea", "web-app-mailu"])
def test_media_category_excluded(self) -> None:
_write_services(
self.roles_dir,
"web-app-jitsi",
{"jitsi": {"ports": {"public": {"media": 10000}, "local": {"http": 8084}}}},
self.assertEqual(ports, [25, 2201])
def test_local_wins_over_public_for_the_same_category(self) -> None:
"""``container_ports`` publishes the local port when the category has
one, so the forward must target that and not the public alias."""
apps = self._apps(
**{
"web-app-x": {
"x": {
"ports": {
"local": {"http": 8080},
"public": {"http": 80},
"onion": {"http": True},
}
}
}
}
)
self.assertEqual(collect_public_ports(["web-app-jitsi"], self.roles_dir), [])
def test_roles_without_public_ports_yield_nothing(self) -> None:
self.assertEqual(collect_public_ports(["web-app-hugo"], self.roles_dir), [])
self.assertEqual(collect_onion_ports(apps, ["web-app-x"]), [8080])
def test_tor_disabled_role_excluded(self) -> None:
_write_services(
self.roles_dir,
"web-app-optout",
{
"optout": {"ports": {"public": {"ssh": 2299}}},
"tor": {"enabled": False},
},
def test_a_falsy_or_unrendered_flag_forwards_nothing(self) -> None:
"""The input must be the rendered view: template text left in the flag
is not quietly read as enabled."""
apps = self._apps(
**{
"web-app-a": {
"a": {"ports": {"public": {"ssh": 22}, "onion": {"ssh": False}}}
},
"web-app-b": {
"b": {
"ports": {
"public": {"ssh": 23},
"onion": {"ssh": "{{ 'svc-net-tor' in group_names }}"},
}
}
},
}
)
self.assertEqual(collect_public_ports(["web-app-optout"], self.roles_dir), [])
def test_unknown_role_ignored(self) -> None:
self.assertEqual(collect_public_ports(["web-app-nope"], self.roles_dir), [])
self.assertEqual(collect_onion_ports(apps, ["web-app-a", "web-app-b"]), [])
def test_udp_only_categories_are_never_forwarded(self) -> None:
apps = self._apps(
**{
"web-svc-coturn": {
"coturn": {
"ports": {
"public": {
"media": 10000,
"stun_turn": 3481,
"stun_turn_tls": 5351,
"ssh": 2299,
"relay": {"start": 20000, "end": 39999},
},
"onion": {
"media": True,
"relay": True,
"stun_turn": True,
"stun_turn_tls": True,
"ssh": True,
},
}
}
}
}
)
self.assertEqual(collect_onion_ports(apps, ["web-svc-coturn"]), [2299])
def test_a_category_with_no_declared_port_is_skipped(self) -> None:
apps = self._apps(
**{
"web-app-x": {
"x": {"ports": {"public": {"ssh": 2201}, "onion": {"typo": True}}}
}
}
)
self.assertEqual(collect_onion_ports(apps, ["web-app-x"]), [])
def test_a_role_without_an_onion_block_forwards_nothing(self) -> None:
apps = self._apps(
**{"web-app-hugo": {"hugo": {"ports": {"local": {"http": 8008}}}}}
)
self.assertEqual(collect_onion_ports(apps, ["web-app-hugo"]), [])
def test_the_port_flag_is_the_gate_not_the_tor_flag(self) -> None:
"""``services.tor.enabled`` is the dependency edge onto svc-net-tor, not
the port forward; ``ports.onion`` alone decides what gets a
HiddenServicePort."""
apps = self._apps(
**{
"web-app-gitea": {
"tor": {"enabled": False},
"gitea": {
"ports": {"public": {"ssh": 2201}, "onion": {"ssh": True}}
},
}
}
)
self.assertEqual(collect_onion_ports(apps, ["web-app-gitea"]), [2201])
def test_role_outside_the_deploy_is_ignored(self) -> None:
apps = self._apps(
**{
"web-app-gitea": {
"gitea": {
"ports": {"public": {"ssh": 2201}, "onion": {"ssh": True}}
}
}
}
)
self.assertEqual(collect_onion_ports(apps, ["web-app-nope"]), [])
def test_collect_onion_ports_ignores_non_mappings(self) -> None:
self.assertEqual(collect_onion_ports({}, ["a"]), [])
self.assertEqual(collect_onion_ports(None, ["a"]), [])
apps = {"a": {"services": {"s": {"ports": {"onion": True}}}}}
self.assertEqual(collect_onion_ports(apps, ["a"]), [])
def test_collect_exposed_ports_gated_and_deployed(self) -> None:
apps = {
@@ -151,6 +278,14 @@ class TestTorPortsLookup(unittest.TestCase):
)[0]
self.assertEqual(result, [{"onion_port": 2201, "target": "127.0.0.1:2201"}])
def test_run_forwards_nothing_without_an_onion_opt_in(self) -> None:
result = self.lookup.run(
[],
variables={"group_names": ["svc-db-openldap", "web-svc-coturn"]},
roles_dir=str(self.roles_dir),
)[0]
self.assertEqual(result, [])
def test_empty_group_names(self) -> None:
result = self.lookup.run([], variables={}, roles_dir=str(self.roles_dir))[0]
self.assertEqual(result, [])