mirror of
https://github.com/neondatabase/neon.git
synced 2026-05-31 03:50:37 +00:00
Merge commit 'dd7fff655' into problame/standby-horizon-leases
This commit is contained in:
@@ -503,6 +503,7 @@ class NeonLocalCli(AbstractNeonCli):
|
||||
pageserver_id: int | None = None,
|
||||
allow_multiple=False,
|
||||
update_catalog: bool = False,
|
||||
privileged_role_name: str | None = None,
|
||||
features: list[str] | None = None,
|
||||
) -> subprocess.CompletedProcess[str]:
|
||||
args = [
|
||||
@@ -535,6 +536,8 @@ class NeonLocalCli(AbstractNeonCli):
|
||||
args.extend(["--allow-multiple"])
|
||||
if update_catalog:
|
||||
args.extend(["--update-catalog"])
|
||||
if privileged_role_name is not None:
|
||||
args.extend(["--privileged-role-name", privileged_role_name])
|
||||
if features is not None:
|
||||
args.extend(["--features", json.dumps(features)])
|
||||
|
||||
|
||||
@@ -4326,6 +4326,7 @@ class Endpoint(PgProtocol, LogUtils):
|
||||
pageserver_id: int | None = None,
|
||||
allow_multiple: bool = False,
|
||||
update_catalog: bool = False,
|
||||
privileged_role_name: str | None = None,
|
||||
features: list[str] | None = None,
|
||||
) -> Self:
|
||||
"""
|
||||
@@ -4354,6 +4355,7 @@ class Endpoint(PgProtocol, LogUtils):
|
||||
pageserver_id=pageserver_id,
|
||||
allow_multiple=allow_multiple,
|
||||
update_catalog=update_catalog,
|
||||
privileged_role_name=privileged_role_name,
|
||||
features=features,
|
||||
)
|
||||
path = Path("endpoints") / self.endpoint_id / "pgdata"
|
||||
@@ -4808,6 +4810,7 @@ class EndpointFactory:
|
||||
config_lines: list[str] | None = None,
|
||||
pageserver_id: int | None = None,
|
||||
update_catalog: bool = False,
|
||||
privileged_role_name: str | None = None,
|
||||
features: list[str] | None = None,
|
||||
) -> Endpoint:
|
||||
ep = Endpoint(
|
||||
@@ -4832,6 +4835,7 @@ class EndpointFactory:
|
||||
config_lines=config_lines,
|
||||
pageserver_id=pageserver_id,
|
||||
update_catalog=update_catalog,
|
||||
privileged_role_name=privileged_role_name,
|
||||
features=features,
|
||||
)
|
||||
|
||||
|
||||
@@ -103,3 +103,90 @@ def test_neon_superuser(neon_simple_env: NeonEnv, pg_version: PgVersion):
|
||||
query = "DROP SUBSCRIPTION sub CASCADE"
|
||||
log.info(f"Dropping subscription: {query}")
|
||||
cur.execute(query)
|
||||
|
||||
|
||||
def test_privileged_role_override(neon_simple_env: NeonEnv, pg_version: PgVersion):
|
||||
"""
|
||||
Test that we can override the privileged role for an endpoint and when we do it,
|
||||
everything is correctly bootstrapped inside Postgres and we don't have neon_superuser
|
||||
role in the database.
|
||||
"""
|
||||
PRIVILEGED_ROLE_NAME = "my_superuser"
|
||||
|
||||
env = neon_simple_env
|
||||
env.create_branch("test_privileged_role_override")
|
||||
ep = env.endpoints.create(
|
||||
"test_privileged_role_override",
|
||||
privileged_role_name=PRIVILEGED_ROLE_NAME,
|
||||
update_catalog=True,
|
||||
)
|
||||
|
||||
ep.start()
|
||||
|
||||
ep.wait_for_migrations()
|
||||
|
||||
member_roles = [
|
||||
"pg_read_all_data",
|
||||
"pg_write_all_data",
|
||||
"pg_monitor",
|
||||
"pg_signal_backend",
|
||||
]
|
||||
|
||||
non_member_roles = [
|
||||
"pg_execute_server_program",
|
||||
"pg_read_server_files",
|
||||
"pg_write_server_files",
|
||||
]
|
||||
|
||||
role_attributes = {
|
||||
"rolsuper": False,
|
||||
"rolinherit": True,
|
||||
"rolcreaterole": True,
|
||||
"rolcreatedb": True,
|
||||
"rolcanlogin": False,
|
||||
"rolreplication": True,
|
||||
"rolconnlimit": -1,
|
||||
"rolbypassrls": True,
|
||||
}
|
||||
|
||||
if pg_version >= PgVersion.V15:
|
||||
non_member_roles.append("pg_checkpoint")
|
||||
|
||||
if pg_version >= PgVersion.V16:
|
||||
member_roles.append("pg_create_subscription")
|
||||
non_member_roles.append("pg_use_reserved_connections")
|
||||
|
||||
with ep.cursor() as cur:
|
||||
cur.execute(f"SELECT rolname FROM pg_roles WHERE rolname = '{PRIVILEGED_ROLE_NAME}'")
|
||||
assert cur.fetchall()[0][0] == PRIVILEGED_ROLE_NAME
|
||||
|
||||
cur.execute("SELECT rolname FROM pg_roles WHERE rolname = 'neon_superuser'")
|
||||
assert len(cur.fetchall()) == 0
|
||||
|
||||
cur.execute("SHOW neon.privileged_role_name")
|
||||
assert cur.fetchall()[0][0] == PRIVILEGED_ROLE_NAME
|
||||
|
||||
# check PRIVILEGED_ROLE_NAME role is created
|
||||
cur.execute(f"select * from pg_roles where rolname = '{PRIVILEGED_ROLE_NAME}'")
|
||||
assert cur.fetchone() is not None
|
||||
|
||||
# check PRIVILEGED_ROLE_NAME role has the correct member roles
|
||||
for role in member_roles:
|
||||
cur.execute(f"SELECT pg_has_role('{PRIVILEGED_ROLE_NAME}', '{role}', 'member')")
|
||||
assert cur.fetchone() == (True,), (
|
||||
f"Role {role} should be a member of {PRIVILEGED_ROLE_NAME}"
|
||||
)
|
||||
|
||||
for role in non_member_roles:
|
||||
cur.execute(f"SELECT pg_has_role('{PRIVILEGED_ROLE_NAME}', '{role}', 'member')")
|
||||
assert cur.fetchone() == (False,), (
|
||||
f"Role {role} should not be a member of {PRIVILEGED_ROLE_NAME}"
|
||||
)
|
||||
|
||||
# check PRIVILEGED_ROLE_NAME role has the correct role attributes
|
||||
for attr, val in role_attributes.items():
|
||||
cur.execute(f"SELECT {attr} FROM pg_roles WHERE rolname = '{PRIVILEGED_ROLE_NAME}'")
|
||||
curr_val = cur.fetchone()
|
||||
assert curr_val == (val,), (
|
||||
f"Role attribute {attr} should be {val} instead of {curr_val}"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user