[cli] Small tweaks
- group subcommands of `rally verify` subcommand - put proper descirptions for rally categories - log deprecation warning on `rally deployment` commands execution - deprecate all --deployment arguments in favor of --env Change-Id: I94ed1f37e59ae266affe45fc7c8a5077923d40cb Signed-off-by: Andriy Kurilin <andr.kurilin@gmail.com>
This commit is contained in:
18 files changed
+459
-317
No files matched your search
@@ -53,6 +53,13 @@ Changed
|
||||
pyflakes and import-convention checks, while flake8 keeps the remaining
|
||||
hacking and Rally-specific rules.
|
||||
|
||||
Deprecated
|
||||
~~~~~~~~~~
|
||||
|
||||
* The ``--deployment`` / ``--deployment-id`` options of ``rally task`` and
|
||||
``rally verify`` are renamed to ``--env``. The old names still work but now
|
||||
print a deprecation warning -- switch to ``--env``.
|
||||
|
||||
Removed
|
||||
~~~~~~~
|
||||
|
||||
@@ -63,6 +70,11 @@ Removed
|
||||
|
||||
* Support for Python 3.9
|
||||
|
||||
* ``rally deployment create --fromenv`` no longer special-cases
|
||||
rally-openstack ``<= 1.4.0`` (it used to drop ``OS_KEY``/``https_key`` for
|
||||
those). That release is ~7 years old and predates every currently supported
|
||||
Python -- old rally-openstack only went up to py37 -- so the shim is gone.
|
||||
|
||||
Fixed
|
||||
~~~~~
|
||||
|
||||
|
||||
+14
-14
@@ -46,35 +46,35 @@ _rally()
|
||||
OPTS["task_abort"]="--soft"
|
||||
OPTS["task_delete"]="--force"
|
||||
OPTS["task_detailed"]="--iterations-data --filter-by"
|
||||
OPTS["task_export"]="--type --to --deployment"
|
||||
OPTS["task_import"]="--file --deployment --tag"
|
||||
OPTS["task_list"]="--deployment --all-deployments --status --tag --uuids-only"
|
||||
OPTS["task_report"]="--out --open --html --html-static --json --deployment"
|
||||
OPTS["task_restart"]="--deployment --scenario --tag --no-use --abort-on-sla-failure"
|
||||
OPTS["task_export"]="--type --to --env"
|
||||
OPTS["task_import"]="--file --env --tag"
|
||||
OPTS["task_list"]="--env --all-envs --status --tag --uuids-only"
|
||||
OPTS["task_report"]="--out --open --html --html-static --json --env"
|
||||
OPTS["task_restart"]="--env --scenario --tag --no-use --abort-on-sla-failure"
|
||||
OPTS["task_results"]=""
|
||||
OPTS["task_sla-check"]="--json"
|
||||
OPTS["task_start"]="--deployment --task-args --task-args-file --tag --no-use --abort-on-sla-failure"
|
||||
OPTS["task_start"]="--env --task-args --task-args-file --tag --no-use --abort-on-sla-failure"
|
||||
OPTS["task_status"]=""
|
||||
OPTS["task_trends"]="--out --open --html-static"
|
||||
OPTS["task_use"]=""
|
||||
OPTS["task_validate"]="--deployment --task-args --task-args-file"
|
||||
OPTS["task_validate"]="--env --task-args --task-args-file"
|
||||
OPTS["verify_add-verifier-ext"]="--source --extra-settings"
|
||||
OPTS["verify_configure-verifier"]="--deployment-id --reconfigure --extend --override --show"
|
||||
OPTS["verify_configure-verifier"]="--env --reconfigure --extend --override --show"
|
||||
OPTS["verify_create-verifier"]="--name --type --platform --source --system-wide --extra-settings --no-use"
|
||||
OPTS["verify_delete"]=""
|
||||
OPTS["verify_delete-verifier"]="--deployment-id --force"
|
||||
OPTS["verify_delete-verifier"]="--env --force"
|
||||
OPTS["verify_delete-verifier-ext"]="--name"
|
||||
OPTS["verify_import"]="--deployment-id --file --run-args --no-use"
|
||||
OPTS["verify_list"]="--id --deployment-id --tag --status"
|
||||
OPTS["verify_import"]="--env --file --run-args --no-use"
|
||||
OPTS["verify_list"]="--id --env --tag --status"
|
||||
OPTS["verify_list-plugins"]="--platform"
|
||||
OPTS["verify_list-verifier-exts"]=""
|
||||
OPTS["verify_list-verifier-tests"]="--pattern"
|
||||
OPTS["verify_list-verifiers"]="--status"
|
||||
OPTS["verify_report"]="--type --to --open"
|
||||
OPTS["verify_rerun"]="--deployment-id --failed --tag --concurrency --detailed --no-use"
|
||||
OPTS["verify_rerun"]="--env --failed --tag --concurrency --detailed --no-use"
|
||||
OPTS["verify_show"]="--sort-by --detailed"
|
||||
OPTS["verify_show-verifier"]=""
|
||||
OPTS["verify_start"]="--deployment-id --tag --pattern --concurrency --load-list --skip-list --xfail-list --detailed --no-use"
|
||||
OPTS["verify_start"]="--env --tag --pattern --concurrency --load-list --skip-list --xfail-list --detailed --no-use"
|
||||
OPTS["verify_update-verifier"]="--update-venv --system-wide --no-system-wide"
|
||||
OPTS["verify_use"]=""
|
||||
OPTS["verify_use-verifier"]=""
|
||||
@@ -105,4 +105,4 @@ _rally()
|
||||
return 0
|
||||
}
|
||||
|
||||
complete -o filenames -F _rally rally
|
||||
complete -o filenames -F _rally rally
|
||||
+93
-7
@@ -29,6 +29,10 @@ import typer
|
||||
import typer.core
|
||||
|
||||
from rally.cli import cliutils
|
||||
from rally.common import logging
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
|
||||
if t.TYPE_CHECKING:
|
||||
@@ -67,6 +71,81 @@ class ArgumentOrKeyword(typer.models.ArgumentInfo):
|
||||
self.kw_decls = kw_decls
|
||||
|
||||
|
||||
class DeprecatedAlias(typer.models.OptionInfo):
|
||||
"""A typer Option whose trailing flag names are deprecated aliases.
|
||||
|
||||
Declare the preferred flag first, then the deprecated one(s)::
|
||||
|
||||
deployment: t.Annotated[
|
||||
str,
|
||||
DeprecatedAlias("--env", deprecated=["--deployment"], help="...")
|
||||
]
|
||||
|
||||
This is for value-taking options; for a boolean flag just declare two typer
|
||||
options (the deprecated one ``hidden=True``) and warn in the command body.
|
||||
|
||||
Both flags keep working; passing a deprecated one logs a warning naming the
|
||||
preferred flag. The deprecated aliases must be listed explicitly via
|
||||
``deprecated=``; ``param_decls`` holds only the preferred flag(s). Only
|
||||
the preferred flag lands on the built option (so the deprecated one stays
|
||||
out of ``--help``); :func:`install` registers each deprecated alias as a
|
||||
separate parser option feeding the same destination and wraps it to emit
|
||||
the warning (a plain callback cannot tell which alias was typed -- both
|
||||
share one handler otherwise).
|
||||
"""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*param_decls: str,
|
||||
deprecated: t.Iterable[str],
|
||||
default: t.Any = ...,
|
||||
**kwargs: t.Any
|
||||
) -> None:
|
||||
# ``default=...`` mirrors ``typer.Option`` (required unless the
|
||||
# annotated parameter carries its own default). Only the preferred
|
||||
# flag(s) reach typer, keeping the deprecated ones out of ``--help``.
|
||||
super().__init__(default=default, param_decls=list(param_decls),
|
||||
**kwargs)
|
||||
self.deprecated = list(deprecated)
|
||||
# the flag we steer users towards must never be a deprecated one
|
||||
self.preferred = next(d for d in param_decls
|
||||
if d not in self.deprecated)
|
||||
|
||||
|
||||
def _patch_deprecated(
|
||||
param: "typer.core.TyperOption",
|
||||
info: DeprecatedAlias
|
||||
) -> None:
|
||||
"""Register the deprecated aliases and warn when one is used."""
|
||||
original_add_to_parser = param.add_to_parser
|
||||
|
||||
def add_to_parser(
|
||||
parser: "typer._click.core._OptionParser",
|
||||
ctx: "typer._click.core.Context"
|
||||
) -> None:
|
||||
original_add_to_parser(parser, ctx)
|
||||
# a separate parser option (own handler) feeding the same destination:
|
||||
# requiredness stays satisfied since both write ``param.name``.
|
||||
action = "append" if param.nargs == -1 else "store"
|
||||
parser.add_option(param, info.deprecated, param.name,
|
||||
action=action, nargs=1)
|
||||
for opt in info.deprecated:
|
||||
handler = parser._long_opt.get(opt) or parser._short_opt.get(opt)
|
||||
if handler is None:
|
||||
continue
|
||||
original_process = handler.process
|
||||
|
||||
def process(value: t.Any, state: t.Any,
|
||||
_process: t.Any = original_process,
|
||||
_opt: str = opt) -> None:
|
||||
LOG.warning(f"The `{_opt}` option is deprecated; use "
|
||||
f"`{info.preferred}` instead.")
|
||||
_process(value, state)
|
||||
handler.process = process # type: ignore[method-assign]
|
||||
|
||||
param.add_to_parser = add_to_parser # type: ignore[method-assign]
|
||||
|
||||
|
||||
def _patch_param(
|
||||
param: "typer.core.TyperOption",
|
||||
kw_decls: t.Sequence[str]
|
||||
@@ -99,18 +178,25 @@ def _patch_param(
|
||||
|
||||
|
||||
def install(command: typer.core.TyperGroup | typer.core.TyperCommand) -> None:
|
||||
"""Wire up every :class:`ArgumentOrKeyword` in a built command tree."""
|
||||
"""Wire up :class:`ArgumentOrKeyword` and :class:`DeprecatedAlias` params.
|
||||
|
||||
Both are declared as annotation metadata; this walks the built command tree
|
||||
and patches the corresponding parser options in place.
|
||||
"""
|
||||
for _path, leaf, params in cliutils.iter_commands(command):
|
||||
if leaf.callback is None:
|
||||
continue
|
||||
signature = inspect.signature(inspect.unwrap(leaf.callback))
|
||||
marks = {}
|
||||
kw_marks = {}
|
||||
deprecated_marks = {}
|
||||
for name, parameter in signature.parameters.items():
|
||||
for meta in getattr(parameter.annotation, "__metadata__", ()):
|
||||
if isinstance(meta, ArgumentOrKeyword):
|
||||
marks[name] = meta.kw_decls
|
||||
if not marks:
|
||||
continue
|
||||
kw_marks[name] = meta.kw_decls
|
||||
elif isinstance(meta, DeprecatedAlias):
|
||||
deprecated_marks[name] = meta
|
||||
for param in params:
|
||||
if param.name in marks:
|
||||
_patch_param(param, marks[param.name])
|
||||
if param.name in kw_marks:
|
||||
_patch_param(param, kw_marks[param.name])
|
||||
if param.name in deprecated_marks:
|
||||
_patch_deprecated(param, deprecated_marks[param.name])
|
||||
@@ -94,6 +94,7 @@ def generate() -> str:
|
||||
and name not in ("--help", "--version"))
|
||||
)
|
||||
for p in params
|
||||
if not getattr(p, "hidden", False)
|
||||
))
|
||||
|
||||
lines.append(f' OPTS["{category}_{name}"]="{opts}"\n')
|
||||
|
||||
@@ -48,6 +48,20 @@ def get_api() -> "API":
|
||||
return _api.get()
|
||||
|
||||
|
||||
_help_requested: "contextvars.ContextVar[bool]" = contextvars.ContextVar(
|
||||
"rally_help_requested", default=False)
|
||||
|
||||
|
||||
def set_help_requested(value: bool) -> None:
|
||||
"""Record whether the current invocation is a ``--help`` call."""
|
||||
_help_requested.set(value)
|
||||
|
||||
|
||||
def is_help_requested() -> bool:
|
||||
"""Return True if the current invocation only renders help."""
|
||||
return _help_requested.get()
|
||||
|
||||
|
||||
def iter_commands(
|
||||
command: "typer._click.core.Command",
|
||||
) -> t.Iterator[
|
||||
|
||||
@@ -22,7 +22,7 @@ from rally.common import db
|
||||
|
||||
db_app = typer.Typer(
|
||||
name="db", no_args_is_help=False,
|
||||
help="Set of commands that allow you to manage Rally's database.")
|
||||
help="Create, upgrade and inspect the database.")
|
||||
|
||||
|
||||
def _print_connection(show_creds: bool) -> None:
|
||||
|
||||
@@ -35,9 +35,20 @@ from rally.common import utils
|
||||
from rally.env import env_mgr
|
||||
|
||||
|
||||
LOG = logging.getLogger(__name__)
|
||||
|
||||
deployment_app = typer.Typer(
|
||||
name="deployment", no_args_is_help=False,
|
||||
help="Set of commands that allow you to manage deployments.")
|
||||
help="Legacy environments (superseded by env).")
|
||||
|
||||
|
||||
@deployment_app.callback()
|
||||
def _deprecation_warning(ctx: typer.Context) -> None:
|
||||
# warn once per invocation, but not when only rendering help or when no
|
||||
# subcommand is actually run
|
||||
if ctx.invoked_subcommand and not cliutils.is_help_requested():
|
||||
LOG.warning("The `deployment` commands are deprecated; use the `env` "
|
||||
"commands instead.")
|
||||
|
||||
|
||||
def _list_deployments(api: API,
|
||||
@@ -186,16 +197,6 @@ def create(
|
||||
if fromenv:
|
||||
result = env_mgr.EnvManager.create_spec_from_sys_environ()
|
||||
config = result["spec"]
|
||||
if "existing@openstack" in config:
|
||||
# NOTE(andreykurilin): if we are here it means that
|
||||
# rally-openstack package is installed
|
||||
import rally_openstack # type: ignore[import-not-found]
|
||||
if rally_openstack.__version_tuple__ <= (1, 4, 0):
|
||||
if ("https_key" in config["existing@openstack"]
|
||||
and config["existing@openstack"]["https_key"]):
|
||||
print("WARNING: OS_KEY is ignored due to old version "
|
||||
"of rally-openstack package.")
|
||||
config["existing@openstack"].pop("https_key")
|
||||
else:
|
||||
if not filename:
|
||||
config = {}
|
||||
|
||||
@@ -28,7 +28,7 @@ from rally.env import env_mgr
|
||||
|
||||
env_app = typer.Typer(
|
||||
name="env", no_args_is_help=False,
|
||||
help="Set of commands that allow you to manage envs.")
|
||||
help="Environments Rally tests against.")
|
||||
|
||||
YES = u":-)"
|
||||
NO = u":-("
|
||||
|
||||
@@ -27,7 +27,7 @@ from rally.common.plugin import plugin
|
||||
|
||||
plugin_app = typer.Typer(
|
||||
name="plugin", no_args_is_help=False,
|
||||
help="Set of commands that allow you to manage Rally plugins.")
|
||||
help="Discover and inspect installed plugins.")
|
||||
|
||||
|
||||
def _print_plugins_list(plugin_list: list) -> None:
|
||||
|
||||
+66
-44
@@ -45,7 +45,7 @@ LOG = logging.getLogger(__name__)
|
||||
|
||||
task_app = typer.Typer(
|
||||
name="task", no_args_is_help=False,
|
||||
help="Set of commands that allow you to manage tasks and results.")
|
||||
help="Run scenario tests and benchmarks.")
|
||||
|
||||
|
||||
class FailedToLoadTask(exceptions.RallyException):
|
||||
@@ -435,11 +435,13 @@ def validate(
|
||||
help="Path to the input task file (or '-' for stdin)."
|
||||
)
|
||||
],
|
||||
deployment: t.Annotated[
|
||||
env: t.Annotated[
|
||||
str,
|
||||
typer.Option(
|
||||
argutils.DeprecatedAlias(
|
||||
"--env",
|
||||
deprecated=["--deployment"],
|
||||
envvar=envutils.ENV_ENV,
|
||||
help="UUID or name of a deployment."
|
||||
help="UUID or name of the environment."
|
||||
)
|
||||
],
|
||||
task_args: t.Annotated[
|
||||
@@ -471,7 +473,7 @@ def validate(
|
||||
task = _load_and_validate_task(api, task_file, raw_args=task_args,
|
||||
args_file=task_args_file)
|
||||
|
||||
api.task.validate(deployment=deployment, config=task)
|
||||
api.task.validate(deployment=env, config=task)
|
||||
|
||||
print("Input Task is valid :)")
|
||||
|
||||
@@ -486,11 +488,13 @@ def start(
|
||||
help="Path to the input task file (or '-' for stdin)."
|
||||
)
|
||||
],
|
||||
deployment: t.Annotated[
|
||||
env: t.Annotated[
|
||||
str,
|
||||
typer.Option(
|
||||
argutils.DeprecatedAlias(
|
||||
"--env",
|
||||
deprecated=["--deployment"],
|
||||
envvar=envutils.ENV_ENV,
|
||||
help="UUID or name of a deployment."
|
||||
help="UUID or name of the environment."
|
||||
)
|
||||
],
|
||||
task_args: t.Annotated[
|
||||
@@ -544,7 +548,7 @@ def start(
|
||||
args_file=task_args_file)
|
||||
print("Running Rally version", version.version_string())
|
||||
|
||||
rc = _start_task(api, deployment, task_config=input_task, tags=tags,
|
||||
rc = _start_task(api, env, task_config=input_task, tags=tags,
|
||||
do_use=not no_use,
|
||||
abort_on_sla_failure=abort_on_sla_failure)
|
||||
if rc:
|
||||
@@ -554,11 +558,13 @@ def start(
|
||||
@task_app.command()
|
||||
@plugins.ensure_plugins_are_loaded
|
||||
def restart(
|
||||
deployment: t.Annotated[
|
||||
env: t.Annotated[
|
||||
str,
|
||||
typer.Option(
|
||||
argutils.DeprecatedAlias(
|
||||
"--env",
|
||||
deprecated=["--deployment"],
|
||||
envvar=envutils.ENV_ENV,
|
||||
help="UUID or name of a deployment."
|
||||
help="UUID or name of the environment."
|
||||
)
|
||||
],
|
||||
task_id: t.Annotated[
|
||||
@@ -636,7 +642,7 @@ def restart(
|
||||
"workloads": workloads})
|
||||
|
||||
if retask["subtasks"]:
|
||||
rc = _start_task(api, deployment, retask, tags=tags,
|
||||
rc = _start_task(api, env, retask, tags=tags,
|
||||
do_use=not no_use,
|
||||
abort_on_sla_failure=abort_on_sla_failure)
|
||||
if rc:
|
||||
@@ -752,25 +758,33 @@ def results(
|
||||
|
||||
@task_app.command(name="list")
|
||||
def list_(
|
||||
deployment: t.Annotated[
|
||||
env: t.Annotated[
|
||||
str,
|
||||
typer.Option(
|
||||
argutils.DeprecatedAlias(
|
||||
"--env",
|
||||
deprecated=["--deployment"],
|
||||
envvar=envutils.ENV_ENV,
|
||||
help="UUID or name of a deployment."
|
||||
help="UUID or name of the environment."
|
||||
)
|
||||
],
|
||||
all_envs: t.Annotated[
|
||||
bool,
|
||||
typer.Option(
|
||||
"--all-envs",
|
||||
help="List tasks from all environments."
|
||||
)
|
||||
] = False,
|
||||
all_deployments: t.Annotated[
|
||||
bool,
|
||||
typer.Option(
|
||||
"--all-deployments",
|
||||
help="List tasks from all deployments."
|
||||
hidden=True
|
||||
)
|
||||
] = False,
|
||||
status: t.Annotated[
|
||||
str | None,
|
||||
status: t.Annotated[ # type: ignore[valid-type]
|
||||
t.Literal[tuple(consts.TaskStatus)] | None,
|
||||
typer.Option(
|
||||
help="List tasks with specified status. Available statuses: %s"
|
||||
% ", ".join(consts.TaskStatus)
|
||||
help="List tasks with the specified status."
|
||||
)
|
||||
] = None,
|
||||
tags: t.Annotated[
|
||||
@@ -790,24 +804,25 @@ def list_(
|
||||
) -> None:
|
||||
"""List tasks, started and finished.
|
||||
|
||||
Displayed tasks can be filtered by status or deployment. By
|
||||
Displayed tasks can be filtered by status or environment. By
|
||||
default 'rally task list' will display tasks from the active
|
||||
deployment without filtering by status.
|
||||
environment without filtering by status.
|
||||
"""
|
||||
api = cliutils.get_api()
|
||||
filters: dict = {}
|
||||
headers = ["UUID", "Deployment name", "Created at", "Load duration",
|
||||
headers = ["UUID", "Environment", "Created at", "Load duration",
|
||||
"Status", "Tag(s)"]
|
||||
|
||||
if status in consts.TaskStatus:
|
||||
if status:
|
||||
filters["status"] = status
|
||||
elif status:
|
||||
print("Error: Invalid task status '%s'.\nAvailable statuses: %s"
|
||||
% (status, ", ".join(consts.TaskStatus)), file=sys.stderr)
|
||||
raise typer.Exit(code=1)
|
||||
|
||||
if not all_deployments:
|
||||
filters["deployment"] = deployment
|
||||
if all_deployments:
|
||||
LOG.warning("The `--all-deployments` option is deprecated; use "
|
||||
"`--all-envs` instead.")
|
||||
all_envs = True
|
||||
|
||||
if not all_envs:
|
||||
filters["deployment"] = env
|
||||
|
||||
if tags:
|
||||
filters["tags"] = tags
|
||||
@@ -825,6 +840,7 @@ def list_(
|
||||
|
||||
formatters = {
|
||||
"Tag(s)": tags_formatter,
|
||||
"Environment": lambda t: t["deployment_name"],
|
||||
"Load duration": cliutils.pretty_float_formatter(
|
||||
"task_duration", 3),
|
||||
"Created at": lambda t: t["created_at"].replace("T", " ")
|
||||
@@ -931,10 +947,12 @@ def report(
|
||||
help="Generate JSON report."
|
||||
)
|
||||
] = False,
|
||||
deployment: t.Annotated[
|
||||
env: t.Annotated[
|
||||
str | None,
|
||||
typer.Option(
|
||||
help="Report all tasks with defined deployment"
|
||||
argutils.DeprecatedAlias(
|
||||
"--env",
|
||||
deprecated=["--deployment"],
|
||||
help="Report all tasks for the defined environment."
|
||||
)
|
||||
] = None,
|
||||
) -> None:
|
||||
@@ -942,7 +960,7 @@ def report(
|
||||
out_format = ("json" if to_json
|
||||
else "html-static" if html_static else "html")
|
||||
_export(cliutils.get_api(), tasks=tasks, output_type=out_format,
|
||||
output_dest=out, open_it=open_it, deployment=deployment)
|
||||
output_dest=out, open_it=open_it, deployment=env)
|
||||
|
||||
|
||||
@task_app.command()
|
||||
@@ -1070,16 +1088,18 @@ def export(
|
||||
"the report type."
|
||||
)
|
||||
] = None,
|
||||
deployment: t.Annotated[
|
||||
env: t.Annotated[
|
||||
str | None,
|
||||
typer.Option(
|
||||
help="Report all tasks with defined deployment"
|
||||
argutils.DeprecatedAlias(
|
||||
"--env",
|
||||
deprecated=["--deployment"],
|
||||
help="Report all tasks for the defined environment."
|
||||
)
|
||||
] = None,
|
||||
) -> None:
|
||||
"""Export task results to the custom task's exporting system."""
|
||||
_export(cliutils.get_api(), tasks=tasks, output_type=output_type,
|
||||
output_dest=output_dest, deployment=deployment)
|
||||
output_dest=output_dest, deployment=env)
|
||||
|
||||
|
||||
@task_app.command(name="import")
|
||||
@@ -1092,11 +1112,13 @@ def import_results(
|
||||
help="JSON file with task results"
|
||||
)
|
||||
],
|
||||
deployment: t.Annotated[
|
||||
env: t.Annotated[
|
||||
str,
|
||||
typer.Option(
|
||||
argutils.DeprecatedAlias(
|
||||
"--env",
|
||||
deprecated=["--deployment"],
|
||||
envvar=envutils.ENV_ENV,
|
||||
help="UUID or name of a deployment."
|
||||
help="UUID or name of the environment."
|
||||
)
|
||||
],
|
||||
tags: t.Annotated[
|
||||
@@ -1107,12 +1129,12 @@ def import_results(
|
||||
)
|
||||
] = None,
|
||||
) -> None:
|
||||
"""Import json results of a test into rally database."""
|
||||
"""Import JSON results of a test into the Rally database."""
|
||||
if os.path.exists(os.path.expanduser(task_file)):
|
||||
api = cliutils.get_api()
|
||||
tasks_results = task_results_loader.load(task_file)
|
||||
for task_results in tasks_results:
|
||||
task = api.task.import_results(deployment=deployment,
|
||||
task = api.task.import_results(deployment=env,
|
||||
task_results=task_results,
|
||||
tags=tags)
|
||||
print("Task UUID: %s." % task["uuid"])
|
||||
|
||||
@@ -24,6 +24,7 @@ import webbrowser
|
||||
|
||||
import typer
|
||||
|
||||
from rally import consts
|
||||
from rally import exceptions
|
||||
from rally import plugins
|
||||
from rally.api import API
|
||||
@@ -38,8 +39,8 @@ TIME_FORMAT = "%Y-%m-%dT%H:%M:%S"
|
||||
|
||||
LIST_VERIFIERS_HINT = ("HINT: You can list all verifiers, executing "
|
||||
"command `rally verify list-verifiers`.")
|
||||
LIST_DEPLOYMENTS_HINT = ("HINT: You can list all deployments, executing "
|
||||
"command `rally deployment list`.")
|
||||
LIST_ENVS_HINT = ("HINT: You can list all environments, executing "
|
||||
"command `rally env list`.")
|
||||
LIST_VERIFICATIONS_HINT = ("HINT: You can list all verifications, executing "
|
||||
"command `rally verify list`.")
|
||||
|
||||
@@ -47,9 +48,14 @@ DEFAULT_REPORT_TYPES = ("HTML", "HTML-Static", "JSON", "JUnit-XML")
|
||||
|
||||
ACTIVE = u":-)"
|
||||
|
||||
# help panels grouping the subcommands in ``rally verify --help``
|
||||
VERIFIER = "Verifier management"
|
||||
VERIFIER_EXT = "Verifier extensions"
|
||||
VERIFICATION = "Verifications"
|
||||
|
||||
verify_app = typer.Typer(
|
||||
name="verify", no_args_is_help=False,
|
||||
help="Verify an OpenStack cloud via a verifier.")
|
||||
help="Run external verifier test suites.")
|
||||
|
||||
|
||||
def _print_totals(totals: dict) -> None:
|
||||
@@ -134,7 +140,7 @@ def list_plugins(
|
||||
normalize_field_names=True)
|
||||
|
||||
|
||||
@verify_app.command(name="create-verifier")
|
||||
@verify_app.command(name="create-verifier", rich_help_panel=VERIFIER)
|
||||
@plugins.ensure_plugins_are_loaded
|
||||
def create_verifier(
|
||||
name: t.Annotated[
|
||||
@@ -206,7 +212,7 @@ def create_verifier(
|
||||
_use_verifier(api, verifier_uuid)
|
||||
|
||||
|
||||
@verify_app.command(name="use-verifier")
|
||||
@verify_app.command(name="use-verifier", rich_help_panel=VERIFIER)
|
||||
def use_verifier(
|
||||
verifier_id: t.Annotated[
|
||||
str,
|
||||
@@ -220,11 +226,11 @@ def use_verifier(
|
||||
_use_verifier(cliutils.get_api(), verifier_id)
|
||||
|
||||
|
||||
@verify_app.command(name="list-verifiers")
|
||||
@verify_app.command(name="list-verifiers", rich_help_panel=VERIFIER)
|
||||
@plugins.ensure_plugins_are_loaded
|
||||
def list_verifiers(
|
||||
status: t.Annotated[
|
||||
str | None,
|
||||
status: t.Annotated[ # type: ignore[valid-type]
|
||||
t.Literal[tuple(consts.VerifierStatus)] | None,
|
||||
typer.Option(
|
||||
help="Status to filter verifiers by."
|
||||
)
|
||||
@@ -251,7 +257,7 @@ def list_verifiers(
|
||||
"command `rally verify create-verifier`.")
|
||||
|
||||
|
||||
@verify_app.command(name="show-verifier")
|
||||
@verify_app.command(name="show-verifier", rich_help_panel=VERIFIER)
|
||||
@plugins.ensure_plugins_are_loaded
|
||||
def show_verifier(
|
||||
verifier_id: t.Annotated[
|
||||
@@ -289,7 +295,7 @@ def show_verifier(
|
||||
"virtual environment, you do it at your own risk!")
|
||||
|
||||
|
||||
@verify_app.command(name="delete-verifier")
|
||||
@verify_app.command(name="delete-verifier", rich_help_panel=VERIFIER)
|
||||
@plugins.ensure_plugins_are_loaded
|
||||
def delete_verifier(
|
||||
verifier_id: t.Annotated[
|
||||
@@ -299,13 +305,14 @@ def delete_verifier(
|
||||
help="Verifier name or UUID. " + LIST_VERIFIERS_HINT
|
||||
)
|
||||
],
|
||||
deployment: t.Annotated[
|
||||
env: t.Annotated[
|
||||
str | None,
|
||||
typer.Option(
|
||||
"--deployment-id",
|
||||
help="Deployment name or UUID. If specified, only the "
|
||||
"deployment-specific data will be deleted for verifier. "
|
||||
+ LIST_DEPLOYMENTS_HINT
|
||||
argutils.DeprecatedAlias(
|
||||
"--env",
|
||||
deprecated=["--deployment-id"],
|
||||
help="Environment name or UUID. If specified, only the "
|
||||
"environment-specific data will be deleted for verifier. "
|
||||
+ LIST_ENVS_HINT
|
||||
)
|
||||
] = None,
|
||||
force: t.Annotated[
|
||||
@@ -321,11 +328,11 @@ def delete_verifier(
|
||||
) -> None:
|
||||
"""Delete a verifier."""
|
||||
api = cliutils.get_api()
|
||||
api.verifier.delete(verifier_id=verifier_id, deployment_id=deployment,
|
||||
api.verifier.delete(verifier_id=verifier_id, deployment_id=env,
|
||||
force=force)
|
||||
|
||||
|
||||
@verify_app.command(name="update-verifier")
|
||||
@verify_app.command(name="update-verifier", rich_help_panel=VERIFIER)
|
||||
@plugins.ensure_plugins_are_loaded
|
||||
def update_verifier(
|
||||
verifier_id: t.Annotated[
|
||||
@@ -394,7 +401,7 @@ def update_verifier(
|
||||
"command to update the config file.")
|
||||
|
||||
|
||||
@verify_app.command(name="configure-verifier")
|
||||
@verify_app.command(name="configure-verifier", rich_help_panel=VERIFIER)
|
||||
@plugins.ensure_plugins_are_loaded
|
||||
def configure_verifier(
|
||||
verifier_id: t.Annotated[
|
||||
@@ -405,12 +412,13 @@ def configure_verifier(
|
||||
help="Verifier name or UUID. " + LIST_VERIFIERS_HINT
|
||||
)
|
||||
],
|
||||
deployment: t.Annotated[
|
||||
env: t.Annotated[
|
||||
str,
|
||||
typer.Option(
|
||||
"--deployment-id",
|
||||
argutils.DeprecatedAlias(
|
||||
"--env",
|
||||
deprecated=["--deployment-id"],
|
||||
envvar=envutils.ENV_ENV,
|
||||
help="Deployment name or UUID. " + LIST_DEPLOYMENTS_HINT
|
||||
help="Environment name or UUID. " + LIST_ENVS_HINT
|
||||
)
|
||||
],
|
||||
reconfigure: t.Annotated[
|
||||
@@ -463,7 +471,7 @@ def configure_verifier(
|
||||
with open(new_configuration) as f:
|
||||
config = f.read()
|
||||
api.verifier.override_configuration(verifier_id=verifier_id,
|
||||
deployment_id=deployment,
|
||||
deployment_id=env,
|
||||
new_configuration=config)
|
||||
else:
|
||||
options: object = extra_options
|
||||
@@ -484,7 +492,7 @@ def configure_verifier(
|
||||
options = yaml.safe_load(extra_options)
|
||||
|
||||
config = api.verifier.configure(verifier=verifier_id,
|
||||
deployment_id=deployment,
|
||||
deployment_id=env,
|
||||
extra_options=options,
|
||||
reconfigure=reconfigure)
|
||||
|
||||
@@ -492,7 +500,7 @@ def configure_verifier(
|
||||
print("\n%s\n" % config.strip())
|
||||
|
||||
|
||||
@verify_app.command(name="list-verifier-tests")
|
||||
@verify_app.command(name="list-verifier-tests", rich_help_panel=VERIFIER)
|
||||
@plugins.ensure_plugins_are_loaded
|
||||
def list_verifier_tests(
|
||||
verifier_id: t.Annotated[
|
||||
@@ -522,7 +530,7 @@ def list_verifier_tests(
|
||||
print("No tests found.")
|
||||
|
||||
|
||||
@verify_app.command(name="add-verifier-ext")
|
||||
@verify_app.command(name="add-verifier-ext", rich_help_panel=VERIFIER_EXT)
|
||||
@plugins.ensure_plugins_are_loaded
|
||||
def add_verifier_ext(
|
||||
verifier_id: t.Annotated[
|
||||
@@ -561,7 +569,7 @@ def add_verifier_ext(
|
||||
version=version, extra_settings=extra)
|
||||
|
||||
|
||||
@verify_app.command(name="list-verifier-exts")
|
||||
@verify_app.command(name="list-verifier-exts", rich_help_panel=VERIFIER_EXT)
|
||||
@plugins.ensure_plugins_are_loaded
|
||||
def list_verifier_exts(
|
||||
verifier_id: t.Annotated[
|
||||
@@ -586,7 +594,7 @@ def list_verifier_exts(
|
||||
"extension, using command `rally verify add-verifier-ext`.")
|
||||
|
||||
|
||||
@verify_app.command(name="delete-verifier-ext")
|
||||
@verify_app.command(name="delete-verifier-ext", rich_help_panel=VERIFIER_EXT)
|
||||
@plugins.ensure_plugins_are_loaded
|
||||
def delete_verifier_ext(
|
||||
verifier_id: t.Annotated[
|
||||
@@ -609,7 +617,7 @@ def delete_verifier_ext(
|
||||
api.verifier.delete_extension(verifier_id=verifier_id, name=name)
|
||||
|
||||
|
||||
@verify_app.command(name="start")
|
||||
@verify_app.command(name="start", rich_help_panel=VERIFICATION)
|
||||
@plugins.ensure_plugins_are_loaded
|
||||
def start(
|
||||
verifier_id: t.Annotated[
|
||||
@@ -620,12 +628,13 @@ def start(
|
||||
help="Verifier name or UUID. " + LIST_VERIFIERS_HINT
|
||||
)
|
||||
],
|
||||
deployment: t.Annotated[
|
||||
env: t.Annotated[
|
||||
str,
|
||||
typer.Option(
|
||||
"--deployment-id",
|
||||
argutils.DeprecatedAlias(
|
||||
"--env",
|
||||
deprecated=["--deployment-id"],
|
||||
envvar=envutils.ENV_ENV,
|
||||
help="Deployment name or UUID. " + LIST_DEPLOYMENTS_HINT
|
||||
help="Environment name or UUID. " + LIST_ENVS_HINT
|
||||
)
|
||||
],
|
||||
tags: t.Annotated[
|
||||
@@ -729,7 +738,7 @@ def start(
|
||||
|
||||
try:
|
||||
results = api.verification.start(
|
||||
verifier_id=verifier_id, deployment_id=deployment,
|
||||
verifier_id=verifier_id, deployment_id=env,
|
||||
tags=tags, **run_args)
|
||||
verification_uuid = results["verification"]["uuid"]
|
||||
except exceptions.DeploymentNotFinishedStatus as e:
|
||||
@@ -753,7 +762,7 @@ def start(
|
||||
raise typer.Exit(code=3)
|
||||
|
||||
|
||||
@verify_app.command(name="use")
|
||||
@verify_app.command(name="use", rich_help_panel=VERIFICATION)
|
||||
def use(
|
||||
verification_uuid: t.Annotated[
|
||||
str,
|
||||
@@ -767,7 +776,7 @@ def use(
|
||||
_use(cliutils.get_api(), verification_uuid)
|
||||
|
||||
|
||||
@verify_app.command(name="rerun")
|
||||
@verify_app.command(name="rerun", rich_help_panel=VERIFICATION)
|
||||
@plugins.ensure_plugins_are_loaded
|
||||
def rerun(
|
||||
verification_uuid: t.Annotated[
|
||||
@@ -778,12 +787,13 @@ def rerun(
|
||||
help="Verification UUID. " + LIST_VERIFICATIONS_HINT
|
||||
)
|
||||
],
|
||||
deployment: t.Annotated[
|
||||
env: t.Annotated[
|
||||
str,
|
||||
typer.Option(
|
||||
"--deployment-id",
|
||||
argutils.DeprecatedAlias(
|
||||
"--env",
|
||||
deprecated=["--deployment-id"],
|
||||
envvar=envutils.ENV_ENV,
|
||||
help="Deployment name or UUID. " + LIST_DEPLOYMENTS_HINT
|
||||
help="Environment name or UUID. " + LIST_ENVS_HINT
|
||||
)
|
||||
],
|
||||
failed: t.Annotated[
|
||||
@@ -827,7 +837,7 @@ def rerun(
|
||||
"""Rerun tests from a verification for a specific deployment."""
|
||||
api = cliutils.get_api()
|
||||
results = api.verification.rerun(verification_uuid=verification_uuid,
|
||||
deployment_id=deployment,
|
||||
deployment_id=env,
|
||||
failed=failed,
|
||||
tags=tags,
|
||||
concurrency=concur)
|
||||
@@ -842,7 +852,7 @@ def rerun(
|
||||
print("Verification UUID: %s." % results["verification"]["uuid"])
|
||||
|
||||
|
||||
@verify_app.command(name="show")
|
||||
@verify_app.command(name="show", rich_help_panel=VERIFICATION)
|
||||
def show(
|
||||
verification_uuid: t.Annotated[
|
||||
str,
|
||||
@@ -854,7 +864,7 @@ def show(
|
||||
],
|
||||
sort_by: t.Annotated[
|
||||
t.Literal["name", "duration", "status"],
|
||||
typer.Option(help="Sort tests by 'name', 'duration' or 'status'.")
|
||||
typer.Option(help="Sort tests.")
|
||||
] = "name",
|
||||
detailed: t.Annotated[
|
||||
bool,
|
||||
@@ -889,7 +899,7 @@ def show(
|
||||
# Main table
|
||||
fields = ["UUID", "Status", "Started at", "Finished at", "Duration",
|
||||
"Run arguments", "Tags", "Verifier name", "Verifier type",
|
||||
"Deployment name", "Tests count", "Tests duration, sec",
|
||||
"Environment", "Tests count", "Tests duration, sec",
|
||||
"Success", "Skipped", "Expected failures",
|
||||
"Unexpected success", "Failures"]
|
||||
formatters = {
|
||||
@@ -905,7 +915,7 @@ def show(
|
||||
"Verifier type": (
|
||||
lambda v: "%s (platform: %s)" % (verifier["type"],
|
||||
verifier["platform"])),
|
||||
"Deployment name": (
|
||||
"Environment": (
|
||||
lambda v: "%s (UUID: %s)" % (deployment["name"],
|
||||
deployment["uuid"])),
|
||||
"Tests duration, sec": lambda v: v["tests_duration"]
|
||||
@@ -937,7 +947,7 @@ def show(
|
||||
print("\nCongratulations! Verification passed all tests ;)")
|
||||
|
||||
|
||||
@verify_app.command(name="list")
|
||||
@verify_app.command(name="list", rich_help_panel=VERIFICATION)
|
||||
def list_(
|
||||
verifier_id: t.Annotated[
|
||||
str | None,
|
||||
@@ -946,11 +956,12 @@ def list_(
|
||||
help="Verifier name or UUID. " + LIST_VERIFIERS_HINT
|
||||
)
|
||||
] = None,
|
||||
deployment: t.Annotated[
|
||||
env: t.Annotated[
|
||||
str | None,
|
||||
typer.Option(
|
||||
"--deployment-id",
|
||||
help="Deployment name or UUID. " + LIST_DEPLOYMENTS_HINT
|
||||
argutils.DeprecatedAlias(
|
||||
"--env",
|
||||
deprecated=["--deployment-id"],
|
||||
help="Environment name or UUID. " + LIST_ENVS_HINT
|
||||
)
|
||||
] = None,
|
||||
tags: t.Annotated[
|
||||
@@ -960,8 +971,8 @@ def list_(
|
||||
help="Tags to filter verifications by."
|
||||
)
|
||||
] = None,
|
||||
status: t.Annotated[
|
||||
str | None,
|
||||
status: t.Annotated[ # type: ignore[valid-type]
|
||||
t.Literal[tuple(consts.VerificationStatus)] | None,
|
||||
typer.Option(
|
||||
help="Status to filter verifications by."
|
||||
)
|
||||
@@ -970,16 +981,16 @@ def list_(
|
||||
"""List all verifications."""
|
||||
api = cliutils.get_api()
|
||||
verifications = api.verification.list(verifier_id=verifier_id,
|
||||
deployment_id=deployment,
|
||||
deployment_id=env,
|
||||
tags=tags, status=status)
|
||||
if verifications:
|
||||
fields = ["UUID", "Tags", "Verifier name", "Deployment name",
|
||||
fields = ["UUID", "Tags", "Verifier name", "Environment",
|
||||
"Started at", "Finished at", "Duration", "Status"]
|
||||
formatters = {
|
||||
"Tags": lambda v: ", ".join(v["tags"]) or "-",
|
||||
"Verifier name": (lambda v: api.verifier.get(
|
||||
verifier_id=v["verifier_uuid"])["name"]),
|
||||
"Deployment name": (lambda v: api.deployment.get(
|
||||
"Environment": (lambda v: api.deployment.get(
|
||||
deployment=v["deployment_uuid"])["name"]),
|
||||
"Started at": lambda v: v["created_at"],
|
||||
"Finished at": lambda v: v["updated_at"],
|
||||
@@ -989,14 +1000,14 @@ def list_(
|
||||
}
|
||||
cliutils.print_list(verifications, fields, formatters=formatters,
|
||||
normalize_field_names=True, sortby_index=4)
|
||||
elif verifier_id or deployment or status or tags:
|
||||
elif verifier_id or env or status or tags:
|
||||
print("There are no verifications that meet specified criteria.")
|
||||
else:
|
||||
print("There are no verifications. You can start verification, "
|
||||
"using command `rally verify start`.")
|
||||
|
||||
|
||||
@verify_app.command(name="delete")
|
||||
@verify_app.command(name="delete", rich_help_panel=VERIFICATION)
|
||||
def delete(
|
||||
verification_uuid: t.Annotated[
|
||||
list[str],
|
||||
@@ -1012,7 +1023,7 @@ def delete(
|
||||
api.verification.delete(verification_uuid=v_uuid)
|
||||
|
||||
|
||||
@verify_app.command(name="report")
|
||||
@verify_app.command(name="report", rich_help_panel=VERIFICATION)
|
||||
@plugins.ensure_plugins_are_loaded
|
||||
def report(
|
||||
verification_uuid: t.Annotated[
|
||||
@@ -1081,7 +1092,7 @@ def report(
|
||||
print("\n%s\n%s" % (cliutils.make_header(h, len(h)), result["print"]))
|
||||
|
||||
|
||||
@verify_app.command(name="import")
|
||||
@verify_app.command(name="import", rich_help_panel=VERIFICATION)
|
||||
@plugins.ensure_plugins_are_loaded
|
||||
def import_results(
|
||||
verifier_id: t.Annotated[
|
||||
@@ -1092,12 +1103,13 @@ def import_results(
|
||||
help="Verifier name or UUID. " + LIST_VERIFIERS_HINT
|
||||
)
|
||||
],
|
||||
deployment: t.Annotated[
|
||||
env: t.Annotated[
|
||||
str,
|
||||
typer.Option(
|
||||
"--deployment-id",
|
||||
argutils.DeprecatedAlias(
|
||||
"--env",
|
||||
deprecated=["--deployment-id"],
|
||||
envvar=envutils.ENV_ENV,
|
||||
help="Deployment name or UUID. " + LIST_DEPLOYMENTS_HINT
|
||||
help="Environment name or UUID. " + LIST_ENVS_HINT
|
||||
)
|
||||
],
|
||||
file_to_parse: t.Annotated[
|
||||
@@ -1133,7 +1145,7 @@ def import_results(
|
||||
|
||||
parsed_run_args = yaml.safe_load(run_args) if run_args else {}
|
||||
verification, results = api.verification.import_results(
|
||||
verifier_id=verifier_id, deployment_id=deployment,
|
||||
verifier_id=verifier_id, deployment_id=env,
|
||||
data=data, **parsed_run_args)
|
||||
_print_totals(results["totals"])
|
||||
|
||||
|
||||
+12
-7
@@ -51,12 +51,15 @@ if t.TYPE_CHECKING:
|
||||
app = typer.Typer(name="rally", help="Rally command-line interface.",
|
||||
no_args_is_help=False, add_completion=True)
|
||||
|
||||
app.add_typer(db_app, name="db")
|
||||
app.add_typer(deployment_app, name="deployment")
|
||||
app.add_typer(env_app, name="env")
|
||||
app.add_typer(plugin_app, name="plugin")
|
||||
app.add_typer(task_app, name="task")
|
||||
app.add_typer(verify_app, name="verify")
|
||||
# the command categories are grouped in their own help panel, separate from
|
||||
# the top-level ``version`` command
|
||||
_CATEGORIES = "Categories"
|
||||
app.add_typer(db_app, name="db", rich_help_panel=_CATEGORIES)
|
||||
app.add_typer(deployment_app, name="deployment", rich_help_panel=_CATEGORIES)
|
||||
app.add_typer(env_app, name="env", rich_help_panel=_CATEGORIES)
|
||||
app.add_typer(plugin_app, name="plugin", rich_help_panel=_CATEGORIES)
|
||||
app.add_typer(task_app, name="task", rich_help_panel=_CATEGORIES)
|
||||
app.add_typer(verify_app, name="verify", rich_help_panel=_CATEGORIES)
|
||||
|
||||
|
||||
@app.command(name="version")
|
||||
@@ -136,7 +139,9 @@ def bootstrap(
|
||||
**kwargs: t.Any,
|
||||
) -> None:
|
||||
"""Build the API and expose it to the sub-commands."""
|
||||
if any(opt in sys.argv[1:] for opt in ctx.help_option_names):
|
||||
is_help = any(opt in sys.argv[1:] for opt in ctx.help_option_names)
|
||||
cliutils.set_help_requested(is_help)
|
||||
if is_help:
|
||||
return
|
||||
envutils.load_globals()
|
||||
config_args: list[str] = []
|
||||
|
||||
@@ -393,6 +393,10 @@ def build_cli_params() -> list:
|
||||
# ``None`` and lets oslo apply its own default when it re-parses argv.
|
||||
default = opt.default if isinstance(opt, cfg.BoolOpt) else None
|
||||
help_text = (opt.help or "").strip().split("\n")[0]
|
||||
# oslo help uses printf placeholders for its own formatter; typer
|
||||
# shows them raw, so resolve ``%(default)s`` and unescape ``%%``.
|
||||
help_text = help_text.replace("%(default)s", str(opt.default))
|
||||
help_text = help_text.replace("%%", "%")
|
||||
option = typer.Option("--%s" % opt.name, help=help_text)
|
||||
params.append(
|
||||
inspect.Parameter(
|
||||
|
||||
@@ -89,11 +89,6 @@ class TaskTestCase(unittest.TestCase):
|
||||
]
|
||||
}
|
||||
|
||||
def _get_deployment_uuid(self, output):
|
||||
return re.search(
|
||||
r"Using deployment: (?P<uuid>[0-9a-f\-]{36})",
|
||||
output).group("uuid")
|
||||
|
||||
def _get_task_uuid(self, output):
|
||||
return re.search(
|
||||
r"\trally task report (?P<uuid>[0-9a-f\-]{36})",
|
||||
@@ -505,19 +500,19 @@ class TaskTestCase(unittest.TestCase):
|
||||
rapi = api.API(config_file=rally.config_filename)
|
||||
task = rapi.task.get(task_id=task_uuid)
|
||||
|
||||
actual = rally("task list --deployment MAIN")
|
||||
actual = rally("task list --env MAIN")
|
||||
duration = "%s" % round(task["task_duration"], 3)
|
||||
duration += " " * (13 - len(duration))
|
||||
expected = (
|
||||
"+--------------------------------------+-----------------+"
|
||||
"+--------------------------------------+-------------+"
|
||||
"---------------------+---------------+----------+--------+\n"
|
||||
"| UUID | Deployment name "
|
||||
"| UUID | Environment "
|
||||
"| Created at | Load duration | Status | Tag(s) |\n"
|
||||
"+--------------------------------------+-----------------+"
|
||||
"+--------------------------------------+-------------+"
|
||||
"---------------------+---------------+----------+--------+\n"
|
||||
"| %(uuid)s | MAIN | %(created_at)s "
|
||||
"| %(duration)s | finished | 'foo' |\n"
|
||||
"+--------------------------------------+-----------------+"
|
||||
"| %(uuid)s | MAIN "
|
||||
"| %(created_at)s | %(duration)s | finished | 'foo' |\n"
|
||||
"+--------------------------------------+-------------+"
|
||||
"---------------------+---------------+----------+--------+\n" % {
|
||||
"uuid": task_uuid,
|
||||
"created_at": task["created_at"].replace("T", " "),
|
||||
@@ -536,7 +531,7 @@ class TaskTestCase(unittest.TestCase):
|
||||
self.assertIn("finished", rally("task list --status finished"))
|
||||
|
||||
self.assertIn(
|
||||
"Deployment name", rally("task list --all-deployments"))
|
||||
"Environment", rally("task list --all-envs"))
|
||||
|
||||
self.assertRaises(utils.RallyCliError,
|
||||
rally, "task list --status not_existing_status")
|
||||
@@ -554,7 +549,13 @@ class TaskTestCase(unittest.TestCase):
|
||||
task_uuid = self._get_task_uuid(res)
|
||||
self.assertEqual(
|
||||
task_uuid,
|
||||
rally("task list --uuids-only --deployment MAIN").strip())
|
||||
rally("task list --uuids-only --env MAIN").strip())
|
||||
# the deprecated --deployment alias still works; no_logs sends its
|
||||
# stderr warning to /dev/null so it can't pollute the compared output
|
||||
self.assertEqual(
|
||||
task_uuid,
|
||||
rally("task list --uuids-only --deployment MAIN",
|
||||
no_logs=True).strip())
|
||||
self.assertIn("finished", rally("task status --uuid %s" % task_uuid))
|
||||
|
||||
# Validate against multiple tasks
|
||||
@@ -565,9 +566,9 @@ class TaskTestCase(unittest.TestCase):
|
||||
task_uuids.append(task_uuid)
|
||||
self.assertIn("finished",
|
||||
rally("task status --uuid %s" % task_uuid))
|
||||
res = rally("task list --uuids-only --deployment MAIN")
|
||||
res = rally("task list --uuids-only --env MAIN")
|
||||
self.assertEqual(set(task_uuids), set(res.strip().split("\n")))
|
||||
res2 = rally("task list --uuids-only --deployment MAIN "
|
||||
res2 = rally("task list --uuids-only --env MAIN "
|
||||
"--status finished")
|
||||
self.assertEqual(res, res2)
|
||||
|
||||
@@ -580,25 +581,21 @@ class TaskTestCase(unittest.TestCase):
|
||||
|
||||
def test_validate_is_invalid(self):
|
||||
rally = utils.Rally()
|
||||
deployment_id = utils.get_global("RALLY_DEPLOYMENT", rally.env)
|
||||
env_id = utils.get_global("RALLY_ENV", rally.env)
|
||||
cfg = {"invalid": "config"}
|
||||
config = utils.TaskConfig(cfg)
|
||||
self.assertRaises(utils.RallyCliError,
|
||||
rally,
|
||||
("task validate --task %(task_file)s "
|
||||
"--deployment %(deployment_id)s") %
|
||||
{"task_file": config.filename,
|
||||
"deployment_id": deployment_id})
|
||||
f"task validate --task {config.filename} "
|
||||
f"--env {env_id}")
|
||||
|
||||
def test_start(self):
|
||||
rally = utils.Rally()
|
||||
deployment_id = utils.get_global("RALLY_DEPLOYMENT", rally.env)
|
||||
env_id = utils.get_global("RALLY_ENV", rally.env)
|
||||
cfg = self._get_sample_task_config()
|
||||
config = utils.TaskConfig(cfg)
|
||||
output = rally(("task start --task %(task_file)s "
|
||||
"--deployment %(deployment_id)s") %
|
||||
{"task_file": config.filename,
|
||||
"deployment_id": deployment_id})
|
||||
output = rally(f"task start --task {config.filename} "
|
||||
f"--env {env_id}")
|
||||
result = re.search(
|
||||
r"(?P<task_id>[0-9a-f\-]{36}): started", output)
|
||||
self.assertIsNotNone(result)
|
||||
@@ -640,12 +637,10 @@ class TaskTestCase(unittest.TestCase):
|
||||
|
||||
def _test_start_abort_on_sla_failure_success(self, cfg, times):
|
||||
rally = utils.Rally()
|
||||
deployment_id = utils.get_global("RALLY_DEPLOYMENT", rally.env)
|
||||
env_id = utils.get_global("RALLY_ENV", rally.env)
|
||||
config = utils.TaskConfig(cfg)
|
||||
rally(("task start --task %(task_file)s "
|
||||
"--deployment %(deployment_id)s --abort-on-sla-failure") %
|
||||
{"task_file": config.filename,
|
||||
"deployment_id": deployment_id})
|
||||
rally(f"task start --task {config.filename} "
|
||||
f"--env {env_id} --abort-on-sla-failure")
|
||||
results = rally("task results", getjson=True)
|
||||
iterations_completed = len(results[0]["result"])
|
||||
self.assertEqual(times, iterations_completed)
|
||||
@@ -714,14 +709,12 @@ class TaskTestCase(unittest.TestCase):
|
||||
|
||||
def _test_start_abort_on_sla_failure(self, cfg, times):
|
||||
rally = utils.Rally()
|
||||
deployment_id = utils.get_global("RALLY_DEPLOYMENT", rally.env)
|
||||
env_id = utils.get_global("RALLY_ENV", rally.env)
|
||||
config = utils.TaskConfig(cfg)
|
||||
self.assertRaises(utils.RallyCliError, rally,
|
||||
("task start --task %(task_file)s "
|
||||
"--deployment %(deployment_id)s "
|
||||
"--abort-on-sla-failure") %
|
||||
{"task_file": config.filename,
|
||||
"deployment_id": deployment_id})
|
||||
f"task start --task {config.filename} "
|
||||
f"--env {env_id} "
|
||||
f"--abort-on-sla-failure")
|
||||
results = rally("task results", getjson=True)
|
||||
self.assertEqual(1, len(results),
|
||||
"Second subtask should not be started")
|
||||
@@ -913,12 +906,9 @@ class TaskTestCase(unittest.TestCase):
|
||||
self._test_start_abort_on_sla_failure(cfg, times)
|
||||
|
||||
def _start_task_in_new_thread(self, rally, cfg, suffix):
|
||||
deployment_id = utils.get_global("RALLY_DEPLOYMENT", rally.env)
|
||||
env_id = utils.get_global("RALLY_ENV", rally.env)
|
||||
config = utils.TaskConfig(cfg)
|
||||
cmd = (("task start --task %(task_file)s "
|
||||
"--deployment %(deployment_id)s") %
|
||||
{"task_file": config.filename,
|
||||
"deployment_id": deployment_id})
|
||||
cmd = f"task start --task {config.filename} --env {env_id}"
|
||||
report_path = rally.gen_report_path(suffix=suffix)
|
||||
task = threading.Thread(target=rally, args=(cmd, ),
|
||||
kwargs={"report_path": report_path})
|
||||
@@ -993,12 +983,10 @@ class TaskTestCase(unittest.TestCase):
|
||||
|
||||
def test_use(self):
|
||||
rally = utils.Rally()
|
||||
deployment_id = utils.get_global("RALLY_DEPLOYMENT", rally.env)
|
||||
env_id = utils.get_global("RALLY_ENV", rally.env)
|
||||
config = utils.TaskConfig(self._get_sample_task_config())
|
||||
output = rally(("task start --task %(task_file)s "
|
||||
"--deployment %(deployment_id)s") %
|
||||
{"task_file": config.filename,
|
||||
"deployment_id": deployment_id})
|
||||
output = rally(f"task start --task {config.filename} "
|
||||
f"--env {env_id}")
|
||||
result = re.search(
|
||||
r"(?P<uuid>[0-9a-f\-]{36}): started", output)
|
||||
uuid = result.group("uuid")
|
||||
@@ -1008,13 +996,11 @@ class TaskTestCase(unittest.TestCase):
|
||||
|
||||
def test_start_v2(self):
|
||||
rally = utils.Rally()
|
||||
deployment_id = utils.get_global("RALLY_DEPLOYMENT", rally.env)
|
||||
env_id = utils.get_global("RALLY_ENV", rally.env)
|
||||
cfg = self._get_sample_task_config_v2()
|
||||
config = utils.TaskConfig(cfg)
|
||||
output = rally(("task start --task %(task_file)s "
|
||||
"--deployment %(deployment_id)s") %
|
||||
{"task_file": config.filename,
|
||||
"deployment_id": deployment_id})
|
||||
output = rally(f"task start --task {config.filename} "
|
||||
f"--env {env_id}")
|
||||
result = re.search(
|
||||
r"(?P<task_id>[0-9a-f\-]{36}): started", output)
|
||||
self.assertIsNotNone(result)
|
||||
@@ -1054,13 +1040,11 @@ class TaskTestCase(unittest.TestCase):
|
||||
|
||||
def test_restart(self):
|
||||
rally = utils.Rally()
|
||||
deployment_id = utils.get_global("RALLY_DEPLOYMENT", rally.env)
|
||||
env_id = utils.get_global("RALLY_ENV", rally.env)
|
||||
cfg = self._get_sample_task_config()
|
||||
config = utils.TaskConfig(cfg)
|
||||
output = rally(("task start --task %(task_file)s "
|
||||
"--deployment %(deployment_id)s") %
|
||||
{"task_file": config.filename,
|
||||
"deployment_id": deployment_id})
|
||||
output = rally(f"task start --task {config.filename} "
|
||||
f"--env {env_id}")
|
||||
|
||||
output = rally("task restart")
|
||||
result = re.search(
|
||||
@@ -1069,13 +1053,11 @@ class TaskTestCase(unittest.TestCase):
|
||||
|
||||
def test_restart_with_scenario(self):
|
||||
rally = utils.Rally()
|
||||
deployment_id = utils.get_global("RALLY_DEPLOYMENT", rally.env)
|
||||
env_id = utils.get_global("RALLY_ENV", rally.env)
|
||||
cfg = self._get_sample_task_config()
|
||||
config = utils.TaskConfig(cfg)
|
||||
output = rally(("task start --task %(task_file)s "
|
||||
"--deployment %(deployment_id)s") %
|
||||
{"task_file": config.filename,
|
||||
"deployment_id": deployment_id})
|
||||
output = rally(f"task start --task {config.filename} "
|
||||
f"--env {env_id}")
|
||||
|
||||
output = rally(
|
||||
"task restart --scenario Dummy.dummy_random_fail_in_atomic")
|
||||
@@ -1088,13 +1070,11 @@ class TaskTestCase(unittest.TestCase):
|
||||
|
||||
def test_restart_with_fake_scenario(self):
|
||||
rally = utils.Rally()
|
||||
deployment_id = utils.get_global("RALLY_DEPLOYMENT", rally.env)
|
||||
env_id = utils.get_global("RALLY_ENV", rally.env)
|
||||
cfg = self._get_sample_task_config()
|
||||
config = utils.TaskConfig(cfg)
|
||||
rally(("task start --task %(task_file)s "
|
||||
"--deployment %(deployment_id)s") %
|
||||
{"task_file": config.filename,
|
||||
"deployment_id": deployment_id})
|
||||
rally(f"task start --task {config.filename} "
|
||||
f"--env {env_id}")
|
||||
self.assertRaises(utils.RallyCliError, rally,
|
||||
"task restart --scenario fake.fake_scenario")
|
||||
|
||||
|
||||
@@ -62,11 +62,11 @@ class Rally(object):
|
||||
Usage:
|
||||
|
||||
rally = Rally()
|
||||
rally("deployment", "create", "--name", "Some Deployment Name")
|
||||
output = rally("deployment list")
|
||||
rally("env", "create", "--name", "Some Environment Name")
|
||||
output = rally("env list")
|
||||
|
||||
"""
|
||||
_DEPLOYMENT_CREATE_ARGS = ""
|
||||
_ENV_CREATE_ARGS = ""
|
||||
|
||||
def __init__(self, force_new_db=False, plugin_path=None):
|
||||
|
||||
@@ -112,7 +112,7 @@ class Rally(object):
|
||||
self.reports_root = os.environ.get("REPORTS_ROOT",
|
||||
"rally-cli-output-files")
|
||||
self._created_files = []
|
||||
self("deployment create --name MAIN%s" % self._DEPLOYMENT_CREATE_ARGS,
|
||||
self(f"env create --name MAIN{self._ENV_CREATE_ARGS}",
|
||||
write_report=False)
|
||||
|
||||
def __del__(self):
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
|
||||
import collections
|
||||
import os
|
||||
import sys
|
||||
import tempfile
|
||||
from unittest import mock
|
||||
|
||||
@@ -37,6 +38,19 @@ class DeploymentCommandsTestCase(test.CLITestCase):
|
||||
extras={}, config={}, spec=spec or {}, platforms=[])
|
||||
return db.env_get(name)
|
||||
|
||||
def test_deprecation_warning(self):
|
||||
# running a subcommand warns that ``deployment`` is deprecated...
|
||||
result = self.invoke(["deployment", "list"])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertIn("deprecated", result.stderr)
|
||||
|
||||
# ...but merely rendering help does not (bootstrap flags --help via
|
||||
# sys.argv)
|
||||
with mock.patch.object(sys, "argv", ["rally", "deployment", "--help"]):
|
||||
result = self.invoke(["deployment", "--help"])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertNotIn("deprecated", result.stderr)
|
||||
|
||||
@mock.patch("rally.api._Deployment.create")
|
||||
def test_create(self, mock_create):
|
||||
mock_create.return_value = CREATED
|
||||
@@ -75,39 +89,6 @@ class DeploymentCommandsTestCase(test.CLITestCase):
|
||||
mock_create.assert_called_once_with(
|
||||
config={"auth_url": "http://fake"}, name="from_env")
|
||||
|
||||
@mock.patch("rally.api._Deployment.create")
|
||||
@mock.patch("rally.env.env_mgr.EnvManager.create_spec_from_sys_environ")
|
||||
def test_create_fromenv_openstack(self, mock_create_spec_from_sys_environ,
|
||||
mock_create):
|
||||
mock_create.return_value = CREATED
|
||||
mock_create_spec_from_sys_environ.side_effect = lambda: {
|
||||
"spec": {
|
||||
"existing@openstack": {
|
||||
"https_key": "some key",
|
||||
"another_key": "another"
|
||||
}
|
||||
}
|
||||
}
|
||||
mock_rally_os = mock.Mock()
|
||||
|
||||
# OS_KEY is dropped for old rally-openstack, kept for newer ones
|
||||
for version, expected in (
|
||||
((1, 4, 0), {"existing@openstack": {"another_key": "another"}}),
|
||||
((1, 5, 0), {"existing@openstack": {"another_key": "another",
|
||||
"https_key": "some key"}}),
|
||||
):
|
||||
with self.subTest(version=version):
|
||||
mock_create.reset_mock()
|
||||
mock_rally_os.__version_tuple__ = version
|
||||
with mock.patch.dict("sys.modules",
|
||||
{"rally_openstack": mock_rally_os}):
|
||||
result = self.invoke([
|
||||
"deployment", "create", "--name", "from_env",
|
||||
"--fromenv"])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
mock_create.assert_called_once_with(config=expected,
|
||||
name="from_env")
|
||||
|
||||
@mock.patch("rally.api._Deployment.create")
|
||||
def test_create_and_use(self, mock_create):
|
||||
mock_create.return_value = CREATED
|
||||
@@ -200,7 +181,7 @@ class DeploymentCommandsTestCase(test.CLITestCase):
|
||||
" demo | RegionOne | internal |\n"
|
||||
"+--------------------------+----------+----------+"
|
||||
"-------------+-------------+---------------+\n",
|
||||
result.output)
|
||||
result.stdout)
|
||||
|
||||
@mock.patch("rally.api._Deployment.get")
|
||||
def test_use(self, mock_get):
|
||||
@@ -316,7 +297,7 @@ class DeploymentCommandsTestCase(test.CLITestCase):
|
||||
"---------------\n\n"
|
||||
"Error while checking users credentials:\n"
|
||||
"\tProviderError: No money - no funny!",
|
||||
result.output.strip())
|
||||
result.stdout.strip())
|
||||
|
||||
@mock.patch("rally.cli.commands.deployment.logging.is_debug",
|
||||
return_value=True)
|
||||
@@ -342,4 +323,4 @@ class DeploymentCommandsTestCase(test.CLITestCase):
|
||||
"Error while checking admin credentials:\n"
|
||||
"file1\n\tline1\n\n"
|
||||
"KeystoneError: connection refused",
|
||||
result.output.strip())
|
||||
result.stdout.strip())
|
||||
@@ -129,15 +129,33 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
):
|
||||
with self.subTest(extra=extra):
|
||||
result = self.invoke(["task", "validate", task_file,
|
||||
"--deployment", env["uuid"], *extra])
|
||||
"--env", env["uuid"], *extra])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertIn(expected, result.output)
|
||||
|
||||
@mock.patch("rally.api._Task.validate")
|
||||
def test_env_alias_deprecation(self, mock_validate):
|
||||
env = self._create_env()
|
||||
task_file = self._write("{'a': 1}")
|
||||
|
||||
# the preferred --env flag does not warn
|
||||
result = self.invoke(["task", "validate", task_file,
|
||||
"--env", env["uuid"]])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertNotIn("deprecated", result.stderr)
|
||||
|
||||
# the legacy --deployment alias still works but warns towards --env
|
||||
result = self.invoke(["task", "validate", task_file,
|
||||
"--deployment", env["uuid"]])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertIn("deprecated", result.stderr)
|
||||
self.assertIn("--env", result.stderr)
|
||||
|
||||
def test__load_task_wrong_task_args_file(self):
|
||||
env = self._create_env()
|
||||
task_file = self._write("{}")
|
||||
result = self.invoke(["task", "validate", task_file,
|
||||
"--deployment", env["uuid"],
|
||||
"--env", env["uuid"],
|
||||
"--task-args-file", "/no/such/args"])
|
||||
self.assertEqual(task.FailedToLoadTask.error_code, result.exit_code)
|
||||
self.assertIn("Invalid --task-args-file passed", result.output)
|
||||
@@ -148,7 +166,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
for raw_args in ("{'test': {}", "foo"):
|
||||
with self.subTest(raw_args=raw_args):
|
||||
result = self.invoke(["task", "validate", task_file,
|
||||
"--deployment", env["uuid"],
|
||||
"--env", env["uuid"],
|
||||
"--task-args", raw_args])
|
||||
self.assertEqual(task.FailedToLoadTask.error_code,
|
||||
result.exit_code)
|
||||
@@ -158,7 +176,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
env = self._create_env()
|
||||
task_file = self._write("{}")
|
||||
bad_args = self._write("{'a': {}")
|
||||
result = self.invoke(["task", "validate", task_file, "--deployment",
|
||||
result = self.invoke(["task", "validate", task_file, "--env",
|
||||
env["uuid"], "--task-args-file", bad_args])
|
||||
self.assertEqual(task.FailedToLoadTask.error_code, result.exit_code)
|
||||
self.assertIn("has to be YAML or JSON", result.output)
|
||||
@@ -167,7 +185,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
env = self._create_env()
|
||||
task_file = self._write("{'test': {{t}}}")
|
||||
result = self.invoke(["task", "validate", task_file,
|
||||
"--deployment", env["uuid"]])
|
||||
"--env", env["uuid"]])
|
||||
self.assertEqual(task.FailedToLoadTask.error_code, result.exit_code)
|
||||
self.assertIn("Failed to render task template", result.output)
|
||||
|
||||
@@ -176,7 +194,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
# renders fine (no jinja) but is not valid YAML/JSON
|
||||
task_file = self._write("{'test': {}")
|
||||
result = self.invoke(["task", "validate", task_file,
|
||||
"--deployment", env["uuid"]])
|
||||
"--env", env["uuid"]])
|
||||
self.assertEqual(task.FailedToLoadTask.error_code, result.exit_code)
|
||||
self.assertIn("Wrong format of rendered input task", result.output)
|
||||
|
||||
@@ -204,7 +222,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
def test__load_and_validate_file_failed(self):
|
||||
env = self._create_env()
|
||||
result = self.invoke(["task", "validate", "/no/such/task",
|
||||
"--deployment", env["uuid"]])
|
||||
"--env", env["uuid"]])
|
||||
self.assertEqual(task.FailedToLoadTask.error_code, result.exit_code)
|
||||
self.assertIn("Error reading /no/such/task", result.output)
|
||||
|
||||
@@ -219,7 +237,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
"pass_sla": True, "subtasks": []}
|
||||
|
||||
result = self.invoke(["task", "start", task_file,
|
||||
"--deployment", env["uuid"]])
|
||||
"--env", env["uuid"]])
|
||||
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertIn("started", result.output)
|
||||
@@ -237,7 +255,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
status=consts.DeployStatus.DEPLOY_INIT)
|
||||
|
||||
result = self.invoke(["task", "start", task_file,
|
||||
"--deployment", env["uuid"], "--tag", "some"])
|
||||
"--env", env["uuid"], "--tag", "some"])
|
||||
|
||||
self.assertEqual(1, result.exit_code, result.output)
|
||||
self.assertIn("unfinished deployment", result.output)
|
||||
@@ -254,7 +272,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
"pass_sla": True, "subtasks": []}
|
||||
|
||||
result = self.invoke(["task", "start", task_file,
|
||||
"--deployment", env["uuid"],
|
||||
"--env", env["uuid"],
|
||||
"--task-args-file", args_file, "--tag", "t"])
|
||||
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
@@ -270,7 +288,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
mock_create.side_effect = exceptions.InvalidTaskException("foo")
|
||||
|
||||
result = self.invoke(["task", "start", task_file,
|
||||
"--deployment", env["uuid"]])
|
||||
"--env", env["uuid"]])
|
||||
|
||||
self.assertEqual(exceptions.InvalidTaskException.error_code,
|
||||
result.exit_code)
|
||||
@@ -286,7 +304,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
mock_get.return_value = {"uuid": "new-uuid", "pass_sla": False,
|
||||
"status": "finished", "subtasks": []}
|
||||
|
||||
result = self.invoke(["task", "start", task_file, "--deployment",
|
||||
result = self.invoke(["task", "start", task_file, "--env",
|
||||
env["uuid"], "--no-use"])
|
||||
|
||||
self.assertEqual(2, result.exit_code, result.output)
|
||||
@@ -306,7 +324,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
"runner_type": "constant",
|
||||
"runner": {"times": 1}, "hooks": [],
|
||||
"sla": {}}]}]}
|
||||
args = ["task", "restart", "--deployment", "dep",
|
||||
args = ["task", "restart", "--env", "dep",
|
||||
"--uuid", "task-uuid"]
|
||||
if scenario:
|
||||
args += ["--scenario", scenario]
|
||||
@@ -326,7 +344,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
"description": "d", "tags": [], "subtasks": [],
|
||||
"validation_result": {"trace": {}, "etype": "E", "msg": "m"}}
|
||||
|
||||
result = self.invoke(["task", "restart", "--deployment", "dep",
|
||||
result = self.invoke(["task", "restart", "--env", "dep",
|
||||
"--uuid", "task-uuid"])
|
||||
|
||||
self.assertEqual(1, result.exit_code, result.output)
|
||||
@@ -343,7 +361,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
"runner_type": "c", "runner": {}, "hooks": [],
|
||||
"sla": {}}]}]}
|
||||
|
||||
result = self.invoke(["task", "restart", "--deployment", "dep",
|
||||
result = self.invoke(["task", "restart", "--env", "dep",
|
||||
"--uuid", "task-uuid"])
|
||||
|
||||
self.assertEqual(2, result.exit_code, result.output)
|
||||
@@ -358,7 +376,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
|
||||
with mock.patch("rally.cli.commands.task.logging.is_debug",
|
||||
return_value=True):
|
||||
result = self.invoke(["task", "restart", "--deployment", "dep",
|
||||
result = self.invoke(["task", "restart", "--env", "dep",
|
||||
"--uuid", "task-uuid"])
|
||||
|
||||
self.assertEqual(1, result.exit_code, result.output)
|
||||
@@ -515,7 +533,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
mock_export.return_value = {"print": "the report body"}
|
||||
|
||||
# --deployment lists the tasks itself; the positional is still required
|
||||
result = self.invoke(["task", "report", "ignored", "--deployment",
|
||||
result = self.invoke(["task", "report", "ignored", "--env",
|
||||
"dep", "--out", "out"])
|
||||
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
@@ -557,7 +575,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
env = self._create_env()
|
||||
task_obj = self._create_task(env=env, tags=["d"])
|
||||
|
||||
result = self.invoke(["task", "list", "--deployment", env["uuid"]])
|
||||
result = self.invoke(["task", "list", "--env", env["uuid"]])
|
||||
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertIn(task_obj["uuid"], result.output)
|
||||
@@ -567,23 +585,24 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
env = self._create_env()
|
||||
task_obj = self._create_task(env=env)
|
||||
|
||||
result = self.invoke(["task", "list", "--deployment", env["uuid"],
|
||||
result = self.invoke(["task", "list", "--env", env["uuid"],
|
||||
"--uuids-only"])
|
||||
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertEqual("%s\n" % task_obj["uuid"], result.stdout)
|
||||
|
||||
def test_list_wrong_status(self):
|
||||
result = self.invoke(["task", "list", "--deployment", "fake",
|
||||
"--status", "wrong non existing status"])
|
||||
# typer rejects an unknown status natively (the option is a Literal)
|
||||
result = self.invoke(["task", "list", "--env", "fake",
|
||||
"--status", "bogus"])
|
||||
|
||||
self.assertEqual(1, result.exit_code, result.output)
|
||||
self.assertIn("Invalid task status", result.output)
|
||||
self.assertEqual(2, result.exit_code, result.output)
|
||||
self.assertIn("Invalid value", result.output)
|
||||
|
||||
def test_list_no_results(self):
|
||||
env = self._create_env()
|
||||
|
||||
result = self.invoke(["task", "list", "--deployment", env["uuid"]])
|
||||
result = self.invoke(["task", "list", "--env", env["uuid"]])
|
||||
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertIn("There are no tasks", result.output)
|
||||
@@ -592,24 +611,29 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
env = self._create_env()
|
||||
self._create_task(env=env) # a task with no tags
|
||||
with self.subTest("no-tag task lists with an empty tag cell"):
|
||||
result = self.invoke(["task", "list", "--deployment",
|
||||
result = self.invoke(["task", "list", "--env",
|
||||
env["uuid"]])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
with self.subTest("valid status filter with no matches"):
|
||||
result = self.invoke(["task", "list", "--deployment",
|
||||
result = self.invoke(["task", "list", "--env",
|
||||
env["uuid"], "--status", "finished"])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertIn("no tasks in 'finished' status", result.output)
|
||||
with self.subTest("all deployments + tag filter"):
|
||||
result = self.invoke(["task", "list", "--deployment",
|
||||
env["uuid"], "--all-deployments",
|
||||
"--tag", "x"])
|
||||
with self.subTest("all envs + tag filter"):
|
||||
result = self.invoke(["task", "list", "--env",
|
||||
env["uuid"], "--all-envs", "--tag", "x"])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
with self.subTest("deprecated --all-deployments still works, warns"):
|
||||
result = self.invoke(["task", "list", "--env",
|
||||
env["uuid"], "--all-deployments"])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertIn("deprecated", result.stderr)
|
||||
self.assertIn("--all-envs", result.stderr)
|
||||
|
||||
def test_list_uuids_only_empty(self):
|
||||
env = self._create_env()
|
||||
|
||||
result = self.invoke(["task", "list", "--deployment", env["uuid"],
|
||||
result = self.invoke(["task", "list", "--env", env["uuid"],
|
||||
"--uuids-only"])
|
||||
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
@@ -667,7 +691,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
task_file = self._write('{"some": "json"}')
|
||||
|
||||
result = self.invoke(["task", "validate", task_file,
|
||||
"--deployment", env["uuid"]])
|
||||
"--env", env["uuid"]])
|
||||
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertIn("Input Task is valid", result.output)
|
||||
@@ -677,7 +701,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
def test_validate_failed_to_load_task(self):
|
||||
env = self._create_env()
|
||||
result = self.invoke(["task", "validate", "/no/such/task",
|
||||
"--deployment", env["uuid"]])
|
||||
"--env", env["uuid"]])
|
||||
|
||||
self.assertEqual(task.FailedToLoadTask.error_code, result.exit_code)
|
||||
|
||||
@@ -688,7 +712,7 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
mock_validate.side_effect = exceptions.InvalidTaskException("foo")
|
||||
|
||||
result = self.invoke(["task", "validate", task_file,
|
||||
"--deployment", env["uuid"]])
|
||||
"--env", env["uuid"]])
|
||||
|
||||
self.assertEqual(exceptions.InvalidTaskException.error_code,
|
||||
result.exit_code)
|
||||
@@ -746,13 +770,13 @@ class TaskCommandsTestCase(test.CLITestCase):
|
||||
mock_import_results.return_value = {"uuid": "new-uuid"}
|
||||
|
||||
result = self.invoke(["task", "import", "--file", results_file,
|
||||
"--deployment", env["uuid"], "--tag", "tag"])
|
||||
"--env", env["uuid"], "--tag", "tag"])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertIn("Task UUID: new-uuid", result.output)
|
||||
mock_import_results.assert_called_once_with(
|
||||
deployment=env["uuid"], task_results="results", tags=["tag"])
|
||||
|
||||
result = self.invoke(["task", "import", "--file", "/no/such/file",
|
||||
"--deployment", env["uuid"]])
|
||||
"--env", env["uuid"]])
|
||||
self.assertEqual(1, result.exit_code, result.output)
|
||||
self.assertIn("Invalid file name", result.output)
|
||||
@@ -127,8 +127,8 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
def test_list_verifiers_empty_verifiers(self):
|
||||
for args, expected in (
|
||||
([], "There are no verifiers."),
|
||||
(["--status", "foo"],
|
||||
"There are no verifiers with status 'foo'."),
|
||||
(["--status", "installed"],
|
||||
"There are no verifiers with status 'installed'."),
|
||||
):
|
||||
with self.subTest(args=args):
|
||||
result = self.invoke(["verify", "list-verifiers", *args])
|
||||
@@ -229,7 +229,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
# --override cannot be combined with --reconfigure/--extend
|
||||
result = self.invoke([
|
||||
"verify", "configure-verifier", verifier.uuid,
|
||||
"--deployment-id", env["uuid"], "--override", "/p/a/t/h",
|
||||
"--env", env["uuid"], "--override", "/p/a/t/h",
|
||||
"--reconfigure", "--show"])
|
||||
self.assertEqual(1, result.exit_code, result.output)
|
||||
self.assertFalse(mock_configure.called)
|
||||
@@ -237,7 +237,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
# a missing --override file is reported and exits 1
|
||||
result = self.invoke([
|
||||
"verify", "configure-verifier", verifier.uuid,
|
||||
"--deployment-id", env["uuid"], "--override", "/p/a/t/h",
|
||||
"--env", env["uuid"], "--override", "/p/a/t/h",
|
||||
"--show"])
|
||||
self.assertEqual(1, result.exit_code, result.output)
|
||||
self.assertIn("not found", result.output)
|
||||
@@ -248,7 +248,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
tf.flush()
|
||||
result = self.invoke([
|
||||
"verify", "configure-verifier", verifier.uuid,
|
||||
"--deployment-id", env["uuid"], "--override", tf.name])
|
||||
"--env", env["uuid"], "--override", tf.name])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
mock_override_configuration.assert_called_once_with(
|
||||
verifier_id=verifier.uuid, deployment_id=env["uuid"],
|
||||
@@ -260,7 +260,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
tf.flush()
|
||||
result = self.invoke([
|
||||
"verify", "configure-verifier", verifier.uuid,
|
||||
"--deployment-id", env["uuid"], "--extend", tf.name])
|
||||
"--env", env["uuid"], "--extend", tf.name])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
mock_configure.assert_called_once_with(
|
||||
verifier=verifier.uuid, deployment_id=env["uuid"],
|
||||
@@ -270,7 +270,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
# a raw json/yaml value is parsed, and --show prints the config
|
||||
result = self.invoke([
|
||||
"verify", "configure-verifier", verifier.uuid,
|
||||
"--deployment-id", env["uuid"], "--extend", "{foo: {opt: val}}",
|
||||
"--env", env["uuid"], "--extend", "{foo: {opt: val}}",
|
||||
"--show"])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertIn("config-body", result.output)
|
||||
@@ -355,14 +355,14 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
|
||||
# --pattern and --load-list are mutually exclusive
|
||||
result = self.invoke([
|
||||
"verify", "start", verifier.uuid, "--deployment-id", env["uuid"],
|
||||
"verify", "start", verifier.uuid, "--env", env["uuid"],
|
||||
"--pattern", "p", "--load-list", "/p/a/t/h"])
|
||||
self.assertEqual(1, result.exit_code, result.output)
|
||||
self.assertFalse(mock_start.called)
|
||||
|
||||
# a missing list file is reported and exits 1
|
||||
result = self.invoke([
|
||||
"verify", "start", verifier.uuid, "--deployment-id", env["uuid"],
|
||||
"verify", "start", verifier.uuid, "--env", env["uuid"],
|
||||
"--load-list", "/p/a/t/h"])
|
||||
self.assertEqual(1, result.exit_code, result.output)
|
||||
self.assertFalse(mock_start.called)
|
||||
@@ -372,7 +372,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
tf.write("test_1\ntest_2")
|
||||
tf.flush()
|
||||
result = self.invoke([
|
||||
"verify", "start", verifier.uuid, "--deployment-id",
|
||||
"verify", "start", verifier.uuid, "--env",
|
||||
env["uuid"], "--tag", "foo", "--load-list", tf.name])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
mock_start.assert_called_once_with(
|
||||
@@ -386,7 +386,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
with self.subTest(opt=opt):
|
||||
mock_start.reset_mock()
|
||||
result = self.invoke([
|
||||
"verify", "start", verifier.uuid, "--deployment-id",
|
||||
"verify", "start", verifier.uuid, "--env",
|
||||
env["uuid"], opt, "/p/a/t/h"])
|
||||
self.assertEqual(1, result.exit_code, result.output)
|
||||
self.assertFalse(mock_start.called)
|
||||
@@ -395,7 +395,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
tf.write("test_1:\ntest_2: Reason\n")
|
||||
tf.flush()
|
||||
result = self.invoke([
|
||||
"verify", "start", verifier.uuid, "--deployment-id",
|
||||
"verify", "start", verifier.uuid, "--env",
|
||||
env["uuid"], opt, tf.name])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertEqual({"test_1": None, "test_2": "Reason"},
|
||||
@@ -409,7 +409,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
"tests": {"t": {"name": "t", "status": "fail",
|
||||
"traceback": "boom-trace"}}}
|
||||
result = self.invoke([
|
||||
"verify", "start", verifier.uuid, "--deployment-id", env["uuid"],
|
||||
"verify", "start", verifier.uuid, "--env", env["uuid"],
|
||||
"--detailed", "--no-use"])
|
||||
self.assertEqual(3, result.exit_code, result.output)
|
||||
self.assertIn("boom-trace", result.output)
|
||||
@@ -421,7 +421,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
"totals": {**RESULTS["totals"], "unexpected_success": 1},
|
||||
"tests": RESULTS["tests"]}
|
||||
result = self.invoke([
|
||||
"verify", "start", verifier.uuid, "--deployment-id", env["uuid"]])
|
||||
"verify", "start", verifier.uuid, "--env", env["uuid"]])
|
||||
self.assertEqual(2, result.exit_code, result.output)
|
||||
|
||||
@mock.patch("rally.api._Verification.start")
|
||||
@@ -432,7 +432,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
status=consts.DeployStatus.DEPLOY_INIT)
|
||||
|
||||
result = self.invoke([
|
||||
"verify", "start", verifier.uuid, "--deployment-id", env["uuid"]])
|
||||
"verify", "start", verifier.uuid, "--env", env["uuid"]])
|
||||
|
||||
self.assertEqual(1, result.exit_code, result.output)
|
||||
|
||||
@@ -453,7 +453,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
"totals": RESULTS["totals"], "tests": RESULTS["tests"]}
|
||||
|
||||
result = self.invoke([
|
||||
"verify", "rerun", verification["uuid"], "--deployment-id",
|
||||
"verify", "rerun", verification["uuid"], "--env",
|
||||
env["uuid"], "--failed"])
|
||||
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
@@ -468,7 +468,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
"tests": {"t": {"name": "t", "status": "fail",
|
||||
"traceback": "boom-trace"}}}
|
||||
result = self.invoke([
|
||||
"verify", "rerun", verification["uuid"], "--deployment-id",
|
||||
"verify", "rerun", verification["uuid"], "--env",
|
||||
env["uuid"], "--detailed", "--no-use"])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertIn("boom-trace", result.output)
|
||||
@@ -527,7 +527,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
"RRRRRRRRRRRRRR) |\n"
|
||||
"| Verifier type | fake-verifier-tool (platform: tests) "
|
||||
" |\n"
|
||||
"| Deployment name | Some Deploy (UUID: EEEEEEEEEEEEEEEEEEEEEE"
|
||||
"| Environment | Some Deploy (UUID: EEEEEEEEEEEEEEEEEEEEEE"
|
||||
"EEEEEEEEEEEEEE) |\n"
|
||||
"| Tests count | 1 "
|
||||
" |\n"
|
||||
@@ -567,8 +567,8 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
|
||||
for args, expected in (
|
||||
([], "There are no verifications."),
|
||||
(["--id", verifier.uuid, "--deployment-id", env["uuid"],
|
||||
"--status", "bar"],
|
||||
(["--id", verifier.uuid, "--env", env["uuid"],
|
||||
"--status", "finished"],
|
||||
"There are no verifications that meet specified criteria."),
|
||||
):
|
||||
with self.subTest(args=args):
|
||||
@@ -629,7 +629,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
|
||||
# a missing input file is reported and exits 1
|
||||
result = self.invoke([
|
||||
"verify", "import", verifier.uuid, "--deployment-id", env["uuid"],
|
||||
"verify", "import", verifier.uuid, "--env", env["uuid"],
|
||||
"--file", "/p/a/t/h"])
|
||||
self.assertEqual(1, result.exit_code, result.output)
|
||||
self.assertFalse(mock_import_results.called)
|
||||
@@ -639,7 +639,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
tf.write("data")
|
||||
tf.flush()
|
||||
result = self.invoke([
|
||||
"verify", "import", verifier.uuid, "--deployment-id",
|
||||
"verify", "import", verifier.uuid, "--env",
|
||||
env["uuid"], "--file", tf.name])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
mock_import_results.assert_called_once_with(
|
||||
@@ -650,7 +650,7 @@ class VerifyCommandsTestCase(test.CLITestCase):
|
||||
tf.write("data")
|
||||
tf.flush()
|
||||
result = self.invoke([
|
||||
"verify", "import", verifier.uuid, "--deployment-id",
|
||||
"verify", "import", verifier.uuid, "--env",
|
||||
env["uuid"], "--file", tf.name, "--no-use"])
|
||||
self.assertEqual(0, result.exit_code, result.output)
|
||||
self.assertIn("Verification UUID", result.output)
|
||||
|
||||
Reference in new issue
Block a user