-
Notifications
You must be signed in to change notification settings - Fork 77
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
first prototype of migration script (#245)
- Loading branch information
1 parent
9c551bb
commit 3ec39e9
Showing
4 changed files
with
104 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,17 @@ | ||
"""migrations/__init__.py | ||
Define available migrations. | ||
""" | ||
|
||
import os | ||
import glob | ||
import importlib | ||
|
||
|
||
MIGRATIONS = {} | ||
|
||
for modname in glob.glob("v*_*.py", root_dir=os.path.dirname(__file__)): | ||
mod = importlib.import_module(f"{__name__}.{modname[:-3]}") | ||
assert all(hasattr(mod, attr) for attr in ("up_version", "down_version", "upgrade_sql", "downgrade_sql")) | ||
assert mod.down_version not in MIGRATIONS | ||
MIGRATIONS[mod.down_version] = mod |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,13 @@ | ||
|
||
|
||
up_version = (0, 8) | ||
down_version = (0, 7) | ||
|
||
upgrade_sql = [ | ||
# "CREATE TABLE", | ||
# "ALTER TABLE keys ADD COLUMN index INTEGER UNIQUE", | ||
# "ALTER TABLE keys RENAME TO key_names", | ||
"UPDATE terracotta SET version='v0.8.0'", | ||
] | ||
|
||
downgrade_sql = [] |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,72 @@ | ||
"""scripts/migrate.py | ||
Migrate databases between Terracotta versions. | ||
""" | ||
|
||
from typing import Tuple | ||
|
||
import click | ||
import sqlalchemy as sqla | ||
|
||
from terracotta import get_driver, __version__ | ||
from terracotta.migrations import MIGRATIONS | ||
|
||
|
||
def parse_version(verstr: str) -> Tuple[int]: | ||
"""Convert 'v<major>.<minor>.<patch>' to (major, minor, patch)""" | ||
components = verstr.split(".") | ||
components[0] = components[0].lstrip("v") | ||
return tuple(int(c) for c in components[:3]) | ||
|
||
|
||
def join_version(vertuple: Tuple[int]) -> str: | ||
return "v" + ".".join(map(str, vertuple)) | ||
|
||
|
||
@click.argument("DATABASE", required=True) | ||
@click.option("--from", "from_version", required=False, default=None) | ||
@click.option("--to", "to_version", required=False, default=__version__) | ||
@click.command("migrate") | ||
def migrate(database: str, to_version: str, from_version: str): | ||
from_version, to_version, tc_version = (parse_version(v)[:2] if v else None for v in (from_version, to_version, __version__)) | ||
|
||
driver = get_driver(database) | ||
|
||
# if to_version > tc_version: | ||
# raise ValueError(f"Unknown target version {join_version(to_version)} (this is {join_version(tc_version)}). Try upgrading terracotta.") | ||
|
||
if from_version is None: | ||
try: | ||
with driver.connect(verify=False): | ||
from_version = parse_version(driver.db_version)[:2] | ||
except: | ||
raise RuntimeError("Cannot determine database version.") | ||
|
||
migration_chain = [] | ||
current_version = from_version | ||
|
||
while current_version != to_version: | ||
if current_version not in MIGRATIONS: | ||
raise RuntimeError("Unexpected error") | ||
|
||
migration = MIGRATIONS[current_version] | ||
migration_chain.append(migration) | ||
current_version = migration.up_version | ||
|
||
click.echo("Upgrade path found\n") | ||
|
||
for migration in migration_chain: | ||
click.echo(f"{join_version(migration.down_version)} -> {join_version(migration.up_version)}") | ||
|
||
for cmd in migration.upgrade_sql: | ||
click.echo(f" {cmd}") | ||
|
||
click.echo("") | ||
|
||
click.echo(f"This will upgrade the database from {join_version(from_version)} -> {join_version(to_version)} and execute the above SQL commands.") | ||
click.confirm("Continue?", abort=True) | ||
|
||
with driver.connect(verify=False): | ||
for migration in migration_chain: | ||
for cmd in migration.upgrade_sql: | ||
driver.meta_store.connection.execute(sqla.text(cmd)) |