diff --git a/mistralclient/api/v2/executions.py b/mistralclient/api/v2/executions.py index 08b3324e..e95c3789 100644 --- a/mistralclient/api/v2/executions.py +++ b/mistralclient/api/v2/executions.py @@ -113,7 +113,13 @@ class ExecutionManager(base.ResourceManager): return self._get('/executions/%s' % id) - def delete(self, id): + def delete(self, id, force=None): self._ensure_not_empty(id=id) + qparams = {} - self._delete('/executions/%s' % id) + qparams['force'] = bool(force) + + query_string = ("?%s" % urlparse.urlencode(list(qparams.items())) + if qparams else "") + + self._delete('/executions/%s%s' % (id, query_string)) diff --git a/mistralclient/commands/v2/executions.py b/mistralclient/commands/v2/executions.py index eba5c829..fffb70ff 100644 --- a/mistralclient/commands/v2/executions.py +++ b/mistralclient/commands/v2/executions.py @@ -248,13 +248,21 @@ class Delete(command.Command): help='Id of execution identifier(s).' ) + parser.add_argument( + '--force', + default=False, + action='store_true', + help='Force the deletion of an execution. Might cause a cascade ' + ' of errors if used for running executions.' + ) + return parser def take_action(self, parsed_args): mistral_client = self.app.client_manager.workflow_engine - + force = parsed_args.force utils.do_action_on_many( - lambda s: mistral_client.executions.delete(s), + lambda s: mistral_client.executions.delete(s, force=force), parsed_args.execution, "Request to delete execution %s has been accepted.", "Unable to delete the specified execution(s)." diff --git a/mistralclient/tests/unit/v2/test_cli_executions.py b/mistralclient/tests/unit/v2/test_cli_executions.py index dbb53c15..7bce7b26 100644 --- a/mistralclient/tests/unit/v2/test_cli_executions.py +++ b/mistralclient/tests/unit/v2/test_cli_executions.py @@ -282,13 +282,24 @@ class TestCLIExecutionsV2(base.BaseCommandTest): def test_delete(self): self.call(execution_cmd.Delete, app_args=['id']) - self.client.executions.delete.assert_called_once_with('id') + self.client.executions.delete.assert_called_once_with( + 'id', + force=False + ) + + def test_delete_with_force(self): + self.call(execution_cmd.Delete, app_args=['id', '--force']) + + self.client.executions.delete.assert_called_once_with( + 'id', + force=True + ) def test_delete_with_multi_names(self): self.call(execution_cmd.Delete, app_args=['id1', 'id2']) self.assertEqual(2, self.client.executions.delete.call_count) self.assertEqual( - [mock.call('id1'), mock.call('id2')], + [mock.call('id1', force=False), mock.call('id2', force=False)], self.client.executions.delete.call_args_list ) diff --git a/mistralclient/tests/unit/v2/test_executions.py b/mistralclient/tests/unit/v2/test_executions.py index 5415cd8e..54689c57 100644 --- a/mistralclient/tests/unit/v2/test_executions.py +++ b/mistralclient/tests/unit/v2/test_executions.py @@ -254,6 +254,12 @@ class TestExecutionsV2(base.BaseClientV2Test): ex.to_dict() ) + def test_delete_with_force(self): + url = self.TEST_URL + URL_TEMPLATE_ID % EXEC['id'] + self.requests_mock.delete(url, status_code=204) + + self.executions.delete(EXEC['id'], force=True) + def test_delete(self): url = self.TEST_URL + URL_TEMPLATE_ID % EXEC['id'] self.requests_mock.delete(url, status_code=204) diff --git a/releasenotes/notes/force-delete-executions-d08ce88a5deb3291.yaml b/releasenotes/notes/force-delete-executions-d08ce88a5deb3291.yaml new file mode 100644 index 00000000..2c51cc22 --- /dev/null +++ b/releasenotes/notes/force-delete-executions-d08ce88a5deb3291.yaml @@ -0,0 +1,7 @@ +--- +features: + - | + Adding a --force optional parameter to delete excetutions. Without it only + finished executions can be deleted. If --force is passed the execution + will be deleted but mistral will generate some errors as expected objects + in memory no longer exist