2
0

test_mariadb.py 46 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332
  1. import logging
  2. import pytest
  3. from flexmock import flexmock
  4. from borgmatic.hooks.data_source import mariadb as module
  5. def test_parse_extra_options_passes_through_empty_options():
  6. assert module.parse_extra_options('') == ((), None)
  7. def test_parse_extra_options_with_defaults_extra_file_removes_and_and_parses_out_filename():
  8. assert module.parse_extra_options('--defaults-extra-file=extra.cnf --skip-ssl') == (
  9. ('--skip-ssl',),
  10. 'extra.cnf',
  11. )
  12. def test_parse_extra_options_without_defaults_extra_file_passes_through_options():
  13. assert module.parse_extra_options('--skip-ssl --and=stuff') == (
  14. ('--skip-ssl', '--and=stuff'),
  15. None,
  16. )
  17. def test_make_defaults_file_pipe_without_username_or_password_bails():
  18. flexmock(module.os).should_receive('pipe').never()
  19. assert module.make_defaults_file_options(username=None, password=None) == ()
  20. def test_make_defaults_file_option_with_username_and_password_writes_them_to_file_descriptor():
  21. read_descriptor = 99
  22. write_descriptor = flexmock()
  23. flexmock(module.os).should_receive('pipe').and_return(read_descriptor, write_descriptor)
  24. flexmock(module.os).should_receive('write').with_args(
  25. write_descriptor, b'[client]\nuser=root\npassword="trustsome1"'
  26. ).once()
  27. flexmock(module.os).should_receive('close')
  28. flexmock(module.os).should_receive('set_inheritable')
  29. assert module.make_defaults_file_options(username='root', password='trustsome1') == (
  30. '--defaults-extra-file=/dev/fd/99',
  31. )
  32. def test_make_defaults_file_escapes_password_containing_backslash():
  33. read_descriptor = 99
  34. write_descriptor = flexmock()
  35. flexmock(module.os).should_receive('pipe').and_return(read_descriptor, write_descriptor)
  36. flexmock(module.os).should_receive('write').with_args(
  37. write_descriptor, b'[client]\nuser=root\n' + br'password="trust\\nsome1"'
  38. ).once()
  39. flexmock(module.os).should_receive('close')
  40. flexmock(module.os).should_receive('set_inheritable')
  41. assert module.make_defaults_file_options(username='root', password=r'trust\nsome1') == (
  42. '--defaults-extra-file=/dev/fd/99',
  43. )
  44. def test_make_defaults_file_pipe_with_only_username_writes_it_to_file_descriptor():
  45. read_descriptor = 99
  46. write_descriptor = flexmock()
  47. flexmock(module.os).should_receive('pipe').and_return(read_descriptor, write_descriptor)
  48. flexmock(module.os).should_receive('write').with_args(
  49. write_descriptor, b'[client]\nuser=root'
  50. ).once()
  51. flexmock(module.os).should_receive('close')
  52. flexmock(module.os).should_receive('set_inheritable')
  53. assert module.make_defaults_file_options(username='root', password=None) == (
  54. '--defaults-extra-file=/dev/fd/99',
  55. )
  56. def test_make_defaults_file_pipe_with_only_password_writes_it_to_file_descriptor():
  57. read_descriptor = 99
  58. write_descriptor = flexmock()
  59. flexmock(module.os).should_receive('pipe').and_return(read_descriptor, write_descriptor)
  60. flexmock(module.os).should_receive('write').with_args(
  61. write_descriptor, b'[client]\npassword="trustsome1"'
  62. ).once()
  63. flexmock(module.os).should_receive('close')
  64. flexmock(module.os).should_receive('set_inheritable')
  65. assert module.make_defaults_file_options(username=None, password='trustsome1') == (
  66. '--defaults-extra-file=/dev/fd/99',
  67. )
  68. def test_make_defaults_file_option_with_defaults_extra_filename_includes_it_in_file_descriptor():
  69. read_descriptor = 99
  70. write_descriptor = flexmock()
  71. flexmock(module.os).should_receive('pipe').and_return(read_descriptor, write_descriptor)
  72. flexmock(module.os).should_receive('write').with_args(
  73. write_descriptor, b'!include extra.cnf\n[client]\nuser=root\npassword="trustsome1"'
  74. ).once()
  75. flexmock(module.os).should_receive('close')
  76. flexmock(module.os).should_receive('set_inheritable')
  77. assert module.make_defaults_file_options(
  78. username='root', password='trustsome1', defaults_extra_filename='extra.cnf'
  79. ) == ('--defaults-extra-file=/dev/fd/99',)
  80. def test_make_defaults_file_option_with_only_defaults_extra_filename_uses_it_instead_of_file_descriptor():
  81. flexmock(module.os).should_receive('pipe').never()
  82. assert module.make_defaults_file_options(
  83. username=None, password=None, defaults_extra_filename='extra.cnf'
  84. ) == ('--defaults-extra-file=extra.cnf',)
  85. def test_database_names_to_dump_passes_through_name():
  86. environment = flexmock()
  87. names = module.database_names_to_dump(
  88. {'name': 'foo'}, {}, 'root', 'trustsome1', environment, dry_run=False
  89. )
  90. assert names == ('foo',)
  91. def test_database_names_to_dump_bails_for_dry_run():
  92. environment = flexmock()
  93. flexmock(module).should_receive('execute_command_and_capture_output').never()
  94. names = module.database_names_to_dump(
  95. {'name': 'all'}, {}, 'root', 'trustsome1', environment, dry_run=True
  96. )
  97. assert names == ()
  98. def test_database_names_to_dump_queries_mariadb_for_database_names():
  99. environment = flexmock()
  100. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  101. 'resolve_credential'
  102. ).replace_with(lambda value, config: value)
  103. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  104. flexmock(module).should_receive('make_defaults_file_options').with_args(
  105. 'root', 'trustsome1', None
  106. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  107. flexmock(module).should_receive('execute_command_and_capture_output').with_args(
  108. (
  109. 'mariadb',
  110. '--defaults-extra-file=/dev/fd/99',
  111. '--skip-column-names',
  112. '--batch',
  113. '--execute',
  114. 'show schemas',
  115. ),
  116. environment=environment,
  117. ).and_return('foo\nbar\nmysql\n').once()
  118. names = module.database_names_to_dump(
  119. {'name': 'all'}, {}, 'root', 'trustsome1', environment, dry_run=False
  120. )
  121. assert names == ('foo', 'bar')
  122. def test_database_names_to_dump_runs_mariadb_with_tls():
  123. environment = flexmock()
  124. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  125. 'resolve_credential'
  126. ).replace_with(lambda value, config: value)
  127. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  128. flexmock(module).should_receive('make_defaults_file_options').with_args(
  129. 'root', 'trustsome1', None
  130. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  131. flexmock(module).should_receive('execute_command_and_capture_output').with_args(
  132. (
  133. 'mariadb',
  134. '--defaults-extra-file=/dev/fd/99',
  135. '--ssl',
  136. '--skip-column-names',
  137. '--batch',
  138. '--execute',
  139. 'show schemas',
  140. ),
  141. environment=environment,
  142. ).and_return('foo\nbar\nmysql\n').once()
  143. names = module.database_names_to_dump(
  144. {'name': 'all', 'tls': True}, {}, 'root', 'trustsome1', environment, dry_run=False
  145. )
  146. assert names == ('foo', 'bar')
  147. def test_database_names_to_dump_runs_mariadb_without_tls():
  148. environment = flexmock()
  149. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  150. 'resolve_credential'
  151. ).replace_with(lambda value, config: value)
  152. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  153. flexmock(module).should_receive('make_defaults_file_options').with_args(
  154. 'root', 'trustsome1', None
  155. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  156. flexmock(module).should_receive('execute_command_and_capture_output').with_args(
  157. (
  158. 'mariadb',
  159. '--defaults-extra-file=/dev/fd/99',
  160. '--skip-ssl',
  161. '--skip-column-names',
  162. '--batch',
  163. '--execute',
  164. 'show schemas',
  165. ),
  166. environment=environment,
  167. ).and_return('foo\nbar\nmysql\n').once()
  168. names = module.database_names_to_dump(
  169. {'name': 'all', 'tls': False}, {}, 'root', 'trustsome1', environment, dry_run=False
  170. )
  171. assert names == ('foo', 'bar')
  172. def test_use_streaming_true_for_any_databases():
  173. assert module.use_streaming(
  174. databases=[flexmock(), flexmock()],
  175. config=flexmock(),
  176. )
  177. def test_use_streaming_false_for_no_databases():
  178. assert not module.use_streaming(databases=[], config=flexmock())
  179. def test_dump_data_sources_dumps_each_database():
  180. flexmock(module.borgmatic.hooks.command).should_receive('Before_after_hooks').and_return(
  181. flexmock()
  182. )
  183. databases = [{'name': 'foo'}, {'name': 'bar'}]
  184. processes = [flexmock(), flexmock()]
  185. flexmock(module).should_receive('make_dump_path').and_return('')
  186. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  187. 'resolve_credential'
  188. ).and_return(None)
  189. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  190. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  191. 'resolve_credential'
  192. ).replace_with(lambda value, config: value)
  193. flexmock(module).should_receive('database_names_to_dump').and_return(('foo',)).and_return(
  194. ('bar',)
  195. )
  196. for name, process in zip(('foo', 'bar'), processes):
  197. flexmock(module).should_receive('execute_dump_command').with_args(
  198. database={'name': name},
  199. config={},
  200. username=None,
  201. password=None,
  202. dump_path=object,
  203. database_names=(name,),
  204. environment={'USER': 'root'},
  205. dry_run=object,
  206. dry_run_label=object,
  207. ).and_return(process).once()
  208. assert (
  209. module.dump_data_sources(
  210. databases,
  211. {},
  212. config_paths=('test.yaml',),
  213. borgmatic_runtime_directory='/run/borgmatic',
  214. patterns=[],
  215. dry_run=False,
  216. )
  217. == processes
  218. )
  219. def test_dump_data_sources_dumps_with_password():
  220. flexmock(module.borgmatic.hooks.command).should_receive('Before_after_hooks').and_return(
  221. flexmock()
  222. )
  223. database = {'name': 'foo', 'username': 'root', 'password': 'trustsome1'}
  224. process = flexmock()
  225. flexmock(module).should_receive('make_dump_path').and_return('')
  226. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  227. 'resolve_credential'
  228. ).replace_with(lambda value, config: value)
  229. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  230. flexmock(module).should_receive('database_names_to_dump').and_return(('foo',)).and_return(
  231. ('bar',)
  232. )
  233. flexmock(module).should_receive('execute_dump_command').with_args(
  234. database=database,
  235. config={},
  236. username='root',
  237. password='trustsome1',
  238. dump_path=object,
  239. database_names=('foo',),
  240. environment={'USER': 'root'},
  241. dry_run=object,
  242. dry_run_label=object,
  243. ).and_return(process).once()
  244. assert module.dump_data_sources(
  245. [database],
  246. {},
  247. config_paths=('test.yaml',),
  248. borgmatic_runtime_directory='/run/borgmatic',
  249. patterns=[],
  250. dry_run=False,
  251. ) == [process]
  252. def test_dump_data_sources_dumps_all_databases_at_once():
  253. flexmock(module.borgmatic.hooks.command).should_receive('Before_after_hooks').and_return(
  254. flexmock()
  255. )
  256. databases = [{'name': 'all'}]
  257. process = flexmock()
  258. flexmock(module).should_receive('make_dump_path').and_return('')
  259. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  260. 'resolve_credential'
  261. ).replace_with(lambda value, config: value)
  262. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  263. flexmock(module).should_receive('database_names_to_dump').and_return(('foo', 'bar'))
  264. flexmock(module).should_receive('execute_dump_command').with_args(
  265. database={'name': 'all'},
  266. config={},
  267. username=None,
  268. password=None,
  269. dump_path=object,
  270. database_names=('foo', 'bar'),
  271. environment={'USER': 'root'},
  272. dry_run=object,
  273. dry_run_label=object,
  274. ).and_return(process).once()
  275. assert module.dump_data_sources(
  276. databases,
  277. {},
  278. config_paths=('test.yaml',),
  279. borgmatic_runtime_directory='/run/borgmatic',
  280. patterns=[],
  281. dry_run=False,
  282. ) == [process]
  283. def test_dump_data_sources_dumps_all_databases_separately_when_format_configured():
  284. flexmock(module.borgmatic.hooks.command).should_receive('Before_after_hooks').and_return(
  285. flexmock()
  286. )
  287. databases = [{'name': 'all', 'format': 'sql'}]
  288. processes = [flexmock(), flexmock()]
  289. flexmock(module).should_receive('make_dump_path').and_return('')
  290. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  291. 'resolve_credential'
  292. ).and_return(None)
  293. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  294. flexmock(module).should_receive('database_names_to_dump').and_return(('foo', 'bar'))
  295. for name, process in zip(('foo', 'bar'), processes):
  296. flexmock(module).should_receive('execute_dump_command').with_args(
  297. database={'name': name, 'format': 'sql'},
  298. config={},
  299. username=None,
  300. password=None,
  301. dump_path=object,
  302. database_names=(name,),
  303. environment={'USER': 'root'},
  304. dry_run=object,
  305. dry_run_label=object,
  306. ).and_return(process).once()
  307. assert (
  308. module.dump_data_sources(
  309. databases,
  310. {},
  311. config_paths=('test.yaml',),
  312. borgmatic_runtime_directory='/run/borgmatic',
  313. patterns=[],
  314. dry_run=False,
  315. )
  316. == processes
  317. )
  318. def test_database_names_to_dump_runs_mariadb_with_list_options():
  319. database = {'name': 'all', 'list_options': '--defaults-extra-file=mariadb.cnf --skip-ssl'}
  320. flexmock(module).should_receive('parse_extra_options').and_return(
  321. ('--skip-ssl',), 'mariadb.cnf'
  322. )
  323. flexmock(module).should_receive('make_defaults_file_options').with_args(
  324. 'root', 'trustsome1', 'mariadb.cnf'
  325. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  326. flexmock(module).should_receive('execute_command_and_capture_output').with_args(
  327. (
  328. 'mariadb',
  329. '--defaults-extra-file=/dev/fd/99',
  330. '--skip-ssl',
  331. '--skip-column-names',
  332. '--batch',
  333. '--execute',
  334. 'show schemas',
  335. ),
  336. environment=None,
  337. ).and_return(('foo\nbar')).once()
  338. assert module.database_names_to_dump(database, {}, 'root', 'trustsome1', None, '') == (
  339. 'foo',
  340. 'bar',
  341. )
  342. def test_database_names_to_dump_runs_non_default_mariadb_with_list_options():
  343. database = {
  344. 'name': 'all',
  345. 'list_options': '--defaults-extra-file=mariadb.cnf --skip-ssl',
  346. 'mariadb_command': 'custom_mariadb',
  347. }
  348. flexmock(module).should_receive('parse_extra_options').and_return(
  349. ('--skip-ssl',), 'mariadb.cnf'
  350. )
  351. flexmock(module).should_receive('make_defaults_file_options').with_args(
  352. 'root', 'trustsome1', 'mariadb.cnf'
  353. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  354. flexmock(module).should_receive('execute_command_and_capture_output').with_args(
  355. environment=None,
  356. full_command=(
  357. 'custom_mariadb', # Custom MariaDB command
  358. '--defaults-extra-file=/dev/fd/99',
  359. '--skip-ssl',
  360. '--skip-column-names',
  361. '--batch',
  362. '--execute',
  363. 'show schemas',
  364. ),
  365. ).and_return(('foo\nbar')).once()
  366. assert module.database_names_to_dump(database, {}, 'root', 'trustsome1', None, '') == (
  367. 'foo',
  368. 'bar',
  369. )
  370. def test_execute_dump_command_runs_mariadb_dump():
  371. process = flexmock()
  372. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  373. flexmock(module.os.path).should_receive('exists').and_return(False)
  374. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  375. 'resolve_credential'
  376. ).replace_with(lambda value, config: value)
  377. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  378. flexmock(module).should_receive('make_defaults_file_options').with_args(
  379. 'root', 'trustsome1', None
  380. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  381. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  382. flexmock(module).should_receive('execute_command').with_args(
  383. (
  384. 'mariadb-dump',
  385. '--defaults-extra-file=/dev/fd/99',
  386. '--add-drop-database',
  387. '--databases',
  388. 'foo',
  389. '--result-file',
  390. 'dump',
  391. ),
  392. environment=None,
  393. run_to_completion=False,
  394. ).and_return(process).once()
  395. assert (
  396. module.execute_dump_command(
  397. database={'name': 'foo'},
  398. config={},
  399. username='root',
  400. password='trustsome1',
  401. dump_path=flexmock(),
  402. database_names=('foo',),
  403. environment=None,
  404. dry_run=False,
  405. dry_run_label='',
  406. )
  407. == process
  408. )
  409. def test_execute_dump_command_runs_mariadb_dump_without_add_drop_database():
  410. process = flexmock()
  411. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  412. flexmock(module.os.path).should_receive('exists').and_return(False)
  413. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  414. 'resolve_credential'
  415. ).replace_with(lambda value, config: value)
  416. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  417. flexmock(module).should_receive('make_defaults_file_options').with_args(
  418. 'root', 'trustsome1', None
  419. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  420. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  421. flexmock(module).should_receive('execute_command').with_args(
  422. (
  423. 'mariadb-dump',
  424. '--defaults-extra-file=/dev/fd/99',
  425. '--databases',
  426. 'foo',
  427. '--result-file',
  428. 'dump',
  429. ),
  430. environment=None,
  431. run_to_completion=False,
  432. ).and_return(process).once()
  433. assert (
  434. module.execute_dump_command(
  435. database={'name': 'foo', 'add_drop_database': False},
  436. config={},
  437. username='root',
  438. password='trustsome1',
  439. dump_path=flexmock(),
  440. database_names=('foo',),
  441. environment=None,
  442. dry_run=False,
  443. dry_run_label='',
  444. )
  445. == process
  446. )
  447. def test_execute_dump_command_runs_mariadb_dump_with_hostname_and_port():
  448. process = flexmock()
  449. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  450. flexmock(module.os.path).should_receive('exists').and_return(False)
  451. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  452. 'resolve_credential'
  453. ).replace_with(lambda value, config: value)
  454. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  455. flexmock(module).should_receive('make_defaults_file_options').with_args(
  456. 'root', 'trustsome1', None
  457. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  458. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  459. flexmock(module).should_receive('execute_command').with_args(
  460. (
  461. 'mariadb-dump',
  462. '--defaults-extra-file=/dev/fd/99',
  463. '--add-drop-database',
  464. '--host',
  465. 'database.example.org',
  466. '--port',
  467. '5433',
  468. '--protocol',
  469. 'tcp',
  470. '--databases',
  471. 'foo',
  472. '--result-file',
  473. 'dump',
  474. ),
  475. environment=None,
  476. run_to_completion=False,
  477. ).and_return(process).once()
  478. assert (
  479. module.execute_dump_command(
  480. database={'name': 'foo', 'hostname': 'database.example.org', 'port': 5433},
  481. config={},
  482. username='root',
  483. password='trustsome1',
  484. dump_path=flexmock(),
  485. database_names=('foo',),
  486. environment=None,
  487. dry_run=False,
  488. dry_run_label='',
  489. )
  490. == process
  491. )
  492. def test_execute_dump_command_runs_mariadb_dump_with_tls():
  493. process = flexmock()
  494. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  495. flexmock(module.os.path).should_receive('exists').and_return(False)
  496. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  497. 'resolve_credential'
  498. ).replace_with(lambda value, config: value)
  499. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  500. flexmock(module).should_receive('make_defaults_file_options').with_args(
  501. 'root', 'trustsome1', None
  502. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  503. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  504. flexmock(module).should_receive('execute_command').with_args(
  505. (
  506. 'mariadb-dump',
  507. '--defaults-extra-file=/dev/fd/99',
  508. '--add-drop-database',
  509. '--ssl',
  510. '--databases',
  511. 'foo',
  512. '--result-file',
  513. 'dump',
  514. ),
  515. environment=None,
  516. run_to_completion=False,
  517. ).and_return(process).once()
  518. assert (
  519. module.execute_dump_command(
  520. database={'name': 'foo', 'tls': True},
  521. config={},
  522. username='root',
  523. password='trustsome1',
  524. dump_path=flexmock(),
  525. database_names=('foo',),
  526. environment=None,
  527. dry_run=False,
  528. dry_run_label='',
  529. )
  530. == process
  531. )
  532. def test_execute_dump_command_runs_mariadb_dump_without_tls():
  533. process = flexmock()
  534. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  535. flexmock(module.os.path).should_receive('exists').and_return(False)
  536. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  537. 'resolve_credential'
  538. ).replace_with(lambda value, config: value)
  539. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  540. flexmock(module).should_receive('make_defaults_file_options').with_args(
  541. 'root', 'trustsome1', None
  542. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  543. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  544. flexmock(module).should_receive('execute_command').with_args(
  545. (
  546. 'mariadb-dump',
  547. '--defaults-extra-file=/dev/fd/99',
  548. '--add-drop-database',
  549. '--skip-ssl',
  550. '--databases',
  551. 'foo',
  552. '--result-file',
  553. 'dump',
  554. ),
  555. environment=None,
  556. run_to_completion=False,
  557. ).and_return(process).once()
  558. assert (
  559. module.execute_dump_command(
  560. database={'name': 'foo', 'tls': False},
  561. config={},
  562. username='root',
  563. password='trustsome1',
  564. dump_path=flexmock(),
  565. database_names=('foo',),
  566. environment=None,
  567. dry_run=False,
  568. dry_run_label='',
  569. )
  570. == process
  571. )
  572. def test_execute_dump_command_runs_mariadb_dump_with_username_and_password():
  573. process = flexmock()
  574. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  575. flexmock(module.os.path).should_receive('exists').and_return(False)
  576. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  577. 'resolve_credential'
  578. ).replace_with(lambda value, config: value)
  579. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  580. flexmock(module).should_receive('make_defaults_file_options').with_args(
  581. 'root', 'trustsome1', None
  582. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  583. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  584. flexmock(module).should_receive('execute_command').with_args(
  585. (
  586. 'mariadb-dump',
  587. '--defaults-extra-file=/dev/fd/99',
  588. '--add-drop-database',
  589. '--databases',
  590. 'foo',
  591. '--result-file',
  592. 'dump',
  593. ),
  594. environment={},
  595. run_to_completion=False,
  596. ).and_return(process).once()
  597. assert (
  598. module.execute_dump_command(
  599. database={'name': 'foo', 'username': 'root', 'password': 'trustsome1'},
  600. config={},
  601. username='root',
  602. password='trustsome1',
  603. dump_path=flexmock(),
  604. database_names=('foo',),
  605. environment={},
  606. dry_run=False,
  607. dry_run_label='',
  608. )
  609. == process
  610. )
  611. def test_execute_dump_command_runs_mariadb_dump_with_options():
  612. process = flexmock()
  613. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  614. flexmock(module.os.path).should_receive('exists').and_return(False)
  615. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  616. 'resolve_credential'
  617. ).replace_with(lambda value, config: value)
  618. flexmock(module).should_receive('parse_extra_options').and_return(('--stuff=such',), None)
  619. flexmock(module).should_receive('make_defaults_file_options').with_args(
  620. 'root', 'trustsome1', None
  621. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  622. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  623. flexmock(module).should_receive('execute_command').with_args(
  624. (
  625. 'mariadb-dump',
  626. '--defaults-extra-file=/dev/fd/99',
  627. '--stuff=such',
  628. '--add-drop-database',
  629. '--databases',
  630. 'foo',
  631. '--result-file',
  632. 'dump',
  633. ),
  634. environment=None,
  635. run_to_completion=False,
  636. ).and_return(process).once()
  637. assert (
  638. module.execute_dump_command(
  639. database={'name': 'foo', 'options': '--stuff=such'},
  640. config={},
  641. username='root',
  642. password='trustsome1',
  643. dump_path=flexmock(),
  644. database_names=('foo',),
  645. environment=None,
  646. dry_run=False,
  647. dry_run_label='',
  648. )
  649. == process
  650. )
  651. def test_execute_dump_command_runs_non_default_mariadb_dump_with_options():
  652. process = flexmock()
  653. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  654. flexmock(module.os.path).should_receive('exists').and_return(False)
  655. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  656. 'resolve_credential'
  657. ).replace_with(lambda value, config: value)
  658. flexmock(module).should_receive('parse_extra_options').and_return(('--stuff=such',), None)
  659. flexmock(module).should_receive('make_defaults_file_options').with_args(
  660. 'root', 'trustsome1', None
  661. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  662. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  663. flexmock(module).should_receive('execute_command').with_args(
  664. (
  665. 'custom_mariadb_dump', # Custom MariaDB dump command
  666. '--defaults-extra-file=/dev/fd/99',
  667. '--stuff=such',
  668. '--add-drop-database',
  669. '--databases',
  670. 'foo',
  671. '--result-file',
  672. 'dump',
  673. ),
  674. environment=None,
  675. run_to_completion=False,
  676. ).and_return(process).once()
  677. assert (
  678. module.execute_dump_command(
  679. database={
  680. 'name': 'foo',
  681. 'mariadb_dump_command': 'custom_mariadb_dump',
  682. 'options': '--stuff=such',
  683. }, # Custom MariaDB dump command specified
  684. config={},
  685. username='root',
  686. password='trustsome1',
  687. dump_path=flexmock(),
  688. database_names=('foo',),
  689. environment=None,
  690. dry_run=False,
  691. dry_run_label='',
  692. )
  693. == process
  694. )
  695. def test_execute_dump_command_with_duplicate_dump_skips_mariadb_dump():
  696. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  697. flexmock(module.os.path).should_receive('exists').and_return(True)
  698. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  699. flexmock(module).should_receive('make_defaults_file_options').with_args(
  700. 'root', 'trustsome1', None
  701. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  702. flexmock(module.dump).should_receive('create_named_pipe_for_dump').never()
  703. flexmock(module).should_receive('execute_command').never()
  704. assert (
  705. module.execute_dump_command(
  706. database={'name': 'foo'},
  707. config={},
  708. username='root',
  709. password='trustsome1',
  710. dump_path=flexmock(),
  711. database_names=('foo',),
  712. environment=None,
  713. dry_run=True,
  714. dry_run_label='SO DRY',
  715. )
  716. is None
  717. )
  718. def test_execute_dump_command_with_dry_run_skips_mariadb_dump():
  719. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  720. flexmock(module.os.path).should_receive('exists').and_return(False)
  721. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  722. 'resolve_credential'
  723. ).replace_with(lambda value, config: value)
  724. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  725. flexmock(module).should_receive('make_defaults_file_options').with_args(
  726. 'root', 'trustsome1', None
  727. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  728. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  729. flexmock(module).should_receive('execute_command').never()
  730. assert (
  731. module.execute_dump_command(
  732. database={'name': 'foo'},
  733. config={},
  734. username='root',
  735. password='trustsome1',
  736. dump_path=flexmock(),
  737. database_names=('foo',),
  738. environment=None,
  739. dry_run=True,
  740. dry_run_label='SO DRY',
  741. )
  742. is None
  743. )
  744. def test_dump_data_sources_errors_for_missing_all_databases():
  745. flexmock(module.borgmatic.hooks.command).should_receive('Before_after_hooks').and_return(
  746. flexmock()
  747. )
  748. databases = [{'name': 'all'}]
  749. flexmock(module).should_receive('make_dump_path').and_return('')
  750. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  751. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  752. 'resolve_credential'
  753. ).replace_with(lambda value, config: value)
  754. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return(
  755. 'databases/localhost/all'
  756. )
  757. flexmock(module).should_receive('database_names_to_dump').and_return(())
  758. with pytest.raises(ValueError):
  759. assert module.dump_data_sources(
  760. databases,
  761. {},
  762. config_paths=('test.yaml',),
  763. borgmatic_runtime_directory='/run/borgmatic',
  764. patterns=[],
  765. dry_run=False,
  766. )
  767. def test_dump_data_sources_does_not_error_for_missing_all_databases_with_dry_run():
  768. flexmock(module.borgmatic.hooks.command).should_receive('Before_after_hooks').and_return(
  769. flexmock()
  770. )
  771. databases = [{'name': 'all'}]
  772. flexmock(module).should_receive('make_dump_path').and_return('')
  773. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  774. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  775. 'resolve_credential'
  776. ).replace_with(lambda value, config: value)
  777. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return(
  778. 'databases/localhost/all'
  779. )
  780. flexmock(module).should_receive('database_names_to_dump').and_return(())
  781. assert (
  782. module.dump_data_sources(
  783. databases,
  784. {},
  785. config_paths=('test.yaml',),
  786. borgmatic_runtime_directory='/run/borgmatic',
  787. patterns=[],
  788. dry_run=True,
  789. )
  790. == []
  791. )
  792. def test_restore_data_source_dump_runs_mariadb_to_restore():
  793. hook_config = [{'name': 'foo'}, {'name': 'bar'}]
  794. extract_process = flexmock(stdout=flexmock())
  795. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  796. 'resolve_credential'
  797. ).replace_with(lambda value, config: value)
  798. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  799. flexmock(module).should_receive('make_defaults_file_options').with_args(
  800. None, None, None
  801. ).and_return(())
  802. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  803. flexmock(module).should_receive('execute_command_with_processes').with_args(
  804. ('mariadb', '--batch'),
  805. processes=[extract_process],
  806. output_log_level=logging.DEBUG,
  807. input_file=extract_process.stdout,
  808. environment={'USER': 'root'},
  809. ).once()
  810. module.restore_data_source_dump(
  811. hook_config,
  812. {},
  813. data_source={'name': 'foo'},
  814. dry_run=False,
  815. extract_process=extract_process,
  816. connection_params={
  817. 'hostname': None,
  818. 'port': None,
  819. 'username': None,
  820. 'password': None,
  821. },
  822. borgmatic_runtime_directory='/run/borgmatic',
  823. )
  824. def test_restore_data_source_dump_runs_mariadb_with_options():
  825. hook_config = [{'name': 'foo', 'restore_options': '--harder'}]
  826. extract_process = flexmock(stdout=flexmock())
  827. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  828. 'resolve_credential'
  829. ).replace_with(lambda value, config: value)
  830. flexmock(module).should_receive('parse_extra_options').and_return(('--harder',), None)
  831. flexmock(module).should_receive('make_defaults_file_options').with_args(
  832. None, None, None
  833. ).and_return(())
  834. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  835. flexmock(module).should_receive('execute_command_with_processes').with_args(
  836. ('mariadb', '--harder', '--batch'),
  837. processes=[extract_process],
  838. output_log_level=logging.DEBUG,
  839. input_file=extract_process.stdout,
  840. environment={'USER': 'root'},
  841. ).once()
  842. module.restore_data_source_dump(
  843. hook_config,
  844. {},
  845. data_source=hook_config[0],
  846. dry_run=False,
  847. extract_process=extract_process,
  848. connection_params={
  849. 'hostname': None,
  850. 'port': None,
  851. 'username': None,
  852. 'password': None,
  853. },
  854. borgmatic_runtime_directory='/run/borgmatic',
  855. )
  856. def test_restore_data_source_dump_runs_non_default_mariadb_with_options():
  857. hook_config = [
  858. {'name': 'foo', 'restore_options': '--harder', 'mariadb_command': 'custom_mariadb'}
  859. ]
  860. extract_process = flexmock(stdout=flexmock())
  861. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  862. 'resolve_credential'
  863. ).replace_with(lambda value, config: value)
  864. flexmock(module).should_receive('parse_extra_options').and_return(('--harder',), None)
  865. flexmock(module).should_receive('make_defaults_file_options').with_args(
  866. None, None, None
  867. ).and_return(())
  868. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  869. flexmock(module).should_receive('execute_command_with_processes').with_args(
  870. ('custom_mariadb', '--harder', '--batch'),
  871. processes=[extract_process],
  872. output_log_level=logging.DEBUG,
  873. input_file=extract_process.stdout,
  874. environment={'USER': 'root'},
  875. ).once()
  876. module.restore_data_source_dump(
  877. hook_config,
  878. {},
  879. data_source=hook_config[0],
  880. dry_run=False,
  881. extract_process=extract_process,
  882. connection_params={
  883. 'hostname': None,
  884. 'port': None,
  885. 'username': None,
  886. 'password': None,
  887. },
  888. borgmatic_runtime_directory='/run/borgmatic',
  889. )
  890. def test_restore_data_source_dump_runs_mariadb_with_hostname_and_port():
  891. hook_config = [{'name': 'foo', 'hostname': 'database.example.org', 'port': 5433}]
  892. extract_process = flexmock(stdout=flexmock())
  893. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  894. 'resolve_credential'
  895. ).replace_with(lambda value, config: value)
  896. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  897. flexmock(module).should_receive('make_defaults_file_options').with_args(
  898. None, None, None
  899. ).and_return(())
  900. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  901. flexmock(module).should_receive('execute_command_with_processes').with_args(
  902. (
  903. 'mariadb',
  904. '--batch',
  905. '--host',
  906. 'database.example.org',
  907. '--port',
  908. '5433',
  909. '--protocol',
  910. 'tcp',
  911. ),
  912. processes=[extract_process],
  913. output_log_level=logging.DEBUG,
  914. input_file=extract_process.stdout,
  915. environment={'USER': 'root'},
  916. ).once()
  917. module.restore_data_source_dump(
  918. hook_config,
  919. {},
  920. data_source=hook_config[0],
  921. dry_run=False,
  922. extract_process=extract_process,
  923. connection_params={
  924. 'hostname': None,
  925. 'port': None,
  926. 'username': None,
  927. 'password': None,
  928. },
  929. borgmatic_runtime_directory='/run/borgmatic',
  930. )
  931. def test_restore_data_source_dump_runs_mariadb_with_tls():
  932. hook_config = [{'name': 'foo', 'tls': True}]
  933. extract_process = flexmock(stdout=flexmock())
  934. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  935. 'resolve_credential'
  936. ).replace_with(lambda value, config: value)
  937. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  938. flexmock(module).should_receive('make_defaults_file_options').with_args(
  939. None, None, None
  940. ).and_return(())
  941. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  942. flexmock(module).should_receive('execute_command_with_processes').with_args(
  943. (
  944. 'mariadb',
  945. '--batch',
  946. '--ssl',
  947. ),
  948. processes=[extract_process],
  949. output_log_level=logging.DEBUG,
  950. input_file=extract_process.stdout,
  951. environment={'USER': 'root'},
  952. ).once()
  953. module.restore_data_source_dump(
  954. hook_config,
  955. {},
  956. data_source=hook_config[0],
  957. dry_run=False,
  958. extract_process=extract_process,
  959. connection_params={
  960. 'hostname': None,
  961. 'port': None,
  962. 'username': None,
  963. 'password': None,
  964. },
  965. borgmatic_runtime_directory='/run/borgmatic',
  966. )
  967. def test_restore_data_source_dump_runs_mariadb_without_tls():
  968. hook_config = [{'name': 'foo', 'tls': False}]
  969. extract_process = flexmock(stdout=flexmock())
  970. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  971. 'resolve_credential'
  972. ).replace_with(lambda value, config: value)
  973. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  974. flexmock(module).should_receive('make_defaults_file_options').with_args(
  975. None, None, None
  976. ).and_return(())
  977. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  978. flexmock(module).should_receive('execute_command_with_processes').with_args(
  979. (
  980. 'mariadb',
  981. '--batch',
  982. '--skip-ssl',
  983. ),
  984. processes=[extract_process],
  985. output_log_level=logging.DEBUG,
  986. input_file=extract_process.stdout,
  987. environment={'USER': 'root'},
  988. ).once()
  989. module.restore_data_source_dump(
  990. hook_config,
  991. {},
  992. data_source=hook_config[0],
  993. dry_run=False,
  994. extract_process=extract_process,
  995. connection_params={
  996. 'hostname': None,
  997. 'port': None,
  998. 'username': None,
  999. 'password': None,
  1000. },
  1001. borgmatic_runtime_directory='/run/borgmatic',
  1002. )
  1003. def test_restore_data_source_dump_runs_mariadb_with_username_and_password():
  1004. hook_config = [{'name': 'foo', 'username': 'root', 'password': 'trustsome1'}]
  1005. extract_process = flexmock(stdout=flexmock())
  1006. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1007. 'resolve_credential'
  1008. ).replace_with(lambda value, config: value)
  1009. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1010. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1011. 'root', 'trustsome1', None
  1012. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1013. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1014. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1015. ('mariadb', '--defaults-extra-file=/dev/fd/99', '--batch'),
  1016. processes=[extract_process],
  1017. output_log_level=logging.DEBUG,
  1018. input_file=extract_process.stdout,
  1019. environment={'USER': 'root'},
  1020. ).once()
  1021. module.restore_data_source_dump(
  1022. hook_config,
  1023. {},
  1024. data_source=hook_config[0],
  1025. dry_run=False,
  1026. extract_process=extract_process,
  1027. connection_params={
  1028. 'hostname': None,
  1029. 'port': None,
  1030. 'username': None,
  1031. 'password': None,
  1032. },
  1033. borgmatic_runtime_directory='/run/borgmatic',
  1034. )
  1035. def test_restore_data_source_dump_with_connection_params_uses_connection_params_for_restore():
  1036. hook_config = [
  1037. {
  1038. 'name': 'foo',
  1039. 'username': 'root',
  1040. 'password': 'trustsome1',
  1041. 'restore_hostname': 'restorehost',
  1042. 'restore_port': 'restoreport',
  1043. 'restore_username': 'restoreusername',
  1044. 'restore_password': 'restorepassword',
  1045. }
  1046. ]
  1047. extract_process = flexmock(stdout=flexmock())
  1048. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1049. 'resolve_credential'
  1050. ).replace_with(lambda value, config: value)
  1051. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1052. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1053. 'cliusername', 'clipassword', None
  1054. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1055. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1056. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1057. (
  1058. 'mariadb',
  1059. '--defaults-extra-file=/dev/fd/99',
  1060. '--batch',
  1061. '--host',
  1062. 'clihost',
  1063. '--port',
  1064. 'cliport',
  1065. '--protocol',
  1066. 'tcp',
  1067. ),
  1068. processes=[extract_process],
  1069. output_log_level=logging.DEBUG,
  1070. input_file=extract_process.stdout,
  1071. environment={'USER': 'root'},
  1072. ).once()
  1073. module.restore_data_source_dump(
  1074. hook_config,
  1075. {},
  1076. data_source=hook_config[0],
  1077. dry_run=False,
  1078. extract_process=extract_process,
  1079. connection_params={
  1080. 'hostname': 'clihost',
  1081. 'port': 'cliport',
  1082. 'username': 'cliusername',
  1083. 'password': 'clipassword',
  1084. },
  1085. borgmatic_runtime_directory='/run/borgmatic',
  1086. )
  1087. def test_restore_data_source_dump_without_connection_params_uses_restore_params_in_config_for_restore():
  1088. hook_config = [
  1089. {
  1090. 'name': 'foo',
  1091. 'username': 'root',
  1092. 'password': 'trustsome1',
  1093. 'hostname': 'dbhost',
  1094. 'port': 'dbport',
  1095. 'tls': True,
  1096. 'restore_username': 'restoreuser',
  1097. 'restore_password': 'restorepass',
  1098. 'restore_hostname': 'restorehost',
  1099. 'restore_port': 'restoreport',
  1100. 'restore_tls': False,
  1101. }
  1102. ]
  1103. extract_process = flexmock(stdout=flexmock())
  1104. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1105. 'resolve_credential'
  1106. ).replace_with(lambda value, config: value)
  1107. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1108. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1109. 'restoreuser', 'restorepass', None
  1110. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1111. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1112. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1113. (
  1114. 'mariadb',
  1115. '--defaults-extra-file=/dev/fd/99',
  1116. '--batch',
  1117. '--host',
  1118. 'restorehost',
  1119. '--port',
  1120. 'restoreport',
  1121. '--protocol',
  1122. 'tcp',
  1123. '--skip-ssl',
  1124. ),
  1125. processes=[extract_process],
  1126. output_log_level=logging.DEBUG,
  1127. input_file=extract_process.stdout,
  1128. environment={'USER': 'root'},
  1129. ).once()
  1130. module.restore_data_source_dump(
  1131. hook_config,
  1132. {},
  1133. data_source=hook_config[0],
  1134. dry_run=False,
  1135. extract_process=extract_process,
  1136. connection_params={
  1137. 'hostname': None,
  1138. 'port': None,
  1139. 'username': None,
  1140. 'password': None,
  1141. },
  1142. borgmatic_runtime_directory='/run/borgmatic',
  1143. )
  1144. def test_restore_data_source_dump_with_dry_run_skips_restore():
  1145. hook_config = [{'name': 'foo'}]
  1146. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1147. 'resolve_credential'
  1148. ).replace_with(lambda value, config: value)
  1149. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1150. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1151. None, None, None
  1152. ).and_return(())
  1153. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1154. flexmock(module).should_receive('execute_command_with_processes').never()
  1155. module.restore_data_source_dump(
  1156. hook_config,
  1157. {},
  1158. data_source={'name': 'foo'},
  1159. dry_run=True,
  1160. extract_process=flexmock(),
  1161. connection_params={
  1162. 'hostname': None,
  1163. 'port': None,
  1164. 'username': None,
  1165. 'password': None,
  1166. },
  1167. borgmatic_runtime_directory='/run/borgmatic',
  1168. )