feat(smolmachines): bundle bringup on per-bottle docker bridge (PRD 0023 chunk 2c) #66

Merged
didericis-claude merged 1 commits from prd-0023-chunk-2c-bundle-bringup into main 2026-05-27 04:27:34 -04:00
Owner

Summary

Chunk 2c: lifecycle primitives for the per-bottle docker bridge + the sidecar bundle container with a pinned IP. The pinning is what makes smolvm's TSI allowlist (<bundle-ip>/32) safe to compute at prepare time — without it, we'd have to inspect the bundle's assigned IP after start and feed it back into the Smolfile.

API

bundle_network_name(slug)                # → claude-bottle-bundle-<slug>
bundle_container_name(slug)              # → claude-bottle-sidecars-<slug>
create_bundle_network(name, subnet, gw)  # docker network create --subnet ... --gateway ...
remove_bundle_network(name)              # docker network rm (idempotent)
start_bundle(BundleLaunchSpec, env=)     # docker run --ip <bundle-ip> -e ... -v ... <image>
stop_bundle(slug)                        # docker rm -f (idempotent)

BundleLaunchSpec is the docker-argv carrier: slug + network/subnet/gateway/bundle_ip + daemons_csv + environment + volumes + image. Chunk 2d populates it from the inner Plans (PipelockProxyPlan, EgressPlan, GitGatePlan, SupervisePlan) that already exist in the docker backend.

Idempotency

Where it matters for partial-teardown safety:

  • create_bundle_network treats "already exists" as success.
  • remove_bundle_network + stop_bundle treat "no such network" / "no such container" as success.
  • Other failures die (create, start) or warn (remove, stop) depending on whether the launch flow can recover.

Tests

  • 15 unit cases (mocked subprocess.run): argv shape per primitive, idempotent paths, host-env inheritance to the docker run subprocess.
  • 1 integration case (real docker daemon, gated on docker + 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 claude-bottle-sidecars:latest isn't built locally yet.

546 unit tests passing. Real-docker bundle bringup green locally.

Chunk 2 remaining

  • 2d: launch.py end-to-end — populate BundleLaunchSpec from the inner Plans (call proxy.prepare / egress.prepare / etc. like the docker backend does), bring up bundle → VM → exec, tear down. Integration smoke (exec("echo hi") inside a started VM) + the localhost-reach probe + the egress-port-bypass probe from the PRD acceptance plan.
## Summary Chunk 2c: lifecycle primitives for the per-bottle docker bridge + the sidecar bundle container with a pinned IP. The pinning is what makes smolvm's TSI allowlist (`<bundle-ip>/32`) safe to compute at prepare time — without it, we'd have to inspect the bundle's assigned IP after start and feed it back into the Smolfile. ## API ```python bundle_network_name(slug) # → claude-bottle-bundle-<slug> bundle_container_name(slug) # → claude-bottle-sidecars-<slug> create_bundle_network(name, subnet, gw) # docker network create --subnet ... --gateway ... remove_bundle_network(name) # docker network rm (idempotent) start_bundle(BundleLaunchSpec, env=) # docker run --ip <bundle-ip> -e ... -v ... <image> stop_bundle(slug) # docker rm -f (idempotent) ``` `BundleLaunchSpec` is the docker-argv carrier: slug + network/subnet/gateway/bundle_ip + daemons_csv + environment + volumes + image. Chunk 2d populates it from the inner Plans (PipelockProxyPlan, EgressPlan, GitGatePlan, SupervisePlan) that already exist in the docker backend. ## Idempotency Where it matters for partial-teardown safety: - `create_bundle_network` treats `"already exists"` as success. - `remove_bundle_network` + `stop_bundle` treat `"no such network"` / `"no such container"` as success. - Other failures `die` (`create`, `start`) or `warn` (`remove`, `stop`) depending on whether the launch flow can recover. ## Tests - **15 unit cases** (mocked `subprocess.run`): argv shape per primitive, idempotent paths, host-env inheritance to the docker run subprocess. - **1 integration case** (real docker daemon, gated on docker + 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 `claude-bottle-sidecars:latest` isn't built locally yet. **546 unit tests passing.** Real-docker bundle bringup green locally. ## Chunk 2 remaining - **2d:** `launch.py` end-to-end — populate `BundleLaunchSpec` from the inner Plans (call `proxy.prepare` / `egress.prepare` / etc. like the docker backend does), bring up bundle → VM → exec, tear down. Integration smoke (`exec("echo hi")` inside a started VM) + the localhost-reach probe + the egress-port-bypass probe from the PRD acceptance plan.
didericis added 1 commit 2026-05-27 04:19:54 -04:00
feat(smolmachines): bundle bringup on per-bottle docker bridge (PRD 0023 chunk 2c)
test / unit (pull_request) Successful in 21s
test / integration (pull_request) Successful in 43s
495be7f9c0
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>
didericis-claude merged commit 6b861a1418 into main 2026-05-27 04:27:34 -04:00
Sign in to join this conversation.