refactor(runtime): rename docker-specific helpers to backend-agnostic names

- check_docker_installed/connection -> check_runtime_installed/connection
- pull_docker_image -> pull_runtime_image
- get_docker_client -> get_runtime_client
- track backend_name on sandbox session/client for accurate error context
- drop unused HOST_GATEWAY_HOSTNAME constant
This commit is contained in:
B661LP 2026-09-09 14:11:23 +02:00
parent fb5fcb17ad
commit ad0a371d80
9 changed files with 100 additions and 37 deletions

59
skills-lock.json Normal file
View file

@ -0,0 +1,59 @@
{
"version": 1,
"skills": {
"api-security-testing": {
"source": "usestrix/strix",
"sourceType": "github",
"skillPath": "skills/api-security-testing/SKILL.md",
"computedHash": "f1ae8b66cf139807a78dde2b50167ae628635a6c026c17edd864b6c6a65cec5c"
},
"application-security-testing": {
"source": "usestrix/strix",
"sourceType": "github",
"skillPath": "skills/application-security-testing/SKILL.md",
"computedHash": "3869b05bff8e91d2eee9ec98845e5a0fe0a73cca74ceef8c80b7dadc011431ff"
},
"ci-security-scanning-with-strix": {
"source": "usestrix/strix",
"sourceType": "github",
"skillPath": "skills/ci-security-scanning-with-strix/SKILL.md",
"computedHash": "ac3b8d18690ee68dcf178f3156caac1006da4377f4e3a02a55cb7ebe99566d9f"
},
"find-security-vulnerabilities-in-code": {
"source": "usestrix/strix",
"sourceType": "github",
"skillPath": "skills/find-security-vulnerabilities-in-code/SKILL.md",
"computedHash": "b9aaebedb74653bed108ad54790be164fc70e60ca6fbca844e379cb0408498cf"
},
"fix-security-vulnerabilities-with-strix": {
"source": "usestrix/strix",
"sourceType": "github",
"skillPath": "skills/fix-security-vulnerabilities-with-strix/SKILL.md",
"computedHash": "1f91d165671877f77b0c23f34a4596375dc425de388f5b17d2a4742194a8bfb8"
},
"managed-pentesting-with-strix": {
"source": "usestrix/strix",
"sourceType": "github",
"skillPath": "skills/managed-pentesting-with-strix/SKILL.md",
"computedHash": "64c0544b9c50750f3d417cae3fdc5cb8710ca0a0d6ac29ed3b81807e37d63ee1"
},
"owasp-top-10-testing": {
"source": "usestrix/strix",
"sourceType": "github",
"skillPath": "skills/owasp-top-10-testing/SKILL.md",
"computedHash": "82a5e167fd58e3641e61097f9206c8ecaab30e18bbf932499c85a4f58a6a49ba"
},
"penetration-testing-with-strix": {
"source": "usestrix/strix",
"sourceType": "github",
"skillPath": "skills/penetration-testing-with-strix/SKILL.md",
"computedHash": "a765131ca550714b55260cca234eeb5e09ae5dc32412d0aa6fc5d03860c13667"
},
"web-app-penetration-testing": {
"source": "usestrix/strix",
"sourceType": "github",
"skillPath": "skills/web-app-penetration-testing/SKILL.md",
"computedHash": "4a26881a2e8d289611e12557aea27f729facfa4aef777ddcb43a6b6f7d6fe2ee"
}
}
}

View file

@ -1,4 +1,4 @@
"""Startup environment validation and Docker image management."""
"""Startup environment validation and sandbox image management."""
import logging
import os
@ -11,7 +11,7 @@ from rich.text import Text
from strix.config import IntegrationSettings, codex, load_settings
from strix.interface.utils import (
check_docker_connection,
check_runtime_connection,
image_exists,
process_pull_line,
)
@ -164,7 +164,7 @@ def validate_environment() -> None:
)
def check_docker_installed() -> None:
def check_runtime_installed() -> None:
backend = os.environ.get("STRIX_RUNTIME_BACKEND", "").strip()
if not backend:
try:
@ -205,7 +205,7 @@ def check_docker_installed() -> None:
logger.debug("%s CLI present", display_name)
def pull_docker_image() -> None:
def pull_runtime_image() -> None:
from docker.errors import DockerException
console = Console()
@ -217,7 +217,7 @@ def pull_docker_image() -> None:
backend = "docker"
backend = (backend or "docker").lower()
display_name = "Podman" if backend == "podman" else "Docker"
client = check_docker_connection(backend)
client = check_runtime_connection(backend)
image = load_settings().runtime.image

View file

