mirror of
https://github.com/usestrix/strix.git
synced 2026-11-01 07:02:32 +00:00
feat(runtime): pass host devices from STRIX_DOCKER_SANDBOX_DEVICES through to the sandbox container
This commit is contained in:
parent
dc40345e26
commit
200a501f15
2 changed files with 60 additions and 0 deletions
|
|
@ -66,6 +66,33 @@ def _apply_sandbox_network(create_kwargs: dict[str, Any]) -> None:
|
|||
create_kwargs.pop("ports", None)
|
||||
|
||||
|
||||
_SANDBOX_DEVICES_ENV = "STRIX_DOCKER_SANDBOX_DEVICES"
|
||||
|
||||
|
||||
def _sandbox_devices() -> list[str]:
|
||||
raw = os.environ.get(_SANDBOX_DEVICES_ENV, "")
|
||||
return [item.strip() for item in raw.split(",") if item.strip()]
|
||||
|
||||
|
||||
def _apply_sandbox_devices(create_kwargs: dict[str, Any]) -> None:
|
||||
"""Pass the host devices listed in ``STRIX_DOCKER_SANDBOX_DEVICES`` through.
|
||||
|
||||
Comma-separated device paths, each mapped to the same path in the container
|
||||
with ``rwm`` access. A tunnel brought up inside the sandbox (OpenVPN,
|
||||
Tailscale) needs ``/dev/net/tun``: Docker's default device cgroup denies it
|
||||
even with ``NET_ADMIN``. Unset means no extra devices.
|
||||
"""
|
||||
devices = _sandbox_devices()
|
||||
if not devices:
|
||||
return
|
||||
existing = [str(item) for item in (create_kwargs.get("devices") or [])]
|
||||
for path in devices:
|
||||
spec = f"{path}:{path}:rwm"
|
||||
if spec not in existing and path not in existing:
|
||||
existing.append(spec)
|
||||
create_kwargs["devices"] = existing
|
||||
|
||||
|
||||
def _apply_resource_limits(create_kwargs: dict[str, Any]) -> None:
|
||||
"""Apply optional cgroup resource caps from the environment. Unset/blank
|
||||
values leave docker's default (unbounded), so this is opt-in per host."""
|
||||
|
|
@ -233,6 +260,7 @@ class StrixDockerSandboxClient(DockerSandboxClient):
|
|||
extra_hosts["host.docker.internal"] = "host-gateway"
|
||||
|
||||
_apply_sandbox_network(create_kwargs)
|
||||
_apply_sandbox_devices(create_kwargs)
|
||||
_apply_resource_limits(create_kwargs)
|
||||
_apply_log_limits(create_kwargs)
|
||||
_apply_run_labels(create_kwargs)
|
||||
|
|
|
|||
32
tests/test_docker_client_devices.py
Normal file
32
tests/test_docker_client_devices.py
Normal file
|
|
@ -0,0 +1,32 @@
|
|||
"""``STRIX_DOCKER_SANDBOX_DEVICES`` passes host devices through to the sandbox container."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from strix.runtime import docker_client
|
||||
|
||||
|
||||
if TYPE_CHECKING:
|
||||
import pytest
|
||||
|
||||
|
||||
def test_unset_adds_no_devices(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.delenv(docker_client._SANDBOX_DEVICES_ENV, raising=False)
|
||||
kwargs: dict[str, object] = {}
|
||||
docker_client._apply_sandbox_devices(kwargs)
|
||||
assert kwargs == {}
|
||||
|
||||
|
||||
def test_devices_are_mapped_to_the_same_path_rwm(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setenv(docker_client._SANDBOX_DEVICES_ENV, " /dev/net/tun, /dev/kvm ,,")
|
||||
kwargs: dict[str, object] = {}
|
||||
docker_client._apply_sandbox_devices(kwargs)
|
||||
assert kwargs["devices"] == ["/dev/net/tun:/dev/net/tun:rwm", "/dev/kvm:/dev/kvm:rwm"]
|
||||
|
||||
|
||||
def test_existing_devices_are_kept_and_not_duplicated(monkeypatch: pytest.MonkeyPatch) -> None:
|
||||
monkeypatch.setenv(docker_client._SANDBOX_DEVICES_ENV, "/dev/fuse,/dev/net/tun")
|
||||
kwargs: dict[str, object] = {"devices": ["/dev/fuse"]}
|
||||
docker_client._apply_sandbox_devices(kwargs)
|
||||
assert kwargs["devices"] == ["/dev/fuse", "/dev/net/tun:/dev/net/tun:rwm"]
|
||||
Loading…
Add table
Reference in a new issue