@@ -94,6 +94,20 @@ def backup_repository_data(faker):
9494 }
9595
9696
97+ @pytest .fixture
98+ def mock_quote_ident ():
99+
100+ def mock_quote_ident (value , connection ):
101+ if value .startswith ('"' ) and value .endswith ('"' ):
102+ return value
103+ return f'"{ value } "'
104+
105+ with mock .patch (
106+ "crate.operator.restore_backup.quote_ident" , side_effect = mock_quote_ident
107+ ):
108+ yield
109+
110+
97111@pytest .mark .k8s
98112@pytest .mark .asyncio
99113@mock .patch ("crate.operator.webhooks.webhook_client._send" )
@@ -353,6 +367,7 @@ async def test_restore_backup_aws(
353367@mock .patch ("crate.operator.webhooks.webhook_client._send" )
354368@mock .patch .object (RestoreBackupSubHandler , "_create_backup_repository" )
355369@mock .patch .object (RestoreBackupSubHandler , "_ensure_snapshot_exists" )
370+ @mock .patch .object (RestoreBackupSubHandler , "_start_restore_snapshot" )
356371@mock .patch .object (RestoreInternalTables , "remove_duplicated_tables" )
357372@mock .patch .object (RestoreInternalTables , "cleanup_tables" )
358373@pytest .mark .parametrize ("gc_enabled" , [True , False ])
@@ -782,24 +797,17 @@ async def test_restore_backup_create_repo_fails(
782797 ),
783798 ],
784799)
785- def test_get_restore_type_keyword (restore_type , expected_keyword , params ):
800+ def test_get_restore_type_keyword (
801+ restore_type , expected_keyword , params , mock_quote_ident
802+ ):
786803 cursor = mock .AsyncMock ()
787-
788- def mock_quote_ident (value , connection ):
789- if value .startswith ('"' ) and value .endswith ('"' ):
790- return value
791- return f'"{ value } "'
792-
793- with mock .patch (
794- "crate.operator.restore_backup.quote_ident" , side_effect = mock_quote_ident
795- ):
796- func_kwargs = {}
797- if params :
798- func_kwargs [restore_type .value ] = params
799- restore_keyword = RestoreType .create (
800- restore_type .value , ** func_kwargs
801- ).get_restore_keyword (cursor = cursor )
802- assert restore_keyword == expected_keyword
804+ func_kwargs = {}
805+ if params :
806+ func_kwargs [restore_type .value ] = params
807+ restore_keyword = RestoreType .create (
808+ restore_type .value , ** func_kwargs
809+ ).get_restore_keyword (cursor = cursor )
810+ assert restore_keyword == expected_keyword
803811
804812
805813@pytest .mark .asyncio
@@ -981,8 +989,10 @@ async def does_credentials_secret_exist(
981989def replace_gc_tables_data (faker , mock_cratedb_connection ):
982990 repository = faker .domain_word ()
983991 snapshot = faker .domain_word ()
984- table_a = f"gc.{ faker .domain_word ()} "
985- table_b = f"gc.{ faker .domain_word ()} "
992+ table_a = faker .domain_word ()
993+ table_b = faker .domain_word ()
994+ tables = [table_a , table_b ]
995+ tables_with_schema = [f"gc.{ t } " for t in tables ]
986996
987997 mock_cursor = mock_cratedb_connection ["mock_cursor" ]
988998 mock_logger = mock .Mock (spec = logging .Logger )
@@ -995,8 +1005,8 @@ def replace_gc_tables_data(faker, mock_cratedb_connection):
9951005 return (
9961006 repository ,
9971007 snapshot ,
998- table_a ,
999- table_b ,
1008+ tables ,
1009+ tables_with_schema ,
10001010 mock_cursor ,
10011011 gc_tables_cls ,
10021012 )
@@ -1006,18 +1016,18 @@ def replace_gc_tables_data(faker, mock_cratedb_connection):
10061016@pytest .mark .parametrize (
10071017 "gc_enabled, type_all" , [(True , False ), (False , True ), (True , True ), (False , False )]
10081018)
1009- async def test_replace_gc_tables (gc_enabled , type_all , replace_gc_tables_data ):
1010- repository , snapshot , table_a , table_b , mock_cursor , gc_tables_cls = (
1019+ async def test_replace_gc_tables (
1020+ gc_enabled , type_all , replace_gc_tables_data , mock_quote_ident
1021+ ):
1022+ repository , snapshot , tables , tables_with_schema , mock_cursor , gc_tables_cls = (
10111023 replace_gc_tables_data
10121024 )
1013- mock_cursor .fetchall .return_value = [(table_a ,), (table_b ,)] if gc_enabled else []
10141025
1015- tables_param = None if type_all else [table_a , table_b ]
1026+ fetch_response = [(t ,) for t in tables_with_schema ]
1027+ mock_cursor .fetchall .return_value = fetch_response if gc_enabled else []
1028+ tables_param = None if type_all else tables_with_schema
10161029
1017- with mock .patch (
1018- "crate.operator.restore_backup.quote_ident" , side_effect = [table_a , table_b ]
1019- ):
1020- await gc_tables_cls .remove_duplicated_tables (tables_param )
1030+ await gc_tables_cls .remove_duplicated_tables (tables_param )
10211031
10221032 if type_all :
10231033 stmts = [
@@ -1039,26 +1049,35 @@ async def test_replace_gc_tables(gc_enabled, type_all, replace_gc_tables_data):
10391049 " FROM sys.snapshots "
10401050 " WHERE repository=%s AND name=%s"
10411051 ") "
1042- f"SELECT * FROM tables WHERE t IN ('{ table_a } ','{ table_b } ');" ,
1052+ "SELECT * FROM tables WHERE t IN "
1053+ f"('{ tables_with_schema [0 ]} ','{ tables_with_schema [1 ]} ');" ,
10431054 (repository , snapshot ),
10441055 ),
10451056 ]
10461057
10471058 if gc_enabled :
1048- stmts .append (mock .call (f"ALTER TABLE { table_a } RENAME TO { table_a } _temp;" ))
1049- stmts .append (mock .call (f"ALTER TABLE { table_b } RENAME TO { table_b } _temp;" ))
1059+ stmts .append (
1060+ mock .call (f'ALTER TABLE "gc"."{ tables [0 ]} " RENAME TO "{ tables [0 ]} _temp";' )
1061+ )
1062+ stmts .append (
1063+ mock .call (f'ALTER TABLE "gc"."{ tables [1 ]} " RENAME TO "{ tables [1 ]} _temp";' )
1064+ )
10501065
10511066 mock_cursor .execute .assert_has_awaits (stmts )
10521067 assert gc_tables_cls .gc_tables_renamed is True
10531068
10541069
10551070@pytest .mark .asyncio
10561071@pytest .mark .parametrize ("gc_tables_renamed" , [True , False ])
1057- async def test_restore_gc_tables (gc_tables_renamed , replace_gc_tables_data ):
1058- _ , _ , table_a , table_b , mock_cursor , gc_tables_cls = replace_gc_tables_data
1072+ async def test_restore_gc_tables (
1073+ gc_tables_renamed , replace_gc_tables_data , mock_quote_ident
1074+ ):
1075+ _ , _ , tables , tables_with_schema , mock_cursor , gc_tables_cls = (
1076+ replace_gc_tables_data
1077+ )
10591078
10601079 gc_tables_cls .gc_tables_renamed = gc_tables_renamed
1061- gc_tables_cls .gc_tables = [ table_a , table_b ]
1080+ gc_tables_cls .gc_tables = tables_with_schema
10621081
10631082 await gc_tables_cls .restore_tables ()
10641083
@@ -1067,19 +1086,27 @@ async def test_restore_gc_tables(gc_tables_renamed, replace_gc_tables_data):
10671086 else :
10681087 mock_cursor .execute .assert_has_awaits (
10691088 [
1070- mock .call (f"ALTER TABLE { table_a } _temp RENAME TO { table_a } ;" ),
1071- mock .call (f"ALTER TABLE { table_b } _temp RENAME TO { table_b } ;" ),
1089+ mock .call (
1090+ f'ALTER TABLE "gc"."{ tables [0 ]} _temp" RENAME TO "{ tables [0 ]} ";'
1091+ ),
1092+ mock .call (
1093+ f'ALTER TABLE "gc"."{ tables [1 ]} _temp" RENAME TO "{ tables [1 ]} ";'
1094+ ),
10721095 ]
10731096 )
10741097
10751098
10761099@pytest .mark .asyncio
10771100@pytest .mark .parametrize ("gc_tables_renamed" , [True , False ])
1078- async def test_cleanup_gc_tables (gc_tables_renamed , replace_gc_tables_data ):
1079- _ , _ , table_a , table_b , mock_cursor , gc_tables_cls = replace_gc_tables_data
1101+ async def test_cleanup_gc_tables (
1102+ gc_tables_renamed , replace_gc_tables_data , mock_quote_ident
1103+ ):
1104+ _ , _ , tables , tables_with_schema , mock_cursor , gc_tables_cls = (
1105+ replace_gc_tables_data
1106+ )
10801107
10811108 gc_tables_cls .gc_tables_renamed = gc_tables_renamed
1082- gc_tables_cls .gc_tables = [ table_a , table_b ]
1109+ gc_tables_cls .gc_tables = tables_with_schema
10831110
10841111 await gc_tables_cls .cleanup_tables ()
10851112
@@ -1088,7 +1115,7 @@ async def test_cleanup_gc_tables(gc_tables_renamed, replace_gc_tables_data):
10881115 else :
10891116 mock_cursor .execute .assert_has_awaits (
10901117 [
1091- mock .call (f" DROP TABLE { table_a } _temp;" ),
1092- mock .call (f" DROP TABLE { table_b } _temp;" ),
1118+ mock .call (f' DROP TABLE "gc"." { tables [ 0 ] } _temp";' ),
1119+ mock .call (f' DROP TABLE "gc"." { tables [ 1 ] } _temp";' ),
10931120 ]
10941121 )
0 commit comments