feat(orchestrator): slice 13d(i) — containerize the orchestrator (validated on docker)
Real-on-host testing surfaced two issues the unit-mocked slices couldn't: 1. The host (NixOS) firewall DROPS container->host traffic, so a host-process orchestrator is unreachable from the gateway container. Fix: run the orchestrator AS a container on the shared gateway network (PRD 0070's "virtualize the orchestrator") — the gateway reaches it by container name over docker DNS (container<->container, no firewall), and the host CLI reaches it via a published loopback port. 2. The control plane crashed the connection on a dispatch error (e.g. a broker failure) instead of returning 500. Changes: - lifecycle: OrchestratorProcess (host process) -> OrchestratorService (containers). Runs the control plane in the bundle image with the repo bind-mounted (orchestrator is stdlib-only), register-only stub broker so it needs NO docker socket (the backend launches agents; the host manages both containers). Registry DB persists via a host-root mount. ensure_running is an idempotent singleton over both containers. - gateway: BOT_BOTTLE_ORCHESTRATOR_URL is now the orchestrator's *by-name* URL on the shared network (dropped the host.docker.internal hack). - control_plane: _serve wraps dispatch — a failure returns 500, never crashes the connection. - OrchestratorProcess default broker -> stub (register-only) for docker. Validated live end-to-end: both containers up, gateway->orchestrator by name OK, register -> resolve-by-source-IP returns the bottle's policy from inside the gateway. pyright 0 errors; pylint 9.83/10; unit suite green (1760 tests; the 13 test_sidecar_init /bin/sleep errors are pre-existing NixOS-local noise). Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
This commit is contained in:
@@ -26,7 +26,7 @@ from ...egress import EgressPlan
|
||||
from ...git_gate import GitGatePlan
|
||||
from ...orchestrator.client import OrchestratorClient
|
||||
from ...orchestrator.gateway import GATEWAY_NAME, GATEWAY_NETWORK
|
||||
from ...orchestrator.lifecycle import OrchestratorProcess
|
||||
from ...orchestrator.lifecycle import OrchestratorService
|
||||
from ...orchestrator.registration import registration_inputs
|
||||
from .gateway_net import next_free_ip
|
||||
from .gateway_provision import deprovision_git_gate, provision_git_gate
|
||||
@@ -92,7 +92,7 @@ def launch_consolidated(
|
||||
git_gate_plan: GitGatePlan,
|
||||
*,
|
||||
image_ref: str = "",
|
||||
process: OrchestratorProcess | None = None,
|
||||
service: OrchestratorService | None = None,
|
||||
gateway_name: str = GATEWAY_NAME,
|
||||
network: str = GATEWAY_NETWORK,
|
||||
) -> LaunchContext:
|
||||
@@ -100,8 +100,8 @@ def launch_consolidated(
|
||||
bottle, and provision its git-gate state. Returns the agent's attach
|
||||
context. Raises `ConsolidatedLaunchError` (or the primitives' own errors)
|
||||
if any step fails — the caller tears down on failure."""
|
||||
process = process or OrchestratorProcess()
|
||||
url = process.ensure_running()
|
||||
service = service or OrchestratorService()
|
||||
url = service.ensure_running()
|
||||
client = OrchestratorClient(url)
|
||||
|
||||
cidr = _network_cidr(network)
|
||||
|
||||
Reference in New Issue
Block a user