Exemplo n.º 1
0
def main(argv=sys.argv):
    args = parser.parse_args(argv[1:])

    setup_logging(args.config)
    app_settings = get_appsettings(args.config)
    alembic_cfg = Config(args.config)

    blame = alembic_cfg.get_main_option('blame')
    engine = create_engine(alembic_cfg.get_main_option('sqlalchemy.url'))
    apps = aslist(app_settings['occams.apps'])
    errors = []

    assert blame, 'Need to blame someone!'

    with engine.begin() as connection:
        connection.info['blame'] = blame

        for app in apps:
            try:
                module = import_module(app)
            except ImportError:
                errors.append('{}: Unable to import'.format(app))
                continue
            else:
                if hasattr(module, 'initdb'):
                    module.initdb(connection)
                else:
                    errors.append('{}: Does not have "initdb"'.format(app))

        for error in errors:
            print(error)

        alembic_cfg.attributes['connection'] = connection
        command.stamp(alembic_cfg, 'heads')
Exemplo n.º 2
0
def alembic_cfg() -> Config:
    cfg = Config("alembic.ini")
    version_locations = cfg.get_main_option("version_locations")
    cfg.set_main_option(
        "version_locations",
        f"{version_locations} {orchestrator_module_location}/{migration_dir}/versions/schema"
    )
    logger.info("Version Locations",
                locations=cfg.get_main_option("version_locations"))
    return cfg
Exemplo n.º 3
0
def make_alembic_config(cmd_opts: Namespace,
                        base_path: str = BASE_PATH) -> Config:
    """
    Create custom alembic config.

    :param cmd_opts: Default config
    :type cmd_opts: Namespace
    :param base_path: Path of config file
    :type base_path: str
    :return: Alembic configuration
    :rtype: Config
    """

    # Make path to config absolute
    if not os.path.isabs(cmd_opts.config):
        cmd_opts.config = os.path.join(base_path, cmd_opts.config)

    config = Config(file_=cmd_opts.config, cmd_opts=cmd_opts)

    # Make path to scripts absolute
    alembic_location = config.get_main_option("script_location")
    if not os.path.isabs(alembic_location):
        config.set_main_option("script_location",
                               os.path.join(base_path, alembic_location))

    # Set alembic db from application config
    config.set_main_option("sqlalchemy.url", AppConfig().db_url)

    return config
Exemplo n.º 4
0
def make_alembic_config(options: Namespace,
                        base_path: str = PROJECT_PATH) -> Config:
    """
    Создает объект конфигурации alembic на основе аргументов командной строки,
    и настраивает его (меняет относительные пути на абсолютные).

    :param options: аргументы командной строки
    :param base_path: путь, относительного которого формируются относительные пути
    :return: объект конфигурации alembic
    """
    # Если указан относительный путь до alembic.ini, то добавляем в начало base_path
    # (формируем абсолютный путь)
    if not os.path.isabs(options.config):
        options.config = os.path.join(base_path, options.config)

    # Создаем объект конфигурации Alembic
    config = Config(file_=options.config,
                    ini_section=options.name,
                    cmd_opts=options)
    if options.db_url:
        # Меняем значение sqlalchemy.url из конфига Alembic
        config.set_main_option("sqlalchemy.url", options.db_url)

    # Подменяем путь до папки с alembic (требуется, чтобы alembic мог найти env.py, шаблон для
    # генерации миграций и сами миграции)
    alembic_location = config.get_main_option("script_location")
    if not os.path.isabs(alembic_location):
        config.set_main_option("script_location",
                               os.path.join(base_path, alembic_location))

    return config
Exemplo n.º 5
0
    def start_db_migration(self) -> None:
        """
        Runs alembic to upgrade the selected database to the current conversion head. This ensures that the database
        schema version matches the python ORM version.

        :return: Nothing
        """
        self.close_last_session()

        local_dir = os.path.dirname(
            os.path.abspath(inspect.getfile(
                inspect.currentframe())))  # script directory
        alembic_cfg = Config(
            os.path.abspath(os.path.join(local_dir, "alembic.ini")))

        # Alembic has problems, when called inside a library,
        # therefore we change the current alembic folder with its absolute path
        alembic_cfg.set_main_option(
            "script_location",
            os.path.abspath(
                os.path.join(
                    local_dir,
                    alembic_cfg.get_main_option("script_location",
                                                "alembic"))))
        alembic_cfg.set_main_option("sqlalchemy.url", self.__connection)
        command.upgrade(alembic_cfg, "head")
