diff --git a/juju/model.py b/juju/model.py index 56af31e75..ccfd78588 100644 --- a/juju/model.py +++ b/juju/model.py @@ -1000,7 +1000,15 @@ async def remove_storage(self, *storage_ids, force=False, destroy_storage=False) if ret.results[0].error: raise JujuError(ret.results[0].error.message) - async def remove_application(self, app_name, block_until_done=False, force=False, destroy_storage=False, no_wait=False): + async def remove_application( + self, + app_name, + block_until_done=False, + force=False, + destroy_storage=False, + no_wait=False, + timeout=None + ): """Removes the given application from the model. :param str app_name: Name of the application @@ -1009,6 +1017,8 @@ async def remove_application(self, app_name, block_until_done=False, force=False :param bool no_wait: Rush through application removal without waiting for each individual step to complete (=false) :param bool block_until_done: Ensure the app is removed from the model when returned + :param int timeout: Raise asyncio.exceptions.TimeoutError if the application is not removed + within the timeout period. """ if app_name not in self.applications: raise JujuError("Given application doesn't seem to appear in the\ @@ -1019,7 +1029,7 @@ async def remove_application(self, app_name, block_until_done=False, force=False no_wait=no_wait, ) if block_until_done: - await self.block_until(lambda: app_name not in self.applications) + await self.block_until(lambda: app_name not in self.applications, timeout=timeout) async def block_until(self, *conditions, timeout=None, wait_period=0.5): """Return only after all conditions are true. diff --git a/tests/integration/test_application.py b/tests/integration/test_application.py index b396f9022..0ab2f4391 100644 --- a/tests/integration/test_application.py +++ b/tests/integration/test_application.py @@ -3,6 +3,7 @@ import logging from pathlib import Path +import asyncio import pytest @@ -326,6 +327,16 @@ async def test_app_remove_wait_flag(): assert a_name not in model.applications +@base.bootstrapped +async def test_app_remove_timeout(): + async with base.CleanModel() as model: + app = await model.deploy('juju-qa-test') + await model.wait_for_idle(status="active") + + with pytest.raises(asyncio.TimeoutError): + await model.remove_application(app.name, block_until_done=True, timeout=1) + + @base.bootstrapped async def test_app_charm_name(): async with base.CleanModel() as model: