Skip to content

Implement sparse keyword for containers.list() #540

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all 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
27 changes: 24 additions & 3 deletions podman/domain/containers_manager.py
Original file line number Diff line number Diff line change
Expand Up @@ -67,16 +67,26 @@ def list(self, **kwargs) -> list[Container]:
Give the container name or id.
- since (str): Only containers created after a particular container.
Give container name or id.
sparse: Ignored
sparse: If False, return basic container information without additional
inspection requests. This improves performance when listing many containers
but might provide less detail. You can call Container.reload() on individual
containers later to retrieve complete attributes. Default: True.
When Docker compatibility is enabled with `compatible=True`: Default: False.
ignore_removed: If True, ignore failures due to missing containers.

Raises:
APIError: when service returns an error
"""
compatible = kwargs.get("compatible", False)
# Libpod behavior: default is sparse=True and containers require a reload call
# to get full details
# Docker behavior: default is sparse=False and containers are inspected during
# list calls
params = {
"all": kwargs.get("all"),
"filters": kwargs.get("filters", {}),
"limit": kwargs.get("limit"),
"sparse": kwargs.get("sparse", not compatible),
}
if "before" in kwargs:
params["filters"]["before"] = kwargs.get("before")
Expand All @@ -86,10 +96,21 @@ def list(self, **kwargs) -> list[Container]:
# filters formatted last because some kwargs may need to be mapped into filters
params["filters"] = api.prepare_filters(params["filters"])

response = self.client.get("/containers/json", params=params)
response = self.client.get("/containers/json", params=params, compatible=compatible)
response.raise_for_status()

return [self.prepare_model(attrs=i) for i in response.json()]
containers: list[Container] = [self.prepare_model(attrs=i) for i in response.json()]

# If sparse is False (default), reload each container to get full details
if not kwargs.get("sparse", False):
for container in containers:
try:
container.reload()
except APIError:
# Skip containers that might have been removed
pass

return containers

def prune(self, filters: Mapping[str, str] = None) -> dict[str, Any]:
"""Delete stopped containers.
Expand Down
16 changes: 16 additions & 0 deletions podman/tests/unit/test_containersmanager.py
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,22 @@ def test_list_no_filters(self, mock):
actual[1].id, "6dc84cc0a46747da94e4c1571efcc01a756b4017261440b4b8985d37203c3c03"
)

@requests_mock.Mocker()
def test_list_sparse_with_compat(self, mock):
mock.get(
tests.COMPATIBLE_URL + "/containers/json?sparse=False",
json=[FIRST_CONTAINER, SECOND_CONTAINER],
)
actual = self.client.containers.list(compatible=True)
self.assertIsInstance(actual, list)

self.assertEqual(
actual[0].id, "87e1325c82424e49a00abdd4de08009eb76c7de8d228426a9b8af9318ced5ecd"
)
self.assertEqual(
actual[1].id, "6dc84cc0a46747da94e4c1571efcc01a756b4017261440b4b8985d37203c3c03"
)

@requests_mock.Mocker()
def test_prune(self, mock):
mock.post(
Expand Down