From 44843c40cc98906e50202431bebb6dc77688a9d9 Mon Sep 17 00:00:00 2001 From: tivaliy Date: Wed, 17 Aug 2016 08:22:57 +0300 Subject: [PATCH] Add filters to 'fuel2 task list' command Now Nailgun supports filtering transactions by statuses, cluster_id and transaction_types (commit 8257a0dbcb680e4eb9c19afe027b3a0fbdb0e7be). This patch adds filtering support for 'fuel2 task list' command. usage: fuel2 task list [-h] [-f {csv,html,json,table,value,yaml}] [-c COLUMN] [--max-width ] [--noindent] [--quote {all,minimal,none,nonnumeric}] [-s SORT_COLUMN [SORT_COLUMN ...]] [-e ENV] [-t {pending,error,ready,running} [{pending,error,ready,running} ...]] [-n NAMES [NAMES ...]] DocImpact Closes-Bug: 1613674 Change-Id: I8e33944a422a7847e055318b9d73e872244117c7 --- fuelclient/commands/task.py | 29 ++++++++++++++++++ fuelclient/tests/unit/v2/cli/test_task.py | 26 +++++++++++++++- fuelclient/tests/unit/v2/lib/test_task.py | 37 ++++++++++++++++++++--- fuelclient/v1/base_v1.py | 9 +++++- fuelclient/v1/task.py | 6 ++-- 5 files changed, 98 insertions(+), 9 deletions(-) diff --git a/fuelclient/commands/task.py b/fuelclient/commands/task.py index dee120a6..e3eeace4 100644 --- a/fuelclient/commands/task.py +++ b/fuelclient/commands/task.py @@ -129,6 +129,35 @@ class TaskList(TaskMixIn, base.BaseListCommand): 'cluster', 'result', 'progress') + filters = {'cluster_id': 'env', + 'statuses': 'statuses', + 'transaction_types': 'names'} + + def get_parser(self, prog_name): + parser = super(TaskList, self).get_parser(prog_name) + + parser.add_argument( + '-e', + '--env', + type=int, + help='Show list of tasks that belong to specified environment') + + parser.add_argument( + '-t', + '--statuses', + type=str, + choices=['pending', 'error', 'ready', 'running'], + nargs='+', + help='Show list of tasks with specified statuses') + + parser.add_argument( + '-n', + '--names', + type=str, + nargs='+', + help='Show list of tasks with specified names') + + return parser class TaskShow(TaskMixIn, base.BaseShowCommand): diff --git a/fuelclient/tests/unit/v2/cli/test_task.py b/fuelclient/tests/unit/v2/cli/test_task.py index c5e0b866..fd7227a2 100644 --- a/fuelclient/tests/unit/v2/cli/test_task.py +++ b/fuelclient/tests/unit/v2/cli/test_task.py @@ -29,7 +29,7 @@ class TestTaskCommand(test_engine.BaseCLITest): super(TestTaskCommand, self).setUp() self.m_client.get_all.return_value = [utils.get_fake_task() - for i in range(10)] + for _ in range(10)] self.m_client.get_by_id.return_value = utils.get_fake_task() self.current_path = os.path.join(os.path.abspath(os.curdir)) @@ -40,6 +40,30 @@ class TestTaskCommand(test_engine.BaseCLITest): self.m_get_client.assert_called_once_with('task', mock.ANY) self.m_client.get_all.assert_called_once_with() + def test_task_list_w_parameters(self): + env_id = 45 + statuses = ['ready', 'error'] + names = ['provision', 'dump'] + args = 'task list -e {env_id} -t {statuses} -n {names}'.format( + env_id=env_id, + statuses=' '.join(statuses), + names=' '.join(names)) + + self.exec_command(args) + + self.m_get_client.assert_called_once_with('task', mock.ANY) + self.m_client.get_all.assert_called_once_with(cluster_id=env_id, + statuses=statuses, + transaction_types=names) + + @mock.patch('sys.stderr') + def test_task_list_w_wrong_parameters(self, mocked_stderr): + statuses = ['ready', 'wrong_status'] + args = 'task list -t {statuses}'.format(statuses=' '.join(statuses)) + self.assertRaises(SystemExit, self.exec_command, args) + self.assertIn('-t/--statuses: invalid choice', + mocked_stderr.write.call_args_list[-1][0][0]) + def test_task_show(self): task_id = 42 args = 'task show {task_id}'.format(task_id=task_id) diff --git a/fuelclient/tests/unit/v2/lib/test_task.py b/fuelclient/tests/unit/v2/lib/test_task.py index a65aa4d3..fa8a1610 100644 --- a/fuelclient/tests/unit/v2/lib/test_task.py +++ b/fuelclient/tests/unit/v2/lib/test_task.py @@ -35,17 +35,46 @@ class TestTaskFacade(test_api.BaseLibTest): def test_task_list(self): - matcher = self.m_request.get(self.res_uri, json=self.fake_task) + matcher = self.m_request.get(self.res_uri, json=self.fake_tasks) self.client.get_all() self.assertTrue(self.res_uri, matcher.called) + def test_task_list_w_parameters(self): + env_id = 36 + statuses = ['ready', 'error'] + names = ['dump', 'provision'] + fake_tasks = [ + utils.get_fake_task(task_id=45, cluster=env_id, + status=statuses[0], name=names[0]), + utils.get_fake_task(task_id=46, cluster=env_id, + status=statuses[0], name=names[1]), + utils.get_fake_task(task_id=49, cluster=env_id, + status=[1], name=names[1]), + ] + params = ('?cluster_id={env_id}' + '&statuses={statuses}' + '&transaction_types={names}') + expected_url = self.res_uri + params.format( + env_id=env_id, + statuses=','.join(statuses), + names=','.join(names)) + + matcher = self.m_request.get(expected_url, json=fake_tasks) + + tasks = self.client.get_all(cluster_id=env_id, + statuses=statuses, + transaction_types=names) + + self.assertTrue(matcher.called) + self.assertEqual(3, len(tasks)) + def test_task_show(self): task_id = 42 expected_uri = self.get_object_uri(self.res_uri, task_id) - matcher = self.m_request.get(expected_uri, json=self.fake_tasks) + matcher = self.m_request.get(expected_uri, json=self.fake_task) self.client.get_by_id(task_id) @@ -54,7 +83,7 @@ class TestTaskFacade(test_api.BaseLibTest): def test_task_delete(self): task_id = 42 expected_uri = self.get_object_uri(self.res_uri, task_id) - matcher = self.m_request.delete(expected_uri, json=self.fake_tasks) + matcher = self.m_request.delete(expected_uri, json=self.fake_task) self.client.delete_by_id(task_id, force=False) @@ -64,7 +93,7 @@ class TestTaskFacade(test_api.BaseLibTest): def test_task_delete_force(self): task_id = 42 expected_uri = self.get_object_uri(self.res_uri, task_id) - matcher = self.m_request.delete(expected_uri, json=self.fake_tasks) + matcher = self.m_request.delete(expected_uri, json=self.fake_task) self.client.delete_by_id(task_id, force=True) diff --git a/fuelclient/v1/base_v1.py b/fuelclient/v1/base_v1.py index 8a725ee8..3639eba1 100644 --- a/fuelclient/v1/base_v1.py +++ b/fuelclient/v1/base_v1.py @@ -39,7 +39,14 @@ class BaseV1Client(object): ) def get_all(self, **kwargs): - result = self._entity_wrapper.get_all_data(**kwargs) + filters = {} + for k, v in six.iteritems(kwargs): + if isinstance(v, list): + if v: + filters[k] = ','.join(str(s) for s in v) + elif v is not None: + filters[k] = str(v) + result = self._entity_wrapper.get_all_data(**filters) return result diff --git a/fuelclient/v1/task.py b/fuelclient/v1/task.py index f588f205..3c80582a 100644 --- a/fuelclient/v1/task.py +++ b/fuelclient/v1/task.py @@ -26,11 +26,11 @@ class TaskClient(base_v1.BaseV1Client): :param task_id: Id of a task to delete. :type task_id: int :param force: Force deletion of a task without - concidering its state + considering its state """ - env_obj = self._entity_wrapper(obj_id=task_id) - env_obj.delete(force=force) + task_obj = self._entity_wrapper(obj_id=task_id) + task_obj.delete(force=force) def get_client(connection):