mirror of
https://github.com/usestrix/strix.git
synced 2026-10-01 02:03:55 +00:00
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:
parent
fb5fcb17ad
commit
ad0a371d80
9 changed files with 100 additions and 37 deletions
59
skills-lock.json
Normal file
59
skills-lock.json
Normal 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"
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -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."""
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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",
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue