Merge remote-tracking branch 'origin/dev' into dev
# Conflicts: # .gitignore
This commit is contained in:
@@ -49,10 +49,8 @@ apps/web/dist/
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
/.stoneforge/.worktrees/
|
||||
|
||||
# Pi / agent cache
|
||||
.pi/
|
||||
.atl/
|
||||
.sisyphus/
|
||||
.pi-lens/
|
||||
|
||||
|
||||
@@ -147,8 +147,9 @@ def get_container_id(instance_name: str) -> str | None:
|
||||
Returns:
|
||||
Container ID or None if not found
|
||||
"""
|
||||
# Docker container names are lowercase internally; normalize to ensure match
|
||||
result = subprocess.run(
|
||||
["docker", "ps", "-a", "-q", "--filter", f"name={instance_name}"],
|
||||
["docker", "ps", "-a", "-q", "--filter", f"name={instance_name.lower()}"],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
)
|
||||
@@ -169,6 +170,7 @@ def get_container_name(instance_name: str) -> str | None:
|
||||
Returns:
|
||||
Container name or None if not found
|
||||
"""
|
||||
# Docker container names are lowercase internally; normalize to ensure match
|
||||
result = subprocess.run(
|
||||
[
|
||||
"docker",
|
||||
@@ -177,7 +179,7 @@ def get_container_name(instance_name: str) -> str | None:
|
||||
"--format",
|
||||
"{{.Names}}",
|
||||
"--filter",
|
||||
f"name={instance_name}",
|
||||
f"name={instance_name.lower()}",
|
||||
],
|
||||
capture_output=True,
|
||||
text=True,
|
||||
@@ -403,6 +405,11 @@ def start_cloudflared_tunnel(
|
||||
start_time = time.time()
|
||||
url = None
|
||||
|
||||
if proc.stdout is None:
|
||||
proc.terminate()
|
||||
proc.wait(timeout=5)
|
||||
raise RuntimeError("Failed to capture cloudflared output")
|
||||
|
||||
while time.time() - start_time < timeout:
|
||||
# Read available output
|
||||
import select
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
"""Unit tests for docker service utilities."""
|
||||
|
||||
from unittest.mock import MagicMock, patch
|
||||
|
||||
from src.services.docker import get_container_id, get_container_name
|
||||
|
||||
|
||||
class TestGetContainerId:
|
||||
"""Tests for get_container_id."""
|
||||
|
||||
@patch("subprocess.run")
|
||||
def test_lowercases_name_for_filter(self, mock_run) -> None:
|
||||
"""Docker ps name filter is case-sensitive; we must lowercase."""
|
||||
mock_run.return_value = MagicMock(returncode=0, stdout="abc123\n")
|
||||
|
||||
result = get_container_id("MyContainer-ABC")
|
||||
|
||||
assert result == "abc123"
|
||||
call_args = mock_run.call_args[0][0]
|
||||
# The filter must use lowercase
|
||||
assert "name=mycontainer-abc" in call_args
|
||||
|
||||
@patch("subprocess.run")
|
||||
def test_returns_none_when_not_found(self, mock_run) -> None:
|
||||
mock_run.return_value = MagicMock(returncode=0, stdout="")
|
||||
|
||||
result = get_container_id("missing")
|
||||
|
||||
assert result is None
|
||||
|
||||
|
||||
class TestGetContainerName:
|
||||
"""Tests for get_container_name."""
|
||||
|
||||
@patch("subprocess.run")
|
||||
def test_lowercases_name_for_filter(self, mock_run) -> None:
|
||||
"""Docker ps name filter is case-sensitive; we must lowercase."""
|
||||
mock_run.return_value = MagicMock(returncode=0, stdout="mycontainer-abc\n")
|
||||
|
||||
result = get_container_name("MyContainer-ABC")
|
||||
|
||||
assert result == "mycontainer-abc"
|
||||
call_args = mock_run.call_args[0][0]
|
||||
assert "name=mycontainer-abc" in call_args
|
||||
|
||||
@patch("subprocess.run")
|
||||
def test_returns_none_when_not_found(self, mock_run) -> None:
|
||||
mock_run.return_value = MagicMock(returncode=0, stdout="")
|
||||
|
||||
result = get_container_name("missing")
|
||||
|
||||
assert result is None
|
||||
Reference in New Issue
Block a user