[CLI] Introduce rally db <command>

Having 2 entrypoint seems redudant and complicated for end users,
so instead of rally-manage db <commands> let's use rally db <commands>

This reduces amount of code and commands needed to know to work with
Rally which is actually good.

This patch doesn't remove rally-manage just deprecates it

Change-Id: Ib35db2d22174cd3d3eee0d87358ad07a91dce0d9
This commit is contained in:
Boris Pavlovic 2017-08-28 23:32:58 -07:00
parent c182493c6a
commit b84a79e98b
8 changed files with 130 additions and 102 deletions

View File

@ -20,7 +20,6 @@ from docutils.parsers import rst
from rally.cli import cliutils from rally.cli import cliutils
from rally.cli import main from rally.cli import main
from rally.cli import manage
import utils import utils
@ -153,10 +152,7 @@ def get_defaults(func):
def make_command_section(category_name, name, parser): def make_command_section(category_name, name, parser):
# NOTE(andreykurilin): there is only one category in rally-manage, so section = utils.subcategory("rally %s %s" % (category_name, name))
# let's just hardcode it.
cmd = "rally-manage" if category_name == "db" else "rally"
section = utils.subcategory("%s %s %s" % (cmd, category_name, name))
section.extend(utils.parse_text(parser["description"])) section.extend(utils.parse_text(parser["description"]))
if parser["parser"].arguments: if parser["parser"].arguments:
defaults = get_defaults(parser["parser"].defaults["action_fn"]) defaults = get_defaults(parser["parser"].defaults["action_fn"])
@ -196,7 +192,6 @@ class CLIReferenceDirective(rst.Directive):
def run(self): def run(self):
parser = Parser() parser = Parser()
categories = copy.copy(main.categories) categories = copy.copy(main.categories)
categories["db"] = manage.DBCommands
if "group" in self.options: if "group" in self.options:
categories = {k: v for k, v in categories.items() categories = {k: v for k, v in categories.items()
if k == self.options["group"]} if k == self.options["group"]}

View File

@ -18,6 +18,11 @@ _rally()
declare -A SUBCOMMANDS declare -A SUBCOMMANDS
declare -A OPTS declare -A OPTS
OPTS["db_create"]=""
OPTS["db_recreate"]=""
OPTS["db_revision"]=""
OPTS["db_show"]=""
OPTS["db_upgrade"]=""
OPTS["deployment_check"]="--deployment" OPTS["deployment_check"]="--deployment"
OPTS["deployment_config"]="--deployment" OPTS["deployment_config"]="--deployment"
OPTS["deployment_create"]="--name --fromenv --filename --no-use" OPTS["deployment_create"]="--name --fromenv --filename --no-use"
@ -91,4 +96,4 @@ _rally()
return 0 return 0
} }
complete -o filenames -F _rally rally complete -o filenames -F _rally rally

59
rally/cli/commands/db.py Normal file
View File

@ -0,0 +1,59 @@
# Copyright 2013: Mirantis Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
from __future__ import print_function
from oslo_config import cfg
from rally.cli import envutils
from rally.common import db
class DBCommands(object):
"""CLI commands for DB management."""
def recreate(self, api):
"""Drop and create Rally database.
This will delete all existing data.
"""
db.schema_cleanup()
db.schema_create()
envutils.clear_env()
def create(self, api):
"""Create Rally database."""
db.schema_create()
def upgrade(self, api):
"""Upgrade Rally database to the latest state."""
print("Upgrading...")
start_revision = db.schema_revision()
db.schema_upgrade()
current_revision = db.schema_revision()
if start_revision != current_revision:
print("Database schema upgraded successfully "
"from {start} to {end} revision."
.format(start=start_revision, end=current_revision))
else:
print("Database is already up to date")
def revision(self, api):
"""Print current Rally database revision UUID."""
print(db.schema_revision())
def show(self, api):
"""Show the connection string."""
print(cfg.CONF.database.connection)

View File

