Skip to content
Open
Show file tree
Hide file tree
Changes from 2 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
48 changes: 43 additions & 5 deletions samcli/local/docker/platform_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -123,11 +123,49 @@ def _read_config(self) -> Optional[str]:

Comment thread
vicheey marked this conversation as resolved.
def get_finch_socket_path(self) -> Optional[str]:
"""
Returns the socket path for Linux.
"""

# Default fallback to system socket
return "unix:///var/run/finch.sock"
Returns the socket path for Linux, checking multiple locations.
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

needs integ test to check builds work too in rootless mode?


Priority order:
1. XDG_RUNTIME_DIR/containerd/containerd.sock (rootless containerd)
2. XDG_RUNTIME_DIR/finch.sock (Finch-specific)
3. ~/.finch/finch.sock (user home directory)
4. /var/run/finch.sock (system-wide)

Returns:
Optional[str]: Socket path if found, None otherwise
"""

# Check XDG_RUNTIME_DIR for rootless containerd
xdg_runtime_dir = os.environ.get("XDG_RUNTIME_DIR")
if xdg_runtime_dir:
# Rootless containerd socket (most common on Linux)
containerd_sock = os.path.join(xdg_runtime_dir, "containerd", "containerd.sock")
if os.path.exists(containerd_sock):
LOG.debug(f"Found Finch socket at XDG_RUNTIME_DIR: {containerd_sock}")
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is the containerd_sock exclusively for finch, though? Couldn't other container clients/engines be using this socket?

return f"unix://{containerd_sock}"

# Finch-specific socket in XDG_RUNTIME_DIR
finch_sock = os.path.join(xdg_runtime_dir, "finch.sock")
if os.path.exists(finch_sock):
LOG.debug(f"Found Finch socket at XDG_RUNTIME_DIR: {finch_sock}")
return f"unix://{finch_sock}"

# Check user home directory for Finch VM socket
home_dir = os.path.expanduser("~")
home_finch_sock = os.path.join(home_dir, ".finch", "finch.sock")
if os.path.exists(home_finch_sock):
LOG.debug(f"Found Finch socket in home directory: {home_finch_sock}")
return f"unix://{home_finch_sock}"

# System-wide socket (fallback)
system_sock = "/var/run/finch.sock"
if os.path.exists(system_sock):
LOG.debug(f"Found Finch socket at system location: {system_sock}")
return f"unix://{system_sock}"

# No socket found - return None to enable future CLI fallback
LOG.debug("No Finch socket found in standard locations")
Comment thread
robbrad marked this conversation as resolved.
Outdated
return None

def supports_finch(self) -> bool:
"""
Expand Down
105 changes: 91 additions & 14 deletions tests/unit/local/docker/test_platform_config.py
Original file line number Diff line number Diff line change
Expand Up @@ -159,11 +159,64 @@ def test_read_config_not_implemented(self):
result = self.handler.read_config()
self.assertIsNone(result)

def test_get_finch_socket_path(self):
"""Test Linux Finch socket path"""
@patch("os.path.exists")
@patch.dict("os.environ", {"XDG_RUNTIME_DIR": "/run/user/1001"})
def test_get_finch_socket_path_xdg_containerd(self, mock_exists):
"""Test Linux Finch socket path with XDG_RUNTIME_DIR containerd socket"""
# Mock that containerd socket exists
def exists_side_effect(path):
return path == "/run/user/1001/containerd/containerd.sock"

mock_exists.side_effect = exists_side_effect
result = self.handler.get_finch_socket_path()
self.assertEqual(result, "unix:///run/user/1001/containerd/containerd.sock")

@patch("os.path.exists")
@patch.dict("os.environ", {"XDG_RUNTIME_DIR": "/run/user/1001"})
def test_get_finch_socket_path_xdg_finch(self, mock_exists):
"""Test Linux Finch socket path with XDG_RUNTIME_DIR finch socket"""
# Mock that finch socket exists (but not containerd)
def exists_side_effect(path):
return path == "/run/user/1001/finch.sock"

