Skip to content

Commit

Permalink
Add option to run plugin migrations for the default plugins
Browse files Browse the repository at this point in the history
  • Loading branch information
sh4nks committed Feb 23, 2018
1 parent 59aa812 commit 4ab2b79
Show file tree
Hide file tree
Showing 4 changed files with 74 additions and 23 deletions.
5 changes: 5 additions & 0 deletions flaskbb/app.py
Expand Up @@ -58,6 +58,7 @@
from flaskbb.utils.settings import flaskbb_config
from flaskbb.utils.translations import FlaskBBDomain


logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -424,6 +425,10 @@ def load_plugins(app):
except (OperationalError, ProgrammingError) as exc:
logger.debug("Database is not setup correctly or has not been "
"setup yet.", exc_info=exc)
# load plugins even though the database isn't setup correctly
# i.e. when creating the initial database and wanting to install
# the plugins migration as well
app.pluggy.load_setuptools_entrypoints('flaskbb_plugins')
return

for plugin in plugins:
Expand Down
48 changes: 28 additions & 20 deletions flaskbb/cli/main.py
Expand Up @@ -8,35 +8,35 @@
:copyright: (c) 2016 by the FlaskBB Team.
:license: BSD, see LICENSE for more details.
"""
import sys
import binascii
import logging
import os
import sys
import time
import requests
import binascii
import traceback
import logging
from datetime import datetime

import click
import click_log
import requests
from celery.bin.celery import CeleryCommand
from werkzeug.utils import import_string
from jinja2 import Environment, FileSystemLoader
from flask import current_app
from flask.cli import FlaskGroup, ScriptInfo, with_appcontext
from sqlalchemy_utils.functions import database_exists
from flask_alembic import alembic_click
from jinja2 import Environment, FileSystemLoader
from sqlalchemy_utils.functions import database_exists
from werkzeug.utils import import_string

from flaskbb import create_app
from flaskbb.extensions import db, whooshee, celery, alembic
from flaskbb.cli.utils import (prompt_save_user, prompt_config_path,
write_config, get_version, FlaskBBCLIError,
EmailType)
from flaskbb.utils.populate import (create_test_data, create_welcome_forum,
create_default_groups,
create_default_settings, insert_bulk_data,
update_settings_from_fixture,
create_latest_db)
from flaskbb.cli.utils import (EmailType, FlaskBBCLIError, get_version,
prompt_config_path, prompt_save_user,
write_config)
from flaskbb.extensions import alembic, celery, db, whooshee
from flaskbb.utils.populate import (create_default_groups,
create_default_settings, create_latest_db,
create_test_data, create_welcome_forum,
insert_bulk_data, run_plugin_migrations,
update_settings_from_fixture)
from flaskbb.utils.translations import compile_translations


Expand Down Expand Up @@ -125,8 +125,10 @@ def flaskbb(ctx):
@click.option("--email", "-e", type=EmailType(),
help="The email address of the user.")
@click.option("--password", "-p", help="The password of the user.")
@click.option("--no-plugins", "-n", default=False, is_flag=True,
help="Don't run the migrations for the default plugins.")
@with_appcontext
def install(welcome, force, username, email, password):
def install(welcome, force, username, email, password, no_plugins):
"""Installs flaskbb. If no arguments are used, an interactive setup
will be run.
"""
Expand Down Expand Up @@ -154,6 +156,10 @@ def install(welcome, force, username, email, password):
click.secho("[+] Creating welcome forum...", fg="cyan")
create_welcome_forum()

if not no_plugins:
click.secho("[+] Installing default plugins...", fg="cyan")
run_plugin_migrations()

click.secho("[+] Compiling translations...", fg="cyan")
compile_translations()

Expand Down Expand Up @@ -187,6 +193,7 @@ def populate(bulk_data, test_data, posts, topics, force, initdb):
if initdb:
click.secho("[+] Initializing database...", fg="cyan")
create_latest_db()
run_plugin_migrations()

if test_data:
click.secho("[+] Adding some test data...", fg="cyan")
Expand Down Expand Up @@ -243,9 +250,10 @@ def upgrade(all_latest, fixture, force):
count = update_settings_from_fixture(
fixture=settings, overwrite_group=force, overwrite_setting=force
)
click.secho("[+] {settings} settings in {groups} setting groups updated.".format(
groups=len(count), settings=sum(len(settings) for settings in count.values())), fg="green"
)
click.secho("[+] {settings} settings in {groups} setting groups "
"updated.".format(groups=len(count), settings=sum(
len(settings) for settings in count.values())
), fg="green")


@flaskbb.command("download-emojis")
Expand Down
9 changes: 9 additions & 0 deletions flaskbb/plugins/manager.py
Expand Up @@ -16,6 +16,7 @@

from flaskbb.utils.helpers import parse_pkg_metadata


logger = logging.getLogger(__name__)


Expand Down Expand Up @@ -149,3 +150,11 @@ def list_disabled_plugins(self):
def get_disabled_plugins(self):
"""Returns a list with disabled plugins."""
return self._disabled_plugins.keys()

def get_internal_plugins(self):
"""Returns a set of registered internal plugins."""
return set(self._internal_name2plugin.values())

def get_external_plugins(self):
"""Returns a set of registered external plugins."""
return set(self.get_plugins() - self.get_internal_plugins())
35 changes: 32 additions & 3 deletions flaskbb/utils/populate.py
Expand Up @@ -12,12 +12,17 @@

import collections
import logging
import os

from flask import current_app
from sqlalchemy_utils.functions import create_database, database_exists
from alembic.util.exc import CommandError

from flaskbb.extensions import alembic, db
from flaskbb.forum.models import Category, Forum, Post, Topic
from flaskbb.management.models import Setting, SettingsGroup
from flaskbb.user.models import Group, User
from sqlalchemy_utils.functions import create_database, database_exists


logger = logging.getLogger(__name__)

Expand Down Expand Up @@ -382,14 +387,38 @@ def insert_bulk_data(topic_count=10, post_count=100):
return created_topics, created_posts


def create_latest_db():
def create_latest_db(target="default@head"):
"""Creates the database including the schema using SQLAlchemy's
db.create_all method instead of going through all the database revisions.
The revision will be set to 'head' which indicates the latest alembic
revision.
:param target: The target branch. Defaults to 'default@head'.
"""
if not database_exists(db.engine.url):
create_database(db.engine.url)

db.create_all()
alembic.stamp()
alembic.stamp(target=target)


def run_plugin_migrations(plugins=None):
"""Runs the migrations for a list of plugins.
:param plugins: A iterable of plugins to run the migrations for. If set
to ``None``, all external plugin migrations will be run.
"""
if plugins is None:
plugins = current_app.pluggy.get_external_plugins()

for plugin in plugins:
plugin_name = current_app.pluggy.get_name(plugin)
if not os.path.exists(os.path.join(plugin.__path__[0], "migrations")):
logger.debug("No migrations found for plugin %s" % plugin_name)
continue
try:
alembic.upgrade(target="{}@head".format(plugin_name))
except CommandError as exc:
logger.debug("Couldn't run migrations for plugin {} because of "
"following exception: ".format(plugin_name),
exc_info=exc)

0 comments on commit 4ab2b79

Please sign in to comment.