test_dump.py 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. import io
  2. import sys
  3. import pytest
  4. from flexmock import flexmock
  5. from borgmatic.hooks.data_source import dump as module
  6. def test_make_data_source_dump_path_joins_arguments():
  7. assert module.make_data_source_dump_path('/tmp', 'super_databases') == '/tmp/super_databases'
  8. def test_make_data_source_dump_filename_uses_name_and_hostname():
  9. assert (
  10. module.make_data_source_dump_filename('databases', 'test', 'hostname')
  11. == 'databases/hostname/test'
  12. )
  13. def test_make_data_source_dump_filename_uses_name_and_hostname_and_port():
  14. assert (
  15. module.make_data_source_dump_filename('databases', 'test', 'hostname', 1234)
  16. == 'databases/hostname:1234/test'
  17. )
  18. def test_make_data_source_dump_filename_uses_label():
  19. assert (
  20. module.make_data_source_dump_filename(
  21. 'databases', 'test', 'hostname', 1234, label='custom_label'
  22. )
  23. == 'databases/custom_label/test'
  24. )
  25. def test_make_data_source_dump_filename_without_hostname_defaults_to_localhost():
  26. assert module.make_data_source_dump_filename('databases', 'test') == 'databases/localhost/test'
  27. def test_make_data_source_dump_filename_with_invalid_name_raises():
  28. with pytest.raises(ValueError):
  29. module.make_data_source_dump_filename('databases', 'invalid/name')
  30. def test_write_data_source_dumps_metadata_writes_json_to_file():
  31. dumps_metadata = [
  32. module.borgmatic.actions.restore.Dump('databases', 'foo'),
  33. module.borgmatic.actions.restore.Dump('databases', 'bar'),
  34. ]
  35. dumps_stream = io.StringIO('password')
  36. dumps_stream.name = '/run/borgmatic/databases/dumps.json'
  37. builtins = flexmock(sys.modules['builtins'])
  38. builtins.should_receive('open').with_args(dumps_stream.name, 'w', encoding='utf-8').and_return(
  39. dumps_stream
  40. )
  41. flexmock(dumps_stream).should_receive('close') # Prevent close() so getvalue() below works.
  42. module.write_data_source_dumps_metadata('/run/borgmatic', 'databases', dumps_metadata)
  43. assert (
  44. dumps_stream.getvalue()
  45. == '{"dumps": [{"data_source_name": "foo", "hook_name": "databases", "hostname": "localhost", "port": null}, {"data_source_name": "bar", "hook_name": "databases", "hostname": "localhost", "port": null}]}'
  46. )
  47. def test_write_data_source_dumps_metadata_with_operating_system_error_raises():
  48. dumps_metadata = [
  49. module.borgmatic.actions.restore.Dump('databases', 'foo'),
  50. module.borgmatic.actions.restore.Dump('databases', 'bar'),
  51. ]
  52. dumps_stream = io.StringIO('password')
  53. dumps_stream.name = '/run/borgmatic/databases/dumps.json'
  54. builtins = flexmock(sys.modules['builtins'])
  55. builtins.should_receive('open').with_args(dumps_stream.name, 'w', encoding='utf-8').and_raise(
  56. OSError
  57. )
  58. with pytest.raises(ValueError):
  59. module.write_data_source_dumps_metadata('/run/borgmatic', 'databases', dumps_metadata)
  60. def test_parse_data_source_dumps_metadata_converts_json_to_dump_instances():
  61. dumps_json = '{"dumps": [{"data_source_name": "foo", "hook_name": "databases", "hostname": "localhost", "port": null}, {"data_source_name": "bar", "hook_name": "databases", "hostname": "example.org", "port": 1234}]}'
  62. assert module.parse_data_source_dumps_metadata(
  63. dumps_json, 'borgmatic/databases/dumps.json'
  64. ) == (
  65. module.borgmatic.actions.restore.Dump('databases', 'foo'),
  66. module.borgmatic.actions.restore.Dump('databases', 'bar', 'example.org', 1234),
  67. )
  68. def test_parse_data_source_dumps_metadata_with_invalid_json_raises():
  69. with pytest.raises(ValueError):
  70. module.parse_data_source_dumps_metadata('[{', 'borgmatic/databases/dumps.json')
  71. def test_parse_data_source_dumps_metadata_with_unknown_keys_raises():
  72. dumps_json = (
  73. '{"dumps": [{"data_source_name": "foo", "hook_name": "databases", "wtf": "is this"}]}'
  74. )
  75. with pytest.raises(ValueError):
  76. module.parse_data_source_dumps_metadata(dumps_json, 'borgmatic/databases/dumps.json')
  77. def test_parse_data_source_dumps_metadata_with_missing_dumps_key_raises():
  78. dumps_json = '{"not": "what we are looking for"}'
  79. with pytest.raises(ValueError):
  80. module.parse_data_source_dumps_metadata(dumps_json, 'borgmatic/databases/dumps.json')
  81. def test_create_parent_directory_for_dump_does_not_raise():
  82. flexmock(module.os).should_receive('makedirs')
  83. module.create_parent_directory_for_dump('/path/to/parent')
  84. def test_create_named_pipe_for_dump_does_not_raise():
  85. flexmock(module).should_receive('create_parent_directory_for_dump')
  86. flexmock(module.os).should_receive('mkfifo')
  87. module.create_named_pipe_for_dump('/path/to/pipe')
  88. def test_remove_data_source_dumps_removes_dump_path():
  89. flexmock(module.os.path).should_receive('exists').and_return(True)
  90. flexmock(module.shutil).should_receive('rmtree').with_args('databases').once()
  91. module.remove_data_source_dumps('databases', 'SuperDB', dry_run=False)
  92. def test_remove_data_source_dumps_with_dry_run_skips_removal():
  93. flexmock(module.os.path).should_receive('exists').never()
  94. flexmock(module.shutil).should_receive('rmtree').never()
  95. module.remove_data_source_dumps('databases', 'SuperDB', dry_run=True)
  96. def test_remove_data_source_dumps_without_dump_path_present_skips_removal():
  97. flexmock(module.os.path).should_receive('exists').and_return(False)
  98. flexmock(module.shutil).should_receive('rmtree').never()
  99. module.remove_data_source_dumps('databases', 'SuperDB', dry_run=False)
  100. def test_convert_glob_patterns_to_borg_pattern_makes_multipart_regular_expression():
  101. assert (
  102. module.convert_glob_patterns_to_borg_pattern(('/etc/foo/bar', '/bar/*/baz'))
  103. == 're:(?s:etc/foo/bar)|(?s:bar/.*/baz)'
  104. )