Skip to content

Commit 4c49c1f

Browse files
authored
Merge pull request #714 from cderici/app-destroy-params
#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
2 parents e8456e1 + 1a13d18 commit 4c49c1f

3 files changed

Lines changed: 42 additions & 6 deletions

File tree

juju/application.py

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -217,16 +217,30 @@ async def destroy_unit(self, *unit_names):
217217
return await self.model.destroy_units(*unit_names)
218218
destroy_units = destroy_unit
219219

220-
async def destroy(self):
220+
async def destroy(self, destroy_storage=False, force=False, no_wait=False):
221221
"""Remove this application from the model.
222222
223+
:param bool destroy_storage: Destroy storage attached to application unit. (=false)
224+
:param bool force: Completely remove an application and all its dependencies. (=false)
225+
:param bool no_wait: Rush through application removal without waiting for each individual step to complete (=false)
226+
:param bool block: Blocks until the application is removed from the model
223227
"""
228+
229+
if no_wait and not force:
230+
raise JujuError("--no-wait without --force is not valid")
231+
224232
app_facade = self._facade()
225233

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

229-
return await app_facade.Destroy(application=self.name)
237+
res = await app_facade.DestroyApplication(applications=[client.DestroyApplicationParams(
238+
application_tag=self.tag,
239+
destroy_storage=destroy_storage,
240+
force=force,
241+
max_wait=0 if no_wait else None,
242+
)])
243+
return res
230244
remove = destroy
231245

232246
def supports_granular_expose_parameters(self):

juju/model.py

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1005,18 +1005,24 @@ async def remove_storage(self, *storage_ids, force=False, destroy_storage=False)
10051005
if ret.results[0].error:
10061006
raise JujuError(ret.results[0].error.message)
10071007

1008-
async def remove_application(self, app_name, block_until_done=False):
1008+
async def remove_application(self, app_name, block_until_done=False, force=False, destroy_storage=False, no_wait=False):
10091009
"""Removes the given application from the model.
10101010
10111011
:param str app_name: Name of the application
1012+
:param bool force: Completely remove an application and all its dependencies. (=false)
1013+
:param bool destroy_storage: Destroy storage attached to application unit. (=false)
1014+
:param bool no_wait: Rush through application removal without waiting for each individual step to complete (=false)
10121015
:param bool block_until_done: Ensure the app is removed from the
10131016
model when returned
10141017
"""
10151018
if app_name not in self.applications:
10161019
raise JujuError("Given application doesn't seem to appear in the\
10171020
model: %s\nCurrent applications are: %s" %
10181021
(app_name, self.applications))
1019-
await self.applications[app_name].remove()
1022+
await self.applications[app_name].remove(destroy_storage=destroy_storage,
1023+
force=force,
1024+
no_wait=no_wait,
1025+
)
10201026
if block_until_done:
10211027
await self.block_until(lambda: app_name not in self.applications)
10221028

tests/integration/test_application.py

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -240,6 +240,22 @@ async def test_trusted(event_loop):
240240
assert trusted is False
241241

242242

243+
@base.bootstrapped
244+
@pytest.mark.asyncio
245+
async def test_app_destroy(event_loop):
246+
async with base.CleanModel() as model:
247+
app = await model.deploy('ubuntu')
248+
a_name = app.name # accessing name is impossible after the app is destroyed
249+
await model.wait_for_idle(status="active")
250+
assert a_name in model.applications
251+
await app.destroy(destroy_storage=True, force=True, no_wait=True)
252+
await model.block_until(
253+
lambda: a_name not in model.applications,
254+
timeout=60,
255+
)
256+
assert a_name not in model.applications
257+
258+
243259
@base.bootstrapped
244260
@pytest.mark.asyncio
245261
async def test_app_remove_wait_flag(event_loop):

0 commit comments

Comments
 (0)