def apply(config_override=None, tag_override=None, rollback=None, skip_missing=None):
    config = get_config(config_override)
    databases = config['databases']
    if rollback and not tag_override:
        raise RuntimeError(
            'To rollback a migration you need to specify the database tag with `--tag`')
    for tag in sorted(databases):
        if tag_override and tag_override != tag:
            continue
        engine = databases[tag].get('engine', 'mysql')
        host = databases[tag].get('host', 'localhost')
        port = databases[tag].get('port', 3306)
        user = databases[tag]['user']
        password = databases[tag]['password']
        db = databases[tag]['db']
        path = add_slash(databases[tag]['path'])
        pre_migration = databases[tag].get('pre_migration', None)
        post_migration = databases[tag].get('post_migration', None)
        if skip_missing:
            try:
                check_exists(path, 'dir')
            except RuntimeError:
                continue
        else:
            check_exists(path, 'dir')
        connection = get_connection(
            engine, host, user, port, password, db, get_ssl(databases[tag]))
        if pre_migration:
            run_migration(connection, pre_migration, engine)
        if rollback:
            print(' * Rolling back %s (`%s` on %s)' % (tag, db, engine))
            rollback_migration(engine, connection, path, rollback)
        else:
            print(' * Applying migrations for %s (`%s` on %s)' %
                  (tag, db, engine))
            apply_migrations(engine, connection, path)
        if post_migration:
            run_migration(connection, post_migration, engine)
    return True