@@ -307,7 +307,7 @@ def create_user(
307
307
f"WITH LOGIN{ ' SUPERUSER' if admin else '' } ENCRYPTED PASSWORD '{ password } '"
308
308
)
309
309
if in_role :
310
- user_definition += f" IN ROLE \ "{ in_role } \" "
310
+ user_definition += f' IN ROLE "{ in_role } "'
311
311
if can_create_database :
312
312
user_definition += " CREATEDB"
313
313
if privileges :
@@ -332,7 +332,7 @@ def create_predefined_instance_roles(self) -> None:
332
332
"""Create predefined instance roles."""
333
333
connection = None
334
334
try :
335
- for database in [ "postgres" , "template1" ] :
335
+ for database in self . _get_existing_databases () :
336
336
with self ._connect_to_database (
337
337
database = database ,
338
338
) as connection , connection .cursor () as cursor :
@@ -776,6 +776,27 @@ def list_valid_privileges_and_roles(self) -> Tuple[Set[str], Set[str]]:
776
776
"superuser" ,
777
777
}, {role [0 ] for role in cursor .fetchall () if role [0 ]}
778
778
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
+
779
800
def set_up_database (self , temp_location : Optional [str ] = None ) -> None :
780
801
"""Set up postgres database with the right permissions."""
781
802
connection = None
@@ -952,10 +973,11 @@ def set_up_login_hook_function(self) -> None:
952
973
END;
953
974
END;
954
975
$$ LANGUAGE plpgsql;"""
976
+ connection = None
955
977
try :
956
- for database in [ "postgres" , "template1" ] :
978
+ for database in self . _get_existing_databases () :
957
979
with self ._connect_to_database (
958
- database = database ,
980
+ database = database
959
981
) as connection , connection .cursor () as cursor :
960
982
cursor .execute (SQL ("CREATE EXTENSION IF NOT EXISTS login_hook;" ))
961
983
cursor .execute (SQL ("CREATE SCHEMA IF NOT EXISTS login_hook;" ))
@@ -964,6 +986,9 @@ def set_up_login_hook_function(self) -> None:
964
986
except psycopg2 .Error as e :
965
987
logger .error (f"Failed to create login hook function: { e } " )
966
988
raise e
989
+ finally :
990
+ if connection :
991
+ connection .close ()
967
992
968
993
def set_up_predefined_catalog_roles_function (self ) -> None :
969
994
"""Create predefined catalog roles function."""
@@ -981,7 +1006,7 @@ def set_up_predefined_catalog_roles_function(self) -> None:
981
1006
owner_user := quote_ident(database || '_owner');
982
1007
admin_user := quote_ident(database || '_admin');
983
1008
database := quote_ident(database);
984
-
1009
+
985
1010
IF (SELECT COUNT(rolname) FROM pg_roles WHERE rolname=admin_user) = 0 THEN
986
1011
statements := ARRAY[
987
1012
'CREATE ROLE ' || owner_user || ' NOSUPERUSER NOCREATEDB NOCREATEROLE NOLOGIN NOREPLICATION;',
@@ -1035,8 +1060,9 @@ def set_up_predefined_catalog_roles_function(self) -> None:
1035
1060
END LOOP;
1036
1061
END;
1037
1062
$$ LANGUAGE plpgsql security definer;"""
1063
+ connection = None
1038
1064
try :
1039
- for database in [ "postgres" , "template1" ] :
1065
+ for database in self . _get_existing_databases () :
1040
1066
with self ._connect_to_database (
1041
1067
database = database
1042
1068
) as connection , connection .cursor () as cursor :
@@ -1052,6 +1078,9 @@ def set_up_predefined_catalog_roles_function(self) -> None:
1052
1078
except psycopg2 .Error as e :
1053
1079
logger .error (f"Failed to set up predefined catalog roles function: { e } " )
1054
1080
raise PostgreSQLCreatePredefinedRolesError () from e
1081
+ finally :
1082
+ if connection :
1083
+ connection .close ()
1055
1084
1056
1085
def update_user_password (
1057
1086
self , username : str , password : str , database_host : Optional [str ] = None
0 commit comments