Merge "Improve rally cli docstrings"

This commit is contained in:
Jenkins 2016-01-19 21:51:40 +00:00 committed by Gerrit Code Review
commit 49c33b5dca
4 changed files with 127 additions and 117 deletions

View File

@ -41,28 +41,28 @@ class DeploymentCommands(object):
"""Set of commands that allow you to manage deployments.""" """Set of commands that allow you to manage deployments."""
@cliutils.args("--name", type=str, required=True, @cliutils.args("--name", type=str, required=True,
help="A name of the deployment.") help="Name of the deployment.")
@cliutils.args("--fromenv", action="store_true", @cliutils.args("--fromenv", action="store_true",
help="Read environment variables instead of config file.") help="Read environment variables instead of config file.")
@cliutils.args("--filename", type=str, required=False, metavar="<path>", @cliutils.args("--filename", type=str, required=False, metavar="<path>",
help="A path to the configuration file of the " help="Path to the configuration file of the deployment.")
"deployment.")
@cliutils.args("--no-use", action="store_false", dest="do_use", @cliutils.args("--no-use", action="store_false", dest="do_use",
help="Don\'t set new deployment as default for" help="Don't set new deployment as default for"
" future operations.") " future operations.")
@plugins.ensure_plugins_are_loaded @plugins.ensure_plugins_are_loaded
def create(self, name, fromenv=False, filename=None, do_use=False): def create(self, name, fromenv=False, filename=None, do_use=False):
"""Create new deployment. """Create new deployment.
This command will create new deployment record in rally database. This command will create a new deployment record in rally
In case of ExistingCloud deployment engine it will use cloud, database. In the case of ExistingCloud deployment engine it
represented in config. will use the cloud represented in the configuration. If the
In cases when cloud doesn't exists Rally will deploy new one cloud doesn't exist, Rally can deploy a new one for you with
for you with Devstack or Fuel. For this purposes different deployment Devstack or Fuel. Different deployment engines exist for these
engines are developed. cases.
If you use the ExistingCloud deployment engine you can pass
a deployment config by environment variables with ``--fromenv``:
If you use ExistingCloud deployment engine you can pass deployment
config by environment variables:
OS_USERNAME OS_USERNAME
OS_PASSWORD OS_PASSWORD
OS_AUTH_URL OS_AUTH_URL
@ -72,18 +72,18 @@ class DeploymentCommands(object):
OS_CACERT OS_CACERT
OS_INSECURE OS_INSECURE
All other deployment engines need more complex configuration data, so All other deployment engines need more complex configuration
it should be stored in configuration file. data, so it should be stored in a configuration file.
You can use physical servers, lxc containers, KVM virtual machines You can use physical servers, LXC containers, KVM virtual
or virtual machines in OpenStack for deploying the cloud in. machines or virtual machines in OpenStack for deploying the
Except physical servers, Rally can create cluster nodes for you. cloud. Except physical servers, Rally can create cluster nodes
Interaction with virtualization software, OpenStack for you. Interaction with virtualization software, OpenStack
cloud or physical servers is provided by server providers. cloud or physical servers is provided by server providers.
:param fromenv: boolean, read environment instead of config file :param fromenv: boolean, read environment instead of config file
:param filename: a path to the configuration file :param filename: path to the configuration file
:param name: a name of the deployment :param name: name of the deployment
""" """
if fromenv: if fromenv:
@ -112,32 +112,33 @@ class DeploymentCommands(object):
@cliutils.args("--deployment", dest="deployment", type=str, @cliutils.args("--deployment", dest="deployment", type=str,
metavar="<uuid>", required=False, metavar="<uuid>", required=False,
help="UUID or name of a deployment.") help="UUID or name of the deployment.")
@envutils.with_default_deployment() @envutils.with_default_deployment()
@plugins.ensure_plugins_are_loaded @plugins.ensure_plugins_are_loaded
def recreate(self, deployment=None): def recreate(self, deployment=None):
"""Destroy and create an existing deployment. """Destroy and create an existing deployment.
Unlike 'deployment destroy' command deployment database record will Unlike 'deployment destroy', the deployment database record
not be deleted, so deployment's UUID stay same. will not be deleted, so the deployment UUID stays the same.
:param deployment: a UUID or name of the deployment :param deployment: UUID or name of the deployment
""" """
api.Deployment.recreate(deployment) api.Deployment.recreate(deployment)
@cliutils.args("--deployment", dest="deployment", type=str, @cliutils.args("--deployment", dest="deployment", type=str,
metavar="<uuid>", required=False, metavar="<uuid>", required=False,
help="UUID or name of a deployment.") help="UUID or name of the deployment.")
@envutils.with_default_deployment() @envutils.with_default_deployment()
@plugins.ensure_plugins_are_loaded @plugins.ensure_plugins_are_loaded
def destroy(self, deployment=None): def destroy(self, deployment=None):
"""Destroy existing deployment. """Destroy existing deployment.
This will delete all containers, virtual machines, OpenStack instances This will delete all containers, virtual machines, OpenStack
or Fuel clusters created during Rally deployment creation. Also it will instances or Fuel clusters created during Rally deployment
remove deployment record from Rally database. creation. Also it will remove the deployment record from the
Rally database.
:param deployment: a UUID or name of the deployment :param deployment: UUID or name of the deployment
""" """
api.Deployment.destroy(deployment) api.Deployment.destroy(deployment)
@ -163,7 +164,7 @@ class DeploymentCommands(object):
@cliutils.args("--deployment", dest="deployment", type=str, @cliutils.args("--deployment", dest="deployment", type=str,
metavar="<uuid>", required=False, metavar="<uuid>", required=False,
help="UUID or name of a deployment.") help="UUID or name of the deployment.")
@envutils.with_default_deployment() @envutils.with_default_deployment()
@cliutils.suppress_warnings @cliutils.suppress_warnings
def config(self, deployment=None): def config(self, deployment=None):
@ -172,7 +173,7 @@ class DeploymentCommands(object):
Output is the configuration of the deployment in a Output is the configuration of the deployment in a
pretty-printed JSON format. pretty-printed JSON format.
:param deployment: a UUID or name of the deployment :param deployment: UUID or name of the deployment
""" """
deploy = api.Deployment.get(deployment) deploy = api.Deployment.get(deployment)
result = deploy["config"] result = deploy["config"]
@ -180,12 +181,12 @@ class DeploymentCommands(object):
@cliutils.args("--deployment", dest="deployment", type=str, @cliutils.args("--deployment", dest="deployment", type=str,
metavar="<uuid>", required=False, metavar="<uuid>", required=False,
help="UUID or name of a deployment.") help="UUID or name of the deployment.")
@envutils.with_default_deployment() @envutils.with_default_deployment()
def show(self, deployment=None): def show(self, deployment=None):
"""Show the credentials of the deployment. """Show the credentials of the deployment.
:param deployment: a UUID or name of the deployment :param deployment: UUID or name of the deployment
""" """
headers = ["auth_url", "username", "password", "tenant_name", headers = ["auth_url", "username", "password", "tenant_name",
@ -205,12 +206,12 @@ class DeploymentCommands(object):
@cliutils.args("--deployment", dest="deployment", type=str, @cliutils.args("--deployment", dest="deployment", type=str,
metavar="<uuid>", required=False, metavar="<uuid>", required=False,
help="UUID or name of a deployment.") help="UUID or name of the deployment.")
@envutils.with_default_deployment() @envutils.with_default_deployment()
def check(self, deployment=None): def check(self, deployment=None):
"""Check keystone authentication and list all available services. """Check keystone authentication and list all available services.
:param deployment: a UUID or name of the deployment :param deployment: UUID or name of the deployment
""" """
headers = ["services", "type", "status"] headers = ["services", "type", "status"]
table_rows = [] table_rows = []
@ -275,7 +276,7 @@ class DeploymentCommands(object):
def use(self, deployment): def use(self, deployment):
"""Set active deployment. """Set active deployment.
:param deployment: UUID or name of a deployment :param deployment: UUID or name of the deployment
""" """
try: try:
deployment = api.Deployment.get(deployment) deployment = api.Deployment.get(deployment)

View File

@ -24,7 +24,7 @@ from rally import plugins
class PluginCommands(object): class PluginCommands(object):
"""Command allows to manage Rally plugins.""" """Set of commands that allow you to manage Rally plugins."""
@staticmethod @staticmethod
def _print_plugins_list(plugin_list): def _print_plugins_list(plugin_list):
@ -41,7 +41,7 @@ class PluginCommands(object):
help="Plugin namespace.") help="Plugin namespace.")
@plugins.ensure_plugins_are_loaded @plugins.ensure_plugins_are_loaded
def show(self, name, namespace=None): def show(self, name, namespace=None):
"""Show detailed information about Rally plugin.""" """Show detailed information about a Rally plugin."""
name_lw = name.lower() name_lw = name.lower()
all_plugins = plugin.Plugin.get_all(namespace=namespace) all_plugins = plugin.Plugin.get_all(namespace=namespace)
found = [p for p in all_plugins if name_lw in p.get_name().lower()] found = [p for p in all_plugins if name_lw in p.get_name().lower()]
@ -78,9 +78,10 @@ class PluginCommands(object):
self._print_plugins_list(found) self._print_plugins_list(found)
@cliutils.args("--name", dest="name", type=str, @cliutils.args("--name", dest="name", type=str,
help="List only plugins that match passed name.") help="List only plugins that match the given name.")
@cliutils.args("--namespace", dest="namespace", type=str, @cliutils.args(
help="List only plugins that are in specified namespace") "--namespace", dest="namespace", type=str,
help="List only plugins that are in the specified namespace.")
@plugins.ensure_plugins_are_loaded @plugins.ensure_plugins_are_loaded
def list(self, name=None, namespace=None): def list(self, name=None, namespace=None):
"""List all Rally plugins that match name and namespace.""" """List all Rally plugins that match name and namespace."""

