Esempio n. 1
0
async def _check_data_dir_compatibility(conn):
    instancedata = await _get_instance_data(conn)
    datadir_version = instancedata.get('version')
    if datadir_version:
        datadir_major = datadir_version.get('major')

    expected_ver = buildmeta.get_version()

    if datadir_major != expected_ver.major:
        raise errors.ConfigurationError(
            'database instance incompatible with this version of EdgeDB',
            details=(f'The database instance was initialized with '
                     f'EdgeDB version {datadir_major}, '
                     f'which is incompatible with this version '
                     f'{expected_ver.major}'),
            hint=(f'You need to recreate the instance and upgrade '
                  f'using dump/restore.'))

    datadir_catver = instancedata.get('catver')
    expected_catver = edbdef.EDGEDB_CATALOG_VERSION

    if datadir_catver != expected_catver:
        raise errors.ConfigurationError(
            'database instance incompatible with this version of EdgeDB',
            details=(f'The database instance was initialized with '
                     f'EdgeDB format version {datadir_catver}, '
                     f'but this version of the server expects '
                     f'format version {expected_catver}'),
            hint=(f'You need to recreate the instance and upgrade '
                  f'using dump/restore.'))
Esempio n. 2
0
def gen_test_dumps(*, jobs, tests_dir):
    version = str(buildmeta.get_version())
    if not jobs:
        jobs = os.cpu_count()

    with tempfile.TemporaryDirectory(dir="/tmp/",
                                     prefix="edb_gen-test-dumps_") as data_dir:
        cluster = edgedb_cluster.Cluster(data_dir, testmode=True)
        print(f"Generating test dumps for version {version}"
              f" with a temporary EdgeDB instance in {data_dir}...")

        try:
            cluster.init()
            cluster.start(port=0)
            cluster.trust_local_connections()
        except BaseException:
            raise

        conn = cluster.get_connect_args()
        try:
            execute(tests_dir, conn, num_workers=jobs, version=version)
        except BaseException:
            raise
        finally:
            cluster.stop()
            cluster.destroy()
async def _populate_misc_instance_data(schema, cluster):

    mock_auth_nonce = scram.B64(scram.generate_nonce())

    instance_data = {
        'mock_auth_nonce': mock_auth_nonce,
    }

    data_dir = cluster.get_data_dir()
    fn = os.path.join(data_dir, 'instance_data.pickle')

    with open(fn, 'wb') as f:
        pickle.dump(instance_data, f)

    ver = buildmeta.get_version()
    json_instance_data = {
        'version': {
            'major': ver.major,
            'minor': ver.minor,
            'stage': ver.stage.name.lower(),
            'stage_no': ver.stage_no,
            'local': tuple(ver.local) if ver.local else (),
        }
    }

    fn = os.path.join(data_dir, 'instance_data.json')

    with open(fn, 'wt') as f:
        json.dump(json_instance_data, f)
Esempio n. 4
0
    async def test_server_version(self):
        srv_ver = await self.con.query_one(r"""
            SELECT sys::get_version()
        """)

        ver = buildmeta.get_version()

        self.assertEqual(
            (ver.major, ver.minor, ver.stage.name.lower(), ver.stage_no,
             ver.local), (srv_ver.major, srv_ver.minor, str(
                 srv_ver.stage), srv_ver.stage_no, tuple(srv_ver.local)))

        srv_ver_string = await self.con.query_one(r"""
            SELECT sys::get_version_as_str()
        """)

        self.assertEqual(srv_ver_string, str(ver))
    async def test_server_version(self):
        srv_ver = await self.con.query_single(r"""
            SELECT sys::get_version()
        """)

        ver = buildmeta.get_version()

        self.assertEqual((
            ver.major,
            ver.minor,
            ver.stage.name.lower(),
            ver.stage_no,
        ), (
            srv_ver.major,
            srv_ver.minor,
            str(srv_ver.stage),
            srv_ver.stage_no,
        ))
Esempio n. 6
0
async def _populate_misc_instance_data(cluster):

    mock_auth_nonce = scram.generate_nonce()
    ver = buildmeta.get_version()
    json_instance_data = {
        'version': {
            'major': ver.major,
            'minor': ver.minor,
            'stage': ver.stage.name.lower(),
            'stage_no': ver.stage_no,
            'local': tuple(ver.local) if ver.local else (),
        },
        'catver': edbdef.EDGEDB_CATALOG_VERSION,
        'mock_auth_nonce': mock_auth_nonce,
    }

    await _store_static_json_cache(
        cluster,
        'instancedata',
        json.dumps(json_instance_data),
    )

    return json_instance_data
