test_mariadb.py 66 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898
  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. '--databases',
  730. 'foo',
  731. '--result-file',
  732. 'dump',
  733. ),
  734. environment=None,
  735. run_to_completion=False,
  736. working_directory=None,
  737. ).and_return(process).once()
  738. assert (
  739. module.execute_dump_command(
  740. database={'name': 'foo'},
  741. config={},
  742. username='root',
  743. password='trustsome1',
  744. dump_path=flexmock(),
  745. database_names=('foo',),
  746. environment=None,
  747. dry_run=False,
  748. dry_run_label='',
  749. )
  750. == process
  751. )
  752. def test_execute_dump_command_with_environment_password_transport_skips_defaults_file_and_passes_user_flag():
  753. process = flexmock()
  754. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  755. flexmock(module.os.path).should_receive('exists').and_return(False)
  756. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  757. 'resolve_credential',
  758. ).replace_with(lambda value, config: value)
  759. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  760. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  761. flexmock(module).should_receive('make_defaults_file_options').never()
  762. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  763. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  764. flexmock(module).should_receive('execute_command').with_args(
  765. (
  766. 'mariadb-dump',
  767. '--add-drop-database',
  768. '--user',
  769. 'root',
  770. '--databases',
  771. 'foo',
  772. '--result-file',
  773. 'dump',
  774. ),
  775. environment=None,
  776. run_to_completion=False,
  777. working_directory=None,
  778. ).and_return(process).once()
  779. assert (
  780. module.execute_dump_command(
  781. database={'name': 'foo', 'password_transport': 'environment'},
  782. config={},
  783. username='root',
  784. password='trustsome1',
  785. dump_path=flexmock(),
  786. database_names=('foo',),
  787. environment=None,
  788. dry_run=False,
  789. dry_run_label='',
  790. )
  791. == process
  792. )
  793. def test_execute_dump_command_runs_mariadb_dump_without_add_drop_database():
  794. process = flexmock()
  795. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  796. flexmock(module.os.path).should_receive('exists').and_return(False)
  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((), None)
  801. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  802. flexmock(module).should_receive('make_defaults_file_options').with_args(
  803. 'root',
  804. 'trustsome1',
  805. None,
  806. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  807. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  808. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  809. flexmock(module).should_receive('execute_command').with_args(
  810. (
  811. 'mariadb-dump',
  812. '--defaults-extra-file=/dev/fd/99',
  813. '--databases',
  814. 'foo',
  815. '--result-file',
  816. 'dump',
  817. ),
  818. environment=None,
  819. run_to_completion=False,
  820. working_directory=None,
  821. ).and_return(process).once()
  822. assert (
  823. module.execute_dump_command(
  824. database={'name': 'foo', 'add_drop_database': False},
  825. config={},
  826. username='root',
  827. password='trustsome1',
  828. dump_path=flexmock(),
  829. database_names=('foo',),
  830. environment=None,
  831. dry_run=False,
  832. dry_run_label='',
  833. )
  834. == process
  835. )
  836. def test_execute_dump_command_runs_mariadb_dump_with_hostname_and_port():
  837. process = flexmock()
  838. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  839. flexmock(module.os.path).should_receive('exists').and_return(False)
  840. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  841. 'resolve_credential',
  842. ).replace_with(lambda value, config: value)
  843. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  844. flexmock(module.database_config).should_receive('resolve_database_option').and_return(
  845. 'database.example.org'
  846. )
  847. flexmock(module).should_receive('make_defaults_file_options').with_args(
  848. 'root',
  849. 'trustsome1',
  850. None,
  851. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  852. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  853. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  854. flexmock(module).should_receive('execute_command').with_args(
  855. (
  856. 'mariadb-dump',
  857. '--defaults-extra-file=/dev/fd/99',
  858. '--add-drop-database',
  859. '--host',
  860. 'database.example.org',
  861. '--port',
  862. '5433',
  863. '--protocol',
  864. 'tcp',
  865. '--databases',
  866. 'foo',
  867. '--result-file',
  868. 'dump',
  869. ),
  870. environment=None,
  871. run_to_completion=False,
  872. working_directory=None,
  873. ).and_return(process).once()
  874. assert (
  875. module.execute_dump_command(
  876. database={'name': 'foo', 'hostname': 'database.example.org', 'port': 5433},
  877. config={},
  878. username='root',
  879. password='trustsome1',
  880. dump_path=flexmock(),
  881. database_names=('foo',),
  882. environment=None,
  883. dry_run=False,
  884. dry_run_label='',
  885. )
  886. == process
  887. )
  888. def test_execute_dump_command_runs_mariadb_dump_with_tls():
  889. process = flexmock()
  890. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  891. flexmock(module.os.path).should_receive('exists').and_return(False)
  892. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  893. 'resolve_credential',
  894. ).replace_with(lambda value, config: value)
  895. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  896. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  897. flexmock(module).should_receive('make_defaults_file_options').with_args(
  898. 'root',
  899. 'trustsome1',
  900. None,
  901. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  902. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  903. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  904. flexmock(module).should_receive('execute_command').with_args(
  905. (
  906. 'mariadb-dump',
  907. '--defaults-extra-file=/dev/fd/99',
  908. '--add-drop-database',
  909. '--ssl',
  910. '--databases',
  911. 'foo',
  912. '--result-file',
  913. 'dump',
  914. ),
  915. environment=None,
  916. run_to_completion=False,
  917. working_directory=None,
  918. ).and_return(process).once()
  919. assert (
  920. module.execute_dump_command(
  921. database={'name': 'foo', 'tls': True},
  922. config={},
  923. username='root',
  924. password='trustsome1',
  925. dump_path=flexmock(),
  926. database_names=('foo',),
  927. environment=None,
  928. dry_run=False,
  929. dry_run_label='',
  930. )
  931. == process
  932. )
  933. def test_execute_dump_command_runs_mariadb_dump_without_tls():
  934. process = flexmock()
  935. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  936. flexmock(module.os.path).should_receive('exists').and_return(False)
  937. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  938. 'resolve_credential',
  939. ).replace_with(lambda value, config: value)
  940. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  941. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  942. flexmock(module).should_receive('make_defaults_file_options').with_args(
  943. 'root',
  944. 'trustsome1',
  945. None,
  946. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  947. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  948. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  949. flexmock(module).should_receive('execute_command').with_args(
  950. (
  951. 'mariadb-dump',
  952. '--defaults-extra-file=/dev/fd/99',
  953. '--add-drop-database',
  954. '--skip-ssl',
  955. '--databases',
  956. 'foo',
  957. '--result-file',
  958. 'dump',
  959. ),
  960. environment=None,
  961. run_to_completion=False,
  962. working_directory=None,
  963. ).and_return(process).once()
  964. assert (
  965. module.execute_dump_command(
  966. database={'name': 'foo', 'tls': False},
  967. config={},
  968. username='root',
  969. password='trustsome1',
  970. dump_path=flexmock(),
  971. database_names=('foo',),
  972. environment=None,
  973. dry_run=False,
  974. dry_run_label='',
  975. )
  976. == process
  977. )
  978. def test_execute_dump_command_runs_mariadb_dump_with_username_and_password():
  979. process = flexmock()
  980. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  981. flexmock(module.os.path).should_receive('exists').and_return(False)
  982. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  983. 'resolve_credential',
  984. ).replace_with(lambda value, config: value)
  985. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  986. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  987. flexmock(module).should_receive('make_defaults_file_options').with_args(
  988. 'root',
  989. 'trustsome1',
  990. None,
  991. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  992. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  993. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  994. flexmock(module).should_receive('execute_command').with_args(
  995. (
  996. 'mariadb-dump',
  997. '--defaults-extra-file=/dev/fd/99',
  998. '--add-drop-database',
  999. '--databases',
  1000. 'foo',
  1001. '--result-file',
  1002. 'dump',
  1003. ),
  1004. environment={},
  1005. run_to_completion=False,
  1006. working_directory=None,
  1007. ).and_return(process).once()
  1008. assert (
  1009. module.execute_dump_command(
  1010. database={'name': 'foo', 'username': 'root', 'password': 'trustsome1'},
  1011. config={},
  1012. username='root',
  1013. password='trustsome1',
  1014. dump_path=flexmock(),
  1015. database_names=('foo',),
  1016. environment={},
  1017. dry_run=False,
  1018. dry_run_label='',
  1019. )
  1020. == process
  1021. )
  1022. def test_execute_dump_command_runs_mariadb_dump_with_options():
  1023. process = flexmock()
  1024. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  1025. flexmock(module.os.path).should_receive('exists').and_return(False)
  1026. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1027. 'resolve_credential',
  1028. ).replace_with(lambda value, config: value)
  1029. flexmock(module).should_receive('parse_extra_options').and_return(('--stuff=such',), None)
  1030. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1031. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1032. 'root',
  1033. 'trustsome1',
  1034. None,
  1035. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1036. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  1037. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1038. flexmock(module).should_receive('execute_command').with_args(
  1039. (
  1040. 'mariadb-dump',
  1041. '--defaults-extra-file=/dev/fd/99',
  1042. '--stuff=such',
  1043. '--add-drop-database',
  1044. '--databases',
  1045. 'foo',
  1046. '--result-file',
  1047. 'dump',
  1048. ),
  1049. environment=None,
  1050. run_to_completion=False,
  1051. working_directory=None,
  1052. ).and_return(process).once()
  1053. assert (
  1054. module.execute_dump_command(
  1055. database={'name': 'foo', 'options': '--stuff=such'},
  1056. config={},
  1057. username='root',
  1058. password='trustsome1',
  1059. dump_path=flexmock(),
  1060. database_names=('foo',),
  1061. environment=None,
  1062. dry_run=False,
  1063. dry_run_label='',
  1064. )
  1065. == process
  1066. )
  1067. def test_execute_dump_command_runs_non_default_mariadb_dump_with_options():
  1068. process = flexmock()
  1069. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  1070. flexmock(module.os.path).should_receive('exists').and_return(False)
  1071. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1072. 'resolve_credential',
  1073. ).replace_with(lambda value, config: value)
  1074. flexmock(module).should_receive('parse_extra_options').and_return(('--stuff=such',), None)
  1075. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1076. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1077. 'root',
  1078. 'trustsome1',
  1079. None,
  1080. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1081. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  1082. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1083. flexmock(module).should_receive('execute_command').with_args(
  1084. (
  1085. 'custom_mariadb_dump', # Custom MariaDB dump command
  1086. '--defaults-extra-file=/dev/fd/99',
  1087. '--stuff=such',
  1088. '--add-drop-database',
  1089. '--databases',
  1090. 'foo',
  1091. '--result-file',
  1092. 'dump',
  1093. ),
  1094. environment=None,
  1095. run_to_completion=False,
  1096. working_directory=None,
  1097. ).and_return(process).once()
  1098. assert (
  1099. module.execute_dump_command(
  1100. database={
  1101. 'name': 'foo',
  1102. 'mariadb_dump_command': 'custom_mariadb_dump',
  1103. 'options': '--stuff=such',
  1104. }, # Custom MariaDB dump command specified
  1105. config={},
  1106. username='root',
  1107. password='trustsome1',
  1108. dump_path=flexmock(),
  1109. database_names=('foo',),
  1110. environment=None,
  1111. dry_run=False,
  1112. dry_run_label='',
  1113. )
  1114. == process
  1115. )
  1116. def test_execute_dump_command_with_duplicate_dump_skips_mariadb_dump():
  1117. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  1118. flexmock(module.os.path).should_receive('exists').and_return(True)
  1119. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1120. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1121. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1122. 'root',
  1123. 'trustsome1',
  1124. None,
  1125. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1126. flexmock(module.dump).should_receive('create_named_pipe_for_dump').never()
  1127. flexmock(module).should_receive('execute_command').never()
  1128. assert (
  1129. module.execute_dump_command(
  1130. database={'name': 'foo'},
  1131. config={},
  1132. username='root',
  1133. password='trustsome1',
  1134. dump_path=flexmock(),
  1135. database_names=('foo',),
  1136. environment=None,
  1137. dry_run=True,
  1138. dry_run_label='SO DRY',
  1139. )
  1140. is None
  1141. )
  1142. def test_execute_dump_command_with_dry_run_skips_mariadb_dump():
  1143. flexmock(module.dump).should_receive('make_data_source_dump_filename').and_return('dump')
  1144. flexmock(module.os.path).should_receive('exists').and_return(False)
  1145. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1146. 'resolve_credential',
  1147. ).replace_with(lambda value, config: value)
  1148. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1149. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1150. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1151. 'root',
  1152. 'trustsome1',
  1153. None,
  1154. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1155. flexmock(module.dump).should_receive('create_named_pipe_for_dump')
  1156. flexmock(module).should_receive('execute_command').never()
  1157. assert (
  1158. module.execute_dump_command(
  1159. database={'name': 'foo'},
  1160. config={},
  1161. username='root',
  1162. password='trustsome1',
  1163. dump_path=flexmock(),
  1164. database_names=('foo',),
  1165. environment=None,
  1166. dry_run=True,
  1167. dry_run_label='SO DRY',
  1168. )
  1169. is None
  1170. )
  1171. def test_restore_data_source_dump_runs_mariadb_to_restore():
  1172. hook_config = [{'name': 'foo'}, {'name': 'bar'}]
  1173. extract_process = flexmock(stdout=flexmock())
  1174. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1175. 'resolve_credential',
  1176. ).replace_with(lambda value, config: value)
  1177. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1178. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1179. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1180. None,
  1181. None,
  1182. None,
  1183. ).and_return(())
  1184. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1185. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1186. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1187. ('mariadb', '--batch'),
  1188. processes=[extract_process],
  1189. output_log_level=logging.DEBUG,
  1190. input_file=extract_process.stdout,
  1191. environment={'USER': 'root'},
  1192. working_directory=None,
  1193. ).once()
  1194. module.restore_data_source_dump(
  1195. hook_config,
  1196. {},
  1197. data_source={'name': 'foo'},
  1198. dry_run=False,
  1199. extract_process=extract_process,
  1200. connection_params={
  1201. 'hostname': None,
  1202. 'port': None,
  1203. 'username': None,
  1204. 'password': None,
  1205. },
  1206. borgmatic_runtime_directory='/run/borgmatic',
  1207. )
  1208. def test_restore_data_source_dump_runs_mariadb_with_options():
  1209. hook_config = [{'name': 'foo', 'restore_options': '--harder'}]
  1210. extract_process = flexmock(stdout=flexmock())
  1211. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1212. 'resolve_credential',
  1213. ).replace_with(lambda value, config: value)
  1214. flexmock(module).should_receive('parse_extra_options').and_return(('--harder',), None)
  1215. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1216. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1217. None,
  1218. None,
  1219. None,
  1220. ).and_return(())
  1221. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1222. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1223. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1224. ('mariadb', '--harder', '--batch'),
  1225. processes=[extract_process],
  1226. output_log_level=logging.DEBUG,
  1227. input_file=extract_process.stdout,
  1228. environment={'USER': 'root'},
  1229. working_directory=None,
  1230. ).once()
  1231. module.restore_data_source_dump(
  1232. hook_config,
  1233. {},
  1234. data_source=hook_config[0],
  1235. dry_run=False,
  1236. extract_process=extract_process,
  1237. connection_params={
  1238. 'hostname': None,
  1239. 'port': None,
  1240. 'username': None,
  1241. 'password': None,
  1242. },
  1243. borgmatic_runtime_directory='/run/borgmatic',
  1244. )
  1245. def test_restore_data_source_dump_runs_non_default_mariadb_with_options():
  1246. hook_config = [
  1247. {'name': 'foo', 'restore_options': '--harder', 'mariadb_command': 'custom_mariadb'},
  1248. ]
  1249. extract_process = flexmock(stdout=flexmock())
  1250. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1251. 'resolve_credential',
  1252. ).replace_with(lambda value, config: value)
  1253. flexmock(module).should_receive('parse_extra_options').and_return(('--harder',), None)
  1254. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1255. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1256. None,
  1257. None,
  1258. None,
  1259. ).and_return(())
  1260. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1261. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1262. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1263. ('custom_mariadb', '--harder', '--batch'),
  1264. processes=[extract_process],
  1265. output_log_level=logging.DEBUG,
  1266. input_file=extract_process.stdout,
  1267. environment={'USER': 'root'},
  1268. working_directory=None,
  1269. ).once()
  1270. module.restore_data_source_dump(
  1271. hook_config,
  1272. {},
  1273. data_source=hook_config[0],
  1274. dry_run=False,
  1275. extract_process=extract_process,
  1276. connection_params={
  1277. 'hostname': None,
  1278. 'port': None,
  1279. 'username': None,
  1280. 'password': None,
  1281. },
  1282. borgmatic_runtime_directory='/run/borgmatic',
  1283. )
  1284. def test_restore_data_source_dump_runs_mariadb_with_hostname_and_port():
  1285. hook_config = [{'name': 'foo', 'hostname': 'database.example.org', 'port': 5433}]
  1286. extract_process = flexmock(stdout=flexmock())
  1287. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1288. 'resolve_credential',
  1289. ).replace_with(lambda value, config: value)
  1290. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1291. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1292. lambda option, data_source, connection_params=None, restore=False: data_source.get(option)
  1293. )
  1294. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1295. None,
  1296. None,
  1297. None,
  1298. ).and_return(())
  1299. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1300. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1301. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1302. (
  1303. 'mariadb',
  1304. '--batch',
  1305. '--host',
  1306. 'database.example.org',
  1307. '--port',
  1308. '5433',
  1309. '--protocol',
  1310. 'tcp',
  1311. ),
  1312. processes=[extract_process],
  1313. output_log_level=logging.DEBUG,
  1314. input_file=extract_process.stdout,
  1315. environment={'USER': 'root'},
  1316. working_directory=None,
  1317. ).once()
  1318. module.restore_data_source_dump(
  1319. hook_config,
  1320. {},
  1321. data_source=hook_config[0],
  1322. dry_run=False,
  1323. extract_process=extract_process,
  1324. connection_params={
  1325. 'hostname': None,
  1326. 'port': None,
  1327. 'username': None,
  1328. 'password': None,
  1329. },
  1330. borgmatic_runtime_directory='/run/borgmatic',
  1331. )
  1332. def test_restore_data_source_dump_runs_mariadb_with_socket_path():
  1333. hook_config = [{'name': 'foo', 'socket_path': '/socket'}]
  1334. extract_process = flexmock(stdout=flexmock())
  1335. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1336. 'resolve_credential',
  1337. ).replace_with(lambda value, config: value)
  1338. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1339. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1340. lambda option, data_source, connection_params=None, restore=False: data_source.get(option)
  1341. )
  1342. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1343. None,
  1344. None,
  1345. None,
  1346. ).and_return(())
  1347. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1348. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1349. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1350. (
  1351. 'mariadb',
  1352. '--batch',
  1353. '--socket',
  1354. '/socket',
  1355. ),
  1356. processes=[extract_process],
  1357. output_log_level=logging.DEBUG,
  1358. input_file=extract_process.stdout,
  1359. environment={'USER': 'root'},
  1360. working_directory=None,
  1361. ).once()
  1362. module.restore_data_source_dump(
  1363. hook_config,
  1364. {},
  1365. data_source=hook_config[0],
  1366. dry_run=False,
  1367. extract_process=extract_process,
  1368. connection_params={
  1369. 'hostname': None,
  1370. 'port': None,
  1371. 'username': None,
  1372. 'password': None,
  1373. },
  1374. borgmatic_runtime_directory='/run/borgmatic',
  1375. )
  1376. def test_restore_data_source_dump_runs_mariadb_with_tls():
  1377. hook_config = [{'name': 'foo', 'tls': True}]
  1378. extract_process = flexmock(stdout=flexmock())
  1379. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1380. 'resolve_credential',
  1381. ).replace_with(lambda value, config: value)
  1382. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1383. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1384. lambda option, data_source, connection_params=None, restore=False: data_source.get(option)
  1385. )
  1386. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1387. None,
  1388. None,
  1389. None,
  1390. ).and_return(())
  1391. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1392. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1393. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1394. (
  1395. 'mariadb',
  1396. '--batch',
  1397. '--ssl',
  1398. ),
  1399. processes=[extract_process],
  1400. output_log_level=logging.DEBUG,
  1401. input_file=extract_process.stdout,
  1402. environment={'USER': 'root'},
  1403. working_directory=None,
  1404. ).once()
  1405. module.restore_data_source_dump(
  1406. hook_config,
  1407. {},
  1408. data_source=hook_config[0],
  1409. dry_run=False,
  1410. extract_process=extract_process,
  1411. connection_params={
  1412. 'hostname': None,
  1413. 'port': None,
  1414. 'username': None,
  1415. 'password': None,
  1416. },
  1417. borgmatic_runtime_directory='/run/borgmatic',
  1418. )
  1419. def test_restore_data_source_dump_runs_mariadb_without_tls():
  1420. hook_config = [{'name': 'foo', 'tls': False}]
  1421. extract_process = flexmock(stdout=flexmock())
  1422. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1423. 'resolve_credential',
  1424. ).replace_with(lambda value, config: value)
  1425. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1426. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1427. lambda option, data_source, connection_params=None, restore=False: data_source.get(option)
  1428. )
  1429. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1430. None,
  1431. None,
  1432. None,
  1433. ).and_return(())
  1434. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1435. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1436. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1437. (
  1438. 'mariadb',
  1439. '--batch',
  1440. '--skip-ssl',
  1441. ),
  1442. processes=[extract_process],
  1443. output_log_level=logging.DEBUG,
  1444. input_file=extract_process.stdout,
  1445. environment={'USER': 'root'},
  1446. working_directory=None,
  1447. ).once()
  1448. module.restore_data_source_dump(
  1449. hook_config,
  1450. {},
  1451. data_source=hook_config[0],
  1452. dry_run=False,
  1453. extract_process=extract_process,
  1454. connection_params={
  1455. 'hostname': None,
  1456. 'port': None,
  1457. 'username': None,
  1458. 'password': None,
  1459. },
  1460. borgmatic_runtime_directory='/run/borgmatic',
  1461. )
  1462. def test_restore_data_source_dump_runs_mariadb_with_username_and_password():
  1463. hook_config = [{'name': 'foo', 'username': 'root', 'password': 'trustsome1'}]
  1464. extract_process = flexmock(stdout=flexmock())
  1465. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1466. 'resolve_credential',
  1467. ).replace_with(lambda value, config: value)
  1468. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1469. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1470. lambda option, data_source, connection_params=None, restore=False: data_source.get(option)
  1471. )
  1472. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1473. 'root',
  1474. 'trustsome1',
  1475. None,
  1476. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1477. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1478. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1479. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1480. ('mariadb', '--defaults-extra-file=/dev/fd/99', '--batch'),
  1481. processes=[extract_process],
  1482. output_log_level=logging.DEBUG,
  1483. input_file=extract_process.stdout,
  1484. environment={'USER': 'root'},
  1485. working_directory=None,
  1486. ).once()
  1487. module.restore_data_source_dump(
  1488. hook_config,
  1489. {},
  1490. data_source=hook_config[0],
  1491. dry_run=False,
  1492. extract_process=extract_process,
  1493. connection_params={
  1494. 'hostname': None,
  1495. 'port': None,
  1496. 'username': None,
  1497. 'password': None,
  1498. },
  1499. borgmatic_runtime_directory='/run/borgmatic',
  1500. )
  1501. def test_restore_data_source_with_environment_password_transport_skips_defaults_file_and_passes_user_flag():
  1502. hook_config = [
  1503. {
  1504. 'name': 'foo',
  1505. 'username': 'root',
  1506. 'password': 'trustsome1',
  1507. 'password_transport': 'environment',
  1508. },
  1509. ]
  1510. extract_process = flexmock(stdout=flexmock())
  1511. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1512. 'resolve_credential',
  1513. ).replace_with(lambda value, config: value)
  1514. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1515. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1516. lambda option, data_source, connection_params=None, restore=False: data_source.get(option)
  1517. )
  1518. flexmock(module).should_receive('make_defaults_file_options').never()
  1519. flexmock(module.os).should_receive('environ').and_return(
  1520. {'USER': 'root', 'MYSQL_PWD': 'trustsome1'},
  1521. )
  1522. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1523. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1524. ('mariadb', '--batch', '--user', 'root'),
  1525. processes=[extract_process],
  1526. output_log_level=logging.DEBUG,
  1527. input_file=extract_process.stdout,
  1528. environment={'USER': 'root', 'MYSQL_PWD': 'trustsome1'},
  1529. working_directory=None,
  1530. ).once()
  1531. module.restore_data_source_dump(
  1532. hook_config,
  1533. {},
  1534. data_source=hook_config[0],
  1535. dry_run=False,
  1536. extract_process=extract_process,
  1537. connection_params={
  1538. 'hostname': None,
  1539. 'port': None,
  1540. 'username': None,
  1541. 'password': None,
  1542. },
  1543. borgmatic_runtime_directory='/run/borgmatic',
  1544. )
  1545. def test_restore_data_source_dump_with_connection_params_uses_connection_params_for_restore():
  1546. hook_config = [
  1547. {
  1548. 'name': 'foo',
  1549. 'username': 'root',
  1550. 'password': 'trustsome1',
  1551. 'restore_hostname': 'restorehost',
  1552. 'restore_port': 'restoreport',
  1553. 'restore_username': 'restoreusername',
  1554. 'restore_password': 'restorepassword',
  1555. },
  1556. ]
  1557. extract_process = flexmock(stdout=flexmock())
  1558. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1559. 'resolve_credential',
  1560. ).replace_with(lambda value, config: value)
  1561. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1562. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1563. lambda option, data_source, connection_params=None, restore=False: (
  1564. connection_params or {}
  1565. ).get(option)
  1566. )
  1567. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1568. 'cliusername',
  1569. 'clipassword',
  1570. None,
  1571. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1572. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1573. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1574. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1575. (
  1576. 'mariadb',
  1577. '--defaults-extra-file=/dev/fd/99',
  1578. '--batch',
  1579. '--host',
  1580. 'clihost',
  1581. '--port',
  1582. 'cliport',
  1583. '--protocol',
  1584. 'tcp',
  1585. ),
  1586. processes=[extract_process],
  1587. output_log_level=logging.DEBUG,
  1588. input_file=extract_process.stdout,
  1589. environment={'USER': 'root'},
  1590. working_directory=None,
  1591. ).once()
  1592. module.restore_data_source_dump(
  1593. hook_config,
  1594. {},
  1595. data_source=hook_config[0],
  1596. dry_run=False,
  1597. extract_process=extract_process,
  1598. connection_params={
  1599. 'hostname': 'clihost',
  1600. 'port': 'cliport',
  1601. 'username': 'cliusername',
  1602. 'password': 'clipassword',
  1603. },
  1604. borgmatic_runtime_directory='/run/borgmatic',
  1605. )
  1606. def test_restore_data_source_dump_without_connection_params_uses_restore_params_in_config_for_restore():
  1607. hook_config = [
  1608. {
  1609. 'name': 'foo',
  1610. 'username': 'root',
  1611. 'password': 'trustsome1',
  1612. 'hostname': 'dbhost',
  1613. 'port': 'dbport',
  1614. 'tls': True,
  1615. 'restore_username': 'restoreuser',
  1616. 'restore_password': 'restorepass',
  1617. 'restore_hostname': 'restorehost',
  1618. 'restore_port': 'restoreport',
  1619. 'restore_tls': False,
  1620. },
  1621. ]
  1622. extract_process = flexmock(stdout=flexmock())
  1623. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1624. 'resolve_credential',
  1625. ).replace_with(lambda value, config: value)
  1626. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1627. flexmock(module.database_config).should_receive('resolve_database_option').replace_with(
  1628. lambda option, data_source, connection_params=None, restore=False: data_source.get(
  1629. f'restore_{option}'
  1630. )
  1631. )
  1632. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1633. 'restoreuser',
  1634. 'restorepass',
  1635. None,
  1636. ).and_return(('--defaults-extra-file=/dev/fd/99',))
  1637. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1638. flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
  1639. flexmock(module).should_receive('execute_command_with_processes').with_args(
  1640. (
  1641. 'mariadb',
  1642. '--defaults-extra-file=/dev/fd/99',
  1643. '--batch',
  1644. '--host',
  1645. 'restorehost',
  1646. '--port',
  1647. 'restoreport',
  1648. '--protocol',
  1649. 'tcp',
  1650. '--skip-ssl',
  1651. ),
  1652. processes=[extract_process],
  1653. output_log_level=logging.DEBUG,
  1654. input_file=extract_process.stdout,
  1655. environment={'USER': 'root'},
  1656. working_directory=None,
  1657. ).once()
  1658. module.restore_data_source_dump(
  1659. hook_config,
  1660. {},
  1661. data_source=hook_config[0],
  1662. dry_run=False,
  1663. extract_process=extract_process,
  1664. connection_params={
  1665. 'hostname': None,
  1666. 'port': None,
  1667. 'username': None,
  1668. 'password': None,
  1669. },
  1670. borgmatic_runtime_directory='/run/borgmatic',
  1671. )
  1672. def test_restore_data_source_dump_with_dry_run_skips_restore():
  1673. hook_config = [{'name': 'foo'}]
  1674. flexmock(module.borgmatic.hooks.credential.parse).should_receive(
  1675. 'resolve_credential',
  1676. ).replace_with(lambda value, config: value)
  1677. flexmock(module).should_receive('parse_extra_options').and_return((), None)
  1678. flexmock(module.database_config).should_receive('resolve_database_option').and_return(None)
  1679. flexmock(module).should_receive('make_defaults_file_options').with_args(
  1680. None,
  1681. None,
  1682. None,
  1683. ).and_return(())
  1684. flexmock(module.os).should_receive('environ').and_return({'USER': 'root'})
  1685. flexmock(module).should_receive('execute_command_with_processes').never()
  1686. module.restore_data_source_dump(
  1687. hook_config,
  1688. {},
  1689. data_source={'name': 'foo'},
  1690. dry_run=True,
  1691. extract_process=flexmock(),
  1692. connection_params={
  1693. 'hostname': None,
  1694. 'port': None,
  1695. 'username': None,
  1696. 'password': None,
  1697. },
  1698. borgmatic_runtime_directory='/run/borgmatic',
  1699. )