View File

@ -46,9 +46,8 @@ class FailedToLoadTask(exceptions.RallyException):
class TaskCommands(object): class TaskCommands(object):
"""Task management. """Set of commands that allow you to manage benchmarking tasks and results.
Set of commands that allow you to manage benchmarking tasks and results.
""" """
def _load_task(self, task_file, task_args=None, task_args_file=None): def _load_task(self, task_file, task_args=None, task_args_file=None):
@ -142,14 +141,14 @@ class TaskCommands(object):
metavar="<uuid>", required=False, metavar="<uuid>", required=False,
help="UUID or name of a deployment.") help="UUID or name of a deployment.")
@cliutils.args("--task", "--filename", metavar="<path>", @cliutils.args("--task", "--filename", metavar="<path>",
help="Path to the file with full configuration of task") help="Path to the input task file.")
@cliutils.args("--task-args", metavar="<json>", dest="task_args", @cliutils.args("--task-args", metavar="<json>", dest="task_args",
help="Input task args (dict in json). These args are used " help="Input task args (JSON dict). These args are used "
"to render input task that is jinja2 template.") "to render the Jinja2 template in the input task.")
@cliutils.args("--task-args-file", metavar="<path>", dest="task_args_file", @cliutils.args("--task-args-file", metavar="<path>", dest="task_args_file",
help="Path to the file with input task args (dict in " help="Path to the file with input task args (dict in "
"json/yaml). These args are used to render input " "JSON/YAML). These args are used "
"task that is jinja2 template.") "to render the Jinja2 template in the input task.")
@envutils.with_default_deployment(cli_arg_name="deployment") @envutils.with_default_deployment(cli_arg_name="deployment")
@plugins.ensure_plugins_are_loaded @plugins.ensure_plugins_are_loaded
def validate(self, task, deployment=None, task_args=None, def validate(self, task, deployment=None, task_args=None,
@ -159,13 +158,19 @@ class TaskCommands(object):
This will check that task configuration file has valid syntax and This will check that task configuration file has valid syntax and
all required options of scenarios, contexts, SLA and runners are set. all required options of scenarios, contexts, SLA and runners are set.
:param task: a file with yaml/json task If both task_args and task_args_file are specified, they will
:param task_args: Input task args (dict in json/yaml). These args are be merged. task_args has a higher priority so it will override
used to render input task that is jinja2 template. values from task_args_file.
:param task_args_file: File with input task args (dict in json/yaml).
These args are used to render input task that :param task: Path to the input task file.
is jinja2 template. :param task_args: Input task args (JSON dict). These args are
:param deployment: UUID or name of a deployment used to render the Jinja2 template in the
input task.
:param task_args_file: 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.
:param deployment: UUID or name of the deployment
""" """
try: try:
self._load_and_validate_task(task, task_args, task_args_file, self._load_and_validate_task(task, task_args, task_args_file,
@ -181,32 +186,38 @@ class TaskCommands(object):
@cliutils.args("--task", "--filename", metavar="<path>", @cliutils.args("--task", "--filename", metavar="<path>",
help="Path to the input task file") help="Path to the input task file")
@cliutils.args("--task-args", dest="task_args", metavar="<json>", @cliutils.args("--task-args", dest="task_args", metavar="<json>",
help="Input task args (dict in json). These args are used " help="Input task args (JSON dict). These args are used "
"to render input task that is jinja2 template.") "to render the Jinja2 template in the input task.")
@cliutils.args("--task-args-file", dest="task_args_file", metavar="<path>", @cliutils.args("--task-args-file", dest="task_args_file", metavar="<path>",
help="Path to the file with input task args (dict in " help="Path to the file with input task args (dict in "
"json/yaml). These args are used to render input " "JSON/YAML). These args are used "
"task that is jinja2 template.") "to render the Jinja2 template in the input task.")
@cliutils.args("--tag", help="Tag for this task") @cliutils.args("--tag", help="Tag for this task")
@cliutils.args("--no-use", action="store_false", dest="do_use", @cliutils.args("--no-use", action="store_false", dest="do_use",
help="Don't set new task as default for future operations") help="Don't set new task as default for future operations.")
@cliutils.args("--abort-on-sla-failure", action="store_true", @cliutils.args("--abort-on-sla-failure", action="store_true",
dest="abort_on_sla_failure", dest="abort_on_sla_failure",
help="Abort the execution of a benchmark scenario when" help="Abort the execution of a benchmark scenario when"
"any SLA check for it fails") "any SLA check for it fails.")
@envutils.with_default_deployment(cli_arg_name="deployment") @envutils.with_default_deployment(cli_arg_name="deployment")
@plugins.ensure_plugins_are_loaded @plugins.ensure_plugins_are_loaded
def start(self, task, deployment=None, task_args=None, task_args_file=None, def start(self, task, deployment=None, task_args=None, task_args_file=None,
tag=None, do_use=False, abort_on_sla_failure=False): tag=None, do_use=False, abort_on_sla_failure=False):
"""Start benchmark task. """Start benchmark task.
:param task: a file with yaml/json task If both task_args and task_args_file are specified, they will
:param task_args: Input task args (dict in json/yaml). These args are be merged. task_args has a higher priority so it will override
used to render input task that is jinja2 template. values from task_args_file.
:param task_args_file: File with input task args (dict in json/yaml).
These args are used to render input task that :param task: Path to the input task file.
is jinja2 template. :param task_args: Input task args (JSON dict). These args are
:param deployment: UUID or name of a deployment used to render the Jinja2 template in the
input task.
:param task_args_file: 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.
:param deployment: UUID or name of the deployment
:param tag: optional tag for this task :param tag: optional tag for this task
:param do_use: if True, the new task will be stored as the default one :param do_use: if True, the new task will be stored as the default one
for future operations for future operations
@ -242,22 +253,23 @@ class TaskCommands(object):
print(e, file=sys.stderr) print(e, file=sys.stderr)
return(1) return(1)
@cliutils.args("--uuid", type=str, dest="task_id", help="UUID of task") @cliutils.args("--uuid", type=str, dest="task_id", help="UUID of task.")
@envutils.with_default_task_id @envutils.with_default_task_id
@cliutils.args("--soft", action="store_true", @cliutils.args(
help="Abort task after current scenario full execution") "--soft", action="store_true",
help="Abort task after current scenario finishes execution.")
def abort(self, task_id=None, soft=False): def abort(self, task_id=None, soft=False):
"""Abort started benchmarking task. """Abort a running benchmarking task.
:param task_id: Task uuid :param task_id: Task uuid
:param soft: if set to True, task should be aborted after execution of :param soft: if set to True, task should be aborted after execution of
current scenario current scenario
""" """
if soft: if soft:
print("INFO: please be informed that soft abort wont stop " print("INFO: please be informed that soft abort won't stop "
"current running scenario, it will prevent to start " "a running scenario, but will prevent new ones from "
"new ones, so if you are running task with only one " "starting. If you are running task with only one "
"scenario - soft abort will not help at all.") "scenario, soft abort will not help at all.")
api.Task.abort(task_id, soft, async=False) api.Task.abort(task_id, soft, async=False)
@ -266,7 +278,7 @@ class TaskCommands(object):
@cliutils.args("--uuid", type=str, dest="task_id", help="UUID of task") @cliutils.args("--uuid", type=str, dest="task_id", help="UUID of task")
@envutils.with_default_task_id @envutils.with_default_task_id
def status(self, task_id=None): def status(self, task_id=None):
"""Display current status of task. """Display the current status of a task.
:param task_id: Task uuid :param task_id: Task uuid
Returns current status of task Returns current status of task
@ -277,11 +289,11 @@ class TaskCommands(object):
% {"task_id": task_id, "status": task["status"]}) % {"task_id": task_id, "status": task["status"]})
@cliutils.args("--uuid", type=str, dest="task_id", @cliutils.args("--uuid", type=str, dest="task_id",
help=("uuid of task, if --uuid is \"last\" results of most " help=("UUID of task. If --uuid is \"last\" the results of "
"recently created task will be displayed.")) " the most recently created task will be displayed."))
@cliutils.args("--iterations-data", dest="iterations_data", @cliutils.args("--iterations-data", dest="iterations_data",
action="store_true", action="store_true",
help="print detailed results for each iteration") help="Print detailed results for each iteration.")
@envutils.with_default_task_id @envutils.with_default_task_id
def detailed(self, task_id=None, iterations_data=False): def detailed(self, task_id=None, iterations_data=False):
"""Display results table. """Display results table.
@ -493,7 +505,7 @@ class TaskCommands(object):
result["data"]["full_duration"]) result["data"]["full_duration"])
_print_hints(task) _print_hints(task)
@cliutils.args("--uuid", type=str, dest="task_id", help="uuid of task") @cliutils.args("--uuid", type=str, dest="task_id", help="UUID of task.")
@envutils.with_default_task_id @envutils.with_default_task_id
@cliutils.suppress_warnings @cliutils.suppress_warnings
def results(self, task_id=None): def results(self, task_id=None):
@ -527,15 +539,16 @@ class TaskCommands(object):
help="List tasks with specified status." help="List tasks with specified status."
" Available statuses: %s" % ", ".join(consts.TaskStatus)) " Available statuses: %s" % ", ".join(consts.TaskStatus))
@cliutils.args("--uuids-only", action="store_true", @cliutils.args("--uuids-only", action="store_true",
dest="uuids_only", help="List task UUIDs only") dest="uuids_only", help="List task UUIDs only.")
@envutils.with_default_deployment(cli_arg_name="deployment") @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): uuids_only=False):
"""List tasks, started and finished. """List tasks, started and finished.
Displayed tasks could be filtered by status or deployment. Displayed tasks can be filtered by status or deployment. By
By default 'rally task list' will display tasks from active deployment default 'rally task list' will display tasks from the active
without filtering by status. deployment without filtering by status.
:param deployment: UUID or name of deployment :param deployment: UUID or name of deployment
:param status: task status to filter by. :param status: task status to filter by.
Available task statuses are in rally.consts.TaskStatus Available task statuses are in rally.consts.TaskStatus
@ -583,12 +596,12 @@ class TaskCommands(object):
"\trally task start")) "\trally task start"))
@cliutils.args("--tasks", dest="tasks", nargs="+", @cliutils.args("--tasks", dest="tasks", nargs="+",
help="uuids of tasks or json files with task results") help="UUIDs of tasks, or JSON files with task results")
@cliutils.args("--out", metavar="<path>", @cliutils.args("--out", metavar="<path>",
type=str, dest="out", required=False, type=str, dest="out", required=False,
help="Path to output file.") help="Path to output file.")
@cliutils.args("--open", dest="open_it", action="store_true", @cliutils.args("--open", dest="open_it", action="store_true",
help="Open it in browser.") help="Open the output in a browser.")
@cliutils.args("--html", dest="out_format", @cliutils.args("--html", dest="out_format",
action="store_const", const="html", action="store_const", const="html",
help="Generate the report in HTML.") help="Generate the report in HTML.")
@ -596,7 +609,7 @@ class TaskCommands(object):
action="store_const", const="html_static", action="store_const", const="html_static",
help=("Generate the report in HTML with embedded " help=("Generate the report in HTML with embedded "
"JS and CSS, so it will not depend on " "JS and CSS, so it will not depend on "
"the Internet availability.")) "Internet availability."))
@cliutils.args("--junit", dest="out_format", @cliutils.args("--junit", dest="out_format",
action="store_const", const="junit", action="store_const", const="junit",
help="Generate the report in the JUnit format.") help="Generate the report in the JUnit format.")
@ -689,7 +702,7 @@ class TaskCommands(object):
@cliutils.args("--force", action="store_true", help="force delete") @cliutils.args("--force", action="store_true", help="force delete")
@cliutils.args("--uuid", type=str, dest="task_id", nargs="*", @cliutils.args("--uuid", type=str, dest="task_id", nargs="*",
metavar="TASK_ID", metavar="TASK_ID",
help="uuid of task or a list of task uuids") help="UUID of task or a list of task UUIDs.")
@envutils.with_default_task_id @envutils.with_default_task_id
def delete(self, task_id=None, force=False): def delete(self, task_id=None, force=False):
"""Delete task and its results. """Delete task and its results.
@ -713,10 +726,10 @@ class TaskCommands(object):
else: else:
_delete_single_task(task_id, force) _delete_single_task(task_id, force)
@cliutils.args("--uuid", type=str, dest="task_id", help="uuid of task") @cliutils.args("--uuid", type=str, dest="task_id", help="UUID of task.")
@cliutils.args("--json", dest="tojson", @cliutils.args("--json", dest="tojson",
action="store_true", action="store_true",
help="output in json format") help="Output in JSON format.")
@envutils.with_default_task_id @envutils.with_default_task_id
def sla_check(self, task_id=None, tojson=False): def sla_check(self, task_id=None, tojson=False):
"""Display SLA check results table. """Display SLA check results table.

