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.'))
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)
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, ))
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
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
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