Skip to content

Commit c8a49ae

Browse files
[DPE-7678] recreate predefined roles (#1017)
* Recreate roles on all existing databases * Remove empty execute * Also set up the login hook on all existing dbs * Close connection if it exists * Enable set_user() extentions for all databases * Loop once and pass the cursor * Use shared db getter * Separate connections * Bump deploy timeout --------- Co-authored-by: Alex Lutay <[email protected]>
1 parent a179e9d commit c8a49ae

File tree

2 files changed

+36
-7
lines changed

2 files changed

+36
-7
lines changed

lib/charms/postgresql_k8s/v1/postgresql.py

Lines changed: 35 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -307,7 +307,7 @@ def create_user(
307307
f"WITH LOGIN{' SUPERUSER' if admin else ''} ENCRYPTED PASSWORD '{password}'"
308308
)
309309
if in_role:
310-
user_definition += f" IN ROLE \"{in_role}\""
310+
user_definition += f' IN ROLE "{in_role}"'
311311
if can_create_database:
312312
user_definition += " CREATEDB"
313313
if privileges:
@@ -332,7 +332,7 @@ def create_predefined_instance_roles(self) -> None:
332332
"""Create predefined instance roles."""
333333
connection = None
334334
try:
335-
for database in ["postgres", "template1"]:
335+
for database in self._get_existing_databases():
336336
with self._connect_to_database(
337337
database=database,
338338
) as connection, connection.cursor() as cursor:
@@ -776,6 +776,27 @@ def list_valid_privileges_and_roles(self) -> Tuple[Set[str], Set[str]]:
776776
"superuser",
777777
}, {role[0] for role in cursor.fetchall() if role[0]}
778778

779+
def _get_existing_databases(self) -> List[str]:
780+
# Template1 should go first
781+
databases = ["template1"]
782+
connection = None
783+
cursor = None
784+
try:
785+
with self._connect_to_database() as connection, connection.cursor() as cursor:
786+
cursor.execute(
787+
"SELECT datname FROM pg_database WHERE datname <> 'template0' AND datname <> 'template1';"
788+
)
789+
db = cursor.fetchone()
790+
while db:
791+
databases.append(db[0])
792+
db = cursor.fetchone()
793+
finally:
794+
if cursor:
795+
cursor.close()
796+
if connection:
797+
connection.close()
798+
return databases
799+
779800
def set_up_database(self, temp_location: Optional[str] = None) -> None:
780801
"""Set up postgres database with the right permissions."""
781802
connection = None
@@ -952,10 +973,11 @@ def set_up_login_hook_function(self) -> None:
952973
END;
953974
END;
954975
$$ LANGUAGE plpgsql;"""
976+
connection = None
955977
try:
956-
for database in ["postgres", "template1"]:
978+
for database in self._get_existing_databases():
957979
with self._connect_to_database(
958-
database=database,
980+
database=database
959981
) as connection, connection.cursor() as cursor:
960982
cursor.execute(SQL("CREATE EXTENSION IF NOT EXISTS login_hook;"))
961983
cursor.execute(SQL("CREATE SCHEMA IF NOT EXISTS login_hook;"))
@@ -964,6 +986,9 @@ def set_up_login_hook_function(self) -> None:
964986
except psycopg2.Error as e:
965987
logger.error(f"Failed to create login hook function: {e}")
966988
raise e
989+
finally:
990+
if connection:
991+
connection.close()
967992

968993
def set_up_predefined_catalog_roles_function(self) -> None:
969994
"""Create predefined catalog roles function."""
@@ -981,7 +1006,7 @@ def set_up_predefined_catalog_roles_function(self) -> None:
9811006
owner_user := quote_ident(database || '_owner');
9821007
admin_user := quote_ident(database || '_admin');
9831008
database := quote_ident(database);
984-
1009+
9851010
IF (SELECT COUNT(rolname) FROM pg_roles WHERE rolname=admin_user) = 0 THEN
9861011
statements := ARRAY[
9871012
'CREATE ROLE ' || owner_user || ' NOSUPERUSER NOCREATEDB NOCREATEROLE NOLOGIN NOREPLICATION;',
@@ -1035,8 +1060,9 @@ def set_up_predefined_catalog_roles_function(self) -> None:
10351060
END LOOP;
10361061
END;
10371062
$$ LANGUAGE plpgsql security definer;"""
1063+
connection = None
10381064
try:
1039-
for database in ["postgres", "template1"]:
1065+
for database in self._get_existing_databases():
10401066
with self._connect_to_database(
10411067
database=database
10421068
) as connection, connection.cursor() as cursor:
@@ -1052,6 +1078,9 @@ def set_up_predefined_catalog_roles_function(self) -> None:
10521078
except psycopg2.Error as e:
10531079
logger.error(f"Failed to set up predefined catalog roles function: {e}")
10541080
raise PostgreSQLCreatePredefinedRolesError() from e
1081+
finally:
1082+
if connection:
1083+
connection.close()
10551084

10561085
def update_user_password(
10571086
self, username: str, password: str, database_host: Optional[str] = None

tests/integration/ha_tests/test_scaling.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -48,7 +48,7 @@ async def test_build_and_deploy(ops_test: OpsTest, charm) -> None:
4848
),
4949
)
5050

51-
await ops_test.model.wait_for_idle(status="active", timeout=1500)
51+
await ops_test.model.wait_for_idle(status="active", timeout=1800)
5252

5353

5454
@pytest.mark.abort_on_fail

0 commit comments

Comments
 (0)