Esempio n. 7
0
async def bootstrap(cluster, args) -> bool:
    pgconn = await cluster.connect()
    pgconn.add_log_listener(_pg_log_listener)
    std_schema = None

    try:
        membership = set()
        session_user = cluster.get_connection_params().user
        if session_user != edbdef.EDGEDB_SUPERUSER:
            membership.add(session_user)

        await _ensure_edgedb_role(
            cluster,
            pgconn,
            edbdef.EDGEDB_SUPERUSER,
            membership=membership,
            is_superuser=True,
        )

        if session_user != edbdef.EDGEDB_SUPERUSER:
            await _execute(
                pgconn,
                f'SET ROLE {edbdef.EDGEDB_SUPERUSER};',
            )
            cluster.set_default_session_authorization(edbdef.EDGEDB_SUPERUSER)

        need_meta_bootstrap = await _ensure_edgedb_template_database(
            cluster, pgconn)

        if need_meta_bootstrap:
            conn = await cluster.connect(database=edbdef.EDGEDB_TEMPLATE_DB)
            conn.add_log_listener(_pg_log_listener)

            await _execute(
                conn,
                f'ALTER SCHEMA public OWNER TO {edbdef.EDGEDB_SUPERUSER}',
            )

            try:
                conn.add_log_listener(_pg_log_listener)

                await _ensure_meta_schema(conn)
                instancedata = await _populate_misc_instance_data(cluster)

                std_schema = await _init_stdlib(cluster,
                                                conn,
                                                testmode=args['testmode'])
                await _bootstrap_config_spec(std_schema, cluster)
                await _compile_sys_queries(std_schema, cluster)
                schema = await _init_defaults(std_schema, std_schema, conn)
                schema = await _populate_data(std_schema, schema, conn)
                await _configure(std_schema,
                                 conn,
                                 cluster,
                                 insecure=args['insecure'],
                                 testmode=args['testmode'])
            finally:
                await conn.close()

            await _ensure_edgedb_database(pgconn,
                                          edbdef.EDGEDB_SUPERUSER_DB,
                                          edbdef.EDGEDB_SUPERUSER,
                                          cluster=cluster)

        else:
            conn = await cluster.connect(database=edbdef.EDGEDB_SUPERUSER_DB)

            try:
                std_schema = await compiler.load_std_schema(conn)
                config_spec = config.load_spec_from_schema(std_schema)
                config.set_settings(config_spec)
                instancedata = await _get_instance_data(conn)
            finally:
                await conn.close()

        datadir_version = instancedata.get('version')
        if datadir_version:
            datadir_major = datadir_version.get('major')

        expected_ver = buildmeta.get_version()

        if datadir_major != expected_ver.major:
            raise errors.ConfigurationError(
                'database instance incompatible with this version of EdgeDB',
                details=(f'The database instance was initialized with '
                         f'EdgeDB version {datadir_major}, '
                         f'which is incompatible with this version '
                         f'{expected_ver.major}'),
                hint=(f'You need to recreate the instance and upgrade '
                      f'using dump/restore.'))

        datadir_catver = instancedata.get('catver')
        expected_catver = edbdef.EDGEDB_CATALOG_VERSION

        if datadir_catver != expected_catver:
            raise errors.ConfigurationError(
                'database instance incompatible with this version of EdgeDB',
                details=(f'The database instance was initialized with '
                         f'EdgeDB format version {datadir_catver}, '
                         f'but this version of the server expects '
                         f'format version {expected_catver}'),
                hint=(f'You need to recreate the instance and upgrade '
                      f'using dump/restore.'))

        await _ensure_edgedb_template_not_connectable(pgconn)

        await _ensure_edgedb_role(
            cluster,
            pgconn,
            args['default_database_user'],
            membership=membership,
            is_superuser=True,
        )

        await _execute(
            pgconn,
            f"SET ROLE {args['default_database_user']};",
        )

        await _ensure_edgedb_database(
            pgconn,
            args['default_database'],
            args['default_database_user'],
            cluster=cluster,
        )

    finally:
        await pgconn.close()

    return need_meta_bootstrap
Esempio n. 8
0
async def _check_catalog_compatibility(
    ctx: BootstrapContext, ) -> asyncpg_con.Connection:
    tenant_id = ctx.cluster.get_runtime_params().instance_params.tenant_id
    is_default_tenant = tenant_id == buildmeta.get_default_tenant_id()

    if is_default_tenant:
        sys_db = await ctx.conn.fetchval(
            f'''
            SELECT datname
            FROM pg_database
            WHERE datname LIKE '%' || $1
            ORDER BY
                datname = $1,
                datname DESC
            LIMIT 1
        ''', edbdef.EDGEDB_SYSTEM_DB)
    else:
        sys_db = await ctx.conn.fetchval(
            f'''
            SELECT datname
            FROM pg_database
            WHERE datname = $1
        ''', ctx.cluster.get_db_name(edbdef.EDGEDB_SYSTEM_DB))

    if not sys_db:
        raise errors.ConfigurationError(
            'database instance is corrupt',
            details=(
                f'The database instance does not appear to have been fully '
                f'initialized or has been corrupted.'))

    conn = await ctx.cluster.connect(database=sys_db)

    try:
        instancedata = await _get_instance_data(conn)
        datadir_version = instancedata.get('version')
        if datadir_version:
            datadir_major = datadir_version.get('major')

        expected_ver = buildmeta.get_version()
        datadir_catver = instancedata.get('catver')
        expected_catver = edbdef.EDGEDB_CATALOG_VERSION

        status = dict(
            data_catalog_version=datadir_catver,
            expected_catalog_version=expected_catver,
        )

        if datadir_major != expected_ver.major:
            if ctx.args.status_sink is not None:
                ctx.args.status_sink(f'INCOMPATIBLE={json.dumps(status)}')
            raise errors.ConfigurationError(
                'database instance incompatible with this version of EdgeDB',
                details=(f'The database instance was initialized with '
                         f'EdgeDB version {datadir_major}, '
                         f'which is incompatible with this version '
                         f'{expected_ver.major}'),
                hint=(f'You need to recreate the instance and upgrade '
                      f'using dump/restore.'))

        if datadir_catver != expected_catver:
            if ctx.args.status_sink is not None:
                ctx.args.status_sink(f'INCOMPATIBLE={json.dumps(status)}')
            raise errors.ConfigurationError(
                'database instance incompatible with this version of EdgeDB',
                details=(f'The database instance was initialized with '
                         f'EdgeDB format version {datadir_catver}, '
                         f'but this version of the server expects '
                         f'format version {expected_catver}'),
                hint=(f'You need to recreate the instance and upgrade '
                      f'using dump/restore.'))
    except Exception:
        await conn.close()
        raise

    return conn