Exemplo n.º 6
0
    def check_current_head(self) -> bool:
        """
        Checks if the selected database schema version matches the python source ORM schema version.
        If false please run start_db_migration to update the database.

        :return: True if both version are matching, else False
        """
        local_dir = os.path.dirname(
            os.path.abspath(inspect.getfile(
                inspect.currentframe())))  # script directory
        alembic_cfg = Config(
            os.path.abspath(os.path.join(local_dir, "alembic.ini")))

        # Alembic has problems, when called inside a library,
        # therefore we change the current folder with its absolute path
        alembic_cfg.set_main_option(
            "script_location",
            os.path.abspath(
                os.path.join(
                    local_dir,
                    alembic_cfg.get_main_option("script_location",
                                                "alembic"))))

        directory = script.ScriptDirectory.from_config(alembic_cfg)
        with self.__engine.begin() as connection:
            context = migration.MigrationContext.configure(connection)
            return set(context.get_current_heads()) == set(
                directory.get_heads())
Exemplo n.º 7
0
def migrate_to_head():
    '''
        Trying to update database to head revision.
        If alembic unable to recognize current revision (In case when database version is newer than backend)
         then do nothing.
    '''

    config_file = Path(__file__).parent / 'alembic.ini'
    config = Config(config_file)

    # mindsdb can runs not from project directory
    script_location_abc = config_file.parent / config.get_main_option('script_location')
    config.set_main_option('script_location', str(script_location_abc))

    script = ScriptDirectory.from_config(config)
    with db.engine.begin() as conn:
        mc = MigrationContext.configure(conn)
        cur_revision = mc.get_current_revision()

        try:
            script.revision_map.get_revision(cur_revision)

        except ResolutionError:
            print('!!! Database version higher than application !!!')
            return

    upgrade(config=config, revision='head')
Exemplo n.º 8
0
def run_migrations_offline(config: Config, target_metadata: MetaData) -> None:
    """
    Run migrations in 'offline' mode.

    This configures the context with just a URL and not an Engine, though an
    Engine is acceptable here as well.  By skipping the Engine creation we
    don't even need a DBAPI to be available.

    Calls to context.execute() here emit the given string to the script output.
    """
    url = config.get_main_option("sqlalchemy.url")
    # RNC
    context.configure(
        url=url,
        target_metadata=target_metadata,
        render_as_batch=
        True,  # for SQLite mode; http://stackoverflow.com/questions/30378233  # noqa
        literal_binds=True,
        version_table=ALEMBIC_VERSION_TABLE,
        compare_type=custom_compare_type,
        # ... http://blog.code4hire.com/2017/06/setting-up-alembic-to-detect-the-column-length-change/  # noqa
        # ... https://eshlox.net/2017/08/06/alembic-migration-for-string-length-change/  # noqa
        # process_revision_directives=writer,
        process_revision_directives=process_revision_directives,
    )
    with context.begin_transaction():
        context.run_migrations()
Exemplo n.º 9
0
Arquivo: cli.py Projeto: swoiow/celorm
def search_models():
    """ running search models function in .alembic/env.py """

    from alembic.config import Config

    alembic_cfg = Config("alembic.ini")
    main_dir = alembic_cfg.get_main_option("script_location")
    main_dir = _set_unix_path(main_dir)

    if path.exists(main_dir):
        import importlib.util

        sp_path = path.join(main_dir, "search_models.py")

        spec = importlib.util.spec_from_file_location("search_models", sp_path)
        script = importlib.util.module_from_spec(spec)
        spec.loader.exec_module(script)
        # f._search_models()
        message = "[I] 搜索完成。"

    else:
        message = "[W] 没找到 .alembic 文件夹。"

    print(Fore.YELLOW + message.strip() + "\n")

    return
Exemplo n.º 10
0
def initConn(inifile):
    """
    Creates connection information from a config.ini file

    :param inifile: name of the ini file for database connection
    :return: connection parameters for sqlalchemy engine
    """

    # create the alembic config object from inifile
    conf = Config(inifile)

    # create the sqlurl and ssl certs from the inifile
    sqlurl = conf.get_main_option('sqlurl')
    sslrootcert = conf.get_main_option('sslrootcert')
    sslcert = conf.get_main_option('sslcert')
    sslkey = conf.get_main_option('sslkey')

    # return sqlurl and ssl certs
    return sqlurl, sslrootcert, sslcert, sslkey
Exemplo n.º 11
0
def get_alembic_config(mm, ini_file=None, ini_section='migrations', stdout=sys.stdout):
	appcfg = mm.cfg.get_settings()
	cfg = Config(file_=ini_file, ini_section=ini_section, stdout=stdout)

	if cfg.get_main_option('script_location') is None:
		cfg.set_main_option('script_location', 'netprofile:alembic')
	if cfg.get_main_option('sqlalchemy.url') is None:
		cfg.set_main_option('sqlalchemy.url', appcfg.get('sqlalchemy.url'))
	if cfg.get_main_option('output_encoding') is None:
		cfg.set_main_option('output_encoding', 'utf-8')
	migration_paths = []
	for mod in mm.modules.values():
		if mod.dist and mod.dist.location:
			path = os.path.join(mod.dist.location, 'migrations')
			if os.path.isdir(path):
				migration_paths.append(path)
	if len(migration_paths) > 0:
		cfg.set_main_option('version_locations', ' '.join(migration_paths))

	cfg.attributes['mm'] = mm
	return cfg
