test_create.py 29 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739
  1. import logging
  2. from flexmock import flexmock
  3. from borgmatic.borg import create as module
  4. from ..test_verbosity import insert_logging_mock
  5. def test_expand_directory_with_basic_path_passes_it_through():
  6. flexmock(module.os.path).should_receive('expanduser').and_return('foo')
  7. flexmock(module.glob).should_receive('glob').and_return([])
  8. paths = module._expand_directory('foo')
  9. assert paths == ['foo']
  10. def test_expand_directory_with_glob_expands():
  11. flexmock(module.os.path).should_receive('expanduser').and_return('foo*')
  12. flexmock(module.glob).should_receive('glob').and_return(['foo', 'food'])
  13. paths = module._expand_directory('foo*')
  14. assert paths == ['foo', 'food']
  15. def test_expand_directories_flattens_expanded_directories():
  16. flexmock(module).should_receive('_expand_directory').with_args('~/foo').and_return(
  17. ['/root/foo']
  18. )
  19. flexmock(module).should_receive('_expand_directory').with_args('bar*').and_return(
  20. ['bar', 'barf']
  21. )
  22. paths = module._expand_directories(('~/foo', 'bar*'))
  23. assert paths == ('/root/foo', 'bar', 'barf')
  24. def test_expand_directories_considers_none_as_no_directories():
  25. paths = module._expand_directories(None)
  26. assert paths == ()
  27. def test_expand_home_directories_expands_tildes():
  28. flexmock(module.os.path).should_receive('expanduser').with_args('~/bar').and_return('/foo/bar')
  29. flexmock(module.os.path).should_receive('expanduser').with_args('baz').and_return('baz')
  30. paths = module._expand_home_directories(('~/bar', 'baz'))
  31. assert paths == ('/foo/bar', 'baz')
  32. def test_expand_home_directories_considers_none_as_no_directories():
  33. paths = module._expand_home_directories(None)
  34. assert paths == ()
  35. def test_write_pattern_file_does_not_raise():
  36. temporary_file = flexmock(name='filename', write=lambda mode: None, flush=lambda: None)
  37. flexmock(module.tempfile).should_receive('NamedTemporaryFile').and_return(temporary_file)
  38. module._write_pattern_file(['exclude'])
  39. def test_write_pattern_file_with_empty_exclude_patterns_does_not_raise():
  40. module._write_pattern_file([])
  41. def insert_subprocess_mock(check_call_command, **kwargs):
  42. subprocess = flexmock(module.subprocess)
  43. subprocess.should_receive('check_call').with_args(check_call_command, **kwargs).once()
  44. def test_make_pattern_flags_includes_pattern_filename_when_given():
  45. pattern_flags = module._make_pattern_flags(
  46. location_config={'patterns': ['R /', '- /var']}, pattern_filename='/tmp/patterns'
  47. )
  48. assert pattern_flags == ('--patterns-from', '/tmp/patterns')
  49. def test_make_pattern_flags_includes_patterns_from_filenames_when_in_config():
  50. pattern_flags = module._make_pattern_flags(
  51. location_config={'patterns_from': ['patterns', 'other']}
  52. )
  53. assert pattern_flags == ('--patterns-from', 'patterns', '--patterns-from', 'other')
  54. def test_make_pattern_flags_includes_both_filenames_when_patterns_given_and_patterns_from_in_config():
  55. pattern_flags = module._make_pattern_flags(
  56. location_config={'patterns_from': ['patterns']}, pattern_filename='/tmp/patterns'
  57. )
  58. assert pattern_flags == ('--patterns-from', 'patterns', '--patterns-from', '/tmp/patterns')
  59. def test_make_pattern_flags_considers_none_patterns_from_filenames_as_empty():
  60. pattern_flags = module._make_pattern_flags(location_config={'patterns_from': None})
  61. assert pattern_flags == ()
  62. def test_make_exclude_flags_includes_exclude_patterns_filename_when_given():
  63. exclude_flags = module._make_exclude_flags(
  64. location_config={'exclude_patterns': ['*.pyc', '/var']}, exclude_filename='/tmp/excludes'
  65. )
  66. assert exclude_flags == ('--exclude-from', '/tmp/excludes')
  67. def test_make_exclude_flags_includes_exclude_from_filenames_when_in_config():
  68. exclude_flags = module._make_exclude_flags(
  69. location_config={'exclude_from': ['excludes', 'other']}
  70. )
  71. assert exclude_flags == ('--exclude-from', 'excludes', '--exclude-from', 'other')
  72. def test_make_exclude_flags_includes_both_filenames_when_patterns_given_and_exclude_from_in_config():
  73. exclude_flags = module._make_exclude_flags(
  74. location_config={'exclude_from': ['excludes']}, exclude_filename='/tmp/excludes'
  75. )
  76. assert exclude_flags == ('--exclude-from', 'excludes', '--exclude-from', '/tmp/excludes')
  77. def test_make_exclude_flags_considers_none_exclude_from_filenames_as_empty():
  78. exclude_flags = module._make_exclude_flags(location_config={'exclude_from': None})
  79. assert exclude_flags == ()
  80. def test_make_exclude_flags_includes_exclude_caches_when_true_in_config():
  81. exclude_flags = module._make_exclude_flags(location_config={'exclude_caches': True})
  82. assert exclude_flags == ('--exclude-caches',)
  83. def test_make_exclude_flags_does_not_include_exclude_caches_when_false_in_config():
  84. exclude_flags = module._make_exclude_flags(location_config={'exclude_caches': False})
  85. assert exclude_flags == ()
  86. def test_make_exclude_flags_includes_exclude_if_present_when_in_config():
  87. exclude_flags = module._make_exclude_flags(location_config={'exclude_if_present': 'exclude_me'})
  88. assert exclude_flags == ('--exclude-if-present', 'exclude_me')
  89. def test_make_exclude_flags_is_empty_when_config_has_no_excludes():
  90. exclude_flags = module._make_exclude_flags(location_config={})
  91. assert exclude_flags == ()
  92. DEFAULT_ARCHIVE_NAME = '{hostname}-{now:%Y-%m-%dT%H:%M:%S.%f}'
  93. CREATE_COMMAND = ('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo', 'bar')
  94. def test_create_archive_calls_borg_with_parameters():
  95. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  96. flexmock(module).should_receive('_expand_home_directories').and_return(())
  97. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  98. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  99. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  100. insert_subprocess_mock(CREATE_COMMAND)
  101. module.create_archive(
  102. dry_run=False,
  103. repository='repo',
  104. location_config={
  105. 'source_directories': ['foo', 'bar'],
  106. 'repositories': ['repo'],
  107. 'exclude_patterns': None,
  108. },
  109. storage_config={},
  110. )
  111. def test_create_archive_with_patterns_calls_borg_with_patterns():
  112. pattern_flags = ('--patterns-from', 'patterns')
  113. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  114. flexmock(module).should_receive('_expand_home_directories').and_return(())
  115. flexmock(module).should_receive('_write_pattern_file').and_return(
  116. flexmock(name='/tmp/patterns')
  117. ).and_return(None)
  118. flexmock(module).should_receive('_make_pattern_flags').and_return(pattern_flags)
  119. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  120. insert_subprocess_mock(CREATE_COMMAND + pattern_flags)
  121. module.create_archive(
  122. dry_run=False,
  123. repository='repo',
  124. location_config={
  125. 'source_directories': ['foo', 'bar'],
  126. 'repositories': ['repo'],
  127. 'patterns': ['pattern'],
  128. },
  129. storage_config={},
  130. )
  131. def test_create_archive_with_exclude_patterns_calls_borg_with_excludes():
  132. exclude_flags = ('--exclude-from', 'excludes')
  133. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  134. flexmock(module).should_receive('_expand_home_directories').and_return(('exclude',))
  135. flexmock(module).should_receive('_write_pattern_file').and_return(None).and_return(
  136. flexmock(name='/tmp/excludes')
  137. )
  138. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  139. flexmock(module).should_receive('_make_exclude_flags').and_return(exclude_flags)
  140. insert_subprocess_mock(CREATE_COMMAND + exclude_flags)
  141. module.create_archive(
  142. dry_run=False,
  143. repository='repo',
  144. location_config={
  145. 'source_directories': ['foo', 'bar'],
  146. 'repositories': ['repo'],
  147. 'exclude_patterns': ['exclude'],
  148. },
  149. storage_config={},
  150. )
  151. def test_create_archive_with_log_info_calls_borg_with_info_parameter():
  152. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  153. flexmock(module).should_receive('_expand_home_directories').and_return(())
  154. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  155. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  156. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  157. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  158. insert_subprocess_mock(CREATE_COMMAND + ('--list', '--filter', 'AME-', '--info', '--stats'))
  159. insert_logging_mock(logging.INFO)
  160. module.create_archive(
  161. dry_run=False,
  162. repository='repo',
  163. location_config={
  164. 'source_directories': ['foo', 'bar'],
  165. 'repositories': ['repo'],
  166. 'exclude_patterns': None,
  167. },
  168. storage_config={},
  169. )
  170. def test_create_archive_with_log_debug_calls_borg_with_debug_parameter():
  171. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  172. flexmock(module).should_receive('_expand_home_directories').and_return(())
  173. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  174. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  175. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  176. insert_subprocess_mock(
  177. CREATE_COMMAND + ('--list', '--filter', 'AME-', '--stats', '--debug', '--show-rc')
  178. )
  179. insert_logging_mock(logging.DEBUG)
  180. module.create_archive(
  181. dry_run=False,
  182. repository='repo',
  183. location_config={
  184. 'source_directories': ['foo', 'bar'],
  185. 'repositories': ['repo'],
  186. 'exclude_patterns': None,
  187. },
  188. storage_config={},
  189. )
  190. def test_create_archive_with_dry_run_calls_borg_with_dry_run_parameter():
  191. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  192. flexmock(module).should_receive('_expand_home_directories').and_return(())
  193. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  194. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  195. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  196. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  197. insert_subprocess_mock(CREATE_COMMAND + ('--dry-run',))
  198. module.create_archive(
  199. dry_run=True,
  200. repository='repo',
  201. location_config={
  202. 'source_directories': ['foo', 'bar'],
  203. 'repositories': ['repo'],
  204. 'exclude_patterns': None,
  205. },
  206. storage_config={},
  207. )
  208. def test_create_archive_with_dry_run_and_log_info_calls_borg_without_stats_parameter():
  209. # --dry-run and --stats are mutually exclusive, see:
  210. # https://borgbackup.readthedocs.io/en/stable/usage/create.html#description
  211. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  212. flexmock(module).should_receive('_expand_home_directories').and_return(())
  213. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  214. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  215. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  216. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  217. insert_subprocess_mock(CREATE_COMMAND + ('--list', '--filter', 'AME-', '--info', '--dry-run'))
  218. insert_logging_mock(logging.INFO)
  219. module.create_archive(
  220. dry_run=True,
  221. repository='repo',
  222. location_config={
  223. 'source_directories': ['foo', 'bar'],
  224. 'repositories': ['repo'],
  225. 'exclude_patterns': None,
  226. },
  227. storage_config={},
  228. )
  229. def test_create_archive_with_dry_run_and_log_debug_calls_borg_without_stats_parameter():
  230. # --dry-run and --stats are mutually exclusive, see:
  231. # https://borgbackup.readthedocs.io/en/stable/usage/create.html#description
  232. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  233. flexmock(module).should_receive('_expand_home_directories').and_return(())
  234. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  235. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  236. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  237. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  238. insert_subprocess_mock(
  239. CREATE_COMMAND + ('--list', '--filter', 'AME-', '--debug', '--show-rc', '--dry-run')
  240. )
  241. insert_logging_mock(logging.DEBUG)
  242. module.create_archive(
  243. dry_run=True,
  244. repository='repo',
  245. location_config={
  246. 'source_directories': ['foo', 'bar'],
  247. 'repositories': ['repo'],
  248. 'exclude_patterns': None,
  249. },
  250. storage_config={},
  251. )
  252. def test_create_archive_with_checkpoint_interval_calls_borg_with_checkpoint_interval_parameters():
  253. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  254. flexmock(module).should_receive('_expand_home_directories').and_return(())
  255. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  256. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  257. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  258. insert_subprocess_mock(CREATE_COMMAND + ('--checkpoint-interval', '600'))
  259. module.create_archive(
  260. dry_run=False,
  261. repository='repo',
  262. location_config={
  263. 'source_directories': ['foo', 'bar'],
  264. 'repositories': ['repo'],
  265. 'exclude_patterns': None,
  266. },
  267. storage_config={'checkpoint_interval': 600},
  268. )
  269. def test_create_archive_with_chunker_params_calls_borg_with_chunker_params_parameters():
  270. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  271. flexmock(module).should_receive('_expand_home_directories').and_return(())
  272. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  273. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  274. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  275. insert_subprocess_mock(CREATE_COMMAND + ('--chunker-params', '1,2,3,4'))
  276. module.create_archive(
  277. dry_run=False,
  278. repository='repo',
  279. location_config={
  280. 'source_directories': ['foo', 'bar'],
  281. 'repositories': ['repo'],
  282. 'exclude_patterns': None,
  283. },
  284. storage_config={'chunker_params': '1,2,3,4'},
  285. )
  286. def test_create_archive_with_compression_calls_borg_with_compression_parameters():
  287. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  288. flexmock(module).should_receive('_expand_home_directories').and_return(())
  289. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  290. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  291. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  292. insert_subprocess_mock(CREATE_COMMAND + ('--compression', 'rle'))
  293. module.create_archive(
  294. dry_run=False,
  295. repository='repo',
  296. location_config={
  297. 'source_directories': ['foo', 'bar'],
  298. 'repositories': ['repo'],
  299. 'exclude_patterns': None,
  300. },
  301. storage_config={'compression': 'rle'},
  302. )
  303. def test_create_archive_with_remote_rate_limit_calls_borg_with_remote_ratelimit_parameters():
  304. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  305. flexmock(module).should_receive('_expand_home_directories').and_return(())
  306. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  307. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  308. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  309. insert_subprocess_mock(CREATE_COMMAND + ('--remote-ratelimit', '100'))
  310. module.create_archive(
  311. dry_run=False,
  312. repository='repo',
  313. location_config={
  314. 'source_directories': ['foo', 'bar'],
  315. 'repositories': ['repo'],
  316. 'exclude_patterns': None,
  317. },
  318. storage_config={'remote_rate_limit': 100},
  319. )
  320. def test_create_archive_with_one_file_system_calls_borg_with_one_file_system_parameters():
  321. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  322. flexmock(module).should_receive('_expand_home_directories').and_return(())
  323. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  324. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  325. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  326. insert_subprocess_mock(CREATE_COMMAND + ('--one-file-system',))
  327. module.create_archive(
  328. dry_run=False,
  329. repository='repo',
  330. location_config={
  331. 'source_directories': ['foo', 'bar'],
  332. 'repositories': ['repo'],
  333. 'one_file_system': True,
  334. 'exclude_patterns': None,
  335. },
  336. storage_config={},
  337. )
  338. def test_create_archive_with_read_special_calls_borg_with_read_special_parameter():
  339. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  340. flexmock(module).should_receive('_expand_home_directories').and_return(())
  341. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  342. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  343. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  344. insert_subprocess_mock(CREATE_COMMAND + ('--read-special',))
  345. module.create_archive(
  346. dry_run=False,
  347. repository='repo',
  348. location_config={
  349. 'source_directories': ['foo', 'bar'],
  350. 'repositories': ['repo'],
  351. 'read_special': True,
  352. 'exclude_patterns': None,
  353. },
  354. storage_config={},
  355. )
  356. def test_create_archive_with_bsd_flags_true_calls_borg_without_nobsdflags_parameter():
  357. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  358. flexmock(module).should_receive('_expand_home_directories').and_return(())
  359. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  360. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  361. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  362. insert_subprocess_mock(CREATE_COMMAND)
  363. module.create_archive(
  364. dry_run=False,
  365. repository='repo',
  366. location_config={
  367. 'source_directories': ['foo', 'bar'],
  368. 'repositories': ['repo'],
  369. 'bsd_flags': True,
  370. 'exclude_patterns': None,
  371. },
  372. storage_config={},
  373. )
  374. def test_create_archive_with_bsd_flags_false_calls_borg_with_nobsdflags_parameter():
  375. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  376. flexmock(module).should_receive('_expand_home_directories').and_return(())
  377. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  378. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  379. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  380. insert_subprocess_mock(CREATE_COMMAND + ('--nobsdflags',))
  381. module.create_archive(
  382. dry_run=False,
  383. repository='repo',
  384. location_config={
  385. 'source_directories': ['foo', 'bar'],
  386. 'repositories': ['repo'],
  387. 'bsd_flags': False,
  388. 'exclude_patterns': None,
  389. },
  390. storage_config={},
  391. )
  392. def test_create_archive_with_files_cache_calls_borg_with_files_cache_parameters():
  393. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  394. flexmock(module).should_receive('_expand_home_directories').and_return(())
  395. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  396. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  397. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  398. insert_subprocess_mock(CREATE_COMMAND + ('--files-cache', 'ctime,size'))
  399. module.create_archive(
  400. dry_run=False,
  401. repository='repo',
  402. location_config={
  403. 'source_directories': ['foo', 'bar'],
  404. 'repositories': ['repo'],
  405. 'files_cache': 'ctime,size',
  406. 'exclude_patterns': None,
  407. },
  408. storage_config={},
  409. )
  410. def test_create_archive_with_local_path_calls_borg_via_local_path():
  411. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  412. flexmock(module).should_receive('_expand_home_directories').and_return(())
  413. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  414. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  415. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  416. insert_subprocess_mock(('borg1',) + CREATE_COMMAND[1:])
  417. module.create_archive(
  418. dry_run=False,
  419. repository='repo',
  420. location_config={
  421. 'source_directories': ['foo', 'bar'],
  422. 'repositories': ['repo'],
  423. 'exclude_patterns': None,
  424. },
  425. storage_config={},
  426. local_path='borg1',
  427. )
  428. def test_create_archive_with_remote_path_calls_borg_with_remote_path_parameters():
  429. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  430. flexmock(module).should_receive('_expand_home_directories').and_return(())
  431. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  432. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  433. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  434. insert_subprocess_mock(CREATE_COMMAND + ('--remote-path', 'borg1'))
  435. module.create_archive(
  436. dry_run=False,
  437. repository='repo',
  438. location_config={
  439. 'source_directories': ['foo', 'bar'],
  440. 'repositories': ['repo'],
  441. 'exclude_patterns': None,
  442. },
  443. storage_config={},
  444. remote_path='borg1',
  445. )
  446. def test_create_archive_with_umask_calls_borg_with_umask_parameters():
  447. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  448. flexmock(module).should_receive('_expand_home_directories').and_return(())
  449. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  450. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  451. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  452. insert_subprocess_mock(CREATE_COMMAND + ('--umask', '740'))
  453. module.create_archive(
  454. dry_run=False,
  455. repository='repo',
  456. location_config={
  457. 'source_directories': ['foo', 'bar'],
  458. 'repositories': ['repo'],
  459. 'exclude_patterns': None,
  460. },
  461. storage_config={'umask': 740},
  462. )
  463. def test_create_archive_with_lock_wait_calls_borg_with_lock_wait_parameters():
  464. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  465. flexmock(module).should_receive('_expand_home_directories').and_return(())
  466. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  467. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  468. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  469. insert_subprocess_mock(CREATE_COMMAND + ('--lock-wait', '5'))
  470. module.create_archive(
  471. dry_run=False,
  472. repository='repo',
  473. location_config={
  474. 'source_directories': ['foo', 'bar'],
  475. 'repositories': ['repo'],
  476. 'exclude_patterns': None,
  477. },
  478. storage_config={'lock_wait': 5},
  479. )
  480. def test_create_archive_with_json_calls_borg_with_json_parameter():
  481. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  482. flexmock(module).should_receive('_expand_home_directories').and_return(())
  483. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  484. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  485. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  486. insert_subprocess_mock(CREATE_COMMAND + ('--json',))
  487. module.create_archive(
  488. dry_run=False,
  489. repository='repo',
  490. location_config={
  491. 'source_directories': ['foo', 'bar'],
  492. 'repositories': ['repo'],
  493. 'exclude_patterns': None,
  494. },
  495. storage_config={},
  496. json=True,
  497. )
  498. def test_create_archive_with_source_directories_glob_expands():
  499. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'food'))
  500. flexmock(module).should_receive('_expand_home_directories').and_return(())
  501. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  502. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  503. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  504. insert_subprocess_mock(
  505. ('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo', 'food')
  506. )
  507. flexmock(module.glob).should_receive('glob').with_args('foo*').and_return(['foo', 'food'])
  508. module.create_archive(
  509. dry_run=False,
  510. repository='repo',
  511. location_config={
  512. 'source_directories': ['foo*'],
  513. 'repositories': ['repo'],
  514. 'exclude_patterns': None,
  515. },
  516. storage_config={},
  517. )
  518. def test_create_archive_with_non_matching_source_directories_glob_passes_through():
  519. flexmock(module).should_receive('_expand_directories').and_return(('foo*',))
  520. flexmock(module).should_receive('_expand_home_directories').and_return(())
  521. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  522. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  523. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  524. insert_subprocess_mock(('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo*'))
  525. flexmock(module.glob).should_receive('glob').with_args('foo*').and_return([])
  526. module.create_archive(
  527. dry_run=False,
  528. repository='repo',
  529. location_config={
  530. 'source_directories': ['foo*'],
  531. 'repositories': ['repo'],
  532. 'exclude_patterns': None,
  533. },
  534. storage_config={},
  535. )
  536. def test_create_archive_with_glob_calls_borg_with_expanded_directories():
  537. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'food'))
  538. flexmock(module).should_receive('_expand_home_directories').and_return(())
  539. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  540. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  541. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  542. insert_subprocess_mock(
  543. ('borg', 'create', 'repo::{}'.format(DEFAULT_ARCHIVE_NAME), 'foo', 'food')
  544. )
  545. module.create_archive(
  546. dry_run=False,
  547. repository='repo',
  548. location_config={
  549. 'source_directories': ['foo*'],
  550. 'repositories': ['repo'],
  551. 'exclude_patterns': None,
  552. },
  553. storage_config={},
  554. )
  555. def test_create_archive_with_archive_name_format_calls_borg_with_archive_name():
  556. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  557. flexmock(module).should_receive('_expand_home_directories').and_return(())
  558. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  559. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  560. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  561. insert_subprocess_mock(('borg', 'create', 'repo::ARCHIVE_NAME', 'foo', 'bar'))
  562. module.create_archive(
  563. dry_run=False,
  564. repository='repo',
  565. location_config={
  566. 'source_directories': ['foo', 'bar'],
  567. 'repositories': ['repo'],
  568. 'exclude_patterns': None,
  569. },
  570. storage_config={'archive_name_format': 'ARCHIVE_NAME'},
  571. )
  572. def test_create_archive_with_archive_name_format_accepts_borg_placeholders():
  573. flexmock(module).should_receive('_expand_directories').and_return(('foo', 'bar'))
  574. flexmock(module).should_receive('_expand_home_directories').and_return(())
  575. flexmock(module).should_receive('_write_pattern_file').and_return(None)
  576. flexmock(module).should_receive('_make_pattern_flags').and_return(())
  577. flexmock(module).should_receive('_make_exclude_flags').and_return(())
  578. insert_subprocess_mock(('borg', 'create', 'repo::Documents_{hostname}-{now}', 'foo', 'bar'))
  579. module.create_archive(
  580. dry_run=False,
  581. repository='repo',
  582. location_config={
  583. 'source_directories': ['foo', 'bar'],
  584. 'repositories': ['repo'],
  585. 'exclude_patterns': None,
  586. },
  587. storage_config={'archive_name_format': 'Documents_{hostname}-{now}'},
  588. )