Skip to content

Commit

Permalink
Merge pull request #714 from cderici/app-destroy-params
Browse files Browse the repository at this point in the history
#714

#### Description

This PR adds the parameters `force`, `no_wait` and `destroy_storage` parameters to `Application.destroy()`.

Fixes #645

#### QA Steps

```
tox -e integration -- tests/integration/test_application.py::test_app_destroy
```

```
tox -e integration -- tests/integration/test_application.py::test_app_remove_wait_flag
```


#### Notes & Discussion
  • Loading branch information
jujubot authored Aug 19, 2022
2 parents e8456e1 + 1a13d18 commit 4c49c1f
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 6 deletions.
22 changes: 18 additions & 4 deletions juju/application.py
Original file line number Diff line number Diff line change
Expand Up @@ -217,16 +217,30 @@ async def destroy_unit(self, *unit_names):
return await self.model.destroy_units(*unit_names)
destroy_units = destroy_unit

async def destroy(self):
async def destroy(self, destroy_storage=False, force=False, no_wait=False):
"""Remove this application from the model.
:param bool destroy_storage: Destroy storage attached to application unit. (=false)
:param bool force: Completely remove an application and all its dependencies. (=false)
:param bool no_wait: Rush through application removal without waiting for each individual step to complete (=false)
:param bool block: Blocks until the application is removed from the model
"""

if no_wait and not force:
raise JujuError("--no-wait without --force is not valid")

app_facade = self._facade()

log.debug(
'Destroying %s', self.name)
log.debug('Destroying {} with parameters -- destroy-storage : {} -- force : {} -- no-wait : {}'.format(
self.name, destroy_storage, force, no_wait))

return await app_facade.Destroy(application=self.name)
res = await app_facade.DestroyApplication(applications=[client.DestroyApplicationParams(
application_tag=self.tag,
destroy_storage=destroy_storage,
force=force,
max_wait=0 if no_wait else None,
)])
return res
remove = destroy

def supports_granular_expose_parameters(self):
Expand Down
10 changes: 8 additions & 2 deletions juju/model.py
Original file line number Diff line number Diff line change
Expand Up @@ -1005,18 +1005,24 @@ 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):
async def remove_application(self, app_name, block_until_done=False, force=False, destroy_storage=False, no_wait=False):
"""Removes the given application from the model.
:param str app_name: Name of the application
:param bool force: Completely remove an application and all its dependencies. (=false)
:param bool destroy_storage: Destroy storage attached to application unit. (=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
"""
if app_name not in self.applications:
raise JujuError("Given application doesn't seem to appear in the\
model: %s\nCurrent applications are: %s" %
(app_name, self.applications))
await self.applications[app_name].remove()
await self.applications[app_name].remove(destroy_storage=destroy_storage,
force=force,
no_wait=no_wait,
)
if block_until_done:
await self.block_until(lambda: app_name not in self.applications)

Expand Down
16 changes: 16 additions & 0 deletions tests/integration/test_application.py
Original file line number Diff line number Diff line change
Expand Up @@ -240,6 +240,22 @@ async def test_trusted(event_loop):
assert trusted is False


@base.bootstrapped
@pytest.mark.asyncio
async def test_app_destroy(event_loop):
async with base.CleanModel() as model:
app = await model.deploy('ubuntu')
a_name = app.name # accessing name is impossible after the app is destroyed
await model.wait_for_idle(status="active")
assert a_name in model.applications
await app.destroy(destroy_storage=True, force=True, no_wait=True)
await model.block_until(
lambda: a_name not in model.applications,
timeout=60,
)
assert a_name not in model.applications


@base.bootstrapped
@pytest.mark.asyncio
async def test_app_remove_wait_flag(event_loop):
Expand Down

0 comments on commit 4c49c1f

Please sign in to comment.