test_mariadb.py 44 KB

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