A wrapper script for Borg backup software that creates and prunes backups
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

704 lines
27KB

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