[Verify] New command to list Tempest plugins

This command allows us to list all Tempest plugins.

E.g.
  $ rally verify listplugins
+----------------------------+--------------------------------------------+
|            Name            |                 EntryPoint                 |
+----------------------------+--------------------------------------------+
| hello-world-tempest-plugin | hello_world_tempest_plugin.plugin:MyPlugin |
+----------------------------+--------------------------------------------+

Change-Id: Ifd53afd749ac47893b0fa11168b30d2536bf89fa
This commit is contained in:
Yaroslav Lobankov 2016-07-18 18:38:02 +03:00
parent 1f9abd092f
commit e33ef2575d
9 changed files with 79 additions and 7 deletions

View File

@ -54,6 +54,7 @@ _rally()
OPTS["verify_install"]="--deployment --source --version --system-wide" OPTS["verify_install"]="--deployment --source --version --system-wide"
OPTS["verify_installplugin"]="--deployment --source --version --system-wide" OPTS["verify_installplugin"]="--deployment --source --version --system-wide"
OPTS["verify_list"]="" OPTS["verify_list"]=""
OPTS["verify_listplugins"]="--deployment --system-wide"
OPTS["verify_reinstall"]="--deployment --source --version --system-wide" OPTS["verify_reinstall"]="--deployment --source --version --system-wide"
OPTS["verify_results"]="--uuid --html --json --output-file" OPTS["verify_results"]="--uuid --html --json --output-file"
OPTS["verify_show"]="--uuid --sort-by --detailed" OPTS["verify_show"]="--uuid --sort-by --detailed"

View File

@ -508,6 +508,21 @@ class Verification(object):
verifier.install_plugin() verifier.install_plugin()
@classmethod
def list_tempest_plugins(cls, deployment, system_wide=False):
"""List all installed Tempest plugins.
:param deployment: UUID or name of a deployment
:param system_wide: List all plugins installed in the local env or
in Tempest virtual env
"""
deployment_uuid = objects.Deployment.get(deployment)["uuid"]
verifier = tempest.Tempest(deployment_uuid, system_wide=system_wide)
cls._check_tempest_tree_existence(verifier)
return verifier.list_plugins()
@classmethod @classmethod
def discover_tests(cls, deployment, pattern=""): def discover_tests(cls, deployment, pattern=""):
"""Get a list of discovered tests. """Get a list of discovered tests.

View File

