From 36c6b1092ba178e5a0ab3caaec893856b301bc6b Mon Sep 17 00:00:00 2001 From: Michael Sherman Date: Wed, 18 Feb 2026 12:26:43 -0600 Subject: [PATCH 1/2] use "force" when deleting containers By default, zun will raise a 409 when deleting a container in either a running, or transitional state. Calling with "stop=True" fixes it for running containers, but still not for transitional ones, such as containers stuck "creating" or "error". Update python-chi to call with force=true to work in call cases. Note: this depends on the following zun policy being set, otherwise the force argument is admin-only. `container:delete_force: rule:admin_or_owner` --- chi/container.py | 9 ++++++--- tests/test_container.py | 12 ++++++++++++ 2 files changed, 18 insertions(+), 3 deletions(-) diff --git a/chi/container.py b/chi/container.py index 084aa05..2608534 100644 --- a/chi/container.py +++ b/chi/container.py @@ -181,6 +181,9 @@ def delete(self): If the container has an ID, it calls the `destroy_container` function to delete the container. After deletion, it sets the ID and status of the container to None. + Note: Delete is called with "force", which depends on the following zun policy: + `container:delete_force: rule:admin_or_owner` + Args: None @@ -188,7 +191,7 @@ def delete(self): None """ if self.id: - destroy_container(self.id) + destroy_container(self.id, force=True) self.id = None self._status = None @@ -478,7 +481,7 @@ def snapshot_container( return zun().containers.commit(container_ref, repository, tag=tag)["uuid"] -def destroy_container(container_ref: "str"): +def destroy_container(container_ref: "str", stop=False, force=False): """ .. deprecated:: 1.0 @@ -489,7 +492,7 @@ def destroy_container(container_ref: "str"): Args: container_ref (str): The name or ID of the container. """ - return zun().containers.delete(container_ref, stop=True) + return zun().containers.delete(container_ref, stop=stop, force=force) def get_logs(container_ref: "str", stdout=True, stderr=True): diff --git a/tests/test_container.py b/tests/test_container.py index cfd1cb8..60a7f9c 100644 --- a/tests/test_container.py +++ b/tests/test_container.py @@ -113,6 +113,18 @@ def test_download_extracts_tar_and_writes_file(mocker): assert f.read() == file_content +def test_delete_calls_force(mocker): + destroy_mock = mocker.patch("chi.container.destroy_container") + container = Container(name="test", image_ref="img") + container.id = "fake-id" + + container.delete() + + destroy_mock.assert_called_once_with("fake-id", force=True) + assert container.id is None + assert container._status is None + + def test_submit_idempotent_returns_existing_without_create(mocker): # idempotent=true, wait=true chi_container = Container(name="dup-name", image_ref="img") From 6caaf30a31ad5c72ffc13ff09cf387f3e00dae80 Mon Sep 17 00:00:00 2001 From: Michael Sherman Date: Thu, 19 Feb 2026 11:02:20 -0600 Subject: [PATCH 2/2] remove policy note in docstring --- chi/container.py | 3 --- 1 file changed, 3 deletions(-) diff --git a/chi/container.py b/chi/container.py index 2608534..bd854af 100644 --- a/chi/container.py +++ b/chi/container.py @@ -181,9 +181,6 @@ def delete(self): If the container has an ID, it calls the `destroy_container` function to delete the container. After deletion, it sets the ID and status of the container to None. - Note: Delete is called with "force", which depends on the following zun policy: - `container:delete_force: rule:admin_or_owner` - Args: None