@ -17,8 +17,8 @@ from strix.config import codex, load_settings, persist_current
from strix.core.paths import run_dir_for
from strix.interface.cli_args import parse_arguments
from strix.interface.environment import (
check_docker_installed,
pull_docker_image,
check_runtime_installed,
pull_runtime_image,
validate_environment,
)
from strix.interface.interactive import (
@ -469,8 +469,8 @@ def main() -> None:
restart_after_update()
sys.exit(0)
check_docker_installed()
pull_docker_image()
check_runtime_installed()
pull_runtime_image()
validate_environment()
# Everything below imports the scan engine; do not race the warm-up thread.

View file

@ -48,8 +48,6 @@ if TYPE_CHECKING:
logger = logging.getLogger(__name__)
HOST_GATEWAY_HOSTNAME = "host.docker.internal"
class ModelConnectionError(RuntimeError):
"""An ordinary model preflight failure, annotated with its model route."""

View file

@ -1597,11 +1597,11 @@ def clone_repository(repo_url: str, run_name: str, dest_name: str | None = None)
) from e
def check_docker_connection(backend: str | None = None) -> Any:
def check_runtime_connection(backend: str | None = None) -> Any:
import os
from strix.config import load_settings
from strix.runtime.backends import get_docker_client
from strix.runtime.backends import get_runtime_client
if backend is None:
backend = os.environ.get("STRIX_RUNTIME_BACKEND", "").strip()
@ -1614,7 +1614,7 @@ def check_docker_connection(backend: str | None = None) -> Any:
display_name = "Podman" if resolved_backend == "podman" else "Docker"
try:
client = get_docker_client(resolved_backend)
client = get_runtime_client(resolved_backend)
client.ping()
except Exception as exc:
report_error(f"{resolved_backend}_unavailable", exc)

View file

