test_prune.py 10.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271
  1. import logging
  2. from collections import OrderedDict
  3. from flexmock import flexmock
  4. from borgmatic.borg import prune as module
  5. from ..test_verbosity import insert_logging_mock
  6. def insert_execute_command_mock(prune_command, output_log_level):
  7. flexmock(module.environment).should_receive('make_environment')
  8. flexmock(module).should_receive('execute_command').with_args(
  9. prune_command,
  10. output_log_level=output_log_level,
  11. borg_local_path=prune_command[0],
  12. extra_environment=None,
  13. ).once()
  14. BASE_PRUNE_FLAGS = (('--keep-daily', '1'), ('--keep-weekly', '2'), ('--keep-monthly', '3'))
  15. def test_make_prune_flags_returns_flags_from_config_plus_default_prefix_glob():
  16. retention_config = OrderedDict((('keep_daily', 1), ('keep_weekly', 2), ('keep_monthly', 3)))
  17. flexmock(module.feature).should_receive('available').and_return(True)
  18. result = module.make_prune_flags(retention_config, local_borg_version='1.2.3')
  19. assert tuple(result) == BASE_PRUNE_FLAGS + (('--match-archives', 'sh:{hostname}-*'),)
  20. def test_make_prune_flags_accepts_prefix_with_placeholders():
  21. retention_config = OrderedDict((('keep_daily', 1), ('prefix', 'Documents_{hostname}-{now}')))
  22. flexmock(module.feature).should_receive('available').and_return(True)
  23. result = module.make_prune_flags(retention_config, local_borg_version='1.2.3')
  24. expected = (('--keep-daily', '1'), ('--match-archives', 'sh:Documents_{hostname}-{now}*'))
  25. assert tuple(result) == expected
  26. def test_make_prune_flags_with_prefix_without_borg_features_uses_glob_archives():
  27. retention_config = OrderedDict((('keep_daily', 1), ('prefix', 'Documents_{hostname}-{now}')))
  28. flexmock(module.feature).should_receive('available').and_return(False)
  29. result = module.make_prune_flags(retention_config, local_borg_version='1.2.3')
  30. expected = (('--keep-daily', '1'), ('--glob-archives', 'Documents_{hostname}-{now}*'))
  31. assert tuple(result) == expected
  32. def test_make_prune_flags_treats_empty_prefix_as_no_prefix():
  33. retention_config = OrderedDict((('keep_daily', 1), ('prefix', '')))
  34. flexmock(module.feature).should_receive('available').and_return(True)
  35. result = module.make_prune_flags(retention_config, local_borg_version='1.2.3')
  36. expected = (('--keep-daily', '1'),)
  37. assert tuple(result) == expected
  38. def test_make_prune_flags_treats_none_prefix_as_no_prefix():
  39. retention_config = OrderedDict((('keep_daily', 1), ('prefix', None)))
  40. flexmock(module.feature).should_receive('available').and_return(True)
  41. result = module.make_prune_flags(retention_config, local_borg_version='1.2.3')
  42. expected = (('--keep-daily', '1'),)
  43. assert tuple(result) == expected
  44. PRUNE_COMMAND = ('borg', 'prune', '--keep-daily', '1', '--keep-weekly', '2', '--keep-monthly', '3')
  45. def test_prune_archives_calls_borg_with_parameters():
  46. flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
  47. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  48. insert_execute_command_mock(PRUNE_COMMAND + ('repo',), logging.INFO)
  49. module.prune_archives(
  50. dry_run=False,
  51. repository='repo',
  52. storage_config={},
  53. retention_config=flexmock(),
  54. local_borg_version='1.2.3',
  55. )
  56. def test_prune_archives_with_log_info_calls_borg_with_info_parameter():
  57. flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
  58. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  59. insert_execute_command_mock(PRUNE_COMMAND + ('--info', 'repo'), logging.INFO)
  60. insert_logging_mock(logging.INFO)
  61. module.prune_archives(
  62. repository='repo',
  63. storage_config={},
  64. dry_run=False,
  65. retention_config=flexmock(),
  66. local_borg_version='1.2.3',
  67. )
  68. def test_prune_archives_with_log_debug_calls_borg_with_debug_parameter():
  69. flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
  70. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  71. insert_execute_command_mock(PRUNE_COMMAND + ('--debug', '--show-rc', 'repo'), logging.INFO)
  72. insert_logging_mock(logging.DEBUG)
  73. module.prune_archives(
  74. repository='repo',
  75. storage_config={},
  76. dry_run=False,
  77. retention_config=flexmock(),
  78. local_borg_version='1.2.3',
  79. )
  80. def test_prune_archives_with_dry_run_calls_borg_with_dry_run_parameter():
  81. flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
  82. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  83. insert_execute_command_mock(PRUNE_COMMAND + ('--dry-run', 'repo'), logging.INFO)
  84. module.prune_archives(
  85. repository='repo',
  86. storage_config={},
  87. dry_run=True,
  88. retention_config=flexmock(),
  89. local_borg_version='1.2.3',
  90. )
  91. def test_prune_archives_with_local_path_calls_borg_via_local_path():
  92. flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
  93. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  94. insert_execute_command_mock(('borg1',) + PRUNE_COMMAND[1:] + ('repo',), logging.INFO)
  95. module.prune_archives(
  96. dry_run=False,
  97. repository='repo',
  98. storage_config={},
  99. retention_config=flexmock(),
  100. local_borg_version='1.2.3',
  101. local_path='borg1',
  102. )
  103. def test_prune_archives_with_remote_path_calls_borg_with_remote_path_parameters():
  104. flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
  105. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  106. insert_execute_command_mock(PRUNE_COMMAND + ('--remote-path', 'borg1', 'repo'), logging.INFO)
  107. module.prune_archives(
  108. dry_run=False,
  109. repository='repo',
  110. storage_config={},
  111. retention_config=flexmock(),
  112. local_borg_version='1.2.3',
  113. remote_path='borg1',
  114. )
  115. def test_prune_archives_with_stats_calls_borg_with_stats_parameter_and_warning_output_log_level():
  116. flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
  117. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  118. insert_execute_command_mock(PRUNE_COMMAND + ('--stats', 'repo'), logging.WARNING)
  119. module.prune_archives(
  120. dry_run=False,
  121. repository='repo',
  122. storage_config={},
  123. retention_config=flexmock(),
  124. local_borg_version='1.2.3',
  125. stats=True,
  126. )
  127. def test_prune_archives_with_stats_and_log_info_calls_borg_with_stats_parameter_and_info_output_log_level():
  128. flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
  129. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  130. insert_logging_mock(logging.INFO)
  131. insert_execute_command_mock(PRUNE_COMMAND + ('--stats', '--info', 'repo'), logging.INFO)
  132. module.prune_archives(
  133. dry_run=False,
  134. repository='repo',
  135. storage_config={},
  136. retention_config=flexmock(),
  137. local_borg_version='1.2.3',
  138. stats=True,
  139. )
  140. def test_prune_archives_with_files_calls_borg_with_list_parameter_and_warning_output_log_level():
  141. flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
  142. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  143. insert_execute_command_mock(PRUNE_COMMAND + ('--list', 'repo'), logging.WARNING)
  144. module.prune_archives(
  145. dry_run=False,
  146. repository='repo',
  147. storage_config={},
  148. retention_config=flexmock(),
  149. local_borg_version='1.2.3',
  150. list_archives=True,
  151. )
  152. def test_prune_archives_with_files_and_log_info_calls_borg_with_list_parameter_and_info_output_log_level():
  153. flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
  154. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  155. insert_logging_mock(logging.INFO)
  156. insert_execute_command_mock(PRUNE_COMMAND + ('--info', '--list', 'repo'), logging.INFO)
  157. module.prune_archives(
  158. dry_run=False,
  159. repository='repo',
  160. storage_config={},
  161. retention_config=flexmock(),
  162. local_borg_version='1.2.3',
  163. list_archives=True,
  164. )
  165. def test_prune_archives_with_umask_calls_borg_with_umask_parameters():
  166. storage_config = {'umask': '077'}
  167. flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
  168. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  169. insert_execute_command_mock(PRUNE_COMMAND + ('--umask', '077', 'repo'), logging.INFO)
  170. module.prune_archives(
  171. dry_run=False,
  172. repository='repo',
  173. storage_config=storage_config,
  174. retention_config=flexmock(),
  175. local_borg_version='1.2.3',
  176. )
  177. def test_prune_archives_with_lock_wait_calls_borg_with_lock_wait_parameters():
  178. storage_config = {'lock_wait': 5}
  179. flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
  180. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  181. insert_execute_command_mock(PRUNE_COMMAND + ('--lock-wait', '5', 'repo'), logging.INFO)
  182. module.prune_archives(
  183. dry_run=False,
  184. repository='repo',
  185. storage_config=storage_config,
  186. retention_config=flexmock(),
  187. local_borg_version='1.2.3',
  188. )
  189. def test_prune_archives_with_extra_borg_options_calls_borg_with_extra_options():
  190. flexmock(module).should_receive('make_prune_flags').and_return(BASE_PRUNE_FLAGS)
  191. flexmock(module.flags).should_receive('make_repository_flags').and_return(('repo',))
  192. insert_execute_command_mock(PRUNE_COMMAND + ('--extra', '--options', 'repo'), logging.INFO)
  193. module.prune_archives(
  194. dry_run=False,
  195. repository='repo',
  196. storage_config={'extra_borg_options': {'prune': '--extra --options'}},
  197. retention_config=flexmock(),
  198. local_borg_version='1.2.3',
  199. )