Exemplo n.º 12
0
def temp_db() -> Generator[None, None, None]:
    """Create new test db for testing session."""
    create_engine(TEST_DB)
    db_exists = database_exists(TEST_DB)
    if db_exists:
        drop_database(TEST_DB)
    create_database(TEST_DB)  # Create the test database.
    config = Config('alembic.ini')  # Run the migrations.
    config.set_main_option('sqlalchemy.url', TEST_DB)
    assert config.get_main_option('sqlalchemy.url') == TEST_DB
    command.upgrade(config, 'head')
    yield  # Run the tests.
    drop_database(TEST_DB)
Exemplo n.º 13
0
def get_alembic_config(mm, ini_file=None, ini_section='migrations',
                       stdout=sys.stdout):
    appcfg = mm.cfg.get_settings()
    cfg = Config(file_=ini_file, ini_section=ini_section, stdout=stdout)

    if cfg.get_main_option('script_location') is None:
        cfg.set_main_option('script_location', 'netprofile:alembic')
    if cfg.get_main_option('sqlalchemy.url') is None:
        cfg.set_main_option('sqlalchemy.url', appcfg.get('sqlalchemy.url'))
    if cfg.get_main_option('output_encoding') is None:
        cfg.set_main_option('output_encoding', 'utf-8')
    migration_paths = []
    for mod in mm.modules.values():
        if mod.dist and mod.dist.location:
            path = os.path.join(mod.dist.location, 'migrations')
            if os.path.isdir(path):
                migration_paths.append(path)
    if len(migration_paths) > 0:
        cfg.set_main_option('version_locations', ' '.join(migration_paths))

    cfg.attributes['mm'] = mm
    return cfg
Exemplo n.º 14
0
def show(args):
    '''Show the current schema information.'''
    alembic_cfg = Config(args.config)
    sa_url = alembic_cfg.get_main_option('sqlalchemy.url')
    engine = sa.create_engine(sa_url)
    with engine.begin() as connection:
        context = MigrationContext.configure(connection)
        current_rev = context.get_current_revision()

    script = ScriptDirectory.from_config(alembic_cfg)
    heads = script.get_heads()
    head_rev = heads[0] if len(heads) > 0 else None
    print(f'Current database revision: {current_rev}')
    print(f'The head revision of available migrations: {head_rev}')
Exemplo n.º 15
0
def main(argv=sys.argv):
    args = parser.parse_args(argv[1:])

    setup_logging(args.config)
    alembic_cfg = Config(args.config)

    blame = alembic_cfg.get_main_option('blame')
    engine = create_engine(alembic_cfg.get_main_option('sqlalchemy.url'))

    assert blame, 'Need to blame someone!'

    with engine.begin() as connection:
        connection.execute(
            sa.text('SET LOCAL "application.name" = :param'), param='occams'
        )
        connection.execute(
            sa.text('SET LOCAL "application.user" = :param'), param=blame
        )

        Base.metadata.create_all(connection)

        alembic_cfg.attributes['connection'] = connection
        command.stamp(alembic_cfg, 'heads')
Exemplo n.º 16
0
    def configure(self, options, config):
        super(AlembicAttrib, self).configure(options, config)

        ini = options.ini if options.ini else "alembic.ini"
        echo = True if options.echo else False

        config = Config(ini)
        url = config.get_main_option("sqlalchemy.url")
        engine = create_engine(url, echo=echo)
        connection = engine.connect()
        context = MigrationContext.configure(connection)
        script = ScriptDirectory.from_config(config)

        self.current_revision = context.get_current_revision()
        self.revisions = [script.revision for script in script.iterate_revisions(self.current_revision, None)]
Exemplo n.º 17
0
def main(argv=sys.argv):
    args = parser.parse_args(argv[1:])

    setup_logging(args.config)
    alembic_cfg = Config(args.config)

    engine = create_engine(alembic_cfg.get_main_option('sqlalchemy.url'))
    blame = models.get_blame_from_url(engine.url)

    with engine.begin() as connection:
        models.set_pg_locals(connection, 'initdb', blame)

        Base.metadata.create_all(connection)

        alembic_cfg.attributes['connection'] = connection
        command.stamp(alembic_cfg, 'heads')
Exemplo n.º 18
0
def make_alembic_config(cmd_opts: Union[Namespace, SimpleNamespace],
                        base_path: str = PROJECT_PATH) -> Config:
    if not os.path.isabs(cmd_opts.config):
        cmd_opts.config = os.path.join(base_path, cmd_opts.config)

    config = Config(file_=cmd_opts.config, ini_section=cmd_opts.name,
                    cmd_opts=cmd_opts)

    alembic_location = config.get_main_option("script_location")
    if not os.path.isabs(alembic_location):
        config.set_main_option("script_location",
                               os.path.join(base_path, alembic_location))
    if cmd_opts.pg_url:
        config.set_main_option("sqlalchemy.url", cmd_opts.pg_url)

    return config