@ -3,9 +3,9 @@
from strix.runtime.backends import (
backend_supports_bind_mounts,
get_backend,
get_docker_client,
get_host_gateway,
get_podman_socket_candidates,
get_runtime_client,
parse_podman_machine_inspect,
register_backend,
resolve_runtime_socket,
@ -16,9 +16,9 @@ from strix.runtime.backends import (
__all__ = [
"backend_supports_bind_mounts",
"get_backend",
"get_docker_client",
"get_host_gateway",
"get_podman_socket_candidates",
"get_runtime_client",
"parse_podman_machine_inspect",
"register_backend",
"resolve_runtime_socket",

View file

@ -298,8 +298,8 @@ def resolve_runtime_socket(backend: str = "docker") -> str | None:
return None
def get_docker_client(backend: str = "docker") -> Any:
"""Create a Docker client for ``backend`` using multi-layer socket fallthrough:
def get_runtime_client(backend: str = "docker") -> Any:
"""Create a container runtime client for ``backend`` using multi-layer socket fallthrough:
STRIX_RUNTIME_SOCKET → DOCKER_HOST → per-backend auto-detection → docker.from_env() default.
Gracefully falls through to docker.from_env() on connection/ping failure.
@ -350,9 +350,10 @@ async def _docker_backend(
from strix.runtime.docker_client import StrixDockerSandboxClient
raw_client = get_docker_client("docker")
raw_client = get_runtime_client("docker")
client = StrixDockerSandboxClient(raw_client)
client.host_gateway = get_host_gateway("docker")
client.backend_name = "docker"
client.strix_bind_mounts = bind_mounts or []
options = DockerSandboxClientOptions(image=image, exposed_ports=exposed_ports)
session = await client.create(options=options, manifest=manifest)
@ -376,9 +377,10 @@ async def _podman_backend(
from strix.runtime.docker_client import StrixDockerSandboxClient
raw_client = get_docker_client("podman")
raw_client = get_runtime_client("podman")
client = StrixDockerSandboxClient(raw_client)
client.host_gateway = get_host_gateway("podman")
client.backend_name = "podman"
client.strix_bind_mounts = bind_mounts or []
options = DockerSandboxClientOptions(image=image, exposed_ports=exposed_ports)
session = await client.create(options=options, manifest=manifest)

View file

@ -125,6 +125,7 @@ def _apply_run_labels(create_kwargs: dict[str, Any]) -> None:
class StrixDockerSandboxSession(DockerSandboxSession):
sandbox_network: str = ""
backend_name: str = "docker"
async def _resolve_exposed_port(self, port: int) -> ExposedPortEndpoint:
try:
@ -135,7 +136,7 @@ class StrixDockerSandboxSession(DockerSandboxSession):
exposed_ports=self.state.exposed_ports,
reason="backend_unavailable",
context={
"backend": "docker",
"backend": self.backend_name,
"detail": "container_reload_failed",
"network": self.sandbox_network,
},
@ -152,7 +153,7 @@ class StrixDockerSandboxSession(DockerSandboxSession):
exposed_ports=self.state.exposed_ports,
reason="backend_unavailable",
context={
"backend": "docker",
"backend": self.backend_name,
"detail": "container_not_on_network",
"network": self.sandbox_network,
},
@ -166,6 +167,7 @@ class StrixDockerSandboxClient(DockerSandboxClient):
# backend before ``create()``. Each item is ``{source, target, read_only}``.
strix_bind_mounts: list[dict[str, Any]] | None = None
host_gateway: str = "host.docker.internal"
backend_name: str = "docker"
async def _create_container(
self,
@ -275,7 +277,9 @@ class StrixDockerSandboxClient(DockerSandboxClient):
inner = session._inner
if network and isinstance(inner, DockerSandboxSession):
inner.__class__ = StrixDockerSandboxSession
cast("StrixDockerSandboxSession", inner).sandbox_network = network
strix_inner = cast("StrixDockerSandboxSession", inner)
strix_inner.sandbox_network = network
strix_inner.backend_name = self.backend_name
return session
async def delete(self, session: SandboxSession) -> SandboxSession:

View file

@ -12,17 +12,17 @@ from unittest.mock import MagicMock, patch
import pytest
from strix.interface.environment import check_docker_installed
from strix.interface.utils import check_docker_connection
from strix.interface.environment import check_runtime_installed
from strix.interface.utils import check_runtime_connection
from strix.runtime.backends import (
_BACKENDS,
_BIND_MOUNT_BACKENDS,
auto_detect_podman_socket,
backend_supports_bind_mounts,
get_backend,
get_docker_client,
get_host_gateway,
get_podman_socket_candidates,
get_runtime_client,
normalize_socket_url,
parse_podman_machine_inspect,
register_backend,
@ -307,7 +307,7 @@ def test_socket_fallthrough_graceful_on_missing_or_failed_socket(
return_value="unix:///unreachable.sock",
),
):
client = get_docker_client("podman")
client = get_runtime_client("podman")
assert client is mock_default_client
mock_docker.from_env.assert_called_once()
@ -325,7 +325,7 @@ def test_socket_fallthrough_strix_runtime_socket_raw_path_normalization() -> Non
# ============================================================================
def test_check_docker_installed_podman_success(monkeypatch: pytest.MonkeyPatch) -> None:
def test_check_runtime_installed_podman_success(monkeypatch: pytest.MonkeyPatch) -> None:
"""When STRIX_RUNTIME_BACKEND=podman, succeeds if podman is in PATH even if docker is not."""
monkeypatch.setenv("STRIX_RUNTIME_BACKEND", "podman")
@ -336,20 +336,20 @@ def test_check_docker_installed_podman_success(monkeypatch: pytest.MonkeyPatch)
monkeypatch.setattr("shutil.which", fake_which)
# Should not raise or sys.exit
check_docker_installed()
check_runtime_installed()
def test_check_docker_installed_podman_missing(monkeypatch: pytest.MonkeyPatch) -> None:
def test_check_runtime_installed_podman_missing(monkeypatch: pytest.MonkeyPatch) -> None:
"""When STRIX_RUNTIME_BACKEND=podman and neither podman nor docker in PATH, exits with error."""
monkeypatch.setenv("STRIX_RUNTIME_BACKEND", "podman")
monkeypatch.setattr("shutil.which", lambda _cmd: None)
with pytest.raises(SystemExit) as exc_info:
check_docker_installed()
check_runtime_installed()
assert exc_info.value.code == 1
def test_check_docker_installed_docker_missing(monkeypatch: pytest.MonkeyPatch) -> None:
def test_check_runtime_installed_docker_missing(monkeypatch: pytest.MonkeyPatch) -> None:
"""When backend is docker and docker is missing from PATH, exits with error."""
monkeypatch.setenv("STRIX_RUNTIME_BACKEND", "docker")
@ -361,19 +361,19 @@ def test_check_docker_installed_docker_missing(monkeypatch: pytest.MonkeyPatch)
monkeypatch.setattr("shutil.which", fake_which)
with pytest.raises(SystemExit) as exc_info:
check_docker_installed()
check_runtime_installed()
assert exc_info.value.code == 1
def test_check_docker_connection_podman_uses_podman_backend(
def test_check_runtime_connection_podman_uses_podman_backend(
monkeypatch: pytest.MonkeyPatch,
) -> None:
"""check_docker_connection connects and pings backend client."""
"""check_runtime_connection connects and pings backend client."""
monkeypatch.setenv("STRIX_RUNTIME_BACKEND", "podman")
mock_client = MagicMock()
with patch("strix.runtime.backends.get_docker_client", return_value=mock_client) as mock_get:
client = check_docker_connection()
with patch("strix.runtime.backends.get_runtime_client", return_value=mock_client) as mock_get:
client = check_runtime_connection()
mock_get.assert_called_once_with("podman")
mock_client.ping.assert_called_once()
assert client is mock_client