refactor(pipelock): start/stop become methods on PipelockProxy
test / run tests/run_tests.py (pull_request) Successful in 31s

ProxyPlan -> PipelockProxyPlan, with two additional fields populated
in launch: internal_network, egress_network (default ""). prepare
fills yaml_path + slug; launch uses dataclasses.replace to populate
the networks before calling start.

pipelock_start -> PipelockProxy.start(plan). Reads yaml_path, slug,
internal_network, egress_network off the plan. Returns the resolved
container name.

pipelock_stop -> PipelockProxy.stop(proxy_target). Takes the resolved
container name directly (the value that start returned); no longer
needs to know about slugs or naming conventions.

Backend launch passes the running container name (state["pipelock"])
to stop. Test for stop's idempotency uses pipelock_container_name to
construct the proxy_target.
This commit is contained in:
2026-05-11 10:57:07 -04:00
parent c2cdb7777d
commit ff962d2893
6 changed files with 107 additions and 101 deletions
+13 -13
View File
@@ -10,6 +10,7 @@ Methods:
from __future__ import annotations
import dataclasses
import os
import subprocess
import sys
@@ -125,15 +126,15 @@ class DockerBottleBackend(BottleBackend):
use_runsc=use_runsc,
)
def prepare_proxy(self, spec: BottleSpec, stage_dir: Path) -> pipelock.ProxyPlan:
def prepare_proxy(self, spec: BottleSpec, stage_dir: Path) -> pipelock.PipelockProxyPlan:
"""Decide where the pipelock yaml lives in `stage_dir`, delegate
to PipelockProxy to write it, and return the resolved ProxyPlan
for the launch step to consume. Stage-only: no Docker resources
created yet."""
to PipelockProxy to write it, and return the resolved
PipelockProxyPlan for the launch step to consume. Stage-only:
no Docker resources created yet."""
yaml_path = stage_dir / "pipelock.yaml"
bottle_name = spec.manifest.agents[spec.agent_name].bottle
self._proxy.prepare(spec.manifest, bottle_name, yaml_path)
return pipelock.ProxyPlan(yaml_path=yaml_path)
slug = docker_mod.slugify(spec.agent_name)
return self._proxy.prepare(spec.manifest, bottle_name, slug, yaml_path)
@contextmanager
def launch(self, plan: BottlePlan) -> Iterator[DockerBottle]:
@@ -160,7 +161,7 @@ class DockerBottleBackend(BottleBackend):
)
state["container"] = ""
if state["pipelock"]:
pipelock.pipelock_stop(plan.slug)
self._proxy.stop(state["pipelock"])
state["pipelock"] = ""
if state["internal_network"]:
network_mod.network_remove(state["internal_network"])
@@ -182,13 +183,12 @@ class DockerBottleBackend(BottleBackend):
state["internal_network"] = network_mod.network_create_internal(plan.slug)
state["egress_network"] = network_mod.network_create_egress(plan.slug)
state["pipelock"] = pipelock.pipelock_start(
plan.slug,
state["internal_network"],
state["egress_network"],
plan.proxy_plan.yaml_path.parent,
plan.proxy_plan.yaml_path.name,
proxy_plan = dataclasses.replace(
plan.proxy_plan,
internal_network=state["internal_network"],
egress_network=state["egress_network"],
)
state["pipelock"] = self._proxy.start(proxy_plan)
container = self._run_agent_container(plan, state["internal_network"])
state["container"] = container