Exemplo n.º 19
0
def make_alembic_config(cmd_opts: Union[Namespace, SimpleNamespace],
                        base_path: Path = PROJECT_PATH) -> Config:
    if not os.path.isabs(cmd_opts.config):
        cmd_opts.config = str(base_path / cmd_opts.config)

    config = Config(file_=cmd_opts.config,
                    ini_section=cmd_opts.name,
                    cmd_opts=cmd_opts)

    # Подменяем путь alembic на абсолютный
    alembic_location = config.get_main_option('script_location')
    if not os.path.isabs(alembic_location):
        config.set_main_option('script_location',
                               str(base_path / alembic_location))
    if cmd_opts.pg_url:
        config.set_main_option('sqlalchemy.url', cmd_opts.pg_url)

    return config
Exemplo n.º 20
0
def make_alembic_config(cmd_opts: Union[Namespace, SimpleNamespace],
                        base_path: str = PROJECT_PATH) -> Config:
    # Replace path to alembic.ini file to absolute
    if not os.path.isabs(cmd_opts.config):
        cmd_opts.config = os.path.join(base_path, cmd_opts.config)

    config = Config(file_=cmd_opts.config, ini_section=cmd_opts.name,
                    cmd_opts=cmd_opts)

    # Replace path to alembic folder to absolute
    alembic_location = config.get_main_option('script_location')
    if not os.path.isabs(alembic_location):
        config.set_main_option('script_location',
                               os.path.join(base_path, alembic_location))
    if cmd_opts.pg_url:
        config.set_main_option('sqlalchemy.url', cmd_opts.pg_url)

    return config
Exemplo n.º 21
0
def get_alembic_config():
    """
    Возвращает alembic.config.Config, который отличается от оригинального
    только заменённым именем БД, чтобы все манипуляции с данными происходили в БД для тестов.

    :return:  alembic.config.Config
    """
    config = Config('alembic.ini')
    sqlalchemy_url = config.get_main_option('sqlalchemy.url')

    # Подменяем db_url для тестовой БД.
    # Подразумевается, что тестовая БД от продуктовой отличается только названием,
    # находится на том же сервере и доступна для того же пользователя, что и продуктовая.
    last_slash_index = sqlalchemy_url.rfind('/')
    new_db_url = sqlalchemy_url[:last_slash_index +
                                1] + app.config.DB_SETTINGS['database']

    config.set_main_option('sqlalchemy.url', new_db_url)
    return config
Exemplo n.º 22
0
def initialize_db(dbconnection):
    alembic_cfg = Config(DEFAULT_ALEMBIC_INI_PATH)

    db = alembic_cfg.get_main_option("sqlalchemy.url", dbconnection)
    alembic_cfg.set_main_option("sqlalchemy.url", db)

    engine = sa.engine_from_config(
        alembic_cfg.get_section(alembic_cfg.config_ini_section),
        prefix='sqlalchemy.')

    node.create_tables(engine)
    groups.create_tables(engine)
    public.create_tables(engine)
    xfeatures.create_tables(engine)
    quotaholder_serials.create_tables(engine)

    # then, load the Alembic configuration and generate the
    # version table, "stamping" it with the most recent rev:
    command.stamp(alembic_cfg, "head")
Exemplo n.º 23
0
def initialize_db():
    alembic_cfg = Config(DEFAULT_ALEMBIC_INI_PATH)

    db = alembic_cfg.get_main_option("sqlalchemy.url",
                                     PITHOS_BACKEND_DB_CONNECTION)
    alembic_cfg.set_main_option("sqlalchemy.url", db)

    engine = sa.engine_from_config(alembic_cfg.get_section(
        alembic_cfg.config_ini_section),
                                   prefix='sqlalchemy.')

    node.create_tables(engine)
    groups.create_tables(engine)
    public.create_tables(engine)
    xfeatures.create_tables(engine)

    # then, load the Alembic configuration and generate the
    # version table, "stamping" it with the most recent rev:
    command.stamp(alembic_cfg, "head")
Exemplo n.º 24
0
Arquivo: cli.py Projeto: swoiow/celorm
def patch_env():
    from alembic.config import Config
    from alembic.script.base import ScriptDirectory

    alembic_cfg = Config("alembic.ini")

    main_dir = alembic_cfg.get_main_option("script_location")
    main_dir = _set_unix_path(main_dir)

    env_path = path.join(main_dir, "env.py")
    with open(env_path, "r") as rf:
        _origin_f = rf.read()

    with open(env_path, "w") as wf:
        _new_f = _origin_f.replace(_origin_line, _new_line)
        wf.write(_new_f)

    script = ScriptDirectory(main_dir)
    script._copy_file(path.join(_package_dir, sp_search_models),
                      path.join(main_dir, "search_models.py"))
