Skip to content

Commit 0430ada

Browse files
authored
Add implementation for DockerService.List (#199)
1 parent 744c673 commit 0430ada

File tree

2 files changed

+78
-3
lines changed

2 files changed

+78
-3
lines changed

host_modules/docker_service.py

Lines changed: 35 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@
44
import docker
55
import signal
66
import errno
7+
import json
78
import logging
89

910
MOD_NAME = "docker_service"
@@ -273,4 +274,37 @@ def load(self, image):
273274
except FileNotFoundError:
274275
return errno.ENOENT, "File {} not found.".format(image)
275276
except Exception as e:
276-
return 1, "Failed to load image {}: {}".format(image, str(e))
277+
return 1, "Failed to load image {}: {}".format(image, str(e))
278+
279+
@host_service.method(
280+
host_service.bus_name(MOD_NAME), in_signature="ba{sv}", out_signature="is"
281+
)
282+
def list(self, all, filter):
283+
"""
284+
List Docker containers.
285+
286+
Args:
287+
all (bool): Whether to list all containers or only running ones.
288+
filter (dict): Filters to apply when listing containers.
289+
290+
Returns:
291+
tuple: A tuple containing the exit code (int) and a JSON string of the container list.
292+
"""
293+
try:
294+
client = docker.from_env()
295+
listed_containers = client.containers.list(all=all, filters=filter)
296+
container_list = [
297+
{
298+
"id": container.id,
299+
"name": container.name,
300+
"status": container.status,
301+
"image": container.image.tags[0] if container.image.tags else "",
302+
"labels": container.labels,
303+
"hash": container.image.id,
304+
}
305+
for container in listed_containers
306+
]
307+
logging.info("List of containers: {}".format(container_list))
308+
return 0, json.dumps(container_list)
309+
except Exception as e:
310+
return 1, "Failed to list containers: {} {}".format(str(e), container_list)

tests/host_modules/docker_service_test.py

Lines changed: 43 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
import errno
22
import docker
3+
import json
34
from unittest import mock
45
from host_modules.docker_service import DockerService
56

@@ -303,7 +304,7 @@ def test_docker_load_success(self, MockInit, MockBusName, MockSystemBus):
303304
assert rc == 0, "Return code is wrong"
304305
mock_docker_client.images.load.assert_called_once_with(MockOpen.return_value)
305306
MockOpen.assert_called_once_with("image.tar", "rb")
306-
307+
307308
@mock.patch("dbus.SystemBus")
308309
@mock.patch("dbus.service.BusName")
309310
@mock.patch("dbus.service.Object.__init__")
@@ -317,4 +318,44 @@ def test_docker_load_file_not_found(self, MockInit, MockBusName, MockSystemBus):
317318
rc, _ = docker_service.load("non_existent_image.tar")
318319

319320
assert rc == errno.ENOENT, "Return code is wrong"
320-
MockOpen.assert_called_once_with("non_existent_image.tar", "rb")
321+
MockOpen.assert_called_once_with("non_existent_image.tar", "rb")
322+
323+
@mock.patch("dbus.SystemBus")
324+
@mock.patch("dbus.service.BusName")
325+
@mock.patch("dbus.service.Object.__init__")
326+
def test_docker_list_success(self, MockInit, MockBusName, MockSystemBus):
327+
mock_docker_client = mock.Mock()
328+
mock_container_1 = mock.Mock(id="1", status="running", image=mock.Mock(tags=["image1"], id="hash1"), labels={})
329+
mock_container_2 = mock.Mock(id="2", status="exited", image=mock.Mock(tags=["image2"], id="hash2"), labels={})
330+
# The name attribute needs to be explicitly set for the mock object.
331+
mock_container_1.name = "container1"
332+
mock_container_2.name = "container2"
333+
mock_docker_client.containers.list.return_value = [
334+
mock_container_1, mock_container_2
335+
]
336+
337+
with mock.patch.object(docker, "from_env", return_value=mock_docker_client):
338+
docker_service = DockerService(MOD_NAME)
339+
rc, containers = docker_service.list(True, {})
340+
341+
assert rc == 0, "Return code is wrong {}".format(containers)
342+
expected_containers = [
343+
{
344+
"id": "1",
345+
"name": "container1",
346+
"status": "running",
347+
"image": "image1",
348+
"labels": {},
349+
"hash": "hash1",
350+
},
351+
{
352+
"id": "2",
353+
"name": "container2",
354+
"status": "exited",
355+
"image": "image2",
356+
"labels": {},
357+
"hash": "hash2",
358+
},
359+
]
360+
assert json.loads(containers) == expected_containers, "Containers list is wrong"
361+
mock_docker_client.containers.list.assert_called_once_with(all=True, filters={})

0 commit comments

Comments
 (0)