mock_exists.side_effect = exists_side_effect
result = self.handler.get_finch_socket_path()
self.assertEqual(result, "unix:///run/user/1001/finch.sock")

@patch("os.path.exists")
@patch("os.path.expanduser")
@patch.dict("os.environ", {}, clear=True)
def test_get_finch_socket_path_home_directory(self, mock_expanduser, mock_exists):
"""Test Linux Finch socket path in home directory"""
mock_expanduser.return_value = "/home/testuser"

# Mock that home finch socket exists
def exists_side_effect(path):
return path == "/home/testuser/.finch/finch.sock"

mock_exists.side_effect = exists_side_effect
result = self.handler.get_finch_socket_path()
self.assertEqual(result, "unix:///home/testuser/.finch/finch.sock")

@patch("os.path.exists")
@patch.dict("os.environ", {}, clear=True)
def test_get_finch_socket_path_system_socket(self, mock_exists):
"""Test Linux Finch socket path at system location"""
# Mock that system socket exists
def exists_side_effect(path):
return path == "/var/run/finch.sock"

mock_exists.side_effect = exists_side_effect
result = self.handler.get_finch_socket_path()
self.assertEqual(result, "unix:///var/run/finch.sock")

@patch("os.path.exists", return_value=False)
@patch.dict("os.environ", {}, clear=True)
def test_get_finch_socket_path_not_found(self, mock_exists):
"""Test Linux Finch socket path when no socket exists"""
result = self.handler.get_finch_socket_path()
self.assertIsNone(result)

def test_supports_finch(self):
"""Test that Linux supports Finch"""
self.assertTrue(self.handler.supports_finch())
Expand Down Expand Up @@ -268,21 +321,45 @@ def test_returns_none_for_unsupported_platform(self, mock_system):
class TestGetFinchSocketPath(unittest.TestCase):
"""Tests for get_finch_socket_path utility function"""

@parameterized.expand(
[
("Linux", "unix:///var/run/finch.sock"),
("Darwin", "unix:////Applications/Finch/lima/data/finch/sock/finch.sock"),
("Windows", None),
]
)
@patch("os.path.exists")
@patch("samcli.local.docker.platform_config.platform.system")
def test_get_finch_socket_path_returns_correct_path(self, platform_name, expected_path, mock_system):
"""Test that get_finch_socket_path returns the correct path based on platform"""
mock_system.return_value = platform_name
def test_get_finch_socket_path_linux_with_system_socket(self, mock_system, mock_exists):
"""Test that get_finch_socket_path returns system socket path on Linux when it exists"""
mock_system.return_value = "Linux"

# Mock that system socket exists
def exists_side_effect(path):
return path == "/var/run/finch.sock"

mock_exists.side_effect = exists_side_effect

result = get_finch_socket_path()
self.assertEqual(result, "unix:///var/run/finch.sock")

@patch("os.path.exists", return_value=False)
@patch("samcli.local.docker.platform_config.platform.system")
def test_get_finch_socket_path_linux_no_socket(self, mock_system, mock_exists):
"""Test that get_finch_socket_path returns None on Linux when no socket exists"""
mock_system.return_value = "Linux"

result = get_finch_socket_path()
self.assertEqual(result, expected_path)
mock_system.assert_called_once()
self.assertIsNone(result)

@patch("samcli.local.docker.platform_config.platform.system")
def test_get_finch_socket_path_macos(self, mock_system):
"""Test that get_finch_socket_path returns correct path on macOS"""
mock_system.return_value = "Darwin"

result = get_finch_socket_path()
self.assertEqual(result, "unix:////Applications/Finch/lima/data/finch/sock/finch.sock")

@patch("samcli.local.docker.platform_config.platform.system")
def test_get_finch_socket_path_windows(self, mock_system):
"""Test that get_finch_socket_path returns None on Windows"""
mock_system.return_value = "Windows"

result = get_finch_socket_path()
self.assertIsNone(result)

@patch("samcli.local.docker.platform_config.get_platform_handler")
def test_get_finch_socket_path_returns_none_when_no_handler(self, mock_get_handler):
Expand Down
Loading