root: auto-migrate on startup, lock database using pg_advisory_lock
Signed-off-by: Jens Langhammer <jens.langhammer@beryju.org>
This commit is contained in:
@ -1,5 +1,6 @@
|
||||
#!/usr/bin/env python
|
||||
"""System Migration handler"""
|
||||
import os
|
||||
from importlib.util import module_from_spec, spec_from_file_location
|
||||
from inspect import getmembers, isclass
|
||||
from pathlib import Path
|
||||
@ -11,6 +12,7 @@ from structlog.stdlib import get_logger
|
||||
from authentik.lib.config import CONFIG
|
||||
|
||||
LOGGER = get_logger()
|
||||
ADV_LOCK_UID = 1000
|
||||
|
||||
|
||||
class BaseMigration:
|
||||
@ -40,18 +42,36 @@ if __name__ == "__main__":
|
||||
host=CONFIG.y("postgresql.host"),
|
||||
)
|
||||
curr = conn.cursor()
|
||||
# lock an advisory lock to prevent multiple instances from migrating at once
|
||||
LOGGER.info("waiting to acquire database lock")
|
||||
curr.execute("SELECT pg_advisory_lock(%s)", (ADV_LOCK_UID,))
|
||||
try:
|
||||
for migration in (
|
||||
Path(__file__).parent.absolute().glob("system_migrations/*.py")
|
||||
):
|
||||
spec = spec_from_file_location("lifecycle.system_migrations", migration)
|
||||
mod = module_from_spec(spec)
|
||||
# pyright: reportGeneralTypeIssues=false
|
||||
spec.loader.exec_module(mod)
|
||||
|
||||
for migration in Path(__file__).parent.absolute().glob("system_migrations/*.py"):
|
||||
spec = spec_from_file_location("lifecycle.system_migrations", migration)
|
||||
mod = module_from_spec(spec)
|
||||
# pyright: reportGeneralTypeIssues=false
|
||||
spec.loader.exec_module(mod)
|
||||
|
||||
for name, sub in getmembers(mod, isclass):
|
||||
if name != "Migration":
|
||||
continue
|
||||
migration = sub(curr, conn)
|
||||
if migration.needs_migration():
|
||||
LOGGER.info("Migration needs to be applied", migration=sub)
|
||||
migration.run()
|
||||
LOGGER.info("Migration finished applying", migration=sub)
|
||||
for name, sub in getmembers(mod, isclass):
|
||||
if name != "Migration":
|
||||
continue
|
||||
migration = sub(curr, conn)
|
||||
if migration.needs_migration():
|
||||
LOGGER.info("Migration needs to be applied", migration=sub)
|
||||
migration.run()
|
||||
LOGGER.info("Migration finished applying", migration=sub)
|
||||
LOGGER.info("applying django migrations")
|
||||
os.environ.setdefault("DJANGO_SETTINGS_MODULE", "authentik.root.settings")
|
||||
try:
|
||||
from django.core.management import execute_from_command_line
|
||||
except ImportError as exc:
|
||||
raise ImportError(
|
||||
"Couldn't import Django. Are you sure it's installed and "
|
||||
"available on your PYTHONPATH environment variable? Did you "
|
||||
"forget to activate a virtual environment?"
|
||||
) from exc
|
||||
execute_from_command_line(["", "migrate"])
|
||||
finally:
|
||||
curr.execute("SELECT pg_advisory_unlock(%s)", (ADV_LOCK_UID,))
|
||||
|
||||
Reference in New Issue
Block a user