mirror of
https://github.com/OpenHands/OpenHands.git
synced 2026-03-22 05:37:20 +08:00
fix: handle containers with tagless images in DockerSandboxService (#13238)
This commit is contained in:
@@ -197,6 +197,12 @@ class DockerSandboxService(SandboxService):
|
||||
)
|
||||
)
|
||||
|
||||
if not container.image.tags:
|
||||
_logger.debug(
|
||||
f'Skipping container {container.name!r}: image has no tags (image id: {container.image.id})'
|
||||
)
|
||||
return None
|
||||
|
||||
return SandboxInfo(
|
||||
id=container.name,
|
||||
created_by_user_id=None,
|
||||
|
||||
@@ -245,6 +245,61 @@ class TestDockerSandboxService:
|
||||
assert len(result.items) == 0
|
||||
assert result.next_page_id is None
|
||||
|
||||
async def test_search_sandboxes_skips_containers_with_no_image_tags(
|
||||
self, service, mock_running_container
|
||||
):
|
||||
"""Test that containers with tagless images are skipped without crashing.
|
||||
|
||||
Regression test: when a container's image has been rebuilt with the same tag,
|
||||
the old container's image loses its tags, causing container.image.tags to be
|
||||
an empty list. Previously this caused an IndexError.
|
||||
"""
|
||||
# Setup a container with no image tags (e.g. image was retagged/rebuilt)
|
||||
tagless_container = MagicMock()
|
||||
tagless_container.name = 'oh-test-tagless'
|
||||
tagless_container.status = 'paused'
|
||||
tagless_container.image.tags = []
|
||||
tagless_container.image.id = 'sha256:abc123def456'
|
||||
tagless_container.attrs = {
|
||||
'Created': '2024-01-15T10:30:00.000000000Z',
|
||||
'Config': {'Env': []},
|
||||
'NetworkSettings': {'Ports': {}},
|
||||
}
|
||||
|
||||
service.docker_client.containers.list.return_value = [
|
||||
mock_running_container,
|
||||
tagless_container,
|
||||
]
|
||||
service.httpx_client.get.return_value.raise_for_status.return_value = None
|
||||
|
||||
# Execute - should not raise IndexError
|
||||
result = await service.search_sandboxes()
|
||||
|
||||
# Verify - only the properly tagged container is returned
|
||||
assert isinstance(result, SandboxPage)
|
||||
assert len(result.items) == 1
|
||||
assert result.items[0].id == 'oh-test-abc123'
|
||||
|
||||
async def test_get_sandbox_returns_none_for_tagless_image(self, service):
|
||||
"""Test that get_sandbox returns None for containers with tagless images."""
|
||||
tagless_container = MagicMock()
|
||||
tagless_container.name = 'oh-test-tagless'
|
||||
tagless_container.status = 'paused'
|
||||
tagless_container.image.tags = []
|
||||
tagless_container.image.id = 'sha256:abc123def456'
|
||||
tagless_container.attrs = {
|
||||
'Created': '2024-01-15T10:30:00.000000000Z',
|
||||
'Config': {'Env': []},
|
||||
'NetworkSettings': {'Ports': {}},
|
||||
}
|
||||
service.docker_client.containers.get.return_value = tagless_container
|
||||
|
||||
# Execute - should not raise IndexError
|
||||
result = await service.get_sandbox('oh-test-tagless')
|
||||
|
||||
# Verify - returns None for tagless container
|
||||
assert result is None
|
||||
|
||||
async def test_search_sandboxes_filters_by_prefix(self, service):
|
||||
"""Test that search filters containers by name prefix."""
|
||||
# Setup
|
||||
|
||||
Reference in New Issue
Block a user