Exemplo n.º 25
0
def oneshot(cli_ctx, alembic_config):
    '''
    Set up your database with one-shot schema migration instead of
    iterating over multiple revisions if there is no existing database.
    It uses alembic.ini to configure database connection.

    Reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
               #building-an-up-to-date-database-from-scratch
    '''
    with cli_ctx.logger:
        alembic_cfg = Config(alembic_config)
        sa_url = alembic_cfg.get_main_option('sqlalchemy.url')

        engine = sa.create_engine(sa_url)
        engine.execute('CREATE EXTENSION IF NOT EXISTS "uuid-ossp";')

        with engine.begin() as connection:
            context = MigrationContext.configure(connection)
            current_rev = context.get_current_revision()

        if current_rev is None:
            # For a fresh clean database, create all from scratch.
            # (it will raise error if tables already exist.)
            log.info('Detected a fresh new database.')
            log.info('Creating tables...')
            with engine.begin() as connection:
                alembic_cfg.attributes['connection'] = connection
                metadata.create_all(engine, checkfirst=False)
                log.info('Stamping alembic version to head...')
                command.stamp(alembic_cfg, 'head')
        else:
            # If alembic version info is already available, perform incremental upgrade.
            log.info('Detected an existing database.')
            log.info('Performing schema upgrade to head...')
            with engine.begin() as connection:
                alembic_cfg.attributes['connection'] = connection
                command.upgrade(alembic_cfg, 'head')

        log.info(
            "If you don't need old migrations, delete them and set "
            "\"down_revision\" value in the earliest migration to \"None\".")
Exemplo n.º 26
0
def main():
    alembic = CommandLine()
    options = alembic.parser.parse_args()

    # Если указан относительный путь (alembic.ini), добавляем в начало
    # абсолютный путь до приложения
    if not os.path.isabs(options.config):
        options.config = os.path.join(PROJECT_PATH, options.config)

    # Создаем объект конфигурации Alembic
    config = Config(file_=options.config,
                    ini_section=options.name,
                    cmd_opts=options)

    # Подменяем путь до папки с alembic на абсолютный (требуется, чтобы alembic
    # мог найти env.py, шаблон для генерации миграций и сами миграции)
    alembic_location = config.get_main_option('script_location')
    if not os.path.isabs(alembic_location):
        config.set_main_option('script_location',
                               os.path.join(PROJECT_PATH, alembic_location))

    # Запускаем команду alembic
    exit(alembic.run_cmd(config, options))
Exemplo n.º 27
0
def make_alembic_config(cmd_opts: Union[Namespace, SimpleNamespace],
                        base_path: str = PROJECT_PATH) -> Config:
    """
    Creates alembic configuration object based on command line arguments,
    replaces relatives pathes with absolute ones.
    """
    # Replace relative path to alembic.ini with absolute one
    if not os.path.isabs(cmd_opts.config):
        cmd_opts.config = os.path.join(base_path, cmd_opts.config)

    config = Config(file_=cmd_opts.config,
                    ini_section=cmd_opts.name,
                    cmd_opts=cmd_opts)

    # Replace relative path to directory with alembic with absolute one
    alembic_location = config.get_main_option('script_location')
    if not os.path.isabs(alembic_location):
        config.set_main_option('script_location',
                               os.path.join(base_path, alembic_location))
    if cmd_opts.pg_url:
        config.set_main_option('sqlalchemy.url', cmd_opts.pg_url)

    return config
Exemplo n.º 28
0
def make_alembic_config(cmd_opts: Union[Namespace, SimpleNamespace],
                        base_path: str = PROJECT_PATH) -> Config:
    """
    Создает объект конфигурации alembic на основе аргументов командной строки,
    подменяет относительные пути на абсолютные.
    """
    # Подменяем путь до файла alembic.ini на абсолютный
    if not os.path.isabs(cmd_opts.config):
        cmd_opts.config = os.path.join(base_path, cmd_opts.config)

    config = Config(file_=cmd_opts.config,
                    ini_section=cmd_opts.name,
                    cmd_opts=cmd_opts)

    # Подменяем путь до папки с alembic на абсолютный
    alembic_location = config.get_main_option('script_location')
    if not os.path.isabs(alembic_location):
        config.set_main_option('script_location',
                               os.path.join(base_path, alembic_location))
    if cmd_opts.pg_url:
        config.set_main_option('sqlalchemy.url', cmd_opts.pg_url)

    return config