@ -495,6 +495,22 @@ class VerifyCommands(object):
api.Verification.install_tempest_plugin(deployment, source, api.Verification.install_tempest_plugin(deployment, source,
version, system_wide) version, system_wide)
@cliutils.args("--deployment", type=str, dest="deployment",
required=False, help="UUID or name of a deployment")
@cliutils.args("--system-wide", dest="system_wide",
help="List all plugins installed in the local env, "
"not in Tempest virtual env",
required=False, action="store_true")
@envutils.with_default_deployment(cli_arg_name="deployment")
def listplugins(self, deployment=None, system_wide=False):
"""List all installed Tempest plugins.
:param deployment: UUID or name of a deployment
:param system_wide: List all plugins installed in the local env or
in Tempest virtual env
"""
print(api.Verification.list_tempest_plugins(deployment, system_wide))
@cliutils.args("--deployment", dest="deployment", type=str, required=False, @cliutils.args("--deployment", dest="deployment", type=str, required=False,
metavar="<uuid>", help="UUID or name of a deployment") metavar="<uuid>", help="UUID or name of a deployment")
@cliutils.args("--pattern", dest="pattern", type=str, @cliutils.args("--pattern", dest="pattern", type=str,

View File

@ -53,10 +53,6 @@
<a href="{{ install.stdout_file }}">Tempest installation</a> <a href="{{ install.stdout_file }}">Tempest installation</a>
<code>$ {{ install.cmd }}</code> <code>$ {{ install.cmd }}</code>
<span class="{{ discover.status }}">[{{ discover.status }}]</span>
<a href="{{ discover.stdout_file }}">Discovering tests</a>
<code>$ {{ discover.cmd }}</code>
<span class="{{ reinstall.status }}">[{{ reinstall.status }}]</span> <span class="{{ reinstall.status }}">[{{ reinstall.status }}]</span>
<a href="{{ reinstall.stdout_file }}">Tempest re-installation</a> <a href="{{ reinstall.stdout_file }}">Tempest re-installation</a>
<code>$ {{ reinstall.cmd }}</code> <code>$ {{ reinstall.cmd }}</code>
@ -65,6 +61,14 @@
<a href="{{ installplugin.stdout_file }}">Tempest plugin installation</a> <a href="{{ installplugin.stdout_file }}">Tempest plugin installation</a>
<code>$ {{ installplugin.cmd }}</code> <code>$ {{ installplugin.cmd }}</code>
<span class="{{ listplugins.status }}">[{{ listplugins.status }}]</span>
<a href="{{ listplugins.stdout_file }}">List installed Tempest plugins</a>
<code>$ {{ listplugins.cmd }}</code>
<span class="{{ discover.status }}">[{{ discover.status }}]</span>
<a href="{{ discover.stdout_file }}">Discovering tests</a>
<code>$ {{ discover.cmd }}</code>
<span class="{{ genconfig.status }}">[{{ genconfig.status }}]</span> <span class="{{ genconfig.status }}">[{{ genconfig.status }}]</span>
<a href="{{ genconfig.stdout_file }}">Tempest config generation</a> <a href="{{ genconfig.stdout_file }}">Tempest config generation</a>
<code>$ {{ genconfig.cmd }}</code> <code>$ {{ genconfig.cmd }}</code>

View File

@ -40,6 +40,7 @@ class TempestSetupFailure(exceptions.RallyException):
def check_output(*args, **kwargs): def check_output(*args, **kwargs):
print_debug_output = kwargs.pop("print_debug_output", True)
kwargs["stderr"] = subprocess.STDOUT kwargs["stderr"] = subprocess.STDOUT
try: try:
output = subprocess.check_output(*args, **kwargs) output = subprocess.check_output(*args, **kwargs)
@ -48,7 +49,8 @@ def check_output(*args, **kwargs):
LOG.error("Error output: '%s'" % encodeutils.safe_decode(e.output)) LOG.error("Error output: '%s'" % encodeutils.safe_decode(e.output))
raise raise
LOG.debug("subprocess output: '%s'" % encodeutils.safe_decode(output)) if print_debug_output:
LOG.debug("Subprocess output: '%s'" % encodeutils.safe_decode(output))
return output return output
@ -305,6 +307,13 @@ class Tempest(object):
check_output(cmd, cwd=self.path()) check_output(cmd, cwd=self.path())
LOG.info(_("Tempest plugin has been successfully installed!")) LOG.info(_("Tempest plugin has been successfully installed!"))
def list_plugins(self):
"""List all installed Tempest plugins for local Tempest repo."""
cmd = ["tempest", "list-plugins"]
if not self._system_wide:
cmd.insert(0, self.path("tools/with_venv.sh"))
return check_output(cmd, cwd=self.path(), print_debug_output=False)
@logging.log_verification_wrapper(LOG.info, _("Run verification.")) @logging.log_verification_wrapper(LOG.info, _("Run verification."))
def _prepare_and_run(self, set_name, regex, tests_file, concur, failing): def _prepare_and_run(self, set_name, regex, tests_file, concur, failing):
if not self.is_configured(): if not self.is_configured():

View File

@ -255,6 +255,9 @@ def main():
render_vars["installplugin"] = call_rally( render_vars["installplugin"] = call_rally(
"verify installplugin --source %s" % TEMPEST_PLUGIN) "verify installplugin --source %s" % TEMPEST_PLUGIN)
# List installed Tempest plugins
render_vars["listplugins"] = call_rally("verify listplugins")
# Discover tests depending on Tempest suite # Discover tests depending on Tempest suite
discover_cmd = "verify discover" discover_cmd = "verify discover"
if args.mode == "light": if args.mode == "light":

View File

@ -483,7 +483,7 @@ class VerifyCommandsTestCase(test.TestCase):
deployment_uuid, None, version, False) deployment_uuid, None, version, False)
@mock.patch("rally.api.Verification.install_tempest_plugin") @mock.patch("rally.api.Verification.install_tempest_plugin")
def test_install_plugin_from_url( def test_installplugin_from_url(
self, mock_verification_install_tempest_plugin): self, mock_verification_install_tempest_plugin):
deployment_uuid = "83514de2-a770-4e28-82dd-2826b725e733" deployment_uuid = "83514de2-a770-4e28-82dd-2826b725e733"
url = "https://github.com/fake/plugin" url = "https://github.com/fake/plugin"
@ -492,7 +492,7 @@ class VerifyCommandsTestCase(test.TestCase):
deployment_uuid, url, None, False) deployment_uuid, url, None, False)
@mock.patch("rally.api.Verification.install_tempest_plugin") @mock.patch("rally.api.Verification.install_tempest_plugin")
def test_install_plugin_from_path( def test_installplugin_from_path(
self, mock_verification_install_tempest_plugin): self, mock_verification_install_tempest_plugin):
deployment_uuid = "83514de2-a770-4e28-82dd-2826b725e733" deployment_uuid = "83514de2-a770-4e28-82dd-2826b725e733"
path = "/tmp/fake/plugin" path = "/tmp/fake/plugin"
@ -500,6 +500,13 @@ class VerifyCommandsTestCase(test.TestCase):
mock_verification_install_tempest_plugin.assert_called_once_with( mock_verification_install_tempest_plugin.assert_called_once_with(
deployment_uuid, path, None, False) deployment_uuid, path, None, False)
@mock.patch("rally.api.Verification.list_tempest_plugins")
def test_listplugins(self, mock_verification_list_tempest_plugins):
deployment_uuid = "83514de2-a770-4e28-82dd-2826b725e733"
self.verify.listplugins(deployment_uuid)
mock_verification_list_tempest_plugins.assert_called_once_with(
deployment_uuid, False)
@mock.patch("rally.api.Verification.discover_tests") @mock.patch("rally.api.Verification.discover_tests")
def test_discover(self, mock_verification_discover_tests): def test_discover(self, mock_verification_discover_tests):
deployment_uuid = "97725f22-1cd2-46a5-8c62-3cdc36ed6d2a" deployment_uuid = "97725f22-1cd2-46a5-8c62-3cdc36ed6d2a"

