Add a --uuids-only option to rally task list

This option prints the list of UUIDs only.

The motivation for this option is scripting, for example:

   for x in $(rally task list --status passed --uuids-only); \
   do \
       rally task report --tasks $x --out $x.html; \
   done

Change-Id: Ia967071bc3e4454116adbc59a790ab684efff15c
Signed-off-by: Andrew McDermott <andrew.mcdermott@linaro.org>
This commit is contained in:
Andrew McDermott 2015-03-23 16:04:42 +00:00
parent a580bce1c5
commit 7126848b5b
6 changed files with 246 additions and 7 deletions

View File

@ -29,7 +29,7 @@ _rally()
OPTS["task_abort"]="--uuid"
OPTS["task_delete"]="--force --uuid"
OPTS["task_detailed"]="--uuid --iterations-data"
OPTS["task_list"]="--deployment --all-deployments --status"
OPTS["task_list"]="--deployment --all-deployments --status --uuids-only"
OPTS["task_report"]="--tasks --out --open"
OPTS["task_results"]="--uuid"
OPTS["task_sla_check"]="--uuid --json"
@ -79,4 +79,4 @@ _rally()
fi
return 0
}
complete -F _rally rally
complete -F _rally rally

View File

@ -84,7 +84,9 @@ def validate_args(fn, *args, **kwargs):
def print_list(objs, fields, formatters=None, sortby_index=0,
mixed_case_fields=None, field_labels=None):
mixed_case_fields=None, field_labels=None,
print_header=True, print_border=True,
out=sys.stdout):
"""Print a list or objects as a table, one row per object.
:param objs: iterable of :class:`Resource`
@ -95,6 +97,9 @@ def print_list(objs, fields, formatters=None, sortby_index=0,
have mixed case names (e.g., 'serverId')
:param field_labels: Labels to use in the heading of the table, default to
fields.
:param print_header: print table header.
:param print_border: print table border.
:param out: stream to write output to.
"""
formatters = formatters or {}
mixed_case_fields = mixed_case_fields or []
@ -125,10 +130,19 @@ def print_list(objs, fields, formatters=None, sortby_index=0,
row.append(data)
pt.add_row(row)
if not print_border or not print_header:
pt.set_style(prettytable.PLAIN_COLUMNS)
pt.left_padding_width = 0
pt.right_padding_width = 1
outstr = pt.get_string(header=print_header,
border=print_border,
**kwargs) + "\n"
if six.PY3:
print(encodeutils.safe_encode(pt.get_string(**kwargs)).decode())
out.write(encodeutils.safe_encode(outstr).decode())
else:
print(encodeutils.safe_encode(pt.get_string(**kwargs)))
out.write(encodeutils.safe_encode(outstr))
def make_header(text, size=80, symbol="-"):

View File

@ -443,8 +443,11 @@ class TaskCommands(object):
@cliutils.args("--status", type=str, dest="status",
help="List tasks with specified status."
" Available statuses: %s" % ", ".join(consts.TaskStatus))
@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, deployment=None, all_deployments=False, status=None):
def list(self, deployment=None, all_deployments=False, status=None,
uuids_only=False):
"""List tasks, started and finished.
Displayed tasks could be filtered by status or deployment.
@ -454,6 +457,7 @@ class TaskCommands(object):
:param status: task status to filter by.
Available task statuses are in rally.consts.TaskStatus
:param all_deployments: display tasks from all deployments
:param uuids_only: list task UUIDs only
"""
filters = {}
@ -477,7 +481,12 @@ class TaskCommands(object):
for x in task_list:
x["duration"] = x["updated_at"] - x["created_at"]
if task_list:
if uuids_only:
if task_list:
cliutils.print_list(task_list, ["uuid"],
print_header=False,
print_border=False)
elif task_list:
cliutils.print_list(
task_list,
headers, sortby_index=headers.index("created_at"))

View File

@ -231,6 +231,36 @@ class TaskTestCase(unittest.TestCase):
self.assertRaises(utils.RallyCmdError,
rally, "task list --status not_existing_status")
def test_list_with_print_uuids_option(self):
rally = utils.Rally()
cfg = self._get_sample_task_config()
config = utils.TaskConfig(cfg)
# Validate against zero tasks
self.assertEqual("", rally("task list --uuids-only"))
# Validate against a single task
res = rally("task start --task %s" % config.filename)
task_uuids = list()
for line in res.splitlines():
if "finished" in line:
task_uuids.append(line.split(" ")[1][:-1])
self.assertTrue(len(task_uuids))
self.assertIn(task_uuids[0],
rally("task list --uuids-only --deployment MAIN"))
# Validate against multiple tasks
for i in range(2):
rally("task start --task %s" % config.filename)
self.assertIn("finished", rally("task list --deployment MAIN"))
res = rally("task list --uuids-only --deployment MAIN")
task_uuids = res.split()
self.assertEqual(3, len(task_uuids))
res = rally("task list --uuids-only --deployment MAIN "
"--status finished")
for uuid in task_uuids:
self.assertIn(uuid, res)
def test_validate_is_valid(self):
rally = utils.Rally()
cfg = self._get_sample_task_config()

View File

