diff --git a/core/src/wildpc_core/deploy.py b/core/src/wildpc_core/deploy.py index c4c5c84..c847404 100644 --- a/core/src/wildpc_core/deploy.py +++ b/core/src/wildpc_core/deploy.py @@ -682,6 +682,11 @@ def _target_url(config: WildpcConfig, target_name: str) -> str | None: base = getattr(dep, "base_url", None) if base: return base + # A raw-TCP service has no URL scheme — project its `host:port`, reachable + # through wildcard DNS (see docs/tcp-exposure.md). + tcp_port = getattr(dep, "tcp_port", None) + if tcp_port and config.gateway.domain: + return f"{target_name}.{config.gateway.domain}:{tcp_port}" expose = getattr(dep, "expose", None) http = getattr(expose, "http", None) if expose else None tport = http.internal.port if http else None diff --git a/core/tests/test_requires_env.py b/core/tests/test_requires_env.py index 15b472d..5e9d2bb 100644 --- a/core/tests/test_requires_env.py +++ b/core/tests/test_requires_env.py @@ -46,3 +46,18 @@ def test_bind_path_on_reference_base_url() -> None: consumer = _svc(requires=[{"ref": "ext", "bind": "EXT", "path": "/v1"}]) cfg = _cfg({"ext": ref, "app": consumer}) assert _requires_env(cfg, consumer) == {"EXT": "https://ext.example/v1"} + + +def test_bind_tcp_service_projects_host_port() -> None: + """A raw-TCP target (e.g. postgres) binds as `.:`.""" + pg = SystemdDeployment.model_validate( + { + "manager": "systemd", + "run": {"launcher": "command", "argv": ["x"]}, + "expose": {"tcp": {"port": 5432}}, + "reach": "internal", + } + ) + consumer = _svc(requires=[{"ref": "postgres", "bind": "DB_HOST"}]) + cfg = _cfg({"postgres": pg, "app": consumer}) + assert _requires_env(cfg, consumer) == {"DB_HOST": "postgres.node.example:5432"} diff --git a/docs/relationships.md b/docs/relationships.md index 3d31abe..82e563c 100644 --- a/docs/relationships.md +++ b/docs/relationships.md @@ -53,6 +53,8 @@ requires: `path` is appended to the bound URL, for a consumer that wants a sub-path as its base (e.g. `{ ref: vllm, bind: VLLM_API_BASE, path: /v1 }`). +A raw-TCP target (`expose.tcp`, e.g. postgres) has no URL scheme, so it binds as +`.:`. A **program**'s host-package preconditions stay on the program as `system_dependencies` (a plain list of package names); the model synthesizes the