Exemplo n.º 29
0
class Database():
    def __init__(self, config, database_url, before_rev, after_rev):
        self.before_rev = before_rev
        self.after_rev = after_rev
        self.alembic_cfg = Config(config)
        self.alembic_cfg.set_main_option("sqlalchemy.url", database_url)
        command.upgrade(self.alembic_cfg, before_rev)
        self.engine = create_engine(
            self.alembic_cfg.get_main_option("sqlalchemy.url"))
        self.metadata = MetaData()
        self.metadata.reflect(bind=self.engine)

    def insert(self, data):
        connection = self.engine.connect()
        for table_name, table_data in data.items():

            table = self.metadata.tables[table_name]

            for entry in table_data:
                for column in table.c:
                    if not column.nullable and column.name not in entry:
                        entry[column.name.split(".")[-1]] = generate_fake_data(
                            column.type)
                print(entry)
                connection.execute(table.insert().values(**entry))
        connection.close()

    def migrate(self):
        command.upgrade(self.alembic_cfg, self.after_rev)
        self.metadata = MetaData()
        self.metadata.reflect(bind=self.engine)

    def get_table(self, table_name):
        return self.metadata.tables[table_name]

    def connection(self):
        return self.engine.connect()
Exemplo n.º 30
0
def oneshot(args):
    '''Set up your database with one-shot schema migration instead of
    iterating over multiple revisions.
    It uses alembic.ini to configure database connection.

    Reference: http://alembic.zzzcomputing.com/en/latest/cookbook.html
               #building-an-up-to-date-database-from-scratch
    '''
    from alembic.config import Config
    from alembic import command

    alembic_cfg = Config(args.config)
    sa_url = alembic_cfg.get_main_option('sqlalchemy.url')

    log.info('Creating tables...')
    engine = sa.create_engine(sa_url)
    engine.execute('CREATE EXTENSION IF NOT EXISTS "uuid-ossp";')
    # it will raise error if tables already exist.
    metadata.create_all(engine, checkfirst=False)

    log.info(f'Stamping alembic version to {args.schema_version}...')
    command.stamp(alembic_cfg, args.schema_version)
    log.info("If you don't need old migrations, delete them and set "
             "\"down_revision\" value in the earliest migration to \"None\".")
