mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-08 11:46:35 +00:00
A sibling container is reached at http://<entity name>:<internal port>,
and that string was written out per call site: a literal protocol, an
entity_name interpolation for the host, and a lookup('config', ...,
'services.<key>.ports.internal.http') for the port. Nine of them across
seven roles, each needing its own `# nocheck: literal-protocol-lookup`,
because the sibling lint rightly objects to a protocol glued in front of
a lookup - the protocol is supposed to come from wherever the TLS
posture is decided.
A container network has no TLS posture. It speaks plaintext by
construction, which is a property of the network rather than of any
caller, so stating it nine times stated it eight times too often.
lookup('container_url', application_id, service_key) holds all three
facts, and because no literal protocol is left at the call site the
suppression markers go with them.
The port is deliberately the internal one. A sibling that goes out to
the published port leaves the container network and comes back through
the ingress, which the dns-search suffix turns into the public FQDN.
The lookup refuses a service that declares no internal http port rather
than falling back to anything.
test_container_url_lookup.py keeps the shape from coming back: a
protocol, an interpolation mentioning entity_name, a colon, a second
interpolation. Nothing else matches that, and `# nocheck:
container-url-lookup` covers an origin this lookup genuinely cannot
express - a port that is not ports.internal.http, or a host that is not
the application's entity.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
95 lines
3.1 KiB
Python
95 lines
3.1 KiB
Python
import unittest
|
|
import unittest.mock as mock
|
|
|
|
from ansible.errors import AnsibleError
|
|
|
|
from plugins.lookup.container_url import LookupModule
|
|
|
|
APPLICATIONS = {
|
|
"web-svc-translate": {
|
|
"services": {
|
|
"translate": {
|
|
"ports": {"internal": {"http": 8000}, "local": {"http": 8101}}
|
|
}
|
|
}
|
|
},
|
|
"svc-ai-agent-broker": {
|
|
"services": {"agent-broker": {"ports": {"internal": {"http": 9000}}}}
|
|
},
|
|
"web-app-portless": {"services": {"portless": {"ports": {"local": {"http": 80}}}}},
|
|
}
|
|
|
|
|
|
def _loader(apps):
|
|
def _get(name, *_a, **_k):
|
|
if name == "applications":
|
|
return mock.MagicMock(run=lambda *_a, **_k: [apps])
|
|
return mock.MagicMock(run=lambda *_a, **_k: [None])
|
|
|
|
loader = mock.MagicMock()
|
|
loader.get.side_effect = _get
|
|
return loader
|
|
|
|
|
|
class ContainerUrlTestCase(unittest.TestCase):
|
|
def setUp(self) -> None:
|
|
self.lookup = LookupModule()
|
|
self.lookup._loader = mock.MagicMock()
|
|
self.patcher = mock.patch(
|
|
"plugins.lookup.container_url.lookup_loader", _loader(APPLICATIONS)
|
|
)
|
|
self.patcher.start()
|
|
self.addCleanup(self.patcher.stop)
|
|
|
|
def _run(self, *terms):
|
|
return self.lookup.run(list(terms), variables={})[0]
|
|
|
|
def test_it_joins_the_entity_name_with_the_internal_port(self) -> None:
|
|
self.assertEqual(
|
|
self._run("web-svc-translate", "translate"), "http://translate:8000"
|
|
)
|
|
|
|
def test_a_service_key_with_a_hyphen_keeps_its_own_port(self) -> None:
|
|
self.assertEqual(
|
|
self._run("svc-ai-agent-broker", "agent-broker"),
|
|
"http://agent-broker:9000",
|
|
)
|
|
|
|
def test_the_published_port_is_never_used(self) -> None:
|
|
"""A sibling reaching the local port leaves the container network and
|
|
returns through the ingress, which the dns-search suffix turns into
|
|
the public FQDN."""
|
|
self.assertNotIn("8101", self._run("web-svc-translate", "translate"))
|
|
|
|
def test_the_protocol_is_plaintext(self) -> None:
|
|
self.assertTrue(
|
|
self._run("web-svc-translate", "translate").startswith("http://")
|
|
)
|
|
|
|
def test_the_origin_carries_no_path_or_trailing_slash(self) -> None:
|
|
self.assertFalse(self._run("web-svc-translate", "translate").endswith("/"))
|
|
|
|
def test_an_unknown_application_is_refused(self) -> None:
|
|
with self.assertRaises(AnsibleError):
|
|
self._run("web-app-absent", "translate")
|
|
|
|
def test_an_unknown_service_key_is_refused(self) -> None:
|
|
with self.assertRaises(AnsibleError):
|
|
self._run("web-svc-translate", "absent")
|
|
|
|
def test_a_service_without_an_internal_http_port_is_refused(self) -> None:
|
|
with self.assertRaises(AnsibleError):
|
|
self._run("web-app-portless", "portless")
|
|
|
|
def test_a_missing_term_is_refused(self) -> None:
|
|
with self.assertRaises(AnsibleError):
|
|
self._run("web-svc-translate")
|
|
|
|
def test_an_empty_term_is_refused(self) -> None:
|
|
with self.assertRaises(AnsibleError):
|
|
self._run("web-svc-translate", " ")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|