refactor(sidecars): instantiate sidecar ABCs directly from any backend
The four sidecar prepare-time helpers (PipelockProxy, Egress, GitGate, Supervise) had docker-flavored subclasses that existed only as instantiation shims for ABCs that already had no abstract methods. PipelockProxy.prepare() reached for class-level CA path constants that were only defined on the docker subclass — so smolmachines had to import DockerPipelockProxy to render pipelock yaml, reaching across the backend boundary for what's actually a platform-neutral operation. This moves the universal in-container CA paths (PIPELOCK_CA_CERT_IN_CONTAINER / PIPELOCK_CA_KEY_IN_CONTAINER) to claude_bottle/pipelock.py, drops the class-attr indirection on the ABC, and deletes the four empty docker subclasses. Both backends now instantiate the ABCs directly; the docker-side modules keep the docker-flavored helpers (image pin, container naming, host CA mint) and re-export the moved pipelock constants for compat. Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -1,11 +1,11 @@
|
||||
"""DockerEgress — the Docker-specific lifecycle for the
|
||||
per-bottle egress sidecar (PRD 0017). Inherits the platform-
|
||||
agnostic prepare step (route lift + routes.yaml render + token-env
|
||||
map derivation) from `Egress`.
|
||||
"""Docker-side egress helpers: port pin, in-container CA paths,
|
||||
container naming, and the host-side mitmproxy CA mint. The
|
||||
prepare-time routes-yaml rendering itself lives on the
|
||||
platform-neutral `Egress` ABC — backends instantiate it directly.
|
||||
|
||||
Chunks 1+2 of the PRD: the lifecycle is implemented and wired into
|
||||
launch.py — cred-proxy is gone. Chunk 3 retargets the cred-proxy-
|
||||
block remediation flow (PRD 0014)."""
|
||||
The per-container `.start()` / `.stop()` lifecycle was removed in
|
||||
PRD 0024 chunk 3; the sidecar bundle (PRD 0024) runs egress
|
||||
under its python init supervisor."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -13,7 +13,6 @@ import os
|
||||
import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
from ...egress import Egress
|
||||
from ...log import die
|
||||
|
||||
|
||||
@@ -130,9 +129,3 @@ def egress_tls_init(stage_dir: Path) -> tuple[Path, Path]:
|
||||
mitm.write_bytes(cert_path.read_bytes() + key_path.read_bytes())
|
||||
mitm.chmod(0o644)
|
||||
return (mitm, cert_path)
|
||||
|
||||
|
||||
class DockerEgress(Egress):
|
||||
"""Docker-flavored Egress: inherits `.prepare()` from the base.
|
||||
Container lifecycle is owned by compose; per-container
|
||||
`.start()` / `.stop()` were removed in PRD 0024 chunk 3."""
|
||||
|
||||
@@ -1,13 +1,12 @@
|
||||
"""DockerGitGate — Docker-flavored git-gate config (PRD 0008).
|
||||
Inherits the platform-agnostic prepare step (upstream lift +
|
||||
entrypoint/hook render) from `GitGate`. The git-gate daemon runs
|
||||
inside the sidecar bundle (PRD 0024); this module just holds the
|
||||
in-container paths the renderer's bind-mounts target."""
|
||||
"""Docker-side git-gate helpers: in-container paths the renderer's
|
||||
bind-mounts target, port pin, and container naming. The
|
||||
prepare-time entrypoint/hook render lives on the platform-neutral
|
||||
`GitGate` ABC — backends instantiate it directly. The git-gate
|
||||
daemon's container lifecycle is owned by the sidecar bundle
|
||||
(PRD 0024)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from ...git_gate import GitGate
|
||||
|
||||
|
||||
GIT_GATE_ENTRYPOINT_IN_CONTAINER = "/git-gate-entrypoint.sh"
|
||||
GIT_GATE_HOOK_IN_CONTAINER = "/etc/git-gate/pre-receive"
|
||||
@@ -31,9 +30,3 @@ def git_gate_host(slug: str) -> str:
|
||||
the bundle's network alias to the bundle container, where the
|
||||
git-gate daemon listens on GIT_GATE_PORT."""
|
||||
return git_gate_container_name(slug)
|
||||
|
||||
|
||||
class DockerGitGate(GitGate):
|
||||
"""Docker-flavored GitGate: inherits `.prepare()` from the base.
|
||||
The git-gate daemon's container lifecycle is owned by the
|
||||
sidecar bundle (PRD 0024)."""
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
"""DockerPipelockProxy — the Docker-specific implementation of the
|
||||
sidecar's `.prepare()` step + in-container CA path constants.
|
||||
Inherits the platform-agnostic YAML-config generation from
|
||||
PipelockProxy.
|
||||
"""Docker-side pipelock helpers: image pin, container naming, and
|
||||
the one-shot `pipelock tls init` host-side CA mint. The
|
||||
prepare-time YAML rendering itself lives on the platform-neutral
|
||||
`PipelockProxy` ABC — backends instantiate it directly.
|
||||
|
||||
The per-container `.start()` / `.stop()` lifecycle was deleted in
|
||||
PRD 0024 chunk 3 — compose-up owns the container lifecycle (PRD
|
||||
PRD 0024 chunk 3; compose-up owns the container lifecycle (PRD
|
||||
0018) and the bundle path (PRD 0024) collapses pipelock + egress
|
||||
+ git-gate + supervise into one container. What remains here is
|
||||
the prepare-time YAML rendering + the CA path constants the
|
||||
compose renderer reads."""
|
||||
+ git-gate + supervise into one container."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
@@ -17,7 +15,13 @@ import subprocess
|
||||
from pathlib import Path
|
||||
|
||||
from ...log import die
|
||||
from ...pipelock import PipelockProxy
|
||||
# Re-exported for the compose renderer + smolmachines launch step
|
||||
# (they used to import these from this module before they moved to
|
||||
# the platform-neutral pipelock module).
|
||||
from ...pipelock import ( # noqa: F401
|
||||
PIPELOCK_CA_CERT_IN_CONTAINER,
|
||||
PIPELOCK_CA_KEY_IN_CONTAINER,
|
||||
)
|
||||
|
||||
|
||||
# Pipelock image, pinned by digest. The digest is the multi-arch image
|
||||
@@ -30,12 +34,6 @@ PIPELOCK_IMAGE = os.environ.get(
|
||||
# Listening port for pipelock's forward proxy.
|
||||
PIPELOCK_PORT = os.environ.get("CLAUDE_BOTTLE_PIPELOCK_PORT", "8888")
|
||||
|
||||
# In-container paths where the per-bottle CA cert + key land via
|
||||
# the compose renderer's bind-mounts. Pipelock's rendered YAML
|
||||
# references these paths under `tls_interception`.
|
||||
PIPELOCK_CA_CERT_IN_CONTAINER = "/etc/pipelock-ca.pem"
|
||||
PIPELOCK_CA_KEY_IN_CONTAINER = "/etc/pipelock-ca-key.pem"
|
||||
|
||||
|
||||
def pipelock_container_name(slug: str) -> str:
|
||||
return f"claude-bottle-pipelock-{slug}"
|
||||
@@ -82,13 +80,3 @@ def pipelock_tls_init(stage_dir: Path) -> tuple[Path, Path]:
|
||||
key.chmod(0o600)
|
||||
cert.chmod(0o644)
|
||||
return (cert, key)
|
||||
|
||||
|
||||
class DockerPipelockProxy(PipelockProxy):
|
||||
"""Docker-flavored PipelockProxy: inherits `.prepare()` from the
|
||||
base, exposes the in-container CA paths the renderer reads.
|
||||
Container lifecycle is owned by compose."""
|
||||
|
||||
CA_CERT_IN_CONTAINER = PIPELOCK_CA_CERT_IN_CONTAINER
|
||||
CA_KEY_IN_CONTAINER = PIPELOCK_CA_KEY_IN_CONTAINER
|
||||
|
||||
|
||||
@@ -14,13 +14,17 @@ import os
|
||||
from datetime import datetime, timezone
|
||||
from pathlib import Path
|
||||
|
||||
from ...egress import Egress
|
||||
from ...env import ResolvedEnv, resolve_env
|
||||
from ...git_gate import GitGate
|
||||
from ...log import die
|
||||
from ...pipelock import PipelockProxy
|
||||
from ...supervise import Supervise
|
||||
from .. import BottleSpec
|
||||
from . import util as docker_mod
|
||||
from .bottle_plan import DockerBottlePlan
|
||||
from .egress import DockerEgress, egress_container_name
|
||||
from .git_gate import DockerGitGate, git_gate_container_name
|
||||
from .egress import egress_container_name
|
||||
from .git_gate import git_gate_container_name
|
||||
from .bottle_state import (
|
||||
BottleMetadata,
|
||||
agent_state_dir,
|
||||
@@ -35,8 +39,8 @@ from .bottle_state import (
|
||||
supervise_state_dir,
|
||||
write_metadata,
|
||||
)
|
||||
from .pipelock import DockerPipelockProxy, pipelock_container_name
|
||||
from .supervise import DockerSupervise, supervise_container_name
|
||||
from .pipelock import pipelock_container_name
|
||||
from .supervise import supervise_container_name
|
||||
|
||||
|
||||
def resolve_plan(
|
||||
@@ -49,10 +53,10 @@ def resolve_plan(
|
||||
validation already ran in the base class."""
|
||||
docker_mod.require_docker()
|
||||
|
||||
proxy = DockerPipelockProxy()
|
||||
git_gate = DockerGitGate()
|
||||
egress = DockerEgress()
|
||||
supervise = DockerSupervise()
|
||||
proxy = PipelockProxy()
|
||||
git_gate = GitGate()
|
||||
egress = Egress()
|
||||
supervise = Supervise()
|
||||
|
||||
manifest = spec.manifest
|
||||
agent = manifest.agents[spec.agent_name]
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
"""DockerSupervise — Docker-flavored supervise config (PRD 0013).
|
||||
Inherits the platform-agnostic prepare step (queue dir +
|
||||
current-config staging) from `Supervise`. The supervise daemon
|
||||
runs inside the sidecar bundle (PRD 0024); this module just holds
|
||||
the container-name helper the renderer's network alias targets."""
|
||||
"""Docker-side supervise helpers: container naming for the legacy
|
||||
per-sidecar topology (kept so the bundle's docker-network alias
|
||||
resolves the old name to the bundle IP). The prepare-time
|
||||
queue-dir + current-config staging lives on the platform-neutral
|
||||
`Supervise` ABC — backends instantiate it directly. The
|
||||
supervise daemon's container lifecycle is owned by the sidecar
|
||||
bundle (PRD 0024)."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from ...supervise import Supervise
|
||||
|
||||
|
||||
def supervise_container_name(slug: str) -> str:
|
||||
"""The legacy per-sidecar container name. Kept as a function so
|
||||
@@ -15,9 +15,3 @@ def supervise_container_name(slug: str) -> str:
|
||||
bundle — any code still referring to
|
||||
`claude-bottle-supervise-<slug>` resolves to the bundle's IP."""
|
||||
return f"claude-bottle-supervise-{slug}"
|
||||
|
||||
|
||||
class DockerSupervise(Supervise):
|
||||
"""Docker-flavored Supervise: inherits `.prepare()` from the base.
|
||||
The supervise daemon's container lifecycle is owned by the
|
||||
sidecar bundle (PRD 0024)."""
|
||||
|
||||
Reference in New Issue
Block a user