@ -20,6 +20,7 @@ from __future__ import print_function
import sys import sys
from rally.cli import cliutils from rally.cli import cliutils
from rally.cli.commands import db
from rally.cli.commands import deployment from rally.cli.commands import deployment
from rally.cli.commands import plugin from rally.cli.commands import plugin
from rally.cli.commands import task from rally.cli.commands import task
@ -27,6 +28,7 @@ from rally.cli.commands import verify
categories = { categories = {
"db": db.DBCommands,
"deployment": deployment.DeploymentCommands, "deployment": deployment.DeploymentCommands,
"plugin": plugin.PluginCommands, "plugin": plugin.PluginCommands,
"task": task.TaskCommands, "task": task.TaskCommands,

View File

@ -13,68 +13,16 @@
# License for the specific language governing permissions and limitations # License for the specific language governing permissions and limitations
# under the License. # under the License.
"""CLI interface for Rally DB management."""
from __future__ import print_function
import contextlib
import sys import sys
from oslo_config import cfg
from rally.cli import cliutils from rally.cli import cliutils
from rally.cli import envutils from rally.cli.commands import db
from rally.common import db
@contextlib.contextmanager
def output_migration_result(method_name):
"""Print migration result."""
print("%s started." % method_name.capitalize())
start_revision = db.schema_revision()
yield
print("%s processed." % method_name.capitalize())
current_revision = db.schema_revision()
if start_revision != current_revision:
print("Database migrated successfully "
"from {start} to {end} revision.".format(start=start_revision,
end=current_revision))
else:
print("Database is already up to date")
class DBCommands(object):
"""Commands for DB management."""
def recreate(self, api):
"""Drop and create Rally database.
This will delete all existing data.
"""
db.schema_cleanup()
db.schema_create()
envutils.clear_env()
def create(self, api):
"""Create Rally database."""
db.schema_create()
def upgrade(self, api):
"""Upgrade Rally database to the latest state."""
with output_migration_result("upgrade"):
db.schema_upgrade()
def revision(self, api):
"""Print current Rally database revision UUID."""
print(db.schema_revision())
def show(self, api):
"""Show the connection string."""
print(cfg.CONF.database.connection)
def main(): def main():
categories = {"db": DBCommands} categories = {"db": db.DBCommands}
print("`rally-manage db <command>` was deprecated since 0.10.0 version "
"and is going to be removed soon. Please use `rally db <command>`.")
return cliutils.run(sys.argv, categories) return cliutils.run(sys.argv, categories)

View File

@ -558,7 +558,7 @@ def check_db_imports_in_cli(logical_line, physical_line, filename):
N360 N360
""" """
if (not filename.startswith("./rally/cli") if (not filename.startswith("./rally/cli")
or filename == "./rally/cli/manage.py"): or filename == "./rally/cli/commands/db.py"):
return return
if re_db_import.search(logical_line): if re_db_import.search(logical_line):
yield (0, "N360 CLI modules do not allow to work with " yield (0, "N360 CLI modules do not allow to work with "

View File

@ -0,0 +1,56 @@
# Copyright 2017: Mirantis Inc.
# All Rights Reserved.
#
# Licensed under the Apache License, Version 2.0 (the "License"); you may
# not use this file except in compliance with the License. You may obtain
# a copy of the License at
#
# http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
# License for the specific language governing permissions and limitations
# under the License.
import mock
from rally.cli.commands import db
from tests.unit import fakes
from tests.unit import test
class DBCommandsTestCase(test.TestCase):
def setUp(self):
super(DBCommandsTestCase, self).setUp()
self.db_commands = db.DBCommands()
self.fake_api = fakes.FakeAPI()
@mock.patch("rally.cli.commands.db.envutils")
@mock.patch("rally.cli.commands.db.db")
def test_recreate(self, mock_db, mock_envutils):
self.db_commands.recreate(self.fake_api)
db_calls = [mock.call.schema_cleanup(),
mock.call.schema_create()]
self.assertEqual(db_calls, mock_db.mock_calls)
envutils_calls = [mock.call.clear_env()]
self.assertEqual(envutils_calls, mock_envutils.mock_calls)
@mock.patch("rally.cli.commands.db.db")
def test_create(self, mock_db):
self.db_commands.create(self.fake_api)
calls = [mock.call.schema_create()]
self.assertEqual(calls, mock_db.mock_calls)
@mock.patch("rally.cli.commands.db.db")
def test_upgrade(self, mock_db):
self.db_commands.upgrade(self.fake_api)
calls = [mock.call.schema_upgrade()]
mock_db.assert_has_calls(calls)
@mock.patch("rally.cli.commands.db.db")
def test_revision(self, mock_db):
self.db_commands.revision(self.fake_api)
calls = [mock.call.schema_revision()]
mock_db.assert_has_calls(calls)

View File

@ -18,7 +18,6 @@ import sys
import mock import mock
from rally.cli import manage from rally.cli import manage
from tests.unit import fakes
from tests.unit import test from tests.unit import test
@ -27,41 +26,5 @@ class CmdManageTestCase(test.TestCase):
@mock.patch("rally.cli.manage.cliutils") @mock.patch("rally.cli.manage.cliutils")
def test_main(self, mock_cliutils): def test_main(self, mock_cliutils):
manage.main() manage.main()
categories = {"db": manage.DBCommands} categories = {"db": manage.db.DBCommands}
mock_cliutils.run.assert_called_once_with(sys.argv, categories) mock_cliutils.run.assert_called_once_with(sys.argv, categories)
class DBCommandsTestCase(test.TestCase):
def setUp(self):
super(DBCommandsTestCase, self).setUp()
self.db_commands = manage.DBCommands()
self.fake_api = fakes.FakeAPI()
@mock.patch("rally.cli.manage.envutils")
@mock.patch("rally.cli.manage.db")
def test_recreate(self, mock_db, mock_envutils):
self.db_commands.recreate(self.fake_api)
db_calls = [mock.call.schema_cleanup(),
mock.call.schema_create()]
self.assertEqual(db_calls, mock_db.mock_calls)
envutils_calls = [mock.call.clear_env()]
self.assertEqual(envutils_calls, mock_envutils.mock_calls)
@mock.patch("rally.cli.manage.db")
def test_create(self, mock_db):
self.db_commands.create(self.fake_api)
calls = [mock.call.schema_create()]
self.assertEqual(calls, mock_db.mock_calls)
@mock.patch("rally.cli.manage.db")
def test_upgrade(self, mock_db):
self.db_commands.upgrade(self.fake_api)
calls = [mock.call.schema_upgrade()]
mock_db.assert_has_calls(calls)
@mock.patch("rally.cli.manage.db")
def test_revision(self, mock_db):
self.db_commands.revision(self.fake_api)
calls = [mock.call.schema_revision()]
mock_db.assert_has_calls(calls)