refactor(de-sidecar): remove the per-bottle companion-container architecture
The per-agent companion container (the egress/git-gate/supervise data plane run once per bottle) is the pre-consolidation architecture. Remove it and disable the backends that still depend on it, per the #385 thread. - Delete `backend/docker/sidecar_bundle.py`; docker's live path uses the consolidated shared gateway, not a per-bottle bundle. - Disable the firecracker and macos-container backends: their `launch()` fails closed (they launched a per-bottle companion; firecracker's consolidated relaunch is #354, macos follows). Their `enumerate` return empty and `cleanup` drop the companion-container discovery (firecracker keeps VMM/run-dir cleanup). - Fail-close both backends' `egress_apply` reload (it signalled the per-bottle container); consolidated egress policy resolves per-request against the orchestrator, so gateway-side apply is a follow-up. - Rename `egress_sidecar_env_entries` → `egress_gateway_env_entries`, `SIDECAR_PORTS` → `GATEWAY_PORTS`. - Move the shared DockerBottlePlan fixture to `tests/unit/_docker_bottle_plan.py`; delete tests for the removed launch paths; update cleanup/egress-apply tests. Docker consolidated launch verified end-to-end (multitenant isolation integration test passes). macos/firecracker are intentionally disabled. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
This commit is contained in:
@@ -1,60 +1,29 @@
|
||||
"""Host-side helper for egress sidecar inspection and live updates.
|
||||
"""Host-side egress route-apply for the docker backend.
|
||||
|
||||
The approve path uses this module to validate a proposed routes file,
|
||||
write it to the bottle's live egress state dir, and signal the sidecar
|
||||
bundle so the mitmproxy addon reloads it.
|
||||
The per-bottle companion container this used to signal (`docker kill
|
||||
--signal HUP <container>`) was removed in the de-sidecar cleanup (#385).
|
||||
In the consolidated model the shared gateway resolves egress policy
|
||||
per-request against the orchestrator rather than reloading a per-bottle
|
||||
routes file, so the live per-bottle reload is not supported here and
|
||||
fails closed until the gateway-side apply lands.
|
||||
"""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
import subprocess
|
||||
|
||||
from ...egress import EGRESS_ROUTES_IN_CONTAINER
|
||||
from ...log import warn
|
||||
from ..egress_apply import EgressApplicator, EgressApplyError
|
||||
from .sidecar_bundle import sidecar_bundle_container_name
|
||||
|
||||
|
||||
def fetch_current_routes(slug: str) -> str:
|
||||
container = sidecar_bundle_container_name(slug)
|
||||
r = subprocess.run(
|
||||
["docker", "exec", container, "cat", EGRESS_ROUTES_IN_CONTAINER],
|
||||
capture_output=True, text=True, check=False,
|
||||
)
|
||||
if r.returncode != 0:
|
||||
raise EgressApplyError(
|
||||
f"could not read routes.yaml from {container}: "
|
||||
f"{(r.stderr or '').strip() or 'container not running?'}"
|
||||
)
|
||||
return r.stdout
|
||||
|
||||
|
||||
class DockerEgressApplicator(EgressApplicator):
|
||||
def _signal_bundle_reload(self, slug: str) -> None:
|
||||
container = sidecar_bundle_container_name(slug)
|
||||
result = subprocess.run(
|
||||
["docker", "kill", "--signal", "HUP", container],
|
||||
capture_output=True, text=True, check=False, env=os.environ,
|
||||
del slug
|
||||
raise EgressApplyError(
|
||||
"live egress route-apply was removed with the per-bottle "
|
||||
"companion container (#385); route changes will flow through "
|
||||
"the consolidated gateway in a follow-up."
|
||||
)
|
||||
if result.returncode != 0:
|
||||
last_error = (result.stderr or "").strip() or (result.stdout or "").strip()
|
||||
warn(
|
||||
f"egress: routes updated on disk for {slug}, but bundle reload failed: "
|
||||
f"{last_error or 'docker kill failed'}"
|
||||
)
|
||||
raise EgressApplyError(
|
||||
f"could not reload egress bundle {container}: "
|
||||
f"{last_error or 'docker kill failed'}"
|
||||
)
|
||||
|
||||
|
||||
applicator = DockerEgressApplicator()
|
||||
|
||||
|
||||
__all__ = [
|
||||
"DockerEgressApplicator",
|
||||
"EgressApplyError",
|
||||
"applicator",
|
||||
"fetch_current_routes",
|
||||
]
|
||||
__all__ = ["DockerEgressApplicator", "EgressApplyError", "applicator"]
|
||||
|
||||
@@ -1,33 +0,0 @@
|
||||
"""Sidecar bundle constants + helpers for the Docker backend
|
||||
(PRD 0024).
|
||||
|
||||
A per-bottle sidecar bundle runs egress + git-gate + supervise as one
|
||||
container under a small Python init supervisor. As of PRD 0024 chunk 5
|
||||
the bundle is the only shape — the legacy four-sidecar topology and its
|
||||
`BOT_BOTTLE_SIDECAR_BUNDLE` feature flag are gone.
|
||||
|
||||
The bundle's image is the **same data plane** as the consolidated
|
||||
per-host gateway (PRD 0070), so it is one image with one name and one
|
||||
Dockerfile: `bot-bottle-gateway` / `Dockerfile.gateway` (#384). These
|
||||
constants alias the gateway's so a per-bottle bundle and the shared
|
||||
gateway can never drift onto different images."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from ...orchestrator.gateway import GATEWAY_DOCKERFILE, GATEWAY_IMAGE
|
||||
|
||||
|
||||
# The per-bottle bundle image == the gateway data-plane image (aliased so
|
||||
# there is one source of truth; the `BOT_BOTTLE_GATEWAY_IMAGE` env override
|
||||
# on the gateway constant applies here too).
|
||||
SIDECAR_BUNDLE_IMAGE = GATEWAY_IMAGE
|
||||
SIDECAR_BUNDLE_DOCKERFILE = GATEWAY_DOCKERFILE
|
||||
|
||||
|
||||
def sidecar_bundle_container_name(slug: str) -> str:
|
||||
"""`bot-bottle-sidecars-<slug>`. Same prefix scheme as the
|
||||
per-sidecar containers it replaces, so the dashboard's
|
||||
discovery-by-prefix logic keeps working. (The per-bottle *container*
|
||||
name keeps the historical `sidecars-` prefix; only the *image* was
|
||||
renamed to `bot-bottle-gateway` in #384.)"""
|
||||
return f"bot-bottle-sidecars-{slug}"
|
||||
Reference in New Issue
Block a user