Merge "Add alembic version stamp capability to the DB"

This commit is contained in:
Zuul 2018-12-11 12:45:17 +00:00 committed by Gerrit Code Review
commit fe9808389e
4 changed files with 38 additions and 8 deletions

View File

@ -65,3 +65,8 @@ Placement Database
connection is determined by ``[placement_database]/connection`` in the
configuration file used by placement-manage. If the ``connection`` option
is not set, the command will fail. The defined database must already exist.
``placement-manage db stamp <version>``
Stamp the revision table with the given revision; dont run any migrations.
This can be used when the database already exists and you want to bring it
under alembic control.

View File

@ -10,6 +10,7 @@
# License for the specific language governing permissions and limitations
# under the License.
import functools
import six
import sys
@ -25,6 +26,8 @@ version_info = pbr.version.VersionInfo('openstack-placement')
class DbCommands(object):
def __init__(self, config):
self.config = config
def db_sync(self):
# Let exceptions raise for now, they will go to stderr.
@ -35,9 +38,13 @@ class DbCommands(object):
print(migration.version())
return 0
def db_stamp(self):
migration.stamp(self.config.command.version)
return 0
def add_db_command_parsers(subparsers):
command_object = DbCommands()
def add_db_command_parsers(subparsers, config):
command_object = DbCommands(config)
# If we set False here, we avoid having an exit during the parse
# args part of CONF processing and we can thus print out meaningful
@ -58,20 +65,27 @@ def add_db_command_parsers(subparsers):
'version', help=help, description=help)
version_parser.set_defaults(func=command_object.db_version)
help = _('Stamp the revision table with the given version.')
stamp_parser = db_parser.add_parser('stamp', help=help, description=help)
stamp_parser.add_argument('version', help=_('the version to stamp'))
stamp_parser.set_defaults(func=command_object.db_stamp)
def setup_commands():
def setup_commands(config):
# This is a separate method because it facilitates unit testing.
# Use an additional SubCommandOpt and parser for each new sub command.
add_db_cmd_parsers = functools.partial(
add_db_command_parsers, config=config)
command_opt = cfg.SubCommandOpt(
'db', dest='command', title='Command', help=_('Available DB commands'),
handler=add_db_command_parsers)
handler=add_db_cmd_parsers)
return [command_opt]
def main():
config = cfg.ConfigOpts()
conf.register_opts(config)
command_opts = setup_commands()
command_opts = setup_commands(config)
config.register_cli_opts(command_opts)
config(sys.argv[1:], project='placement',
version=version_info.version_string(),

View File

@ -65,3 +65,13 @@ def upgrade(revision, config=None):
revision = revision or "head"
config = config or _alembic_config()
alembic.command.upgrade(config, revision)
def stamp(version, config=None):
"""Used for stamp the database version.
:param version: Database version to stamp
:type version: string
"""
config = config or _alembic_config()
alembic.command.stamp(config, version)

View File

@ -37,7 +37,7 @@ class TestCommandParsers(testtools.TestCase):
# We don't use a database, but we need to set the opt as
# it's required for a valid config.
conf_fixture.config(group="placement_database", connection='sqlite://')
command_opts = manage.setup_commands()
command_opts = manage.setup_commands(conf_fixture)
# Command line opts must be registered on the conf_fixture, otherwise
# they carry over globally.
conf_fixture.register_cli_opts(command_opts)
@ -50,6 +50,7 @@ class TestCommandParsers(testtools.TestCase):
for command, args in [
('db_version', ['db', 'version']),
('db_sync', ['db', 'sync']),
('db_stamp', ['db', 'stamp', 'b4ed3a175331']),
]:
with mock.patch('placement.cmd.manage.DbCommands.'
+ command) as mock_command:
@ -100,6 +101,6 @@ class TestCommandParsers(testtools.TestCase):
self.output.stderr.seek(0)
if six.PY2:
self.assertIn('{sync,version}', self.output.stderr.read())
self.assertIn('{sync,version,stamp}', self.output.stderr.read())
else:
self.assertIn('{sync,version}', self.output.stdout.read())
self.assertIn('{sync,version,stamp}', self.output.stdout.read())