c07ebca867
Delete the smolmachines backend (the whole bot_bottle/backend/smolmachines package and its tests). It had fatal Linux issues (TSI networking under sustained use, exec-channel contention, no SIGWINCH) and is superseded by the Firecracker backend (issue #342). Backend selection now: - default is macos-container on macOS, firecracker on KVM-capable Linux hosts, and docker as the last resort (was smolmachines). - firecracker is selected on a KVM host even when the `firecracker` binary isn't installed, so start routes through its preflight and prints an install pointer (same UX as require_container), instead of silently falling back. Split is_host_capable() (Linux + KVM) out of is_available() (adds the binary check) to drive this. Retarget the cross-backend tests (parity, print-parity, prepare, workspace, freezer, selection) from smolmachines to firecracker rather than dropping the coverage. Remove docker.util.image_id/save, which only smolmachines used. Update README/AGENTS/example bottles and stale comments; historical docs/prds are left as a point-in-time record. BREAKING: BOT_BOTTLE_BACKEND=smolmachines now errors as unknown. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_01WBMWTEtQdJ4W5UrWuLHCck
72 lines
2.3 KiB
Python
72 lines
2.3 KiB
Python
"""Unit: commit_container helper in
|
|
bot_bottle.backend.docker.util (PRD 0023 chunk 4c additions).
|
|
|
|
Tests mock `subprocess.run` and assert on argv shape + parsing.
|
|
The actual docker round-trip is covered by the chunk 4c
|
|
integration smoke."""
|
|
|
|
from __future__ import annotations
|
|
|
|
import subprocess
|
|
import unittest
|
|
from unittest.mock import patch
|
|
|
|
from bot_bottle.backend.docker import util as docker_mod
|
|
|
|
|
|
def _ok(stdout: str = "", stderr: str = "") -> subprocess.CompletedProcess: # type: ignore
|
|
return subprocess.CompletedProcess(
|
|
args=[], returncode=0, stdout=stdout, stderr=stderr,
|
|
)
|
|
|
|
|
|
def _fail(stderr: str = "boom") -> subprocess.CompletedProcess: # type: ignore
|
|
return subprocess.CompletedProcess(
|
|
args=[], returncode=1, stdout="", stderr=stderr,
|
|
)
|
|
|
|
|
|
class TestCommitContainer(unittest.TestCase):
|
|
def test_runs_docker_commit(self):
|
|
with patch.object(
|
|
docker_mod.subprocess, "run", return_value=_ok(),
|
|
) as run, patch.object(docker_mod, "info"):
|
|
docker_mod.commit_container(
|
|
"bot-bottle-dev-abc12",
|
|
"bot-bottle-committed-dev-abc12:latest",
|
|
)
|
|
argv = run.call_args.args[0]
|
|
self.assertEqual(
|
|
[
|
|
"docker", "commit",
|
|
"bot-bottle-dev-abc12",
|
|
"bot-bottle-committed-dev-abc12:latest",
|
|
],
|
|
argv,
|
|
)
|
|
|
|
def test_dies_on_docker_commit_failure(self):
|
|
with patch.object(
|
|
docker_mod.subprocess, "run", return_value=_fail("No such container"),
|
|
), patch.object(
|
|
docker_mod, "die", side_effect=SystemExit("die"),
|
|
) as die:
|
|
with self.assertRaises(SystemExit):
|
|
docker_mod.commit_container("missing-container", "some:tag")
|
|
die.assert_called_once()
|
|
self.assertIn("missing-container", die.call_args.args[0])
|
|
|
|
def test_die_message_includes_image_tag(self):
|
|
with patch.object(
|
|
docker_mod.subprocess, "run", return_value=_fail("boom"),
|
|
), patch.object(
|
|
docker_mod, "die", side_effect=SystemExit("die"),
|
|
) as die:
|
|
with self.assertRaises(SystemExit):
|
|
docker_mod.commit_container("ctr", "my-tag:v1")
|
|
self.assertIn("my-tag:v1", die.call_args.args[0])
|
|
|
|
|
|
if __name__ == "__main__":
|
|
unittest.main()
|