View File

@ -515,6 +515,15 @@ class VerificationAPITestCase(BaseDeploymentTestCase):
"/tmp/fake/plugin") "/tmp/fake/plugin")
self.tempest.install_plugin.assert_called_once_with() self.tempest.install_plugin.assert_called_once_with()
@mock.patch("os.path.exists", return_value=True)
@mock.patch("rally.common.objects.Deployment.get")
@mock.patch("rally.verification.tempest.tempest.Tempest")
def test_list_tempest_plugins(
self, mock_tempest, mock_deployment_get, mock_exists):
mock_tempest.return_value = self.tempest
api.Verification.list_tempest_plugins(self.deployment_uuid)
self.tempest.list_plugins.assert_called_once_with()
@mock.patch("os.path.exists", return_value=True) @mock.patch("os.path.exists", return_value=True)
@mock.patch("rally.common.objects.Deployment.get") @mock.patch("rally.common.objects.Deployment.get")
@mock.patch("rally.verification.tempest.tempest.Tempest") @mock.patch("rally.verification.tempest.tempest.Tempest")

View File

@ -341,6 +341,14 @@ class TempestInstallPluginsTestCase(BaseTestCase):
mock_tempest_check_output.assert_called_with(cmd, mock_tempest_check_output.assert_called_with(cmd,
cwd=self.verifier.path()) cwd=self.verifier.path())
@mock.patch(TEMPEST_PATH + ".tempest.check_output")
def test_list_plugins(self, mock_tempest_check_output):
self.verifier.list_plugins()
cmd = [self.verifier.venv_wrapper, "tempest", "list-plugins"]
mock_tempest_check_output.assert_called_with(
cmd, cwd=self.verifier.path(), print_debug_output=False)
class TempestVerifyTestCase(BaseTestCase): class TempestVerifyTestCase(BaseTestCase):
def _get_fake_call(self, testr_args, def _get_fake_call(self, testr_args,