mirror of
https://github.com/kevinveenbirkenbach/computer-playbook.git
synced 2026-11-06 02:54:26 +00:00
Run 34421944328 web-app-litellm#1 (README host-mode replay) answered
every health probe on llm.ai.infinito.test with 502: litellm
crash-looped on "P1000: Authentication failed against database server
at postgres" while postgres logged 'Role "litellm" does not exist'. The
README inventory has no svc-db-postgres group, so sys-svc-rdbms skipped
the central provisioning, yet svc-ai-litellm pinned postgres.shared to
true and kept consuming a shared database nobody had created its role in.
postgres.shared now reads "{{ 'svc-db-postgres' in group_names }}":
an inventory with the central group keeps the shared database, the
README inventory gets a dedicated one.
That dedicated instance, rendered by sys-svc-rdbms postgres.yml.j2,
joins only the compose default network, and the networks renderer
dropped default from every svc-db-*/svc-ai-* role. A local variant-1
deploy measured litellm-database on litellm_default alone and litellm on
the shared litellm network alone. _suppress_default now keeps default
when the role's database is local. The variants pin shared to true (0)
and false (1) so the matrix exercises both paths, and the generated
READMEs show the postgres relation as 0..1.
The three attachment helpers move from render.py to attachments.py,
which render.py re-exports, and test_render.py splits along the same
seams into five files plus _render_helpers.py with every test id kept.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
225 lines
7.7 KiB
Python
225 lines
7.7 KiB
Python
"""Attachment computation for the compose networks renderers.
|
|
|
|
Which provider overlays a role attaches to, and which proxy aliases the
|
|
default network harvests, derived from the service_registry. Kept apart from
|
|
the emitters in :mod:`utils.networks.render` so a change to the consumer rules
|
|
cannot be confused with a change to the YAML they produce.
|
|
"""
|
|
|
|
from __future__ import annotations
|
|
|
|
from typing import TYPE_CHECKING, Any
|
|
|
|
from utils.roles.entity.name import get_entity_name
|
|
|
|
if TYPE_CHECKING:
|
|
from collections.abc import Callable
|
|
|
|
|
|
def _is_consumer(
|
|
entry: dict[str, Any],
|
|
application_id: str,
|
|
lookup_config: Callable[[str, str, Any], Any],
|
|
lookup_database: Callable[[str, str], Any],
|
|
) -> bool:
|
|
overlay = entry.get("overlay") or {}
|
|
consumer = overlay.get("consumer") or {}
|
|
declared = consumer.get("kind") or "services_flags"
|
|
kinds = declared if isinstance(declared, list) else [declared]
|
|
return any(
|
|
_matches_kind(
|
|
str(kind), entry, consumer, application_id, lookup_config, lookup_database
|
|
)
|
|
for kind in kinds
|
|
)
|
|
|
|
|
|
def _matches_kind(
|
|
kind: str,
|
|
entry: dict[str, Any],
|
|
consumer: dict[str, Any],
|
|
application_id: str,
|
|
lookup_config: Callable[[str, str, Any], Any],
|
|
lookup_database: Callable[[str, str], Any],
|
|
) -> bool:
|
|
if kind == "database":
|
|
if not _coerce_bool(lookup_database(application_id, "enabled")):
|
|
return False
|
|
if not _coerce_bool(lookup_database(application_id, "shared")):
|
|
return False
|
|
return lookup_database(application_id, "id") == entry.get("role")
|
|
if kind == "services_flags":
|
|
key = consumer.get("key") or entry.get("provides") or entry.get("entity_name")
|
|
flags = consumer.get("flags") or ["enabled", "shared"]
|
|
for flag in flags:
|
|
if not _coerce_bool(
|
|
lookup_config(application_id, f"services.{key}.{flag}", False)
|
|
):
|
|
return False
|
|
return True
|
|
if kind == "mcp_client":
|
|
if not _coerce_bool(lookup_config(application_id, "mcp.enabled", False)):
|
|
return False
|
|
if not _coerce_bool(lookup_config(application_id, "mcp.shared", False)):
|
|
return False
|
|
direction = str(
|
|
lookup_config(application_id, "mcp.direction", "") or ""
|
|
).strip()
|
|
if direction not in ("client", "both"):
|
|
return False
|
|
consumer_key = get_entity_name(application_id)
|
|
if (
|
|
lookup_config(application_id, f"services.{consumer_key}.mcp_consumer", None)
|
|
is not True
|
|
):
|
|
return False
|
|
refusal = lookup_config(
|
|
entry.get("role") or "", f"services.{consumer_key}.mcp_consumer", True
|
|
)
|
|
return refusal is not False
|
|
if kind == "onion_sso":
|
|
provider = consumer.get("provider")
|
|
if not provider:
|
|
return False
|
|
key = consumer.get("key") or "sso"
|
|
if not _coerce_bool(
|
|
lookup_config(application_id, f"services.{key}.enabled", False)
|
|
):
|
|
return False
|
|
provider_key = consumer.get("provider_key") or "tor"
|
|
return _coerce_bool(
|
|
lookup_config(provider, f"services.{provider_key}.enabled", False)
|
|
)
|
|
if kind == "web_facing":
|
|
return application_id.startswith(("web-app-", "web-svc-"))
|
|
return False
|
|
|
|
|
|
def _coerce_bool(value: Any) -> bool:
|
|
if isinstance(value, bool):
|
|
return value
|
|
if isinstance(value, str):
|
|
return value.strip().lower() in ("true", "1", "yes")
|
|
return bool(value)
|
|
|
|
|
|
def _compute_attachments(
|
|
registry: dict[str, dict[str, Any]],
|
|
application_id: str,
|
|
deployment_mode: str,
|
|
lookup_config: Callable[[str, str, Any], Any],
|
|
lookup_database: Callable[[str, str], Any],
|
|
) -> tuple[list[dict[str, Any]], list[str]]:
|
|
attachments: list[dict[str, Any]] = []
|
|
default_aliases: list[str] = []
|
|
|
|
for entry in registry.values():
|
|
if "canonical" in entry:
|
|
continue
|
|
overlay = entry.get("overlay")
|
|
if not overlay:
|
|
continue
|
|
if deployment_mode not in overlay.get("modes", []):
|
|
continue
|
|
|
|
is_provider = application_id == entry.get("role")
|
|
topology = overlay.get("topology")
|
|
|
|
if is_provider:
|
|
if topology == "default_net":
|
|
default_aliases.extend(overlay.get("aliases") or [])
|
|
for peer in registry.values():
|
|
peer_overlay = peer.get("overlay")
|
|
if not peer_overlay:
|
|
continue
|
|
if not peer_overlay.get("proxy_resolvable"):
|
|
continue
|
|
if deployment_mode not in peer_overlay.get("modes", []):
|
|
continue
|
|
if "canonical" in peer:
|
|
continue
|
|
if peer.get("role") == entry.get("role"):
|
|
continue
|
|
default_aliases.extend(
|
|
peer_overlay.get("proxy_aliases")
|
|
or peer_overlay.get("aliases")
|
|
or []
|
|
)
|
|
elif topology:
|
|
aliases = list(
|
|
overlay.get("aliases", [entry.get("entity_name")])
|
|
or [entry.get("entity_name")]
|
|
)
|
|
if overlay.get("collect_proxy_resolvable"):
|
|
for peer in registry.values():
|
|
peer_overlay = peer.get("overlay")
|
|
if not peer_overlay:
|
|
continue
|
|
if not peer_overlay.get("proxy_resolvable"):
|
|
continue
|
|
if deployment_mode not in peer_overlay.get("modes", []):
|
|
continue
|
|
if "canonical" in peer:
|
|
continue
|
|
if peer.get("role") == entry.get("role"):
|
|
continue
|
|
aliases.extend(
|
|
peer_overlay.get("proxy_aliases")
|
|
or peer_overlay.get("aliases")
|
|
or []
|
|
)
|
|
attachments.append(
|
|
{
|
|
"role": entry["role"],
|
|
"topology": topology,
|
|
"aliases": aliases,
|
|
"is_provider": True,
|
|
}
|
|
)
|
|
continue
|
|
|
|
if not topology:
|
|
continue
|
|
if _is_consumer(entry, application_id, lookup_config, lookup_database):
|
|
attachments.append(
|
|
{
|
|
"role": entry["role"],
|
|
"topology": topology,
|
|
"aliases": [],
|
|
"is_provider": False,
|
|
}
|
|
)
|
|
|
|
return attachments, default_aliases
|
|
|
|
|
|
def _suppress_default(
|
|
application_id: str, lookup_database: Callable[[str, str], Any]
|
|
) -> bool:
|
|
if not application_id.startswith(("svc-db-", "svc-ai-")):
|
|
return False
|
|
return not bool(lookup_database(application_id, "local"))
|
|
|
|
|
|
def _own_shared_net_provider(
|
|
attachments: list[dict[str, Any]],
|
|
own_entity: str,
|
|
get_entity_name: Callable[[str], str],
|
|
) -> bool:
|
|
return any(
|
|
att["is_provider"]
|
|
and att["topology"] == "shared_net"
|
|
and get_entity_name(att["role"]) == own_entity
|
|
for att in attachments
|
|
)
|
|
|
|
|
|
def _shared_network_key(
|
|
attachments: list[dict[str, Any]],
|
|
own_entity: str,
|
|
get_entity_name: Callable[[str], str],
|
|
) -> str:
|
|
if _own_shared_net_provider(attachments, own_entity, get_entity_name):
|
|
return own_entity
|
|
return "default"
|