@ -504,6 +504,26 @@ class TaskCommandsTestCase(test.TestCase):
mock_objects_list.return_value, headers,
sortby_index=headers.index("created_at"))
@mock.patch("rally.cmd.commands.task.cliutils.print_list")
@mock.patch("rally.cmd.commands.task.envutils.get_global",
return_value="123456789")
@mock.patch("rally.cmd.commands.task.objects.Task.list",
return_value=[fakes.FakeTask(uuid="a",
created_at=date.datetime.now(),
updated_at=date.datetime.now(),
status="c",
tag="d",
deployment_name="some_name")])
def test_list_uuids_only(self, mock_objects_list, mock_default,
mock_print_list):
self.task.list(status="running", uuids_only=True)
mock_objects_list.assert_called_once_with(
deployment=mock_default.return_value,
status=consts.TaskStatus.RUNNING)
mock_print_list.assert_called_once_with(
mock_objects_list.return_value, ["uuid"],
print_header=False, print_border=False)
def test_list_wrong_status(self):
self.assertEqual(1, self.task.list(deployment="fake",
status="wrong non existing status"))

View File

@ -15,6 +15,7 @@
import mock
from oslo_config import cfg
from six import moves
from rally.cmd import cliutils
from rally.cmd.commands import deployment
@ -170,6 +171,171 @@ class CliUtilsTestCase(test.TestCase):
{"failure": FailuresCommands})
self.assertEqual(1, ret)
def test_print_list(self):
class TestObj(object):
x = 1
y = 2
z = 3.142857142857143
aOrB = 3 # mixed case field
out = moves.StringIO()
cliutils.print_list([TestObj()], ["x", "y"],
print_header=True,
print_border=True,
sortby_index=None,
out=out)
self.assertEqual("+---+---+\n"
"| x | y |\n"
"+---+---+\n"
"| 1 | 2 |\n"
"+---+---+",
out.getvalue().strip())
out = moves.StringIO()
formatter = cliutils.pretty_float_formatter("z", 5)
cliutils.print_list([TestObj()], ["z"],
print_header=True,
print_border=True,
sortby_index=None,
formatters={"z": formatter},
out=out)
self.assertEqual("+---------+\n"
"| z |\n"
"+---------+\n"
"| 3.14286 |\n"
"+---------+",
out.getvalue().strip())
out = moves.StringIO()
cliutils.print_list([TestObj()], ["x"],
print_header=True,
print_border=True,
out=out)
self.assertEqual("+---+\n"
"| x |\n"
"+---+\n"
"| 1 |\n"
"+---+",
out.getvalue().strip())
out = moves.StringIO()
cliutils.print_list([TestObj()], ["x", "y"],
print_header=True,
print_border=True,
out=out)
self.assertEqual("+---+---+\n"
"| x | y |\n"
"+---+---+\n"
"| 1 | 2 |\n"
"+---+---+",
out.getvalue().strip())
out = moves.StringIO()
cliutils.print_list([TestObj()], ["x"],
print_header=False,
print_border=False,
out=out)
self.assertEqual("1",
out.getvalue().strip())
out = moves.StringIO()
cliutils.print_list([TestObj()], ["x", "y"],
print_header=False,
print_border=False,
out=out)
self.assertEqual("1 2",
out.getvalue().strip())
out = moves.StringIO()
cliutils.print_list([TestObj()], ["x"],
print_header=True,
print_border=False,
out=out)
self.assertEqual("x \n1",
out.getvalue().strip())
out = moves.StringIO()
cliutils.print_list([TestObj()], ["x", "y"],
print_header=True,
print_border=False,
out=out)
self.assertEqual("x y \n1 2",
out.getvalue().strip())
out = moves.StringIO()
cliutils.print_list([TestObj()], ["x"],
print_header=False,
print_border=True,
out=out)
self.assertEqual("+--+\n"
"|1 |\n"
"+--+",
out.getvalue().strip())
out = moves.StringIO()
cliutils.print_list([TestObj()], ["x", "y"],
print_header=False,
print_border=True,
out=out)
self.assertEqual("+--+--+\n"
"|1 |2 |\n"
"+--+--+",
out.getvalue().strip())
out = moves.StringIO()
cliutils.print_list([TestObj()], ["aOrB"],
mixed_case_fields=["aOrB"],
print_header=True,
print_border=True,
out=out)
self.assertEqual("+------+\n"
"| aOrB |\n"
"+------+\n"
"| 3 |\n"
"+------+",
out.getvalue().strip())
out = moves.StringIO()
cliutils.print_list([TestObj()], ["aOrB"],
mixed_case_fields=["aOrB"],
print_header=False,
print_border=True,
out=out)
self.assertEqual("+--+\n"
"|3 |\n"
"+--+",
out.getvalue().strip())
out = moves.StringIO()
cliutils.print_list([TestObj()], ["aOrB"],
mixed_case_fields=["aOrB"],
print_header=True,
print_border=False,
out=out)
self.assertEqual("aOrB \n"
"3",
out.getvalue().strip())
out = moves.StringIO()
cliutils.print_list([TestObj()], ["aOrB"],
mixed_case_fields=["aOrB"],
print_header=False,
print_border=False,
out=out)
self.assertEqual("3",
out.getvalue().strip())
out = moves.StringIO()
self.assertRaisesRegexp(ValueError,
"Field labels list.*has different number "
"of elements than fields list",
cliutils.print_list,
[TestObj()],
["x"],
field_labels=["x", "y"],
sortby_index=None,
out=out)
class ValidateArgsTest(test.TestCase):