View File

@ -51,23 +51,23 @@ class VerifyCommands(object):
help="Name of a Tempest test set. " help="Name of a Tempest test set. "
"Available sets are %s" % ", ".join(AVAILABLE_SETS)) "Available sets are %s" % ", ".join(AVAILABLE_SETS))
@cliutils.args("--regex", dest="regex", type=str, required=False, @cliutils.args("--regex", dest="regex", type=str, required=False,
help="Regular expression of test") help="Test name regular expression")
@cliutils.args("--tests-file", metavar="<path>", dest="tests_file", @cliutils.args("--tests-file", metavar="<path>", dest="tests_file",
type=str, required=False, type=str, required=False,
help="Path to a file with a list of Tempest tests") help="Path to a file with a list of Tempest tests")
@cliutils.args("--tempest-config", dest="tempest_config", type=str, @cliutils.args("--tempest-config", dest="tempest_config", type=str,
required=False, metavar="<path>", required=False, metavar="<path>",
help="User specified Tempest config file location") help="User-specified Tempest config file location")
@cliutils.args("--xfails-file", dest="xfails_file", type=str, @cliutils.args("--xfails-file", dest="xfails_file", type=str,
required=False, metavar="<path>", required=False, metavar="<path>",
help="Path to a file in YAML format with a list of Tempest " help="Path to a YAML file with a list of Tempest "
"tests that are expected to fail") "tests that are expected to fail")
@cliutils.args("--no-use", action="store_false", dest="do_use", @cliutils.args("--no-use", action="store_false", dest="do_use",
help="Don't set new task as default for future operations") help="Don't set the task as default for future operations")
@cliutils.args("--system-wide", dest="system_wide", @cliutils.args("--system-wide", dest="system_wide",
help="Don't create a virtual env when installing Tempest; " help="Don't create a virtual env when installing Tempest; "
"use the local env instead of the Tempest virtual env " "use the local env instead of the Tempest virtual env "
"when running the tests. Take notice that all Tempest " "when running the tests. Note that all Tempest "
"requirements have to be already installed in " "requirements have to be already installed in "
"the local env!", "the local env!",
required=False, action="store_true") required=False, action="store_true")
@ -172,7 +172,7 @@ class VerifyCommands(object):
self.use(verification["uuid"]) self.use(verification["uuid"])
def list(self): def list(self):
"""Display verifications table.""" """List verification runs."""
fields = ["UUID", "Deployment UUID", "Set name", "Tests", "Failures", fields = ["UUID", "Deployment UUID", "Set name", "Tests", "Failures",
"Created at", "Duration", "Status"] "Created at", "Duration", "Status"]
@ -189,14 +189,14 @@ class VerifyCommands(object):
"To start verification use:\nrally verify start")) "To start verification use:\nrally verify start"))
@cliutils.args("--uuid", type=str, dest="verification", @cliutils.args("--uuid", type=str, dest="verification",
help="UUID of a verification") help="UUID of a verification.")
@cliutils.args("--html", action="store_true", dest="output_html", @cliutils.args("--html", action="store_true", dest="output_html",
help="Display results in HTML format") help="Display results in HTML format.")
@cliutils.args("--json", action="store_true", dest="output_json", @cliutils.args("--json", action="store_true", dest="output_json",
help="Display results in JSON format") help="Display results in JSON format.")
@cliutils.args("--output-file", type=str, required=False, @cliutils.args("--output-file", type=str, required=False,
dest="output_file", metavar="<path>", dest="output_file", metavar="<path>",
help="Path to a file to save results") help="Path to a file to save results to.")
@envutils.with_default_verification_id @envutils.with_default_verification_id
@cliutils.suppress_warnings @cliutils.suppress_warnings
def results(self, verification=None, output_file=None, def results(self, verification=None, output_file=None,
@ -234,7 +234,7 @@ class VerifyCommands(object):
required=False, required=False,
help="UUID of a verification") help="UUID of a verification")
@cliutils.args("--sort-by", metavar="<query>", dest="sort_by", type=str, @cliutils.args("--sort-by", metavar="<query>", dest="sort_by", type=str,
required=False, required=False, choices=("name", "duration"),
help="Sort results by 'name' or 'duration'") help="Sort results by 'name' or 'duration'")
@cliutils.args("--detailed", dest="detailed", action="store_true", @cliutils.args("--detailed", dest="detailed", action="store_true",
required=False, required=False,
@ -247,12 +247,6 @@ class VerifyCommands(object):
:param sort_by: Sort results by 'name' or 'duration' :param sort_by: Sort results by 'name' or 'duration'
:param detailed: Display detailed errors of failed tests :param detailed: Display detailed errors of failed tests
""" """
try:
sortby_index = ("name", "duration").index(sort_by)
except ValueError:
print(_("Verification results can't be sorted by '%s'.") % sort_by)
return 1
try: try:
verification = api.Verification.get(verification) verification = api.Verification.get(verification)
tests = verification.get_results() tests = verification.get_results()
@ -270,6 +264,7 @@ class VerifyCommands(object):
results = tests["test_cases"] results = tests["test_cases"]
values = [utils.Struct(**results[test_name]) for test_name in results] values = [utils.Struct(**results[test_name]) for test_name in results]
sortby_index = ("name", "duration").index(sort_by)
cliutils.print_list(values, fields, sortby_index=sortby_index) cliutils.print_list(values, fields, sortby_index=sortby_index)
if detailed: if detailed:
@ -285,9 +280,9 @@ class VerifyCommands(object):
print(formatted_test) print(formatted_test)
@cliutils.args("--uuid", dest="verification", type=str, @cliutils.args("--uuid", dest="verification", type=str,
required=False, help="UUID of a verification") required=False, help="UUID of a verification.")
@cliutils.args("--sort-by", dest="sort_by", type=str, required=False, @cliutils.args("--sort-by", dest="sort_by", choices=("name", "duration"),
help="Sort results by 'name' or 'duration'") required=False, help="Sort results by 'name' or 'duration'")
@envutils.with_default_verification_id @envutils.with_default_verification_id
def detailed(self, verification=None, sort_by="name"): def detailed(self, verification=None, sort_by="name"):
"""Display results table of a verification with detailed errors. """Display results table of a verification with detailed errors.
@ -378,16 +373,16 @@ class VerifyCommands(object):
help="UUID or name of a deployment.") help="UUID or name of a deployment.")
@cliutils.args("--tempest-config", dest="tempest_config", type=str, @cliutils.args("--tempest-config", dest="tempest_config", type=str,
required=False, metavar="<path>", required=False, metavar="<path>",
help="User specified Tempest config file location") help="User-specified Tempest config file location")
@cliutils.args("--override", dest="override", @cliutils.args("--override", dest="override",
help="Override existing Tempest config file", help="Override existing Tempest config file",
required=False, action="store_true") required=False, action="store_true")
@envutils.with_default_deployment(cli_arg_name="deployment") @envutils.with_default_deployment(cli_arg_name="deployment")
def genconfig(self, deployment=None, tempest_config=None, override=False): def genconfig(self, deployment=None, tempest_config=None, override=False):
"""Generate configuration file of Tempest. """Generate Tempest configuration file.
:param deployment: UUID or name of a deployment :param deployment: UUID or name of a deployment
:param tempest_config: User specified Tempest config file location :param tempest_config: User-specified Tempest config file location
:param override: Whether or not to override existing Tempest :param override: Whether or not to override existing Tempest
config file config file
""" """
@ -400,7 +395,7 @@ class VerifyCommands(object):
@cliutils.args("--source", type=str, dest="source", required=False, @cliutils.args("--source", type=str, dest="source", required=False,
help="Path/URL to repo to clone Tempest from") help="Path/URL to repo to clone Tempest from")
@cliutils.args("--system-wide", dest="system_wide", @cliutils.args("--system-wide", dest="system_wide",
help="Don't create a virtual env for Tempest. Take notice " help="Don't create a virtual env for Tempest. Note "
"that all Tempest requirements have to be already " "that all Tempest requirements have to be already "
"installed in the local env!", "installed in the local env!",
required=False, action="store_true") required=False, action="store_true")
@ -422,7 +417,7 @@ class VerifyCommands(object):
help="UUID or name of a deployment.") help="UUID or name of a deployment.")
@envutils.with_default_deployment(cli_arg_name="deployment") @envutils.with_default_deployment(cli_arg_name="deployment")
def uninstall(self, deployment=None): def uninstall(self, deployment=None):
"""Remove deployment's local Tempest installation. """Remove the deployment's local Tempest installation.
:param deployment: UUID or name of a deployment :param deployment: UUID or name of a deployment
""" """
@ -437,7 +432,7 @@ class VerifyCommands(object):
@cliutils.args("--source", type=str, dest="source", required=False, @cliutils.args("--source", type=str, dest="source", required=False,
help="Path/URL to repo to clone Tempest from") help="Path/URL to repo to clone Tempest from")
@cliutils.args("--system-wide", dest="system_wide", @cliutils.args("--system-wide", dest="system_wide",
help="Don't create a virtual env for Tempest. Take notice " help="Don't create a virtual env for Tempest. Note "
"that all Tempest requirements have to be already " "that all Tempest requirements have to be already "
"installed in the local env!", "installed in the local env!",
required=False, action="store_true") required=False, action="store_true")