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

View File

@ -18,6 +18,11 @@ _rally()
declare -A SUBCOMMANDS
declare -A OPTS
OPTS["db_create"]=""
OPTS["db_recreate"]=""
OPTS["db_revision"]=""
OPTS["db_show"]=""
OPTS["db_upgrade"]=""
OPTS["deployment_check"]="--deployment"
OPTS["deployment_config"]="--deployment"
OPTS["deployment_create"]="--name --fromenv --filename --no-use"

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
from rally.cli import cliutils
from rally.cli.commands import db
from rally.cli.commands import deployment
from rally.cli.commands import plugin
from rally.cli.commands import task
@ -27,6 +28,7 @@ from rally.cli.commands import verify
categories = {
"db": db.DBCommands,
"deployment": deployment.DeploymentCommands,
"plugin": plugin.PluginCommands,
"task": task.TaskCommands,

View File

@ -13,68 +13,16 @@
# License for the specific language governing permissions and limitations
# under the License.
"""CLI interface for Rally DB management."""
from __future__ import print_function
import contextlib
import sys
from oslo_config import cfg
from rally.cli import cliutils
from rally.cli import envutils
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)
from rally.cli.commands import db
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)

View File

@ -558,7 +558,7 @@ def check_db_imports_in_cli(logical_line, physical_line, filename):
N360
"""
if (not filename.startswith("./rally/cli")
or filename == "./rally/cli/manage.py"):
or filename == "./rally/cli/commands/db.py"):
return
if re_db_import.search(logical_line):
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
from rally.cli import manage
from tests.unit import fakes
from tests.unit import test
@ -27,41 +26,5 @@ class CmdManageTestCase(test.TestCase):
@mock.patch("rally.cli.manage.cliutils")
def test_main(self, mock_cliutils):
manage.main()
categories = {"db": manage.DBCommands}
categories = {"db": manage.db.DBCommands}
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)