test_normalize.py 6.8 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253
  1. import pytest
  2. from flexmock import flexmock
  3. from borgmatic.config import normalize as module
  4. @pytest.mark.parametrize(
  5. 'config,expected_config,produces_logs',
  6. (
  7. (
  8. {'location': {'foo': 'bar', 'baz': 'quux'}},
  9. {'foo': 'bar', 'baz': 'quux'},
  10. True,
  11. ),
  12. (
  13. {'retention': {'foo': 'bar', 'baz': 'quux'}},
  14. {'foo': 'bar', 'baz': 'quux'},
  15. True,
  16. ),
  17. (
  18. {'consistency': {'foo': 'bar', 'baz': 'quux'}},
  19. {'foo': 'bar', 'baz': 'quux'},
  20. True,
  21. ),
  22. (
  23. {'output': {'foo': 'bar', 'baz': 'quux'}},
  24. {'foo': 'bar', 'baz': 'quux'},
  25. True,
  26. ),
  27. (
  28. {'hooks': {'foo': 'bar', 'baz': 'quux'}},
  29. {'foo': 'bar', 'baz': 'quux'},
  30. True,
  31. ),
  32. (
  33. {'location': {'foo': 'bar'}, 'storage': {'baz': 'quux'}},
  34. {'foo': 'bar', 'baz': 'quux'},
  35. True,
  36. ),
  37. (
  38. {'foo': 'bar', 'baz': 'quux'},
  39. {'foo': 'bar', 'baz': 'quux'},
  40. False,
  41. ),
  42. (
  43. {'location': {'prefix': 'foo'}, 'consistency': {'prefix': 'foo'}},
  44. {'prefix': 'foo'},
  45. True,
  46. ),
  47. (
  48. {'location': {'prefix': 'foo'}, 'consistency': {'prefix': 'foo'}},
  49. {'prefix': 'foo'},
  50. True,
  51. ),
  52. (
  53. {'location': {'prefix': 'foo'}, 'consistency': {'bar': 'baz'}},
  54. {'prefix': 'foo', 'bar': 'baz'},
  55. True,
  56. ),
  57. (
  58. {'storage': {'umask': 'foo'}, 'hooks': {'umask': 'foo'}},
  59. {'umask': 'foo'},
  60. True,
  61. ),
  62. (
  63. {'storage': {'umask': 'foo'}, 'hooks': {'umask': 'foo'}},
  64. {'umask': 'foo'},
  65. True,
  66. ),
  67. (
  68. {'storage': {'umask': 'foo'}, 'hooks': {'bar': 'baz'}},
  69. {'umask': 'foo', 'bar': 'baz'},
  70. True,
  71. ),
  72. (
  73. {'location': {'bar': 'baz'}, 'consistency': {'prefix': 'foo'}},
  74. {'bar': 'baz', 'prefix': 'foo'},
  75. True,
  76. ),
  77. (
  78. {},
  79. {},
  80. False,
  81. ),
  82. ),
  83. )
  84. def test_normalize_sections_moves_section_options_to_global_scope(
  85. config, expected_config, produces_logs
  86. ):
  87. logs = module.normalize_sections('test.yaml', config)
  88. assert config == expected_config
  89. if produces_logs:
  90. assert logs
  91. else:
  92. assert logs == []
  93. def test_normalize_sections_with_different_prefix_values_raises():
  94. config = {'location': {'prefix': 'foo'}, 'consistency': {'prefix': 'bar'}}
  95. with pytest.raises(ValueError):
  96. module.normalize_sections('test.yaml', config)
  97. def test_normalize_sections_with_different_umask_values_raises():
  98. config = {'storage': {'umask': 'foo'}, 'hooks': {'umask': 'bar'}}
  99. with pytest.raises(ValueError):
  100. module.normalize_sections('test.yaml', config)
  101. @pytest.mark.parametrize(
  102. 'config,expected_config,produces_logs',
  103. (
  104. (
  105. {'exclude_if_present': '.nobackup'},
  106. {'exclude_if_present': ['.nobackup']},
  107. True,
  108. ),
  109. (
  110. {'exclude_if_present': ['.nobackup']},
  111. {'exclude_if_present': ['.nobackup']},
  112. False,
  113. ),
  114. (
  115. {'source_directories': ['foo', 'bar']},
  116. {'source_directories': ['foo', 'bar']},
  117. False,
  118. ),
  119. (
  120. {'compression': 'yes_please'},
  121. {'compression': 'yes_please'},
  122. False,
  123. ),
  124. (
  125. {'healthchecks': 'https://example.com'},
  126. {'healthchecks': {'ping_url': 'https://example.com'}},
  127. True,
  128. ),
  129. (
  130. {'cronitor': 'https://example.com'},
  131. {'cronitor': {'ping_url': 'https://example.com'}},
  132. True,
  133. ),
  134. (
  135. {'pagerduty': 'https://example.com'},
  136. {'pagerduty': {'integration_key': 'https://example.com'}},
  137. True,
  138. ),
  139. (
  140. {'cronhub': 'https://example.com'},
  141. {'cronhub': {'ping_url': 'https://example.com'}},
  142. True,
  143. ),
  144. (
  145. {'checks': ['archives']},
  146. {'checks': [{'name': 'archives'}]},
  147. True,
  148. ),
  149. (
  150. {'checks': ['archives']},
  151. {'checks': [{'name': 'archives'}]},
  152. True,
  153. ),
  154. (
  155. {'numeric_owner': False},
  156. {'numeric_ids': False},
  157. True,
  158. ),
  159. (
  160. {'bsd_flags': False},
  161. {'flags': False},
  162. True,
  163. ),
  164. (
  165. {'remote_rate_limit': False},
  166. {'upload_rate_limit': False},
  167. True,
  168. ),
  169. (
  170. {'repositories': ['foo@bar:/repo']},
  171. {'repositories': [{'path': 'ssh://foo@bar/repo'}]},
  172. True,
  173. ),
  174. (
  175. {'repositories': ['foo@bar:repo']},
  176. {'repositories': [{'path': 'ssh://foo@bar/./repo'}]},
  177. True,
  178. ),
  179. (
  180. {'repositories': ['foo@bar:~/repo']},
  181. {'repositories': [{'path': 'ssh://foo@bar/~/repo'}]},
  182. True,
  183. ),
  184. (
  185. {'repositories': ['ssh://foo@bar:1234/repo']},
  186. {'repositories': [{'path': 'ssh://foo@bar:1234/repo'}]},
  187. True,
  188. ),
  189. (
  190. {'repositories': ['file:///repo']},
  191. {'repositories': [{'path': '/repo'}]},
  192. True,
  193. ),
  194. (
  195. {'repositories': [{'path': 'foo@bar:/repo', 'label': 'foo'}]},
  196. {'repositories': [{'path': 'ssh://foo@bar/repo', 'label': 'foo'}]},
  197. True,
  198. ),
  199. (
  200. {'repositories': [{'path': 'file:///repo', 'label': 'foo'}]},
  201. {'repositories': [{'path': '/repo', 'label': 'foo'}]},
  202. False,
  203. ),
  204. (
  205. {'repositories': [{'path': '/repo', 'label': 'foo'}]},
  206. {'repositories': [{'path': '/repo', 'label': 'foo'}]},
  207. False,
  208. ),
  209. (
  210. {'prefix': 'foo'},
  211. {'prefix': 'foo'},
  212. True,
  213. ),
  214. ),
  215. )
  216. def test_normalize_applies_hard_coded_normalization_to_config(
  217. config, expected_config, produces_logs
  218. ):
  219. flexmock(module).should_receive('normalize_sections').and_return([])
  220. logs = module.normalize('test.yaml', config)
  221. assert config == expected_config
  222. if produces_logs:
  223. assert logs
  224. else:
  225. assert logs == []
  226. def test_normalize_raises_error_if_repository_data_is_not_consistent():
  227. flexmock(module).should_receive('normalize_sections').and_return([])
  228. with pytest.raises(TypeError):
  229. module.normalize(
  230. 'test.yaml',
  231. {
  232. 'repositories': [{'path': 'foo@bar:/repo', 'label': 'foo'}, 'file:///repo'],
  233. },
  234. )