Exemplo n.º 31
0
class MakeMigrations(DataBaseCommands):
    def create_model_branch(self,
                            apps: typing.List[typing.Union[str]]) -> None:
        for app in apps:
            os.environ["CRAX_CURRENT"] = app
            version_path = self.create_version_dir(app)
            try:
                self.config.set_main_option("version_locations", version_path)
                revision(
                    self.config,
                    branch_label=f"{self.db_name}/{app}",
                    autogenerate=True,
                    version_path=version_path,
                    message=self.args.message,
                )
            except CommandError as e:
                sys.stderr.write(
                    f"Failed to create initial migrations: {e} \n")
                break

    def get_revisions(self) -> dict:
        revisions = {}
        for app in self.applications:
            alembic_script = ScriptDirectory.from_config(self.config)
            try:
                rev = alembic_script.get_revisions(
                    f"{self.db_name}/{app}@head")
                if rev:
                    label = list(rev[0].branch_labels)[0]
                    revisions.update(
                        {label: [rev[0].revision, rev[0].down_revision]})
            except (CommandError, KeyError):
                pass
        return revisions

    def wipe_existing_versions(self) -> None:
        engine = create_engine(self.default_connection, echo=False)
        session = sessionmaker()
        _session = session(bind=engine)
        try:
            _session.execute("delete from alembic_version")
            _session.commit()
        except (ProgrammingError, OperationalError):
            sys.stdout.write(
                "Failed to delete alembic versions. If you had an errors, please check it out. \n"
            )

    def check_migrations_exist(self, app: str) -> Optional[bool]:
        if app != "crax.auth":
            app_dir = f"{self.project_url}/{app}"
        else:
            module = "crax.auth"
            spl_module = module.split(".")
            auth_path = __import__(module, fromlist=spl_module)
            app_dir = auth_path.__path__[0]
        if "models.py" in os.listdir(app_dir):
            if len(self.databases) > 1:
                try:
                    app_content = os.listdir(
                        f"{app_dir}/{self.migrations_dir}")
                    check_path = self.db_name
                except FileNotFoundError:
                    return False
            else:
                try:
                    app_content = os.listdir(app_dir)
                    check_path = self.migrations_dir
                except FileNotFoundError:  # pragma: no cover
                    return False
            if check_path in app_content:
                return True
            else:
                return False

    def delete_crax_migrations(self, module: str) -> None:
        spl_module = module.split(".")
        auth_path = __import__(module, fromlist=spl_module)
        path = f"{auth_path.__path__[0]}/{self.migrations_dir}"
        if os.path.exists(path):
            shutil.rmtree(path)

    def check_deleted(self) -> None:
        dir_exists = os.path.exists(f"{self.project_url}/{self.alembic_dir}")
        if self.config is not None and dir_exists:
            if len(self.databases) > 1:
                migration_dirs = [
                    f"{self.project_url}/{app}/{self.migrations_dir}/{self.db_name}"
                    for app in self.applications if app != "crax.auth"
                ]
            else:
                migration_dirs = [
                    f"{self.project_url}/{app}/{self.migrations_dir}"
                    for app in self.applications if app != "crax.auth"
                ]

            engine = create_engine(self.default_connection, echo=False)
            session = sessionmaker()
            _session = session(bind=engine)
            try:
                existing_versions = [
                    x
                    for x in _session.execute("select * from alembic_version")
                ]
                not_existing_dirs = any(
                    [not os.path.exists(x) for x in migration_dirs])
                if existing_versions and not_existing_dirs:
                    self.delete_crax_migrations("crax.auth")
                    if os.path.isfile(f"{self.project_url}/alembic.ini"):
                        self.write_config("alembic", "crax_migrated",
                                          "migrated")
                    self.wipe_existing_versions()
            except (ProgrammingError, OperationalError):
                sys.stdout.write(
                    "Failed to get alembic versions. If you had an errors, please check it out. \n"
                )

    def make_migrations(self) -> None:
        os.environ["CRAX_ONLINE"] = "true"
        dir_exists = os.path.exists(f"{self.project_url}/{self.alembic_dir}")

        if self.config is None or not dir_exists:
            if os.path.isfile(f"{self.project_url}/alembic.ini"):
                os.remove(f"{self.project_url}/alembic.ini")
            if os.path.exists(f"{self.project_url}/{self.alembic_dir}"):
                shutil.rmtree(f"{self.project_url}/{self.alembic_dir}")

            self.delete_crax_migrations("crax.auth")
            self.wipe_existing_versions()
            self.config = Config("alembic.ini")
            init(self.config, self.alembic_dir, package=True)
            shutil.copy(env.__file__,
                        f"{self.project_url}/{self.alembic_dir}/env.py")
            self.create_model_branch(self.applications)
            self.create_db_map()

        else:
            self.check_deleted()
            migrated = self.config.get_main_option("crax_migrated")
            if migrated == "not migrated":
                sys.stderr.write(
                    "You have unapplied migrations. Please run migrate command first. \n"
                )
                sys.exit(1)
            db_map = self.config.get_main_option("crax_db_map")

            if db_map:
                try:
                    map_dict = json.loads(
                        self.config.get_main_option("crax_db_map"))
                    current_db_map = map_dict[self.db_name]
                    if isinstance(current_db_map, dict):
                        os.environ["CRAX_DB_TABLES"] = json.dumps(
                            current_db_map)
                except KeyError:
                    pass
            for app in self.applications:
                os.environ["CRAX_CURRENT"] = app
                version_dir = self.create_version_dir(app)
                exists = self.check_migrations_exist(app)
                message = self.get_option("message")
                if exists is not None:
                    if exists is False:
                        revision(
                            self.config,
                            branch_label=f"{self.db_name}/{app}",
                            head="base",
                            version_path=version_dir,
                            autogenerate=True,
                            message=message,
                        )
                        if self.check_branch_exists(f"{self.db_name}/{app}"):
                            revisions = self.get_revisions()
                            if revisions:
                                try:
                                    stamp(
                                        self.config,
                                        revisions[f"{self.db_name}/{app}"][0],
                                    )
                                except (KeyError, IndexError):
                                    stamp(self.config,
                                          f"{self.db_name}/{app}@head")

                    else:
                        revision(
                            self.config,
                            head=f"{self.db_name}/{app}@head",
                            version_path=version_dir,
                            autogenerate=True,
                            message=message,
                        )
                        if self.check_branch_exists(f"{self.db_name}/{app}"):
                            revisions = self.get_revisions()
                            if revisions:
                                try:
                                    stamp(
                                        self.config,
                                        revisions[f"{self.db_name}/{app}"][0],
                                    )
                                except (KeyError, IndexError):
                                    stamp(self.config,
                                          f"{self.db_name}/{app}@head")
                else:
                    sys.stdout.write(
                        f"No models found in application {app}. Skipping. \n")
            revisions = self.get_revisions()
            for app in self.applications:
                if revisions:
                    if self.check_branch_exists(f"{self.db_name}/{app}"):
                        try:
                            conf_latest = self.config.get_main_option(
                                "crax_latest_revisions", None)
                            if conf_latest:
                                latest = json.loads(conf_latest)
                                app_latest = latest[f"{self.db_name}/{app}"]
                                if revisions[f"{self.db_name}/{app}"][
                                        0] != app_latest:
                                    if (revisions[f"{self.db_name}/{app}"][1]
                                            is not None):
                                        stamp(
                                            self.config,
                                            revisions[f"{self.db_name}/{app}"]
                                            [1],
                                        )
                                    else:
                                        stamp(self.config,
                                              f"{self.db_name}/{app}@base")
                        except (KeyError, IndexError, CommandError) as e:
                            branch = f"{self.db_name}/{app}"
                            if branch in revisions:
                                stamp(self.config,
                                      f"{self.db_name}/{app}@base")
                            else:
                                sys.stderr.write(
                                    f"Failed to stamp: {e}. Please check it out. \n"
                                )
        self.write_config("alembic", "crax_migrated", "not migrated")
