"""Compose command configuration and snapshot hooks.""" from unittest.mock import patch import pytest from sandboxer.extensions.compose_ssh import ComposeSSHExtension from sandboxer.models import Profile def _profile() -> Profile: return Profile.model_validate( { "id": "profile.compose-checkpoint", "version": "1.0.0", "extension": "ext.compose-ssh", } ) def test_compose_cmd_from_config() -> None: ext = ComposeSSHExtension({"compose_cmd": "podman-compose"}) assert ext._compose_bin() == "podman-compose" def test_compose_cmd_env_override(monkeypatch) -> None: monkeypatch.setenv("SANDBOXER_COMPOSE_CMD", "nerdctl compose") ext = ComposeSSHExtension({"compose_cmd": "docker compose"}) assert ext._compose_bin() == "nerdctl compose" def test_supports_snapshots() -> None: ext = ComposeSSHExtension() assert ext.supports_snapshots() is True def test_snapshot_creates_remote_tarball() -> None: ext = ComposeSSHExtension({"base_dir": "/tmp/sandboxer"}) handle = { "sandbox_id": "abc12345", "host": "coulombcore", "remote_dir": "/tmp/sandboxer/abc12345", "compose_file": "docker-compose.yml", "compose_project": "sbx-e2e-abc12345", "ssh_user": "root", } def fake_run(cmd, *, timeout=60): if "tar czf" in cmd: return 0, "" if "stat" in cmd: return 0, "2048" return 0, "" with patch.object(ext, "_ssh_for_handle") as ssh_factory: ssh = ssh_factory.return_value ssh.run.side_effect = fake_run meta = ext.snapshot(handle) assert meta["artifact_path"].endswith(".tar.gz") assert meta["snapshot_id"] assert meta["size_bytes"] == "2048" def test_restore_from_snapshot_extracts_and_compose_up() -> None: ext = ComposeSSHExtension({"base_dir": "/tmp/sandboxer"}) snapshot_meta = { "snapshot_id": "snap12345678", "artifact_path": "/tmp/sandboxer/snapshots/snap12345678.tar.gz", "host": "coulombcore", "compose_file": "docker-compose.yml", "ssh_user": "root", } with patch("sandboxer.extensions.compose_ssh.SSHConfig.from_env") as ssh_factory: ssh = ssh_factory.return_value ssh.run.return_value = (0, "") ssh.user = "root" handle = ext.restore_from_snapshot(_profile(), snapshot_meta, {}, "coulombcore") assert handle["sandbox_id"] assert handle["remote_dir"].endswith(handle["sandbox_id"]) calls = [c.args[0] for c in ssh.run.call_args_list] assert any("tar xzf" in c for c in calls) assert any("up -d" in c for c in calls) def test_restore_cross_host_not_supported() -> None: ext = ComposeSSHExtension() snapshot_meta = { "snapshot_id": "snap1", "artifact_path": "/tmp/snap.tar.gz", "host": "host-a", "compose_file": "docker-compose.yml", } with pytest.raises(NotImplementedError, match="cross-host"): ext.restore_from_snapshot(_profile(), snapshot_meta, {}, "host-b")