test_mariadb.py 67 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907
  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,
  26. b'[client]\nuser=root\npassword="trustsome1"',
  27. ).once()
  28. flexmock(module.os).should_receive('close')
  29. flexmock(module.os).should_receive('set_inheritable')
  30. assert module.make_defaults_file_options(username='root', password='trustsome1') == (
  31. '--defaults-extra-file=/dev/fd/99',
  32. )
  33. def test_make_defaults_file_escapes_password_containing_backslash():
  34. read_descriptor = 99
  35. write_descriptor = flexmock()
  36. flexmock(module.os).should_receive('pipe').and_return(read_descriptor, write_descriptor)
  37. flexmock(module.os).should_receive('write').with_args(
  38. write_descriptor,
  39. b'[client]\nuser=root\n' + rb'password="trust\\nsome1"',
  40. ).once()
  41. flexmock(module.os).should_receive('close')
  42. flexmock(module.os).should_receive('set_inheritable')
  43. assert module.make_defaults_file_options(username='root', password=r'trust\nsome1') == (
  44. '--defaults-extra-file=/dev/fd/99',
  45. )
  46. def test_make_defaults_file_pipe_with_only_username_writes_it_to_file_descriptor():
  47. read_descriptor = 99
  48. write_descriptor = flexmock()
  49. flexmock(module.os).should_receive('pipe').and_return(read_descriptor, write_descriptor)
  50. flexmock(module.os).should_receive('write').with_args(
  51. write_descriptor,
  52. b'[client]\nuser=root',
  53. ).once()
  54. flexmock(module.os).should_receive('close')
  55. flexmock(module.os).should_receive('set_inheritable')
  56. assert module.make_defaults_file_options(username='root', password=None) == (
  57. '--defaults-extra-file=/dev/fd/99',
  58. )
  59. def test_make_defaults_file_pipe_with_only_password_writes_it_to_file_descriptor():
  60. read_descriptor = 99
  61. write_descriptor = flexmock()
  62. flexmock(module.os).should_receive('pipe').and_return(read_descriptor, write_descriptor)
  63. flexmock(module.os).should_receive('write').with_args(
  64. write_descriptor,
  65. b'[client]\npassword="trustsome1"',
  66. ).once()
  67. flexmock(module.os).should_receive('close')
  68. flexmock(module.os).should_receive('set_inheritable')
  69. assert module.make_defaults_file_options(username=None, password='trustsome1') == (
  70. '--defaults-extra-file=/dev/fd/99',
  71. )
  72. def test_make_defaults_file_option_with_defaults_extra_filename_includes_it_in_file_descriptor():
  73. read_descriptor = 99
  74. write_descriptor = flexmock()
  75. flexmock(module.os).should_receive('pipe').and_return(read_descriptor, write_descriptor)
  76. flexmock(module.os).should_receive('write').with_args(
  77. write_descriptor,
  78. b'!include extra.cnf\n[client]\nuser=root\npassword="trustsome1"',
  79. ).once()
  80. flexmock(module.os).should_receive('close')
  81. flexmock(module.os).should_receive('set_inheritable')
  82. assert module.make_defaults_file_options(
  83. username='root',
  84. password='trustsome1',
  85. defaults_extra_filename='extra.cnf',
  86. ) == ('--defaults-extra-file=/dev/fd/99',)
  87. def test_make_defaults_file_option_with_only_defaults_extra_filename_uses_it_instead_of_file_descriptor():
  88. flexmock(module.os).should_receive('pipe').never()
  89. assert module.make_defaults_file_options(
  90. username=None,
  91. password=None,
  92. defaults_extra_filename='extra.cnf',
  93. ) == ('--defaults-extra-file=extra.cnf',)
  94. def test_database_names_to_dump_passes_through_name():
  95. environment = flexmock()
  96. names = module.database_names_to_dump(
  97. {'name': 'foo'},
  98. {},
  99. 'root',
  100. 'trustsome1',
  101. environment,
  102. dry_run=False,
  103. )
  104. assert names == ('foo',)
  105. def test_database_names_to_dump_with_non_all_name_and_skip_names_warns():
  106. environment = flexmock()
  107. flexmock(module.logger).should_receive('warning').once()
  108. names = module.database_names_to_dump(
  109. {'name': 'foo', 'skip_names': ('foo', 'bar')},
  110. {},
  111. 'root',
  112. 'trustsome1',
  113. environment,
  114. dry_run=False,
  115. )
  116. assert names == ('foo',)
  117. def test_database_names_to_dump_bails_for_dry_run():
  118. environment = flexmock()
  119. flexmock(module).should_receive('execute_command_and_capture_output').never()
  120. names = module.database_names_to_dump(
  121. {'name': 'all'},
  122. {},
  123. 'root',
  124. 'trustsome1',
  125. environment,
  126. dry_run=True,
  127. )
  128. assert names == ()
  129. def test_database_names_to_dump_queries_mariadb_for_database_names():
  130. environment = flexmock()
  131. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  132. 'resolve_credential',
  133. ).replace_with(lambda value, config: value)
  134. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  135. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  136. flexmock(module).should_receive('make_defaults_file_options').with_args(
  137. 'root',
  138. 'trustsome1',
  139. None,
  140. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  141. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
  142. '/path/to/working/dir'
  143. )
  144. flexmock(module).should_receive('execute_command_and_capture_output').with_args(
  145. (
  146. 'mariadb',
  147. '--defaults-extra-file=/dev/fd/99',
  148. '--skip-column-names',
  149. '--batch',
  150. '--execute',
  151. 'show schemas',
  152. ),
  153. environment=environment,
  154. working_directory='/path/to/working/dir',
  155. ).and_return('foo\nbar\nmysql\n').once()
  156. names = module.database_names_to_dump(
  157. {'name': 'all'},
  158. {},
  159. 'root',
  160. 'trustsome1',
  161. environment,
  162. dry_run=False,
  163. )
  164. assert names == ('foo', 'bar')
  165. def test_database_names_to_dump_with_database_name_all_and_skip_names_filters_out_unwanted_databases():
  166. environment = flexmock()
  167. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  168. 'resolve_credential',
  169. ).replace_with(lambda value, config: value)
  170. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  171. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  172. flexmock(module).should_receive('make_defaults_file_options').with_args(
  173. 'root',
  174. 'trustsome1',
  175. None,
  176. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  177. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  178. flexmock(module).should_receive('execute_command_and_capture_output').with_args(
  179. (
  180. 'mariadb',
  181. '--defaults-extra-file=/dev/fd/99',
  182. '--skip-column-names',
  183. '--batch',
  184. '--execute',
  185. 'show schemas',
  186. ),
  187. environment=environment,
  188. working_directory=None,
  189. ).and_return('foo\nbar\nbaz\nmysql\n').once()
  190. names = module.database_names_to_dump(
  191. {'name': 'all', 'skip_names': ('foo', 'bar')},
  192. {},
  193. 'root',
  194. 'trustsome1',
  195. environment,
  196. dry_run=False,
  197. )
  198. assert names == ('baz',)
  199. def test_database_names_to_dump_runs_mariadb_with_socket_path():
  200. environment = flexmock()
  201. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  202. 'resolve_credential',
  203. ).replace_with(lambda value, config: value)
  204. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  205. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  206. flexmock(module).should_receive('make_defaults_file_options').with_args(
  207. 'root',
  208. 'trustsome1',
  209. None,
  210. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  211. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  212. flexmock(module).should_receive('execute_command_and_capture_output').with_args(
  213. (
  214. 'mariadb',
  215. '--defaults-extra-file=/dev/fd/99',
  216. '--socket',
  217. '/socket',
  218. '--skip-column-names',
  219. '--batch',
  220. '--execute',
  221. 'show schemas',
  222. ),
  223. environment=environment,
  224. working_directory=None,
  225. ).and_return('foo\nbar\nmysql\n').once()
  226. names = module.database_names_to_dump(
  227. {'name': 'all', 'socket_path': '/socket'},
  228. {},
  229. 'root',
  230. 'trustsome1',
  231. environment,
  232. dry_run=False,
  233. )
  234. assert names == ('foo', 'bar')
  235. def test_database_names_to_dump_with_environment_password_transport_skips_defaults_file_and_passes_user_flag():
  236. environment = flexmock()
  237. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  238. 'resolve_credential',
  239. ).replace_with(lambda value, config: value)
  240. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  241. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  242. flexmock(module).should_receive('make_defaults_file_options').never()
  243. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  244. flexmock(module).should_receive('execute_command_and_capture_output').with_args(
  245. (
  246. 'mariadb',
  247. '--user',
  248. 'root',
  249. '--skip-column-names',
  250. '--batch',
  251. '--execute',
  252. 'show schemas',
  253. ),
  254. environment=environment,
  255. working_directory=None,
  256. ).and_return('foo\nbar\nmysql\n').once()
  257. names = module.database_names_to_dump(
  258. {'name': 'all', 'password_transport': 'environment'},
  259. {},
  260. 'root',
  261. 'trustsome1',
  262. environment,
  263. dry_run=False,
  264. )
  265. assert names == ('foo', 'bar')
  266. def test_database_names_to_dump_runs_mariadb_with_tls():
  267. environment = flexmock()
  268. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  269. 'resolve_credential',
  270. ).replace_with(lambda value, config: value)
  271. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  272. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  273. flexmock(module).should_receive('make_defaults_file_options').with_args(
  274. 'root',
  275. 'trustsome1',
  276. None,
  277. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  278. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  279. flexmock(module).should_receive('execute_command_and_capture_output').with_args(
  280. (
  281. 'mariadb',
  282. '--defaults-extra-file=/dev/fd/99',
  283. '--ssl',
  284. '--skip-column-names',
  285. '--batch',
  286. '--execute',
  287. 'show schemas',
  288. ),
  289. environment=environment,
  290. working_directory=None,
  291. ).and_return('foo\nbar\nmysql\n').once()
  292. names = module.database_names_to_dump(
  293. {'name': 'all', 'tls': True},
  294. {},
  295. 'root',
  296. 'trustsome1',
  297. environment,
  298. dry_run=False,
  299. )
  300. assert names == ('foo', 'bar')
  301. def test_database_names_to_dump_runs_mariadb_without_tls():
  302. environment = flexmock()
  303. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  304. 'resolve_credential',
  305. ).replace_with(lambda value, config: value)
  306. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  307. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  308. flexmock(module).should_receive('make_defaults_file_options').with_args(
  309. 'root',
  310. 'trustsome1',
  311. None,
  312. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  313. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  314. flexmock(module).should_receive('execute_command_and_capture_output').with_args(
  315. (
  316. 'mariadb',
  317. '--defaults-extra-file=/dev/fd/99',
  318. '--skip-ssl',
  319. '--skip-column-names',
  320. '--batch',
  321. '--execute',
  322. 'show schemas',
  323. ),
  324. environment=environment,
  325. working_directory=None,
  326. ).and_return('foo\nbar\nmysql\n').once()
  327. names = module.database_names_to_dump(
  328. {'name': 'all', 'tls': False},
  329. {},
  330. 'root',
  331. 'trustsome1',
  332. environment,
  333. dry_run=False,
  334. )
  335. assert names == ('foo', 'bar')
  336. def test_use_streaming_true_for_any_databases():
  337. assert module.use_streaming(
  338. databases=[flexmock(), flexmock()],
  339. config=flexmock(),
  340. )
  341. def test_use_streaming_false_for_no_databases():
  342. assert not module.use_streaming(databases=[], config=flexmock())
  343. def test_dump_data_sources_dumps_each_database():
  344. databases = [{'name': 'foo'}, {'name': 'bar'}]
  345. processes = [flexmock(), flexmock()]
  346. flexmock(module).should_receive('make_dump_path').and_return('')
  347. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  348. 'resolve_credential',
  349. ).and_return(None)
  350. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  351. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  352. 'resolve_credential',
  353. ).replace_with(lambda value, config: value)
  354. flexmock(module).should_receive('database_names_to_dump').with_args(
  355. database=databases[0],
  356. config={},
  357. username=None,
  358. password=None,
  359. environment={'USER': 'root'},
  360. dry_run=False,
  361. ).and_return(('foo',))
  362. flexmock(module).should_receive('database_names_to_dump').with_args(
  363. database=databases[1],
  364. config={},
  365. username=None,
  366. password=None,
  367. environment={'USER': 'root'},
  368. dry_run=False,
  369. ).and_return(('bar',))
  370. for name, process in zip(('foo', 'bar'), processes):
  371. flexmock(module).should_receive('execute_dump_command').with_args(
  372. database={'name': name},
  373. config={},
  374. username=None,
  375. password=None,
  376. dump_path=object,
  377. database_names=(name,),
  378. environment={'USER': 'root'},
  379. dry_run=object,
  380. dry_run_label=object,
  381. ).and_return(process).once()
  382. flexmock(module.dump).should_receive('write_data_source_dumps_metadata').with_args(
  383. '/run/borgmatic',
  384. 'mariadb_databases',
  385. [
  386. module.borgmatic.actions.restore.Dump('mariadb_databases', 'foo'),
  387. module.borgmatic.actions.restore.Dump('mariadb_databases', 'bar'),
  388. ],
  389. ).once()
  390. flexmock(module.borgmatic.hooks.data_source.config).should_receive('inject_pattern').with_args(
  391. object,
  392. module.borgmatic.borg.pattern.Pattern(
  393. '/run/borgmatic/mariadb_databases',
  394. source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
  395. ),
  396. ).once()
  397. assert (
  398. module.dump_data_sources(
  399. databases,
  400. {},
  401. config_paths=('test.yaml',),
  402. borgmatic_runtime_directory='/run/borgmatic',
  403. patterns=[],
  404. dry_run=False,
  405. )
  406. == processes
  407. )
  408. def test_dump_data_sources_dumps_with_password():
  409. database = {'name': 'foo', 'username': 'root', 'password': 'trustsome1'}
  410. process = flexmock()
  411. flexmock(module).should_receive('make_dump_path').and_return('')
  412. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  413. 'resolve_credential',
  414. ).replace_with(lambda value, config: value)
  415. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  416. flexmock(module).should_receive('database_names_to_dump').with_args(
  417. database=database,
  418. config={},
  419. username='root',
  420. password='trustsome1',
  421. environment={'USER': 'root'},
  422. dry_run=False,
  423. ).and_return(('foo',))
  424. flexmock(module).should_receive('execute_dump_command').with_args(
  425. database=database,
  426. config={},
  427. username='root',
  428. password='trustsome1',
  429. dump_path=object,
  430. database_names=('foo',),
  431. environment={'USER': 'root'},
  432. dry_run=object,
  433. dry_run_label=object,
  434. ).and_return(process).once()
  435. flexmock(module.dump).should_receive('write_data_source_dumps_metadata').with_args(
  436. '/run/borgmatic',
  437. 'mariadb_databases',
  438. [
  439. module.borgmatic.actions.restore.Dump('mariadb_databases', 'foo'),
  440. ],
  441. ).once()
  442. flexmock(module.borgmatic.hooks.data_source.config).should_receive('inject_pattern').with_args(
  443. object,
  444. module.borgmatic.borg.pattern.Pattern(
  445. '/run/borgmatic/mariadb_databases',
  446. source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
  447. ),
  448. ).once()
  449. assert module.dump_data_sources(
  450. [database],
  451. {},
  452. config_paths=('test.yaml',),
  453. borgmatic_runtime_directory='/run/borgmatic',
  454. patterns=[],
  455. dry_run=False,
  456. ) == [process]
  457. def test_dump_data_sources_dumps_with_environment_password_transport_passes_password_environment_variable():
  458. database = {
  459. 'name': 'foo',
  460. 'username': 'root',
  461. 'password': 'trustsome1',
  462. 'password_transport': 'environment',
  463. }
  464. process = flexmock()
  465. flexmock(module).should_receive('make_dump_path').and_return('')
  466. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  467. 'resolve_credential',
  468. ).replace_with(lambda value, config: value)
  469. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  470. flexmock(module).should_receive('database_names_to_dump').with_args(
  471. database=database,
  472. config={},
  473. username='root',
  474. password='trustsome1',
  475. environment={'USER': 'root', 'MYSQL_PWD': 'trustsome1'},
  476. dry_run=False,
  477. ).and_return(('foo',))
  478. flexmock(module).should_receive('execute_dump_command').with_args(
  479. database=database,
  480. config={},
  481. username='root',
  482. password='trustsome1',
  483. dump_path=object,
  484. database_names=('foo',),
  485. environment={'USER': 'root', 'MYSQL_PWD': 'trustsome1'},
  486. dry_run=object,
  487. dry_run_label=object,
  488. ).and_return(process).once()
  489. flexmock(module.dump).should_receive('write_data_source_dumps_metadata').with_args(
  490. '/run/borgmatic',
  491. 'mariadb_databases',
  492. [
  493. module.borgmatic.actions.restore.Dump('mariadb_databases', 'foo'),
  494. ],
  495. ).once()
  496. flexmock(module.borgmatic.hooks.data_source.config).should_receive('inject_pattern').with_args(
  497. object,
  498. module.borgmatic.borg.pattern.Pattern(
  499. '/run/borgmatic/mariadb_databases',
  500. source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
  501. ),
  502. ).once()
  503. assert module.dump_data_sources(
  504. [database],
  505. {},
  506. config_paths=('test.yaml',),
  507. borgmatic_runtime_directory='/run/borgmatic',
  508. patterns=[],
  509. dry_run=False,
  510. ) == [process]
  511. def test_dump_data_sources_dumps_all_databases_at_once():
  512. databases = [{'name': 'all'}]
  513. process = flexmock()
  514. flexmock(module).should_receive('make_dump_path').and_return('')
  515. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  516. 'resolve_credential',
  517. ).replace_with(lambda value, config: value)
  518. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  519. flexmock(module).should_receive('database_names_to_dump').and_return(('foo', 'bar'))
  520. flexmock(module).should_receive('execute_dump_command').with_args(
  521. database={'name': 'all'},
  522. config={},
  523. username=None,
  524. password=None,
  525. dump_path=object,
  526. database_names=('foo', 'bar'),
  527. environment={'USER': 'root'},
  528. dry_run=object,
  529. dry_run_label=object,
  530. ).and_return(process).once()
  531. flexmock(module.dump).should_receive('write_data_source_dumps_metadata').with_args(
  532. '/run/borgmatic',
  533. 'mariadb_databases',
  534. [
  535. module.borgmatic.actions.restore.Dump('mariadb_databases', 'all'),
  536. ],
  537. ).once()
  538. flexmock(module.borgmatic.hooks.data_source.config).should_receive('inject_pattern').with_args(
  539. object,
  540. module.borgmatic.borg.pattern.Pattern(
  541. '/run/borgmatic/mariadb_databases',
  542. source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
  543. ),
  544. ).once()
  545. assert module.dump_data_sources(
  546. databases,
  547. {},
  548. config_paths=('test.yaml',),
  549. borgmatic_runtime_directory='/run/borgmatic',
  550. patterns=[],
  551. dry_run=False,
  552. ) == [process]
  553. def test_dump_data_sources_dumps_all_databases_separately_when_format_configured():
  554. databases = [{'name': 'all', 'format': 'sql'}]
  555. processes = [flexmock(), flexmock()]
  556. flexmock(module).should_receive('make_dump_path').and_return('')
  557. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  558. 'resolve_credential',
  559. ).and_return(None)
  560. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  561. flexmock(module).should_receive('database_names_to_dump').and_return(('foo', 'bar'))
  562. for name, process in zip(('foo', 'bar'), processes):
  563. flexmock(module).should_receive('execute_dump_command').with_args(
  564. database={'name': name, 'format': 'sql'},
  565. config={},
  566. username=None,
  567. password=None,
  568. dump_path=object,
  569. database_names=(name,),
  570. environment={'USER': 'root'},
  571. dry_run=object,
  572. dry_run_label=object,
  573. ).and_return(process).once()
  574. flexmock(module.dump).should_receive('write_data_source_dumps_metadata').with_args(
  575. '/run/borgmatic',
  576. 'mariadb_databases',
  577. [
  578. module.borgmatic.actions.restore.Dump('mariadb_databases', 'foo'),
  579. module.borgmatic.actions.restore.Dump('mariadb_databases', 'bar'),
  580. ],
  581. ).once()
  582. flexmock(module.borgmatic.hooks.data_source.config).should_receive('inject_pattern').with_args(
  583. object,
  584. module.borgmatic.borg.pattern.Pattern(
  585. '/run/borgmatic/mariadb_databases',
  586. source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
  587. ),
  588. ).once()
  589. assert (
  590. module.dump_data_sources(
  591. databases,
  592. {},
  593. config_paths=('test.yaml',),
  594. borgmatic_runtime_directory='/run/borgmatic',
  595. patterns=[],
  596. dry_run=False,
  597. )
  598. == processes
  599. )
  600. def test_dump_data_sources_errors_for_missing_all_databases():
  601. databases = [{'name': 'all'}]
  602. flexmock(module).should_receive('make_dump_path').and_return('')
  603. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  604. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  605. 'resolve_credential',
  606. ).replace_with(lambda value, config: value)
  607. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return(
  608. 'databases/localhost/all',
  609. )
  610. flexmock(module).should_receive('database_names_to_dump').and_return(())
  611. flexmock(module.borgmatic.hooks.data_source.config).should_receive('inject_pattern').never()
  612. with pytest.raises(ValueError):
  613. assert module.dump_data_sources(
  614. databases,
  615. {},
  616. config_paths=('test.yaml',),
  617. borgmatic_runtime_directory='/run/borgmatic',
  618. patterns=[],
  619. dry_run=False,
  620. )
  621. def test_dump_data_sources_does_not_error_for_missing_all_databases_with_dry_run():
  622. databases = [{'name': 'all'}]
  623. flexmock(module).should_receive('make_dump_path').and_return('')
  624. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  625. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  626. 'resolve_credential',
  627. ).replace_with(lambda value, config: value)
  628. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return(
  629. 'databases/localhost/all',
  630. )
  631. flexmock(module).should_receive('database_names_to_dump').and_return(())
  632. flexmock(module.borgmatic.hooks.data_source.config).should_receive('inject_pattern').never()
  633. assert (
  634. module.dump_data_sources(
  635. databases,
  636. {},
  637. config_paths=('test.yaml',),
  638. borgmatic_runtime_directory='/run/borgmatic',
  639. patterns=[],
  640. dry_run=True,
  641. )
  642. == []
  643. )
  644. def test_database_names_to_dump_runs_mariadb_with_list_options():
  645. database = {'name': 'all', 'list_options': '--defaults-extra-file=mariadb.cnf --skip-ssl'}
  646. flexmock(module).should_receive('parse_extra_options').and_return(
  647. ('--skip-ssl',),
  648. 'mariadb.cnf',
  649. )
  650. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  651. flexmock(module).should_receive('make_defaults_file_options').with_args(
  652. 'root',
  653. 'trustsome1',
  654. 'mariadb.cnf',
  655. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  656. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  657. flexmock(module).should_receive('execute_command_and_capture_output').with_args(
  658. (
  659. 'mariadb',
  660. '--defaults-extra-file=/dev/fd/99',
  661. '--skip-ssl',
  662. '--skip-column-names',
  663. '--batch',
  664. '--execute',
  665. 'show schemas',
  666. ),
  667. environment=None,
  668. working_directory=None,
  669. ).and_return('foo\nbar').once()
  670. assert module.database_names_to_dump(database, {}, 'root', 'trustsome1', None, '') == (
  671. 'foo',
  672. 'bar',
  673. )
  674. def test_database_names_to_dump_runs_non_default_mariadb_with_list_options():
  675. database = {
  676. 'name': 'all',
  677. 'list_options': '--defaults-extra-file=mariadb.cnf --skip-ssl',
  678. 'mariadb_command': 'custom_mariadb',
  679. }
  680. flexmock(module).should_receive('parse_extra_options').and_return(
  681. ('--skip-ssl',),
  682. 'mariadb.cnf',
  683. )
  684. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  685. flexmock(module).should_receive('make_defaults_file_options').with_args(
  686. 'root',
  687. 'trustsome1',
  688. 'mariadb.cnf',
  689. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  690. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  691. flexmock(module).should_receive('execute_command_and_capture_output').with_args(
  692. environment=None,
  693. full_command=(
  694. 'custom_mariadb', # Custom MariaDB command
  695. '--defaults-extra-file=/dev/fd/99',
  696. '--skip-ssl',
  697. '--skip-column-names',
  698. '--batch',
  699. '--execute',
  700. 'show schemas',
  701. ),
  702. working_directory=None,
  703. ).and_return('foo\nbar').once()
  704. assert module.database_names_to_dump(database, {}, 'root', 'trustsome1', None, '') == (
  705. 'foo',
  706. 'bar',
  707. )
  708. def test_execute_dump_command_runs_mariadb_dump():
  709. process = flexmock()
  710. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  711. flexmock(module.os.path).should_receive('exists').and_return(False)
  712. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  713. 'resolve_credential',
  714. ).replace_with(lambda value, config: value)
  715. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  716. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  717. flexmock(module).should_receive('make_defaults_file_options').with_args(
  718. 'root',
  719. 'trustsome1',
  720. None,
  721. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  722. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  723. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  724. flexmock(module).should_receive('execute_command').with_args(
  725. (
  726. 'mariadb-dump',
  727. '--defaults-extra-file=/dev/fd/99',
  728. '--add-drop-database',
  729. '--single-transaction',
  730. '--databases',
  731. 'foo',
  732. '--result-file',
  733. 'dump',
  734. ),
  735. environment=None,
  736. run_to_completion=False,
  737. working_directory=None,
  738. ).and_return(process).once()
  739. assert (
  740. module.execute_dump_command(
  741. database={'name': 'foo'},
  742. config={},
  743. username='root',
  744. password='trustsome1',
  745. dump_path=flexmock(),
  746. database_names=('foo',),
  747. environment=None,
  748. dry_run=False,
  749. dry_run_label='',
  750. )
  751. == process
  752. )
  753. def test_execute_dump_command_with_environment_password_transport_skips_defaults_file_and_passes_user_flag():
  754. process = flexmock()
  755. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  756. flexmock(module.os.path).should_receive('exists').and_return(False)
  757. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  758. 'resolve_credential',
  759. ).replace_with(lambda value, config: value)
  760. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  761. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  762. flexmock(module).should_receive('make_defaults_file_options').never()
  763. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  764. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  765. flexmock(module).should_receive('execute_command').with_args(
  766. (
  767. 'mariadb-dump',
  768. '--add-drop-database',
  769. '--single-transaction',
  770. '--user',
  771. 'root',
  772. '--databases',
  773. 'foo',
  774. '--result-file',
  775. 'dump',
  776. ),
  777. environment=None,
  778. run_to_completion=False,
  779. working_directory=None,
  780. ).and_return(process).once()
  781. assert (
  782. module.execute_dump_command(
  783. database={'name': 'foo', 'password_transport': 'environment'},
  784. config={},
  785. username='root',
  786. password='trustsome1',
  787. dump_path=flexmock(),
  788. database_names=('foo',),
  789. environment=None,
  790. dry_run=False,
  791. dry_run_label='',
  792. )
  793. == process
  794. )
  795. def test_execute_dump_command_runs_mariadb_dump_without_add_drop_database():
  796. process = flexmock()
  797. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  798. flexmock(module.os.path).should_receive('exists').and_return(False)
  799. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  800. 'resolve_credential',
  801. ).replace_with(lambda value, config: value)
  802. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  803. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  804. flexmock(module).should_receive('make_defaults_file_options').with_args(
  805. 'root',
  806. 'trustsome1',
  807. None,
  808. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  809. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  810. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  811. flexmock(module).should_receive('execute_command').with_args(
  812. (
  813. 'mariadb-dump',
  814. '--defaults-extra-file=/dev/fd/99',
  815. '--single-transaction',
  816. '--databases',
  817. 'foo',
  818. '--result-file',
  819. 'dump',
  820. ),
  821. environment=None,
  822. run_to_completion=False,
  823. working_directory=None,
  824. ).and_return(process).once()
  825. assert (
  826. module.execute_dump_command(
  827. database={'name': 'foo', 'add_drop_database': False},
  828. config={},
  829. username='root',
  830. password='trustsome1',
  831. dump_path=flexmock(),
  832. database_names=('foo',),
  833. environment=None,
  834. dry_run=False,
  835. dry_run_label='',
  836. )
  837. == process
  838. )
  839. def test_execute_dump_command_runs_mariadb_dump_with_hostname_and_port():
  840. process = flexmock()
  841. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  842. flexmock(module.os.path).should_receive('exists').and_return(False)
  843. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  844. 'resolve_credential',
  845. ).replace_with(lambda value, config: value)
  846. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  847. flexmock(module.database_config).should_receive('resolve_database_option').and_return(
  848. 'database.example.org'
  849. )
  850. flexmock(module).should_receive('make_defaults_file_options').with_args(
  851. 'root',
  852. 'trustsome1',
  853. None,
  854. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  855. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  856. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  857. flexmock(module).should_receive('execute_command').with_args(
  858. (
  859. 'mariadb-dump',
  860. '--defaults-extra-file=/dev/fd/99',
  861. '--add-drop-database',
  862. '--single-transaction',
  863. '--host',
  864. 'database.example.org',
  865. '--port',
  866. '5433',
  867. '--protocol',
  868. 'tcp',
  869. '--databases',
  870. 'foo',
  871. '--result-file',
  872. 'dump',
  873. ),
  874. environment=None,
  875. run_to_completion=False,
  876. working_directory=None,
  877. ).and_return(process).once()
  878. assert (
  879. module.execute_dump_command(
  880. database={'name': 'foo', 'hostname': 'database.example.org', 'port': 5433},
  881. config={},
  882. username='root',
  883. password='trustsome1',
  884. dump_path=flexmock(),
  885. database_names=('foo',),
  886. environment=None,
  887. dry_run=False,
  888. dry_run_label='',
  889. )
  890. == process
  891. )
  892. def test_execute_dump_command_runs_mariadb_dump_with_tls():
  893. process = flexmock()
  894. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  895. flexmock(module.os.path).should_receive('exists').and_return(False)
  896. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  897. 'resolve_credential',
  898. ).replace_with(lambda value, config: value)
  899. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  900. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  901. flexmock(module).should_receive('make_defaults_file_options').with_args(
  902. 'root',
  903. 'trustsome1',
  904. None,
  905. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  906. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  907. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  908. flexmock(module).should_receive('execute_command').with_args(
  909. (
  910. 'mariadb-dump',
  911. '--defaults-extra-file=/dev/fd/99',
  912. '--add-drop-database',
  913. '--single-transaction',
  914. '--ssl',
  915. '--databases',
  916. 'foo',
  917. '--result-file',
  918. 'dump',
  919. ),
  920. environment=None,
  921. run_to_completion=False,
  922. working_directory=None,
  923. ).and_return(process).once()
  924. assert (
  925. module.execute_dump_command(
  926. database={'name': 'foo', 'tls': True},
  927. config={},
  928. username='root',
  929. password='trustsome1',
  930. dump_path=flexmock(),
  931. database_names=('foo',),
  932. environment=None,
  933. dry_run=False,
  934. dry_run_label='',
  935. )
  936. == process
  937. )
  938. def test_execute_dump_command_runs_mariadb_dump_without_tls():
  939. process = flexmock()
  940. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  941. flexmock(module.os.path).should_receive('exists').and_return(False)
  942. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  943. 'resolve_credential',
  944. ).replace_with(lambda value, config: value)
  945. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  946. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  947. flexmock(module).should_receive('make_defaults_file_options').with_args(
  948. 'root',
  949. 'trustsome1',
  950. None,
  951. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  952. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  953. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  954. flexmock(module).should_receive('execute_command').with_args(
  955. (
  956. 'mariadb-dump',
  957. '--defaults-extra-file=/dev/fd/99',
  958. '--add-drop-database',
  959. '--single-transaction',
  960. '--skip-ssl',
  961. '--databases',
  962. 'foo',
  963. '--result-file',
  964. 'dump',
  965. ),
  966. environment=None,
  967. run_to_completion=False,
  968. working_directory=None,
  969. ).and_return(process).once()
  970. assert (
  971. module.execute_dump_command(
  972. database={'name': 'foo', 'tls': False},
  973. config={},
  974. username='root',
  975. password='trustsome1',
  976. dump_path=flexmock(),
  977. database_names=('foo',),
  978. environment=None,
  979. dry_run=False,
  980. dry_run_label='',
  981. )
  982. == process
  983. )
  984. def test_execute_dump_command_runs_mariadb_dump_with_username_and_password():
  985. process = flexmock()
  986. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  987. flexmock(module.os.path).should_receive('exists').and_return(False)
  988. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  989. 'resolve_credential',
  990. ).replace_with(lambda value, config: value)
  991. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  992. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  993. flexmock(module).should_receive('make_defaults_file_options').with_args(
  994. 'root',
  995. 'trustsome1',
  996. None,
  997. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  998. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  999. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1000. flexmock(module).should_receive('execute_command').with_args(
  1001. (
  1002. 'mariadb-dump',
  1003. '--defaults-extra-file=/dev/fd/99',
  1004. '--add-drop-database',
  1005. '--single-transaction',
  1006. '--databases',
  1007. 'foo',
  1008. '--result-file',
  1009. 'dump',
  1010. ),
  1011. environment={},
  1012. run_to_completion=False,
  1013. working_directory=None,
  1014. ).and_return(process).once()
  1015. assert (
  1016. module.execute_dump_command(
  1017. database={'name': 'foo', 'username': 'root', 'password': 'trustsome1'},
  1018. config={},
  1019. username='root',
  1020. password='trustsome1',
  1021. dump_path=flexmock(),
  1022. database_names=('foo',),
  1023. environment={},
  1024. dry_run=False,
  1025. dry_run_label='',
  1026. )
  1027. == process
  1028. )
  1029. def test_execute_dump_command_runs_mariadb_dump_with_options():
  1030. process = flexmock()
  1031. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  1032. flexmock(module.os.path).should_receive('exists').and_return(False)
  1033. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1034. 'resolve_credential',
  1035. ).replace_with(lambda value, config: value)
  1036. flexmock(module).should_receive('parse_extra_options').and_return(('--stuff=such',), None)
  1037. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1038. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1039. 'root',
  1040. 'trustsome1',
  1041. None,
  1042. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1043. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  1044. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1045. flexmock(module).should_receive('execute_command').with_args(
  1046. (
  1047. 'mariadb-dump',
  1048. '--defaults-extra-file=/dev/fd/99',
  1049. '--stuff=such',
  1050. '--add-drop-database',
  1051. '--single-transaction',
  1052. '--databases',
  1053. 'foo',
  1054. '--result-file',
  1055. 'dump',
  1056. ),
  1057. environment=None,
  1058. run_to_completion=False,
  1059. working_directory=None,
  1060. ).and_return(process).once()
  1061. assert (
  1062. module.execute_dump_command(
  1063. database={'name': 'foo', 'options': '--stuff=such'},
  1064. config={},
  1065. username='root',
  1066. password='trustsome1',
  1067. dump_path=flexmock(),
  1068. database_names=('foo',),
  1069. environment=None,
  1070. dry_run=False,
  1071. dry_run_label='',
  1072. )
  1073. == process
  1074. )
  1075. def test_execute_dump_command_runs_non_default_mariadb_dump_with_options():
  1076. process = flexmock()
  1077. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  1078. flexmock(module.os.path).should_receive('exists').and_return(False)
  1079. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1080. 'resolve_credential',
  1081. ).replace_with(lambda value, config: value)
  1082. flexmock(module).should_receive('parse_extra_options').and_return(('--stuff=such',), None)
  1083. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1084. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1085. 'root',
  1086. 'trustsome1',
  1087. None,
  1088. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1089. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  1090. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1091. flexmock(module).should_receive('execute_command').with_args(
  1092. (
  1093. 'custom_mariadb_dump', # Custom MariaDB dump command
  1094. '--defaults-extra-file=/dev/fd/99',
  1095. '--stuff=such',
  1096. '--add-drop-database',
  1097. '--single-transaction',
  1098. '--databases',
  1099. 'foo',
  1100. '--result-file',
  1101. 'dump',
  1102. ),
  1103. environment=None,
  1104. run_to_completion=False,
  1105. working_directory=None,
  1106. ).and_return(process).once()
  1107. assert (
  1108. module.execute_dump_command(
  1109. database={
  1110. 'name': 'foo',
  1111. 'mariadb_dump_command': 'custom_mariadb_dump',
  1112. 'options': '--stuff=such',
  1113. }, # Custom MariaDB dump command specified
  1114. config={},
  1115. username='root',
  1116. password='trustsome1',
  1117. dump_path=flexmock(),
  1118. database_names=('foo',),
  1119. environment=None,
  1120. dry_run=False,
  1121. dry_run_label='',
  1122. )
  1123. == process
  1124. )
  1125. def test_execute_dump_command_with_duplicate_dump_skips_mariadb_dump():
  1126. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  1127. flexmock(module.os.path).should_receive('exists').and_return(True)
  1128. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1129. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1130. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1131. 'root',
  1132. 'trustsome1',
  1133. None,
  1134. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1135. flexmock(module.dump).should_receive('create_named_pipe_for_dump').never()
  1136. flexmock(module).should_receive('execute_command').never()
  1137. assert (
  1138. module.execute_dump_command(
  1139. database={'name': 'foo'},
  1140. config={},
  1141. username='root',
  1142. password='trustsome1',
  1143. dump_path=flexmock(),
  1144. database_names=('foo',),
  1145. environment=None,
  1146. dry_run=True,
  1147. dry_run_label='SO DRY',
  1148. )
  1149. is None
  1150. )
  1151. def test_execute_dump_command_with_dry_run_skips_mariadb_dump():
  1152. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  1153. flexmock(module.os.path).should_receive('exists').and_return(False)
  1154. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1155. 'resolve_credential',
  1156. ).replace_with(lambda value, config: value)
  1157. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1158. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1159. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1160. 'root',
  1161. 'trustsome1',
  1162. None,
  1163. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1164. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  1165. flexmock(module).should_receive('execute_command').never()
  1166. assert (
  1167. module.execute_dump_command(
  1168. database={'name': 'foo'},
  1169. config={},
  1170. username='root',
  1171. password='trustsome1',
  1172. dump_path=flexmock(),
  1173. database_names=('foo',),
  1174. environment=None,
  1175. dry_run=True,
  1176. dry_run_label='SO DRY',
  1177. )
  1178. is None
  1179. )
  1180. def test_restore_data_source_dump_runs_mariadb_to_restore():
  1181. hook_config = [{'name': 'foo'}, {'name': 'bar'}]
  1182. extract_process = flexmock(stdout=flexmock())
  1183. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1184. 'resolve_credential',
  1185. ).replace_with(lambda value, config: value)
  1186. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1187. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1188. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1189. None,
  1190. None,
  1191. None,
  1192. ).and_return(())
  1193. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1194. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1195. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1196. ('mariadb', '--batch'),
  1197. processes=[extract_process],
  1198. output_log_level=logging.DEBUG,
  1199. input_file=extract_process.stdout,
  1200. environment={'USER': 'root'},
  1201. working_directory=None,
  1202. ).once()
  1203. module.restore_data_source_dump(
  1204. hook_config,
  1205. {},
  1206. data_source={'name': 'foo'},
  1207. dry_run=False,
  1208. extract_process=extract_process,
  1209. connection_params={
  1210. 'hostname': None,
  1211. 'port': None,
  1212. 'username': None,
  1213. 'password': None,
  1214. },
  1215. borgmatic_runtime_directory='/run/borgmatic',
  1216. )
  1217. def test_restore_data_source_dump_runs_mariadb_with_options():
  1218. hook_config = [{'name': 'foo', 'restore_options': '--harder'}]
  1219. extract_process = flexmock(stdout=flexmock())
  1220. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1221. 'resolve_credential',
  1222. ).replace_with(lambda value, config: value)
  1223. flexmock(module).should_receive('parse_extra_options').and_return(('--harder',), None)
  1224. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1225. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1226. None,
  1227. None,
  1228. None,
  1229. ).and_return(())
  1230. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1231. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1232. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1233. ('mariadb', '--harder', '--batch'),
  1234. processes=[extract_process],
  1235. output_log_level=logging.DEBUG,
  1236. input_file=extract_process.stdout,
  1237. environment={'USER': 'root'},
  1238. working_directory=None,
  1239. ).once()
  1240. module.restore_data_source_dump(
  1241. hook_config,
  1242. {},
  1243. data_source=hook_config[0],
  1244. dry_run=False,
  1245. extract_process=extract_process,
  1246. connection_params={
  1247. 'hostname': None,
  1248. 'port': None,
  1249. 'username': None,
  1250. 'password': None,
  1251. },
  1252. borgmatic_runtime_directory='/run/borgmatic',
  1253. )
  1254. def test_restore_data_source_dump_runs_non_default_mariadb_with_options():
  1255. hook_config = [
  1256. {'name': 'foo', 'restore_options': '--harder', 'mariadb_command': 'custom_mariadb'},
  1257. ]
  1258. extract_process = flexmock(stdout=flexmock())
  1259. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1260. 'resolve_credential',
  1261. ).replace_with(lambda value, config: value)
  1262. flexmock(module).should_receive('parse_extra_options').and_return(('--harder',), None)
  1263. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1264. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1265. None,
  1266. None,
  1267. None,
  1268. ).and_return(())
  1269. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1270. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1271. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1272. ('custom_mariadb', '--harder', '--batch'),
  1273. processes=[extract_process],
  1274. output_log_level=logging.DEBUG,
  1275. input_file=extract_process.stdout,
  1276. environment={'USER': 'root'},
  1277. working_directory=None,
  1278. ).once()
  1279. module.restore_data_source_dump(
  1280. hook_config,
  1281. {},
  1282. data_source=hook_config[0],
  1283. dry_run=False,
  1284. extract_process=extract_process,
  1285. connection_params={
  1286. 'hostname': None,
  1287. 'port': None,
  1288. 'username': None,
  1289. 'password': None,
  1290. },
  1291. borgmatic_runtime_directory='/run/borgmatic',
  1292. )
  1293. def test_restore_data_source_dump_runs_mariadb_with_hostname_and_port():
  1294. hook_config = [{'name': 'foo', 'hostname': 'database.example.org', 'port': 5433}]
  1295. extract_process = flexmock(stdout=flexmock())
  1296. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1297. 'resolve_credential',
  1298. ).replace_with(lambda value, config: value)
  1299. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1300. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1301. lambda option, data_source, connection_params=None, restore=False: data_source.get(option)
  1302. )
  1303. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1304. None,
  1305. None,
  1306. None,
  1307. ).and_return(())
  1308. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1309. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1310. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1311. (
  1312. 'mariadb',
  1313. '--batch',
  1314. '--host',
  1315. 'database.example.org',
  1316. '--port',
  1317. '5433',
  1318. '--protocol',
  1319. 'tcp',
  1320. ),
  1321. processes=[extract_process],
  1322. output_log_level=logging.DEBUG,
  1323. input_file=extract_process.stdout,
  1324. environment={'USER': 'root'},
  1325. working_directory=None,
  1326. ).once()
  1327. module.restore_data_source_dump(
  1328. hook_config,
  1329. {},
  1330. data_source=hook_config[0],
  1331. dry_run=False,
  1332. extract_process=extract_process,
  1333. connection_params={
  1334. 'hostname': None,
  1335. 'port': None,
  1336. 'username': None,
  1337. 'password': None,
  1338. },
  1339. borgmatic_runtime_directory='/run/borgmatic',
  1340. )
  1341. def test_restore_data_source_dump_runs_mariadb_with_socket_path():
  1342. hook_config = [{'name': 'foo', 'socket_path': '/socket'}]
  1343. extract_process = flexmock(stdout=flexmock())
  1344. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1345. 'resolve_credential',
  1346. ).replace_with(lambda value, config: value)
  1347. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1348. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1349. lambda option, data_source, connection_params=None, restore=False: data_source.get(option)
  1350. )
  1351. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1352. None,
  1353. None,
  1354. None,
  1355. ).and_return(())
  1356. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1357. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1358. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1359. (
  1360. 'mariadb',
  1361. '--batch',
  1362. '--socket',
  1363. '/socket',
  1364. ),
  1365. processes=[extract_process],
  1366. output_log_level=logging.DEBUG,
  1367. input_file=extract_process.stdout,
  1368. environment={'USER': 'root'},
  1369. working_directory=None,
  1370. ).once()
  1371. module.restore_data_source_dump(
  1372. hook_config,
  1373. {},
  1374. data_source=hook_config[0],
  1375. dry_run=False,
  1376. extract_process=extract_process,
  1377. connection_params={
  1378. 'hostname': None,
  1379. 'port': None,
  1380. 'username': None,
  1381. 'password': None,
  1382. },
  1383. borgmatic_runtime_directory='/run/borgmatic',
  1384. )
  1385. def test_restore_data_source_dump_runs_mariadb_with_tls():
  1386. hook_config = [{'name': 'foo', 'tls': True}]
  1387. extract_process = flexmock(stdout=flexmock())
  1388. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1389. 'resolve_credential',
  1390. ).replace_with(lambda value, config: value)
  1391. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1392. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1393. lambda option, data_source, connection_params=None, restore=False: data_source.get(option)
  1394. )
  1395. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1396. None,
  1397. None,
  1398. None,
  1399. ).and_return(())
  1400. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1401. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1402. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1403. (
  1404. 'mariadb',
  1405. '--batch',
  1406. '--ssl',
  1407. ),
  1408. processes=[extract_process],
  1409. output_log_level=logging.DEBUG,
  1410. input_file=extract_process.stdout,
  1411. environment={'USER': 'root'},
  1412. working_directory=None,
  1413. ).once()
  1414. module.restore_data_source_dump(
  1415. hook_config,
  1416. {},
  1417. data_source=hook_config[0],
  1418. dry_run=False,
  1419. extract_process=extract_process,
  1420. connection_params={
  1421. 'hostname': None,
  1422. 'port': None,
  1423. 'username': None,
  1424. 'password': None,
  1425. },
  1426. borgmatic_runtime_directory='/run/borgmatic',
  1427. )
  1428. def test_restore_data_source_dump_runs_mariadb_without_tls():
  1429. hook_config = [{'name': 'foo', 'tls': False}]
  1430. extract_process = flexmock(stdout=flexmock())
  1431. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1432. 'resolve_credential',
  1433. ).replace_with(lambda value, config: value)
  1434. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1435. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1436. lambda option, data_source, connection_params=None, restore=False: data_source.get(option)
  1437. )
  1438. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1439. None,
  1440. None,
  1441. None,
  1442. ).and_return(())
  1443. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1444. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1445. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1446. (
  1447. 'mariadb',
  1448. '--batch',
  1449. '--skip-ssl',
  1450. ),
  1451. processes=[extract_process],
  1452. output_log_level=logging.DEBUG,
  1453. input_file=extract_process.stdout,
  1454. environment={'USER': 'root'},
  1455. working_directory=None,
  1456. ).once()
  1457. module.restore_data_source_dump(
  1458. hook_config,
  1459. {},
  1460. data_source=hook_config[0],
  1461. dry_run=False,
  1462. extract_process=extract_process,
  1463. connection_params={
  1464. 'hostname': None,
  1465. 'port': None,
  1466. 'username': None,
  1467. 'password': None,
  1468. },
  1469. borgmatic_runtime_directory='/run/borgmatic',
  1470. )
  1471. def test_restore_data_source_dump_runs_mariadb_with_username_and_password():
  1472. hook_config = [{'name': 'foo', 'username': 'root', 'password': 'trustsome1'}]
  1473. extract_process = flexmock(stdout=flexmock())
  1474. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1475. 'resolve_credential',
  1476. ).replace_with(lambda value, config: value)
  1477. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1478. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1479. lambda option, data_source, connection_params=None, restore=False: data_source.get(option)
  1480. )
  1481. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1482. 'root',
  1483. 'trustsome1',
  1484. None,
  1485. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1486. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1487. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1488. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1489. ('mariadb', '--defaults-extra-file=/dev/fd/99', '--batch'),
  1490. processes=[extract_process],
  1491. output_log_level=logging.DEBUG,
  1492. input_file=extract_process.stdout,
  1493. environment={'USER': 'root'},
  1494. working_directory=None,
  1495. ).once()
  1496. module.restore_data_source_dump(
  1497. hook_config,
  1498. {},
  1499. data_source=hook_config[0],
  1500. dry_run=False,
  1501. extract_process=extract_process,
  1502. connection_params={
  1503. 'hostname': None,
  1504. 'port': None,
  1505. 'username': None,
  1506. 'password': None,
  1507. },
  1508. borgmatic_runtime_directory='/run/borgmatic',
  1509. )
  1510. def test_restore_data_source_with_environment_password_transport_skips_defaults_file_and_passes_user_flag():
  1511. hook_config = [
  1512. {
  1513. 'name': 'foo',
  1514. 'username': 'root',
  1515. 'password': 'trustsome1',
  1516. 'password_transport': 'environment',
  1517. },
  1518. ]
  1519. extract_process = flexmock(stdout=flexmock())
  1520. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1521. 'resolve_credential',
  1522. ).replace_with(lambda value, config: value)
  1523. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1524. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1525. lambda option, data_source, connection_params=None, restore=False: data_source.get(option)
  1526. )
  1527. flexmock(module).should_receive('make_defaults_file_options').never()
  1528. flexmock(module.os).should_receive('environ').and_return(
  1529. {'USER': 'root', 'MYSQL_PWD': 'trustsome1'},
  1530. )
  1531. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1532. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1533. ('mariadb', '--batch', '--user', 'root'),
  1534. processes=[extract_process],
  1535. output_log_level=logging.DEBUG,
  1536. input_file=extract_process.stdout,
  1537. environment={'USER': 'root', 'MYSQL_PWD': 'trustsome1'},
  1538. working_directory=None,
  1539. ).once()
  1540. module.restore_data_source_dump(
  1541. hook_config,
  1542. {},
  1543. data_source=hook_config[0],
  1544. dry_run=False,
  1545. extract_process=extract_process,
  1546. connection_params={
  1547. 'hostname': None,
  1548. 'port': None,
  1549. 'username': None,
  1550. 'password': None,
  1551. },
  1552. borgmatic_runtime_directory='/run/borgmatic',
  1553. )
  1554. def test_restore_data_source_dump_with_connection_params_uses_connection_params_for_restore():
  1555. hook_config = [
  1556. {
  1557. 'name': 'foo',
  1558. 'username': 'root',
  1559. 'password': 'trustsome1',
  1560. 'restore_hostname': 'restorehost',
  1561. 'restore_port': 'restoreport',
  1562. 'restore_username': 'restoreusername',
  1563. 'restore_password': 'restorepassword',
  1564. },
  1565. ]
  1566. extract_process = flexmock(stdout=flexmock())
  1567. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1568. 'resolve_credential',
  1569. ).replace_with(lambda value, config: value)
  1570. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1571. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1572. lambda option, data_source, connection_params=None, restore=False: (
  1573. connection_params or {}
  1574. ).get(option)
  1575. )
  1576. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1577. 'cliusername',
  1578. 'clipassword',
  1579. None,
  1580. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1581. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1582. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1583. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1584. (
  1585. 'mariadb',
  1586. '--defaults-extra-file=/dev/fd/99',
  1587. '--batch',
  1588. '--host',
  1589. 'clihost',
  1590. '--port',
  1591. 'cliport',
  1592. '--protocol',
  1593. 'tcp',
  1594. ),
  1595. processes=[extract_process],
  1596. output_log_level=logging.DEBUG,
  1597. input_file=extract_process.stdout,
  1598. environment={'USER': 'root'},
  1599. working_directory=None,
  1600. ).once()
  1601. module.restore_data_source_dump(
  1602. hook_config,
  1603. {},
  1604. data_source=hook_config[0],
  1605. dry_run=False,
  1606. extract_process=extract_process,
  1607. connection_params={
  1608. 'hostname': 'clihost',
  1609. 'port': 'cliport',
  1610. 'username': 'cliusername',
  1611. 'password': 'clipassword',
  1612. },
  1613. borgmatic_runtime_directory='/run/borgmatic',
  1614. )
  1615. def test_restore_data_source_dump_without_connection_params_uses_restore_params_in_config_for_restore():
  1616. hook_config = [
  1617. {
  1618. 'name': 'foo',
  1619. 'username': 'root',
  1620. 'password': 'trustsome1',
  1621. 'hostname': 'dbhost',
  1622. 'port': 'dbport',
  1623. 'tls': True,
  1624. 'restore_username': 'restoreuser',
  1625. 'restore_password': 'restorepass',
  1626. 'restore_hostname': 'restorehost',
  1627. 'restore_port': 'restoreport',
  1628. 'restore_tls': False,
  1629. },
  1630. ]
  1631. extract_process = flexmock(stdout=flexmock())
  1632. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1633. 'resolve_credential',
  1634. ).replace_with(lambda value, config: value)
  1635. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1636. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1637. lambda option, data_source, connection_params=None, restore=False: data_source.get(
  1638. f'restore_{option}'
  1639. )
  1640. )
  1641. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1642. 'restoreuser',
  1643. 'restorepass',
  1644. None,
  1645. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1646. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1647. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1648. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1649. (
  1650. 'mariadb',
  1651. '--defaults-extra-file=/dev/fd/99',
  1652. '--batch',
  1653. '--host',
  1654. 'restorehost',
  1655. '--port',
  1656. 'restoreport',
  1657. '--protocol',
  1658. 'tcp',
  1659. '--skip-ssl',
  1660. ),
  1661. processes=[extract_process],
  1662. output_log_level=logging.DEBUG,
  1663. input_file=extract_process.stdout,
  1664. environment={'USER': 'root'},
  1665. working_directory=None,
  1666. ).once()
  1667. module.restore_data_source_dump(
  1668. hook_config,
  1669. {},
  1670. data_source=hook_config[0],
  1671. dry_run=False,
  1672. extract_process=extract_process,
  1673. connection_params={
  1674. 'hostname': None,
  1675. 'port': None,
  1676. 'username': None,
  1677. 'password': None,
  1678. },
  1679. borgmatic_runtime_directory='/run/borgmatic',
  1680. )
  1681. def test_restore_data_source_dump_with_dry_run_skips_restore():
  1682. hook_config = [{'name': 'foo'}]
  1683. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1684. 'resolve_credential',
  1685. ).replace_with(lambda value, config: value)
  1686. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1687. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1688. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1689. None,
  1690. None,
  1691. None,
  1692. ).and_return(())
  1693. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1694. flexmock(module).should_receive('execute_command_with_processes').never()
  1695. module.restore_data_source_dump(
  1696. hook_config,
  1697. {},
  1698. data_source={'name': 'foo'},
  1699. dry_run=True,
  1700. extract_process=flexmock(),
  1701. connection_params={
  1702. 'hostname': None,
  1703. 'port': None,
  1704. 'username': None,
  1705. 'password': None,
  1706. },
  1707. borgmatic_runtime_directory='/run/borgmatic',
  1708. )