Skip to content
Draft
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 55 additions & 1 deletion materializationengine/admin.py
Original file line number Diff line number Diff line change
@@ -1,10 +1,64 @@
from flask_admin import Admin
from flask_admin import Admin, BaseView, expose
from flask_admin.contrib.sqla import ModelView
from dynamicannotationdb.models import AnalysisVersion, AnalysisTable
from flask import request
from flask import redirect, url_for, request, current_app
from dynamicannotationdb.migration import DynamicMigration, run_alembic_migration
from sqlalchemy.engine.url import make_url
from materializationengine.info_client import (
get_datastacks,
get_relevant_datastack_info,
)


def setup_admin(app, db):
admin = Admin(app, name="materializationengine")
admin.add_view(MigrationView(name="Migration"))
admin.add_view(ModelView(AnalysisVersion, db.session))
admin.add_view(ModelView(AnalysisTable, db.session))
return admin



def get_allowed_aligned_volumes():
with current_app.app_context():
datastacks = get_datastacks()
aligned_volumes = []
for datastack in datastacks:
aligned_volume_name, pcg_table_name = get_relevant_datastack_info(datastack)
aligned_volumes.append(aligned_volume_name)
return aligned_volumes

class MigrationView(BaseView):
@expose('/')
def index(self):
aligned_volumes = get_allowed_aligned_volumes()
return self.render('admin/migration.html', aligned_volumes=aligned_volumes)

@expose('/migrate_static_schemas', methods=['POST'])
def migrate_static_schemas(self):
sql_url = request.form.get('sql_url')
aligned_volume = request.form.get('aligned_volume')
sql_base_uri = sql_url.rpartition("/")[0]
sql_uri = make_url(f"{sql_base_uri}/{aligned_volume}")
migrator = run_alembic_migration(str(sql_uri))
return self.render('admin/migration.html', message=migrator, aligned_volumes=get_allowed_aligned_volumes())

@expose('/migrate_annotation_schemas', methods=['POST'])
def migrate_annotation_schemas(self):
sql_url = request.form.get('sql_url')
aligned_volume = request.form.get('aligned_volume')
dry_run = request.form.get('dry_run') == 'true'
migrator = DynamicMigration(sql_url, aligned_volume)
migrations = migrator.upgrade_annotation_models(dry_run=dry_run)
return self.render('admin/migration.html', message=migrations, aligned_volumes=get_allowed_aligned_volumes())

@expose('/migrate_foreign_key_constraints', methods=['POST'])
def migrate_foreign_key_constraints(self):
sql_url = request.form.get('sql_url')
aligned_volume = request.form.get('aligned_volume')
dry_run = request.form.get('dry_run') == 'true'
migrator = DynamicMigration(sql_url, aligned_volume)
fkey_constraint_mapping = migrator.apply_cascade_option_to_tables(dry_run=dry_run)
return self.render('admin/migration.html', message=fkey_constraint_mapping, aligned_volumes=get_allowed_aligned_volumes())

102 changes: 102 additions & 0 deletions templates/admin/migration.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Migrations</title>
<link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css">
</head>
<body>
<div class="container mt-5">
<h1 class="mb-4">Database Migrations</h1>

<div class="card mb-4">
<div class="card-header">
Migrate Static Schemas
</div>
<div class="card-body">
<form method="post" action="{{ url_for('migrationview.migrate_static_schemas') }}">
<div class="form-group">
<label for="sql_url">SQL URL:</label>
<input type="text" class="form-control" id="sql_url" name="sql_url" value="{{ config['SQLALCHEMY_DATABASE_URI'] }}">
</div>
<div class="form-group">
<label for="aligned_volume">Aligned Volume:</label>
<select class="form-control" id="aligned_volume" name="aligned_volume">
{% for volume in aligned_volumes %}
<option value="{{ volume }}">{{ volume }}</option>
{% endfor %}
</select>
</div>
<button type="submit" class="btn btn-primary">Migrate Static Schemas</button>
</form>
</div>
</div>

<div class="card mb-4">
<div class="card-header">
Migrate Annotation Schemas
</div>
<div class="card-body">
<form method="post" action="{{ url_for('migrationview.migrate_annotation_schemas') }}">
<div class="form-group">
<label for="sql_url">SQL URL:</label>
<input type="text" class="form-control" id="sql_url" name="sql_url" value="{{ config['SQLALCHEMY_DATABASE_URI'] }}">
</div>
<div class="form-group">
<label for="aligned_volume">Aligned Volume:</label>
<select class="form-control" id="aligned_volume" name="aligned_volume">
{% for volume in aligned_volumes %}
<option value="{{ volume }}">{{ volume }}</option>
{% endfor %}
</select>
</div>
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="dry_run" name="dry_run" value="true" checked>
<label class="form-check-label" for="dry_run">Dry Run</label>
</div>
<button type="submit" class="btn btn-primary">Migrate Annotation Schemas</button>
</form>
</div>
</div>

<div class="card mb-4">
<div class="card-header">
Alter Foreign Key Constraints
</div>
<div class="card-body">
<form method="post" action="{{ url_for('migrationview.migrate_foreign_key_constraints') }}">
<div class="form-group">
<label for="sql_url">SQL URL:</label>
<input type="text" class="form-control" id="sql_url" name="sql_url" value="{{ config['SQLALCHEMY_DATABASE_URI'] }}">
</div>
<div class="form-group">
<label for="aligned_volume">Aligned Volume:</label>
<select class="form-control" id="aligned_volume" name="aligned_volume">
{% for volume in aligned_volumes %}
<option value="{{ volume }}">{{ volume }}</option>
{% endfor %}
</select>
</div>
<div class="form-group form-check">
<input type="checkbox" class="form-check-input" id="dry_run" name="dry_run" value="true" checked>
<label class="form-check-label" for="dry_run">Dry Run</label>
</div>
<button type="submit" class="btn btn-primary">Alter Foreign Key Constraints</button>
</form>
</div>
</div>

{% if message %}
<div class="alert alert-info mt-4">
<h3>Migration Result:</h3>
<pre>{{ message }}</pre>
</div>
{% endif %}
</div>

<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@popperjs/core@2.5.3/dist/umd/popper.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js"></script>
</body>
</html>