claude_bottle/backend/smolmachines/sidecar_bundle.py — primitives
for the per-bottle bridge + bundle container with pinned IP:
- bundle_network_name(slug) / bundle_container_name(slug)
- create_bundle_network(name, subnet, gateway)
- remove_bundle_network(name)
- start_bundle(BundleLaunchSpec, env=)
- stop_bundle(slug)
`BundleLaunchSpec` carries the launch-time fields (network +
subnet + gateway + bundle_ip + daemons_csv + environment +
volumes). Wiring it up from the inner Plans (PipelockProxyPlan,
EgressPlan, GitGatePlan, SupervisePlan) is chunk 2d's job; this
module is the docker-argv surface only.
Pinning the bundle IP via `docker run --ip <bundle-ip>` is what
makes smolvm's TSI allowlist (`<bundle-ip>/32`) safe to compute
at prepare time — without pinning, we'd have to inspect the
assigned IP after start and feed it back into the Smolfile.
Idempotent semantics where it matters: `create_bundle_network`
treats "already exists" as success, `remove_bundle_network` +
`stop_bundle` treat "no such ..." as success. Other failures
die / warn depending on whether the launch flow can recover.
Tests:
- 15 unit cases (mocked subprocess.run): argv shape for create
/ remove / start / stop, idempotent paths, host-env
inheritance to docker run subprocess.
- 1 integration case (real docker daemon, gated on docker
available + not GITEA_ACTIONS): end-to-end bringup of an
empty-daemons bundle on a 192.168.211.0/24 bridge, confirms
the container lands at the pinned IP. Skipped if the
claude-bottle-sidecars:latest image isn't built (operator
hasn't run a docker bottle yet).
546 unit tests passing. Real-docker bundle bringup green
locally.
Launch wiring + provisioning + PRD 0022 acceptance probes
land in chunk 2d.
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>