mirror of
https://github.com/usestrix/strix.git
synced 2026-11-14 09:01:25 +00:00
Merge e4b311986c into 851743adcf
This commit is contained in:
commit
46b993d16f
2 changed files with 90 additions and 0 deletions
|
|
@ -25,6 +25,14 @@ from strix.utils.api_spec import detect_spec_format
|
|||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
DOCKER_PERMISSION_ERROR_MARKERS = ("permission denied", "operation not permitted")
|
||||
DOCKER_LOCAL_SOCKET_SCHEME = "unix://"
|
||||
DOCKER_SOCKET_ACCESS_HINT = (
|
||||
"Docker is installed, but Strix cannot access the Docker socket. "
|
||||
"Run Strix with a user that can access Docker, or add your user to the docker group "
|
||||
"and restart your shell before trying again.\n"
|
||||
)
|
||||
|
||||
|
||||
def get_severity_color(severity: str) -> str:
|
||||
severity_colors = {
|
||||
|
|
@ -1598,6 +1606,24 @@ def clone_repository(repo_url: str, run_name: str, dest_name: str | None = None)
|
|||
) from e
|
||||
|
||||
|
||||
def _is_docker_permission_error(exc: BaseException) -> bool:
|
||||
message = str(exc).lower()
|
||||
return any(marker in message for marker in DOCKER_PERMISSION_ERROR_MARKERS)
|
||||
|
||||
|
||||
def _is_docker_socket_permission_error(exc: Any) -> bool:
|
||||
"""A permission error against the *local* Docker socket.
|
||||
|
||||
The docker-group remedy only applies to a Unix-socket daemon. A permission
|
||||
failure against a remote DOCKER_HOST (TCP/SSH) endpoint is not fixed by
|
||||
group membership, so the socket hint must not be shown for it.
|
||||
"""
|
||||
if not _is_docker_permission_error(exc):
|
||||
return False
|
||||
host = exc.endpoint.host
|
||||
return host is None or host.startswith(DOCKER_LOCAL_SOCKET_SCHEME)
|
||||
|
||||
|
||||
def check_docker_connection() -> Any:
|
||||
from strix.runtime.docker_connection import DockerConnectionError, connect_docker
|
||||
|
||||
|
|
@ -1611,6 +1637,8 @@ def check_docker_connection() -> Any:
|
|||
error_text.append("\n\n", style="white")
|
||||
error_text.append(f"Cannot connect to Docker at {exc.endpoint.label}.\n", style="white")
|
||||
error_text.append(f"{exc.detail}\n\n", style="dim red")
|
||||
if _is_docker_socket_permission_error(exc):
|
||||
error_text.append(DOCKER_SOCKET_ACCESS_HINT, style="white")
|
||||
error_text.append(
|
||||
"Make sure Docker is running. If `docker info` works in this shell, strix uses "
|
||||
"the same daemon. Otherwise set DOCKER_HOST.\n",
|
||||
|
|
|
|||
62
tests/test_docker_connection_message.py
Normal file
62
tests/test_docker_connection_message.py
Normal file
|
|
@ -0,0 +1,62 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import io
|
||||
|
||||
import pytest
|
||||
from docker.errors import DockerException
|
||||
from rich.console import Console
|
||||
|
||||
from strix.interface import utils
|
||||
from strix.runtime import docker_connection
|
||||
from strix.runtime.docker_connection import DockerConnectionError, DockerEndpoint
|
||||
|
||||
|
||||
DOCKER_PERMISSION_ERROR = "permission denied while trying to connect to the Docker daemon socket"
|
||||
DOCKER_SOCKET_HINT = "Docker socket"
|
||||
DOCKER_GROUP_HINT = "docker group"
|
||||
|
||||
|
||||
def test_docker_connection_permission_error_mentions_socket_access(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
output = io.StringIO()
|
||||
|
||||
def fake_console() -> Console:
|
||||
return Console(file=output, color_system=None, force_terminal=False)
|
||||
|
||||
def fail_connect() -> None:
|
||||
endpoint = DockerEndpoint(None, "default socket")
|
||||
raise DockerConnectionError(endpoint, DockerException(DOCKER_PERMISSION_ERROR))
|
||||
|
||||
monkeypatch.setattr(utils, "Console", fake_console)
|
||||
monkeypatch.setattr(docker_connection, "connect_docker", fail_connect)
|
||||
|
||||
with pytest.raises(SystemExit):
|
||||
utils.check_docker_connection()
|
||||
|
||||
rendered = output.getvalue()
|
||||
assert DOCKER_SOCKET_HINT in rendered
|
||||
assert DOCKER_GROUP_HINT in rendered
|
||||
|
||||
|
||||
def test_docker_connection_permission_error_on_remote_host_skips_socket_hint(
|
||||
monkeypatch: pytest.MonkeyPatch,
|
||||
) -> None:
|
||||
output = io.StringIO()
|
||||
|
||||
def fake_console() -> Console:
|
||||
return Console(file=output, color_system=None, force_terminal=False)
|
||||
|
||||
def fail_connect() -> None:
|
||||
endpoint = DockerEndpoint("tcp://10.0.0.5:2376", "DOCKER_HOST")
|
||||
raise DockerConnectionError(endpoint, DockerException(DOCKER_PERMISSION_ERROR))
|
||||
|
||||
monkeypatch.setattr(utils, "Console", fake_console)
|
||||
monkeypatch.setattr(docker_connection, "connect_docker", fail_connect)
|
||||
|
||||
with pytest.raises(SystemExit):
|
||||
utils.check_docker_connection()
|
||||
|
||||
rendered = output.getvalue()
|
||||
assert DOCKER_SOCKET_HINT not in rendered
|
||||
assert DOCKER_GROUP_HINT not in rendered
|
||||
Loading…
Add table
Reference in a new issue