feat(ssh-gate): wire gate into DockerBottlePlan, prepare, launch
PRD 0007: thread the DockerSSHGate through the bottle lifecycle. - DockerBottlePlan gains gate_plan: SSHGatePlan. - prepare.resolve_plan accepts a gate and renders its entrypoint script next to the pipelock yaml. - launch.launch starts the gate sidecar after pipelock (so it's on the same internal + egress networks) and registers its stop in the ExitStack. Skipped when the bottle has no ssh entries. - DockerBottleBackend instantiates DockerSSHGate alongside the pipelock proxy. - bottle_plan.print + to_dict surface the upstream table so --dry-run shows the per-host listen-port mapping. ssh_config provisioning still points at pipelock; that swap lands in the next commit so this one stays a pure wiring change.
This commit is contained in:
@@ -24,6 +24,7 @@ from .bottle import DockerBottle
|
||||
from .bottle_plan import DockerBottlePlan
|
||||
from .pipelock import DockerPipelockProxy, pipelock_proxy_url, pipelock_tls_init
|
||||
from .provision.ca import AGENT_CA_BUNDLE, AGENT_CA_PATH
|
||||
from .ssh_gate import DockerSSHGate
|
||||
|
||||
|
||||
# Where the repo root lives, for `docker build` context. Computed once.
|
||||
@@ -35,6 +36,7 @@ def launch(
|
||||
plan: DockerBottlePlan,
|
||||
*,
|
||||
proxy: DockerPipelockProxy,
|
||||
gate: DockerSSHGate,
|
||||
provision: Callable[[DockerBottlePlan, str], str | None],
|
||||
) -> Generator[DockerBottle, None, None]:
|
||||
"""Build, launch, and provision a Docker bottle. Teardown on exit.
|
||||
@@ -85,6 +87,21 @@ def launch(
|
||||
pipelock_name = proxy.start(plan.proxy_plan)
|
||||
stack.callback(proxy.stop, pipelock_name)
|
||||
|
||||
# SSH egress gate (PRD 0007). One sidecar per agent, only
|
||||
# brought up when the bottle has ssh entries. Lives on the
|
||||
# same internal + egress networks pipelock straddles; the
|
||||
# agent dials it by container name (DNS works on --internal,
|
||||
# confirmed by the PRD 0007 spike).
|
||||
if plan.gate_plan.upstreams:
|
||||
gate_plan = dataclasses.replace(
|
||||
plan.gate_plan,
|
||||
internal_network=internal_network,
|
||||
egress_network=egress_network,
|
||||
)
|
||||
plan = dataclasses.replace(plan, gate_plan=gate_plan)
|
||||
gate_name = gate.start(plan.gate_plan)
|
||||
stack.callback(gate.stop, gate_name)
|
||||
|
||||
container = _run_agent_container(plan, internal_network)
|
||||
stack.callback(docker_mod.force_remove_container, container)
|
||||
|
||||
|
||||
Reference in New Issue
Block a user