From 26cc4be584cfacf0f7ff440651c22751845e256b Mon Sep 17 00:00:00 2001 From: Andrey Kurilin Date: Wed, 7 Jun 2017 17:02:36 +0300 Subject: [PATCH] Extend tags feature of tasks * Add ability to setup multiple tags for a task. The database supports an unlimited number of tags per tasks. It would be nice to support that feature from user side too. * The tags feature is a bit useless, if there is no way to filter by them. This patch adds this ability to `rally task list` command. Change-Id: I959fa904a38f193f77f25b53ba3ee86760fff91c --- etc/rally.bash_completion | 2 +- rally/api.py | 11 ++-- rally/cli/commands/task.py | 50 +++++++++------- rally/common/db/api.py | 7 ++- rally/common/db/sqlalchemy/api.py | 71 ++++++++++++----------- rally/common/objects/task.py | 5 +- tests/unit/cli/commands/test_task.py | 85 ++++++++++++++++++++++------ tests/unit/common/db/test_api.py | 12 ++-- tests/unit/test_api.py | 24 ++++---- 9 files changed, 170 insertions(+), 97 deletions(-) diff --git a/etc/rally.bash_completion b/etc/rally.bash_completion index fb62dd6985..82ddd3327e 100644 --- a/etc/rally.bash_completion +++ b/etc/rally.bash_completion @@ -33,7 +33,7 @@ _rally() OPTS["task_detailed"]="--uuid --iterations-data" OPTS["task_export"]="--uuid --type --to" OPTS["task_import"]="--file --deployment --tag" - OPTS["task_list"]="--deployment --all-deployments --status --uuids-only" + OPTS["task_list"]="--deployment --all-deployments --status --tag --uuids-only" OPTS["task_report"]="--out --open --html --html-static --uuid" OPTS["task_results"]="--uuid" OPTS["task_sla-check"]="--uuid --json" diff --git a/rally/api.py b/rally/api.py index 4a7ab0ad06..aed91093e8 100644 --- a/rally/api.py +++ b/rally/api.py @@ -381,14 +381,14 @@ class _Task(APIGroup): @api_wrapper(path=API_REQUEST_PREFIX + "/task/create", method="POST") - def create(self, deployment, tag): + def create(self, deployment, tags=None): """Create a task without starting it. Task is a list of benchmarks that will be called one by one, results of execution will be stored in DB. :param deployment: UUID or name of the deployment - :param tag: tag for this task + :param tags: a list of tags for this task :returns: Task object """ deployment = objects.Deployment.get(deployment) @@ -399,7 +399,7 @@ class _Task(APIGroup): status=deployment["status"]) return objects.Task(deployment_uuid=deployment["uuid"], - tag=tag).to_dict() + tags=tags).to_dict() @api_wrapper(path=API_REQUEST_PREFIX + "/task/validate", method="GET") @@ -548,7 +548,7 @@ class _Task(APIGroup): @api_wrapper(path=API_REQUEST_PREFIX + "/task/import_results", method="POST") - def import_results(self, deployment, task_results, tag=None): + def import_results(self, deployment, task_results, tags=None): """Import json results of a test into rally database""" deployment = objects.Deployment.get(deployment) if deployment["status"] != consts.DeployStatus.DEPLOY_FINISHED: @@ -557,7 +557,8 @@ class _Task(APIGroup): uuid=deployment["uuid"], status=deployment["status"]) - task_inst = objects.Task(deployment_uuid=deployment["uuid"], tag=tag) + task_inst = objects.Task(deployment_uuid=deployment["uuid"], + tags=tags) task_inst.update_status(consts.TaskStatus.RUNNING) for result in task_results: subtask_obj = task_inst.add_subtask(title=result["key"]["name"]) diff --git a/rally/cli/commands/task.py b/rally/cli/commands/task.py index fbce213708..165cc71391 100644 --- a/rally/cli/commands/task.py +++ b/rally/cli/commands/task.py @@ -194,7 +194,8 @@ class TaskCommands(object): help="Path to the file with input task args (dict in " "JSON/YAML). These args are used " "to render the Jinja2 template in the input task.") - @cliutils.args("--tag", help="Tag for this task") + @cliutils.args("--tag", nargs="+", dest="tags", type=str, required=False, + help="Mark the task with a tag or a few tags.") @cliutils.args("--no-use", action="store_false", dest="do_use", help="Don't set new task as default for future operations.") @cliutils.args("--abort-on-sla-failure", action="store_true", @@ -204,7 +205,7 @@ class TaskCommands(object): @envutils.with_default_deployment(cli_arg_name="deployment") @plugins.ensure_plugins_are_loaded def start(self, api, task_file, deployment=None, task_args=None, - task_args_file=None, tag=None, do_use=False, + task_args_file=None, tags=None, do_use=False, abort_on_sla_failure=False): """Start benchmark task. @@ -221,26 +222,25 @@ class TaskCommands(object): used to render the Jinja2 template in the input task. :param deployment: UUID or name of the deployment - :param tag: optional tag for this task + :param tags: optional tag for this task :param do_use: if True, the new task will be stored as the default one for future operations :param abort_on_sla_failure: if True, the execution of a benchmark scenario will stop when any SLA check for it fails """ - input_task = self._load_and_validate_task(api, task_file, raw_args=task_args, args_file=task_args_file) print("Running Rally version", version.version_string()) try: - task_instance = api.task.create(deployment=deployment, tag=tag) + task_instance = api.task.create(deployment=deployment, tags=tags) + tags = "[tags: '%s']" % "', '".join(tags) if tags else "" print(cliutils.make_header( - _("Task %(tag)s %(uuid)s: started") - % {"uuid": task_instance["uuid"], - "tag": task_instance["tag"]})) + _("Task %(tags)s %(uuid)s: started") + % {"uuid": task_instance["uuid"], "tags": tags})) print("Benchmarking... This can take a while...\n") print("To track task status use:\n") print("\trally task status\n\tor\n\trally task detailed\n") @@ -498,11 +498,13 @@ class TaskCommands(object): @cliutils.args("--status", type=str, dest="status", help="List tasks with specified status." " Available statuses: %s" % ", ".join(consts.TaskStatus)) + @cliutils.args("--tag", nargs="+", dest="tags", type=str, required=False, + help="Tags to filter tasks by.") @cliutils.args("--uuids-only", action="store_true", dest="uuids_only", help="List task UUIDs only.") @envutils.with_default_deployment(cli_arg_name="deployment") def list(self, api, deployment=None, all_deployments=False, status=None, - uuids_only=False): + tags=None, uuids_only=False): """List tasks, started and finished. Displayed tasks can be filtered by status or deployment. By @@ -518,10 +520,10 @@ class TaskCommands(object): filters = {} headers = ["uuid", "deployment_name", "created_at", "duration", - "status", "tag"] + "status", "tags"] if status in consts.TaskStatus: - filters.setdefault("status", status) + filters["status"] = status elif status: print(_("Error: Invalid task status '%s'.\n" "Available statuses: %s") % ( @@ -530,7 +532,10 @@ class TaskCommands(object): return(1) if not all_deployments: - filters.setdefault("deployment", deployment) + filters["deployment"] = deployment + + if tags: + filters["tags"] = tags task_list = api.task.list(**filters) @@ -540,9 +545,16 @@ class TaskCommands(object): print_header=False, print_border=False) elif task_list: + def tags_formatter(t): + if not t["tags"]: + return "" + return "'%s'" % "', '".join(t["tags"]) + cliutils.print_list( task_list, - headers, sortby_index=headers.index("created_at")) + headers, + sortby_index=headers.index("created_at"), + formatters={"tags": tags_formatter}) else: if status: print(_("There are no tasks in '%s' status. " @@ -885,26 +897,26 @@ class TaskCommands(object): @cliutils.args("--deployment", dest="deployment", type=str, metavar="", required=False, help="UUID or name of a deployment.") - @cliutils.args("--tag", help="Tag for this task") + @cliutils.args("--tag", nargs="+", dest="tags", type=str, required=False, + help="Mark the task with a tag or a few tags.") @envutils.with_default_deployment(cli_arg_name="deployment") @cliutils.alias("import") @cliutils.suppress_warnings - def import_results(self, api, deployment=None, task_file=None, tag=None): + def import_results(self, api, deployment=None, task_file=None, tags=None): """Import json results of a test into rally database :param task_file: list, pathes files with tasks results :param deployment: UUID or name of the deployment - :param tag: optional tag for this task + :param tags: optional tag for this task """ if os.path.exists(os.path.expanduser(task_file)): tasks_results = self._load_task_results_file(api, task_file) task = api.task.import_results(deployment=deployment, task_results=tasks_results, - tag=tag) + tags=tags) print(_("Task UUID: %s.") % task["uuid"]) else: - print(_("ERROR: Invalid file name passed: %s" - ) % task_file, + print(_("ERROR: Invalid file name passed: %s") % task_file, file=sys.stderr) return 1 diff --git a/rally/common/db/api.py b/rally/common/db/api.py index cb2a1079d6..bd5e05d075 100644 --- a/rally/common/db/api.py +++ b/rally/common/db/api.py @@ -197,7 +197,7 @@ def task_update_status(task_uuid, status, allowed_statuses): status) -def task_list(status=None, deployment=None): +def task_list(status=None, deployment=None, tags=None): """Get a list of tasks. :param status: Task status to filter the returned list on. If set to @@ -205,9 +205,12 @@ def task_list(status=None, deployment=None): :param deployment: Deployment UUID to filter the returned list on. If set to None, tasks from all deployments will be returned. + :param tags: A list of tags to filter tasks by. :returns: A list of dicts with data on the tasks. """ - return get_impl().task_list(status=status, deployment=deployment) + return get_impl().task_list(status=status, + deployment=deployment, + tags=tags) def task_delete(uuid, status=None): diff --git a/rally/common/db/sqlalchemy/api.py b/rally/common/db/sqlalchemy/api.py index c2c63584e5..25ba55aad0 100644 --- a/rally/common/db/sqlalchemy/api.py +++ b/rally/common/db/sqlalchemy/api.py @@ -205,8 +205,7 @@ class Connection(object): return task def _make_old_task(self, task): - tags = self._tags_get(task.uuid, consts.TagType.TASK) - tag = tags[0] if tags else "" + tags = sorted(self._tags_get(task.uuid, consts.TagType.TASK)) return { "id": task.id, @@ -215,7 +214,7 @@ class Connection(object): "status": task.status, "created_at": task.created_at, "updated_at": task.updated_at, - "tag": tag, + "tags": tags, "verification_log": json.dumps(task.validation_result) } @@ -302,9 +301,9 @@ class Connection(object): task["results"] = self._task_result_get_all_by_uuid(task["uuid"]) return task - # @db_api.serialize + @db_api.serialize def task_create(self, values): - new_tag = values.pop("tag", None) + tags = values.pop("tags", None) # TODO(ikhudoshyn): currently 'input_task' # does not come in 'values' # After completely switching to the new @@ -317,34 +316,32 @@ class Connection(object): task.update(values) task.save() - if new_tag: - tag = models.Tag() - tag.update({ - "uuid": task.uuid, - "type": consts.TagType.TASK, - "tag": new_tag - }) - tag.save() - - return self._make_old_task(task) + if tags: + for t in set(tags): + tag = models.Tag() + tag.update({"uuid": task.uuid, + "type": consts.TagType.TASK, + "tag": t}) + tag.save() + task.tags = sorted(self._tags_get(task.uuid, consts.TagType.TASK)) + return task # @db_api.serialize def task_update(self, uuid, values): session = get_session() values.pop("uuid", None) - new_tag = values.pop("tag", None) + tags = values.pop("tags", None) with session.begin(): task = self._task_get(uuid, session=session) task.update(values) - if new_tag: - tag = models.Tag() - tag.update({ - "uuid": uuid, - "type": consts.TagType.TASK, - "tag": new_tag - }) - tag.save() + if tags: + for t in set(tags): + tag = models.Tag() + tag.update({"uuid": task.uuid, + "type": consts.TagType.TASK, + "tag": t}) + tag.save() return self._make_old_task(task) @@ -365,18 +362,24 @@ class Connection(object): return result # @db_api.serialize - def task_list(self, status=None, deployment=None): - query = self.model_query(models.Task) + def task_list(self, status=None, deployment=None, tags=None): + session = get_session() + with session.begin(): + query = self.model_query(models.Task) - filters = {} - if status is not None: - filters["status"] = status - if deployment is not None: - filters["deployment_uuid"] = self.deployment_get( - deployment)["uuid"] + filters = {} + if status is not None: + filters["status"] = status + if deployment is not None: + filters["deployment_uuid"] = self.deployment_get( + deployment)["uuid"] + if filters: + query = query.filter_by(**filters) - if filters: - query = query.filter_by(**filters) + if tags: + uuids = self._uuids_by_tags_get( + consts.TagType.TASK, tags) + query = query.filter(models.Task.uuid.in_(uuids)) return [self._make_old_task(task) for task in query.all()] diff --git a/rally/common/objects/task.py b/rally/common/objects/task.py index d54e861989..74afc3eea8 100644 --- a/rally/common/objects/task.py +++ b/rally/common/objects/task.py @@ -406,8 +406,9 @@ class Task(object): return db.task_get_status(uuid) @staticmethod - def list(status=None, deployment=None): - return [Task(db_task) for db_task in db.task_list(status, deployment)] + def list(status=None, deployment=None, tags=None): + return [Task(db_task) for db_task in db.task_list( + status, deployment=deployment, tags=tags)] @staticmethod def delete_by_uuid(uuid, status=None): diff --git a/tests/unit/cli/commands/test_task.py b/tests/unit/cli/commands/test_task.py index 33ceea1d4a..0973707ff0 100644 --- a/tests/unit/cli/commands/test_task.py +++ b/tests/unit/cli/commands/test_task.py @@ -19,9 +19,11 @@ import os.path import ddt import mock +import six import rally from rally import api +from rally.cli import cliutils from rally.cli.commands import task from rally.common import yamlutils as yaml from rally import consts @@ -201,7 +203,7 @@ class TaskCommandsTestCase(test.TestCase): mock_version): deployment_id = "e0617de9-77d1-4875-9b49-9d5789e29f20" task_path = "path_to_config.json" - fake_task = fakes.FakeTask(uuid="some_new_uuid", tag="tag") + fake_task = fakes.FakeTask(uuid="some_new_uuid", tags=["tag"]) self.fake_api.task.create.return_value = fake_task self.fake_api.task.validate.return_value = fakes.FakeTask( some="json", uuid="some_uuid", temporary=True) @@ -209,7 +211,7 @@ class TaskCommandsTestCase(test.TestCase): self.task.start(self.fake_api, task_path, deployment_id, do_use=True) mock_version.version_string.assert_called_once_with() self.fake_api.task.create.assert_called_once_with( - deployment=deployment_id, tag=None) + deployment=deployment_id, tags=None) self.fake_api.task.start.assert_called_once_with( deployment=deployment_id, config=mock__load_and_validate_task.return_value, @@ -238,7 +240,8 @@ class TaskCommandsTestCase(test.TestCase): status=consts.DeployStatus.DEPLOY_INIT) self.fake_api.task.create.side_effect = exc self.assertEqual(1, self.task.start(self.fake_api, task_path, - deployment="any", tag="some_tag")) + deployment="any", + tags=["some_tag"])) self.assertFalse(mock_detailed.called) @mock.patch("rally.cli.commands.task.TaskCommands.detailed") @@ -246,9 +249,9 @@ class TaskCommandsTestCase(test.TestCase): return_value="some_config") def test_start_with_task_args(self, mock__load_and_validate_task, mock_detailed): - fake_task = fakes.FakeTask(uuid="new_uuid", tag="some_tag") + fake_task = fakes.FakeTask(uuid="new_uuid", tags=["some_tag"]) self.fake_api.task.create.return_value = fakes.FakeTask( - uuid="new_uuid", tag="some_tag") + uuid="new_uuid", tags=["some_tag"]) self.fake_api.task.validate.return_value = fakes.FakeTask( uuid="some_id") @@ -257,7 +260,7 @@ class TaskCommandsTestCase(test.TestCase): task_args_file = "task_args_file" self.task.start(self.fake_api, task_path, deployment="any", task_args=task_args, task_args_file=task_args_file, - tag="some_tag") + tags=["some_tag"]) mock__load_and_validate_task.assert_called_once_with( self.fake_api, task_path, raw_args=task_args, @@ -272,7 +275,7 @@ class TaskCommandsTestCase(test.TestCase): self.fake_api, task_id=fake_task["uuid"]) self.fake_api.task.create.assert_called_once_with( - deployment="any", tag="some_tag") + deployment="any", tags=["some_tag"]) @mock.patch("rally.cli.commands.task.envutils.get_global") def test_start_no_deployment_id(self, mock_get_global): @@ -292,7 +295,7 @@ class TaskCommandsTestCase(test.TestCase): self.assertRaises(exceptions.InvalidTaskException, self.task.start, self.fake_api, "task_path", - "deployment", tag="tag") + "deployment", tags=["tag"]) self.assertFalse(self.fake_api.task.create.called) self.assertFalse(self.fake_api.task.start.called) @@ -304,10 +307,10 @@ class TaskCommandsTestCase(test.TestCase): self.assertRaises(KeyError, self.task.start, self.fake_api, "task_path", - "deployment", tag="tag") + "deployment", tags=["tag"]) self.fake_api.task.create.assert_called_once_with( - deployment="deployment", tag="tag") + deployment="deployment", tags=["tag"]) self.fake_api.task.start.assert_called_once_with( deployment="deployment", config=task_cfg, @@ -835,7 +838,7 @@ class TaskCommandsTestCase(test.TestCase): created_at=dt.datetime.now(), updated_at=dt.datetime.now(), status="c", - tag="d", + tags=["d"], deployment_name="some_name")] self.task.list(self.fake_api, status="running") self.fake_api.task.list.assert_called_once_with( @@ -843,11 +846,12 @@ class TaskCommandsTestCase(test.TestCase): status=consts.TaskStatus.RUNNING) headers = ["uuid", "deployment_name", "created_at", "duration", - "status", "tag"] + "status", "tags"] mock_print_list.assert_called_once_with( self.fake_api.task.list.return_value, headers, - sortby_index=headers.index("created_at")) + sortby_index=headers.index("created_at"), + formatters=mock.ANY) @mock.patch("rally.cli.commands.task.cliutils.print_list") @mock.patch("rally.cli.commands.task.envutils.get_global", @@ -884,6 +888,54 @@ class TaskCommandsTestCase(test.TestCase): self.fake_api.task.list.assert_called_once_with( deployment="d", status=consts.TaskStatus.RUNNING) + @mock.patch("rally.cli.commands.task.envutils.get_global", + return_value="123456789") + def test_list_output(self, mock_get_global): + self.fake_api.task.list.return_value = [ + fakes.FakeTask(uuid="UUID-1", + created_at="2007-01-01T00:00:01", + duration="0:00:00.000009", + status="init", + tags=[], + deployment_name="some_name"), + fakes.FakeTask(uuid="UUID-2", + created_at="2007-02-01T00:00:01", + duration="0:00:00.000010", + status="finished", + tags=["tag-1", "tag-2"], + deployment_name="some_name")] + + # It is a hard task to mock default value of function argument, so we + # need to apply this workaround + original_print_list = cliutils.print_list + print_list_calls = [] + + def print_list(*args, **kwargs): + print_list_calls.append(six.StringIO()) + kwargs["out"] = print_list_calls[-1] + original_print_list(*args, **kwargs) + + with mock.patch.object(task.cliutils, "print_list", + new=print_list): + self.task.list(self.fake_api, status="running") + + self.assertEqual(1, len(print_list_calls)) + + self.assertEqual( + "+--------+-----------------+---------------------" + "+----------------+----------+------------------+\n" + "| uuid | deployment_name | created_at " + "| duration | status | tags |\n" + "+--------+-----------------+---------------------" + "+----------------+----------+------------------+\n" + "| UUID-1 | some_name | 2007-01-01T00:00:01 " + "| 0:00:00.000009 | init | |\n" + "| UUID-2 | some_name | 2007-02-01T00:00:01 " + "| 0:00:00.000010 | finished | 'tag-1', 'tag-2' |\n" + "+--------+-----------------+---------------------" + "+----------------+----------+------------------+\n", + print_list_calls[0].getvalue()) + def test_delete(self): task_uuid = "8dcb9c5e-d60b-4022-8975-b5987c7833f7" force = False @@ -1117,13 +1169,14 @@ class TaskCommandsTestCase(test.TestCase): self.task.import_results(self.fake_api, "deployment_uuid", - "task_file", "tag") + "task_file", tags=["tag"]) self.task._load_task_results_file.assert_called_once_with( self.fake_api, "task_file" ) self.fake_api.task.import_results.assert_called_once_with( - deployment="deployment_uuid", task_results=["results"], tag="tag") + deployment="deployment_uuid", task_results=["results"], + tags=["tag"]) # not exist mock_os_path.exists.return_value = False @@ -1131,5 +1184,5 @@ class TaskCommandsTestCase(test.TestCase): 1, self.task.import_results(self.fake_api, "deployment_uuid", - "task_file", "tag") + "task_file", ["tag"]) ) diff --git a/tests/unit/common/db/test_api.py b/tests/unit/common/db/test_api.py index 1680452a7c..359a52ef76 100644 --- a/tests/unit/common/db/test_api.py +++ b/tests/unit/common/db/test_api.py @@ -122,12 +122,12 @@ class TasksTestCase(test.DBTestCase): self.assertEqual(db_task["status"], consts.TaskStatus.INIT) def test_task_create_with_tag(self): - task = self._create_task(values={"tag": "test_tag"}) + task = self._create_task(values={"tags": ["test_tag"]}) db_task = self._get_task(task["uuid"]) self.assertIsNotNone(db_task["uuid"]) self.assertIsNotNone(db_task["id"]) self.assertEqual(db_task["status"], consts.TaskStatus.INIT) - self.assertEqual(db_task["tag"], "test_tag") + self.assertEqual(db_task["tags"], ["test_tag"]) def test_task_create_without_uuid(self): _uuid = "19be8589-48b0-4af1-a369-9bebaaa563ab" @@ -145,11 +145,11 @@ class TasksTestCase(test.DBTestCase): task = self._create_task({}) db.task_update(task["uuid"], { "status": consts.TaskStatus.CRASHED, - "tag": "test_tag" + "tags": ["test_tag"] }) db_task = self._get_task(task["uuid"]) self.assertEqual(db_task["status"], consts.TaskStatus.CRASHED) - self.assertEqual(db_task["tag"], "test_tag") + self.assertEqual(db_task["tags"], ["test_tag"]) def test_task_update_not_found(self): self.assertRaises(exceptions.TaskNotFound, @@ -375,7 +375,7 @@ class TasksTestCase(test.DBTestCase): "trace": "foo t/b", } task1 = self._create_task({"validation_result": validation_result, - "tag": "bar"}) + "tags": ["bar"]}) key = { "name": "atata", "description": "tatata", @@ -408,7 +408,7 @@ class TasksTestCase(test.DBTestCase): task1_full = db.task_get_detailed(task1["uuid"]) self.assertEqual(validation_result, json.loads(task1_full["verification_log"])) - self.assertEqual("bar", task1_full["tag"]) + self.assertEqual(["bar"], task1_full["tags"]) results = task1_full["results"] self.assertEqual(1, len(results)) self.assertEqual(key, results[0]["key"]) diff --git a/tests/unit/test_api.py b/tests/unit/test_api.py index d4bd9ef5c4..abb624d500 100644 --- a/tests/unit/test_api.py +++ b/tests/unit/test_api.py @@ -224,17 +224,18 @@ class TaskAPITestCase(test.TestCase): self.assertEqual("2", self.task_inst.render_template( task_template=template)) - @mock.patch("rally.common.objects.Deployment.get", - return_value={ - "uuid": "b0d9cd6c-2c94-4417-a238-35c7019d0257", - "status": consts.DeployStatus.DEPLOY_FINISHED}) + @mock.patch("rally.common.objects.Deployment.get") @mock.patch("rally.common.objects.Task") def test_create(self, mock_task, mock_deployment_get): - tag = "a" + mock_deployment_get.return_value = { + "uuid": "b0d9cd6c-2c94-4417-a238-35c7019d0257", + "status": consts.DeployStatus.DEPLOY_FINISHED} + tags = ["a"] self.task_inst.create( - deployment=mock_deployment_get.return_value["uuid"], tag=tag) + deployment=mock_deployment_get.return_value["uuid"], tags=tags) mock_task.assert_called_once_with( - deployment_uuid=mock_deployment_get.return_value["uuid"], tag=tag) + deployment_uuid=mock_deployment_get.return_value["uuid"], + tags=tags) @mock.patch("rally.common.objects.Deployment.get", return_value={ @@ -243,10 +244,9 @@ class TaskAPITestCase(test.TestCase): "status": consts.DeployStatus.DEPLOY_INIT}) def test_create_on_unfinished_deployment(self, mock_deployment_get): deployment_id = mock_deployment_get.return_value["uuid"] - tag = "a" self.assertRaises(exceptions.DeploymentNotFinishedStatus, self.task_inst.create, deployment=deployment_id, - tag=tag) + tags=["a"]) @mock.patch("rally.api.objects.Task") @mock.patch("rally.api.objects.Deployment.get") @@ -489,7 +489,7 @@ class TaskAPITestCase(test.TestCase): ) mock_task.assert_called_once_with(deployment_uuid="deployment_uuid", - tag=None) + tags=None) mock_task.return_value.update_status.assert_has_calls( [mock.call(consts.TaskStatus.RUNNING), mock.call(consts.SubtaskStatus.FINISHED)] @@ -536,7 +536,7 @@ class TaskAPITestCase(test.TestCase): ) mock_task.assert_called_once_with(deployment_uuid="deployment_uuid", - tag=None) + tags=None) mock_task.return_value.update_status.assert_has_calls( [mock.call(consts.TaskStatus.RUNNING), mock.call(consts.SubtaskStatus.FINISHED)] @@ -575,7 +575,7 @@ class TaskAPITestCase(test.TestCase): self.task_inst.import_results, deployment="deployment_uuid", task_results=[], - tag="tag") + tags=["tag"]) class BaseDeploymentTestCase(test.TestCase):