0
votes

I have a multi-tenancy structure set up where each client has a schema set up for them. The structure mirrors the "parent" schema, so any migration that happens needs to happen for each schema identically.

I am using Flask-Script with Flask-Migrate to handle migrations.

What I tried so far is iterating over my schema names, building a URI for them, scoping a new db.session with the engine generated from the URI, and finally running the upgrade function from flask_migrate.

    @manager.command
    def upgrade_all_clients():
        clients = clients_model.query.all()
        for c in clients:
            application.extensions["migrate"].migrate.db.session.close_all()
            application.extensions["migrate"].migrate.db.session = db.create_scoped_session(
                options={
                    "bind": create_engine(generateURIForSchema(c.subdomain)),
                    "binds": {},
                }
            )
            upgrade()
        return

I am not entirely sure why this doesn't work, but the result is that it only runs the migration for the db that was set up when the application starts.

My theory is that I am not changing the session that was originally set up when the manager script runs.

Is there a better way to migrate each of these schemas without setting multiple binds and using the --multidb parameter? I don't think I can use SQLALCHEMY_BINDS in the config since these schemas need to be able to be dynamically created/destroyed.

1

1 Answers

0
votes

For those who are encountering the same issue, the answer to my specific situation was incredibly simple.

@manager.command
def upgrade_all_clients():
    clients = clients_model.query.all()
    for c in clients:
        print("Upgrading client '{}'...".format(c.subdomain))
        db.engine.url.database = c.subdomain
        _upgrade()
    return

The database attribute of the db.engine.url is what targets the schema. I don't know if this is the best way to solve this, but it does work and I can migrate each schema individually.