Exemplo n.º 32
0
from com.app_utils import load_config_secrets

LOCALDEV_PORT = 8080

NAME = 'Sitemap'
ROOT_URL_PROD = 'http://sitemap.baylaunch.com'
ROOT_URL_DEV = 'http://localhost:%d' % LOCALDEV_PORT

IS_REAL_PROD = os.environ.get('COMMIT') is not None
IS_LIKE_PROD = (IS_REAL_PROD or (os.environ.get('PRODUCTION') == '1')
                or (len(sys.argv) >= 2 and sys.argv[1] == 'prod'))

ALEMBIC_CONFIG_FILE = 'alembic_prod.ini' if IS_LIKE_PROD else 'alembic.ini'
ALEMBIC_CONFIG = Config(ALEMBIC_CONFIG_FILE)
DB_URL = ALEMBIC_CONFIG.get_main_option('sqlalchemy.url')

VERSION = os.environ.get('COMMIT') or str(int(
    time.time() * 1000))  # cache-busts Angular templates

CONFIG = {
    'SQLALCHEMY_DATABASE_URI': DB_URL,
    'ROOT_URL_WITH_SLASH': (ROOT_URL_PROD if IS_LIKE_PROD else ROOT_URL_DEV) +
    '/',  # for auto_context

    # render
    'RENDER_URL':
    'http://localhost:%s' % (os.environ.get('RENDER_PORT') or 3000),
    #'RENDER_PROD_ONLY': True,

    #'LOG_SQL': True,
Exemplo n.º 33
0
def create_db(params):
    params = process_connection_values(params)
    db_name = params["database"]
    username = params["username"]

    params["username"] = MASTER_USER
    params["password"] = MASTER_PASSWORD

    master_params = params.copy()
    master_params["database"] = MASTER_DB
    engine = connect(master_params)
    engine.execute('COMMIT')
    sql = 'CREATE DATABASE "{}";'.format(db_name)
    try:
        engine.execute(sql)
    except Exception as e:
        print sql, e

    # TODO: This will only run for the first time and fail in all other cases.
    # Maybe test before instead?
    sql = 'CREATE ROLE {user} LOGIN PASSWORD "{user}" VALID UNTIL "infinity";'.format(
        user=username)
    try:
        engine.execute(sql)
    except Exception as e:
        pass

    engine = connect(params)

    # TODO: Alembic (and sqlalchemy for that matter) don't like schemas. We should
    # figure out a way to add these later
    config = load_flask_config()
    models = config.get("models", [])
    if not models:
        raise Exception("This app has no models defined in config")

    for model_module_name in models:
        log.info("Building models from %s", model_module_name)
        models = importlib.import_module(model_module_name)
        models.ModelBase.metadata.create_all(engine)

    # stamp the db with the latest alembic upgrade version
    from drift.flaskfactory import _find_app_root
    approot = _find_app_root()
    ini_path = os.path.join(approot, "alembic.ini")
    alembic_cfg = Config(ini_path)
    script_path = os.path.join(
        os.path.split(os.path.abspath(ini_path))[0], "alembic")
    alembic_cfg.set_main_option("script_location", script_path)
    db_names = alembic_cfg.get_main_option('databases')
    connection_string = format_connection_string(params)
    alembic_cfg.set_section_option(db_names, "sqlalchemy.url",
                                   connection_string)
    command.stamp(alembic_cfg, "head")

    for schema in SCHEMAS:
        # Note that this does not automatically grant on tables added later
        sql = '''
                 GRANT SELECT, INSERT, UPDATE, DELETE ON ALL TABLES IN SCHEMA "{schema}" TO {user};
                 GRANT USAGE, SELECT, UPDATE ON ALL SEQUENCES IN SCHEMA "{schema}" TO {user};
                 GRANT ALL ON SCHEMA "{schema}" TO {user};'''.format(
            schema=schema, user=username)
        try:
            engine.execute(sql)
        except Exception as e:
            print sql, e

    return db_name
Exemplo n.º 34
0
def parse_config():
    alembic_cfg = Config(alembic_ini_file_path)
    app_ini_file_name = alembic_cfg.get_main_option('pylons_config_file')
    app_ini_file_dir = os.path.dirname(alembic_cfg.config_file_name)
    app_config_uri = 'config:%s' % app_ini_file_name
    return appconfig(app_config_uri, 'thelma', relative_to=app_ini_file_dir)