test_load.py 8.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243
  1. import sys
  2. import pytest
  3. import ruamel.yaml
  4. from flexmock import flexmock
  5. from borgmatic.config import load as module
  6. def test_load_configuration_parses_contents():
  7. builtins = flexmock(sys.modules['builtins'])
  8. builtins.should_receive('open').with_args('config.yaml').and_return('key: value')
  9. assert module.load_configuration('config.yaml') == {'key': 'value'}
  10. def test_load_configuration_inlines_include():
  11. builtins = flexmock(sys.modules['builtins'])
  12. builtins.should_receive('open').with_args('include.yaml').and_return('value')
  13. builtins.should_receive('open').with_args('config.yaml').and_return(
  14. 'key: !include include.yaml'
  15. )
  16. assert module.load_configuration('config.yaml') == {'key': 'value'}
  17. def test_load_configuration_merges_include():
  18. builtins = flexmock(sys.modules['builtins'])
  19. builtins.should_receive('open').with_args('include.yaml').and_return(
  20. '''
  21. foo: bar
  22. baz: quux
  23. '''
  24. )
  25. builtins.should_receive('open').with_args('config.yaml').and_return(
  26. '''
  27. foo: override
  28. <<: !include include.yaml
  29. '''
  30. )
  31. assert module.load_configuration('config.yaml') == {'foo': 'override', 'baz': 'quux'}
  32. def test_load_configuration_does_not_merge_include_list():
  33. builtins = flexmock(sys.modules['builtins'])
  34. builtins.should_receive('open').with_args('include.yaml').and_return(
  35. '''
  36. - one
  37. - two
  38. '''
  39. )
  40. builtins.should_receive('open').with_args('config.yaml').and_return(
  41. '''
  42. foo: bar
  43. repositories:
  44. <<: !include include.yaml
  45. '''
  46. )
  47. with pytest.raises(ruamel.yaml.error.YAMLError):
  48. assert module.load_configuration('config.yaml')
  49. def test_deep_merge_nodes_replaces_colliding_scalar_values():
  50. node_values = [
  51. (
  52. ruamel.yaml.nodes.ScalarNode(tag='tag:yaml.org,2002:str', value='retention'),
  53. ruamel.yaml.nodes.MappingNode(
  54. tag='tag:yaml.org,2002:map',
  55. value=[
  56. (
  57. ruamel.yaml.nodes.ScalarNode(
  58. tag='tag:yaml.org,2002:str', value='keep_hourly'
  59. ),
  60. ruamel.yaml.nodes.ScalarNode(tag='tag:yaml.org,2002:int', value='24'),
  61. ),
  62. (
  63. ruamel.yaml.nodes.ScalarNode(
  64. tag='tag:yaml.org,2002:str', value='keep_daily'
  65. ),
  66. ruamel.yaml.nodes.ScalarNode(tag='tag:yaml.org,2002:int', value='7'),
  67. ),
  68. ],
  69. ),
  70. ),
  71. (
  72. ruamel.yaml.nodes.ScalarNode(tag='tag:yaml.org,2002:str', value='retention'),
  73. ruamel.yaml.nodes.MappingNode(
  74. tag='tag:yaml.org,2002:map',
  75. value=[
  76. (
  77. ruamel.yaml.nodes.ScalarNode(
  78. tag='tag:yaml.org,2002:str', value='keep_daily'
  79. ),
  80. ruamel.yaml.nodes.ScalarNode(tag='tag:yaml.org,2002:int', value='5'),
  81. ),
  82. ],
  83. ),
  84. ),
  85. ]
  86. result = module.deep_merge_nodes(node_values)
  87. assert len(result) == 1
  88. (section_key, section_value) = result[0]
  89. assert section_key.value == 'retention'
  90. options = section_value.value
  91. assert len(options) == 2
  92. assert options[0][0].value == 'keep_hourly'
  93. assert options[0][1].value == '24'
  94. assert options[1][0].value == 'keep_daily'
  95. assert options[1][1].value == '5'
  96. def test_deep_merge_nodes_keeps_non_colliding_scalar_values():
  97. node_values = [
  98. (
  99. ruamel.yaml.nodes.ScalarNode(tag='tag:yaml.org,2002:str', value='retention'),
  100. ruamel.yaml.nodes.MappingNode(
  101. tag='tag:yaml.org,2002:map',
  102. value=[
  103. (
  104. ruamel.yaml.nodes.ScalarNode(
  105. tag='tag:yaml.org,2002:str', value='keep_hourly'
  106. ),
  107. ruamel.yaml.nodes.ScalarNode(tag='tag:yaml.org,2002:int', value='24'),
  108. ),
  109. (
  110. ruamel.yaml.nodes.ScalarNode(
  111. tag='tag:yaml.org,2002:str', value='keep_daily'
  112. ),
  113. ruamel.yaml.nodes.ScalarNode(tag='tag:yaml.org,2002:int', value='7'),
  114. ),
  115. ],
  116. ),
  117. ),
  118. (
  119. ruamel.yaml.nodes.ScalarNode(tag='tag:yaml.org,2002:str', value='retention'),
  120. ruamel.yaml.nodes.MappingNode(
  121. tag='tag:yaml.org,2002:map',
  122. value=[
  123. (
  124. ruamel.yaml.nodes.ScalarNode(
  125. tag='tag:yaml.org,2002:str', value='keep_minutely'
  126. ),
  127. ruamel.yaml.nodes.ScalarNode(tag='tag:yaml.org,2002:int', value='10'),
  128. ),
  129. ],
  130. ),
  131. ),
  132. ]
  133. result = module.deep_merge_nodes(node_values)
  134. assert len(result) == 1
  135. (section_key, section_value) = result[0]
  136. assert section_key.value == 'retention'
  137. options = section_value.value
  138. assert len(options) == 3
  139. assert options[0][0].value == 'keep_hourly'
  140. assert options[0][1].value == '24'
  141. assert options[1][0].value == 'keep_daily'
  142. assert options[1][1].value == '7'
  143. assert options[2][0].value == 'keep_minutely'
  144. assert options[2][1].value == '10'
  145. def test_deep_merge_nodes_keeps_deeply_nested_values():
  146. node_values = [
  147. (
  148. ruamel.yaml.nodes.ScalarNode(tag='tag:yaml.org,2002:str', value='storage'),
  149. ruamel.yaml.nodes.MappingNode(
  150. tag='tag:yaml.org,2002:map',
  151. value=[
  152. (
  153. ruamel.yaml.nodes.ScalarNode(
  154. tag='tag:yaml.org,2002:str', value='lock_wait'
  155. ),
  156. ruamel.yaml.nodes.ScalarNode(tag='tag:yaml.org,2002:int', value='5'),
  157. ),
  158. (
  159. ruamel.yaml.nodes.ScalarNode(
  160. tag='tag:yaml.org,2002:str', value='extra_borg_options'
  161. ),
  162. ruamel.yaml.nodes.MappingNode(
  163. tag='tag:yaml.org,2002:map',
  164. value=[
  165. (
  166. ruamel.yaml.nodes.ScalarNode(
  167. tag='tag:yaml.org,2002:str', value='init'
  168. ),
  169. ruamel.yaml.nodes.ScalarNode(
  170. tag='tag:yaml.org,2002:str', value='--init-option'
  171. ),
  172. ),
  173. ],
  174. ),
  175. ),
  176. ],
  177. ),
  178. ),
  179. (
  180. ruamel.yaml.nodes.ScalarNode(tag='tag:yaml.org,2002:str', value='storage'),
  181. ruamel.yaml.nodes.MappingNode(
  182. tag='tag:yaml.org,2002:map',
  183. value=[
  184. (
  185. ruamel.yaml.nodes.ScalarNode(
  186. tag='tag:yaml.org,2002:str', value='extra_borg_options'
  187. ),
  188. ruamel.yaml.nodes.MappingNode(
  189. tag='tag:yaml.org,2002:map',
  190. value=[
  191. (
  192. ruamel.yaml.nodes.ScalarNode(
  193. tag='tag:yaml.org,2002:str', value='prune'
  194. ),
  195. ruamel.yaml.nodes.ScalarNode(
  196. tag='tag:yaml.org,2002:str', value='--prune-option'
  197. ),
  198. ),
  199. ],
  200. ),
  201. ),
  202. ],
  203. ),
  204. ),
  205. ]
  206. result = module.deep_merge_nodes(node_values)
  207. assert len(result) == 1
  208. (section_key, section_value) = result[0]
  209. assert section_key.value == 'storage'
  210. options = section_value.value
  211. assert len(options) == 2
  212. assert options[0][0].value == 'lock_wait'
  213. assert options[0][1].value == '5'
  214. assert options[1][0].value == 'extra_borg_options'
  215. nested_options = options[1][1].value
  216. assert len(nested_options) == 2
  217. assert nested_options[0][0].value == 'init'
  218. assert nested_options[0][1].value == '--init-option'
  219. assert nested_options[1][0].value == 'prune'
  220. assert nested_options[1][1].value == '--prune-option'