From ee38e46c12773e6da1256c27e965507a79396043 Mon Sep 17 00:00:00 2001 From: Ferdinand Thiessen Date: Thu, 18 Aug 2022 22:59:19 +0200 Subject: [PATCH] [core] Cleanup + Fix loading migrations of (dis)abled plugins Signed-off-by: Ferdinand Thiessen --- flaschengeist/alembic/__init__.py | 3 ++- flaschengeist/app.py | 7 ++---- flaschengeist/cli/install_cmd.py | 4 ++-- flaschengeist/controller/pluginController.py | 23 +++++++++++++++++++- flaschengeist/database/__init__.py | 19 +++++++++------- 5 files changed, 39 insertions(+), 17 deletions(-) diff --git a/flaschengeist/alembic/__init__.py b/flaschengeist/alembic/__init__.py index cf71018..cd7fe4a 100644 --- a/flaschengeist/alembic/__init__.py +++ b/flaschengeist/alembic/__init__.py @@ -1,4 +1,5 @@ from pathlib import Path -alembic_migrations = str(Path(__file__).resolve().parent / "migrations") +alembic_migrations_path = str(Path(__file__).resolve().parent / "migrations") +alembic_script_path = str(Path(__file__).resolve().parent) diff --git a/flaschengeist/app.py b/flaschengeist/app.py index 29ece60..ee8a6bd 100644 --- a/flaschengeist/app.py +++ b/flaschengeist/app.py @@ -5,11 +5,10 @@ from flask_cors import CORS from datetime import datetime, date from flask.json import JSONEncoder, jsonify from importlib.metadata import entry_points -from sqlalchemy.exc import OperationalError from werkzeug.exceptions import HTTPException from flaschengeist import logger -from flaschengeist.models import Plugin +from flaschengeist.controller import pluginController from flaschengeist.utils.hook import Hook from flaschengeist.config import configure_app @@ -38,11 +37,9 @@ class CustomJSONEncoder(JSONEncoder): @Hook("plugins.loaded") def load_plugins(app: Flask): app.config["FG_PLUGINS"] = {} - - enabled_plugins = Plugin.query.filter(Plugin.enabled == True).all() all_plugins = entry_points(group="flaschengeist.plugins") - for plugin in enabled_plugins: + for plugin in pluginController.get_enabled_plugins(): logger.debug(f"Searching for enabled plugin {plugin.name}") entry_point = all_plugins.select(name=plugin.name) if not entry_point: diff --git a/flaschengeist/cli/install_cmd.py b/flaschengeist/cli/install_cmd.py index 3d1b1ff..e566163 100644 --- a/flaschengeist/cli/install_cmd.py +++ b/flaschengeist/cli/install_cmd.py @@ -3,7 +3,7 @@ from click.decorators import pass_context from flask.cli import with_appcontext from flask_migrate import upgrade -from flaschengeist.alembic import alembic_migrations +from flaschengeist.alembic import alembic_migrations_path from flaschengeist.cli.plugin_cmd import install_plugin_command from flaschengeist.utils.hook import Hook @@ -14,7 +14,7 @@ from flaschengeist.utils.hook import Hook @Hook("plugins.installed") def install(ctx): # Install database - upgrade(alembic_migrations, revision="heads") + upgrade(alembic_migrations_path, revision="heads") # Install plugins install_plugin_command(ctx, [], True) diff --git a/flaschengeist/controller/pluginController.py b/flaschengeist/controller/pluginController.py index 6c16491..ba0e91b 100644 --- a/flaschengeist/controller/pluginController.py +++ b/flaschengeist/controller/pluginController.py @@ -8,14 +8,35 @@ import sqlalchemy from typing import Union from flask import current_app from werkzeug.exceptions import NotFound +from sqlalchemy.exc import OperationalError from importlib.metadata import entry_points from .. import logger from ..database import db -from ..utils import Hook +from ..utils.hook import Hook from ..models import Plugin, PluginSetting, Notification +def get_enabled_plugins(): + try: + enabled_plugins = Plugin.query.filter(Plugin.enabled == True).all() + except OperationalError as e: + + class PluginStub: + def __init__(self, name) -> None: + self.name = name + + logger.error("Could not connect to database or database not initialized! No plugins enabled!") + logger.debug("Can not query enabled plugins", exc_info=True) + enabled_plugins = [ + PluginStub("auth"), + PluginStub("roles"), + PluginStub("users"), + PluginStub("scheduler"), + ] + return enabled_plugins + + def get_setting(plugin_id: str, name: str, **kwargs): """Get plugin setting from database diff --git a/flaschengeist/database/__init__.py b/flaschengeist/database/__init__.py index 5bb30ef..21301d7 100644 --- a/flaschengeist/database/__init__.py +++ b/flaschengeist/database/__init__.py @@ -4,7 +4,9 @@ from flask_sqlalchemy import SQLAlchemy from importlib.metadata import EntryPoint, entry_points, distribution from sqlalchemy import MetaData +from flaschengeist.alembic import alembic_script_path from flaschengeist import logger +from flaschengeist.controller import pluginController # https://alembic.sqlalchemy.org/en/latest/naming.html metadata = MetaData( @@ -31,25 +33,26 @@ def configure_alembic(config: Config): uninstall can break the alembic version management. """ # Set main script location - config.set_main_option( - "script_location", str(distribution("flaschengeist").locate_file("") / "flaschengeist" / "alembic") - ) + config.set_main_option("script_location", alembic_script_path) # Set Flaschengeist's migrations migrations = [config.get_main_option("script_location") + "/migrations"] # Gather all migration paths - ep: EntryPoint - for ep in entry_points(group="flaschengeist.plugins"): + all_plugins = entry_points(group="flaschengeist.plugins") + for plugin in pluginController.get_enabled_plugins(): + entry_point = all_plugins.select(name=plugin.name) + if not entry_point: + continue try: - directory = ep.dist.locate_file("") - for loc in ep.module.split(".") + ["migrations"]: + directory = entry_point.dist.locate_file("") + for loc in entry_point.module.split(".") + ["migrations"]: directory /= loc if directory.exists(): logger.debug(f"Adding migration version path {directory}") migrations.append(str(directory.resolve())) except: - logger.warning(f"Could not load migrations of plugin {ep.name} for database migration.") + logger.warning(f"Could not load migrations of plugin {plugin.name} for database migration.") logger.debug("Plugin loading failed", exc_info=True) # write back seperator (we changed it if neither seperator nor locations were specified)