test_database.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128
  1. import json
  2. import os
  3. import shutil
  4. import subprocess
  5. import sys
  6. import tempfile
  7. import pytest
  8. def write_configuration(config_path, repository_path, borgmatic_source_directory):
  9. '''
  10. Write out borgmatic configuration into a file at the config path. Set the options so as to work
  11. for testing. This includes injecting the given repository path, borgmatic source directory for
  12. storing database dumps, and encryption passphrase.
  13. '''
  14. config = '''
  15. location:
  16. source_directories:
  17. - {}
  18. repositories:
  19. - {}
  20. borgmatic_source_directory: {}
  21. storage:
  22. encryption_passphrase: "test"
  23. hooks:
  24. postgresql_databases:
  25. - name: test
  26. hostname: postgresql
  27. username: postgres
  28. password: test
  29. - name: all
  30. hostname: postgresql
  31. username: postgres
  32. password: test
  33. mysql_databases:
  34. - name: test
  35. hostname: mysql
  36. username: root
  37. password: test
  38. - name: all
  39. hostname: mysql
  40. username: root
  41. password: test
  42. '''.format(
  43. config_path, repository_path, borgmatic_source_directory
  44. )
  45. config_file = open(config_path, 'w')
  46. config_file.write(config)
  47. config_file.close()
  48. def test_database_dump_and_restore():
  49. # Create a Borg repository.
  50. temporary_directory = tempfile.mkdtemp()
  51. repository_path = os.path.join(temporary_directory, 'test.borg')
  52. borgmatic_source_directory = os.path.join(temporary_directory, '.borgmatic')
  53. original_working_directory = os.getcwd()
  54. try:
  55. config_path = os.path.join(temporary_directory, 'test.yaml')
  56. write_configuration(config_path, repository_path, borgmatic_source_directory)
  57. subprocess.check_call(
  58. 'borgmatic -v 2 --config {} init --encryption repokey'.format(config_path).split(' ')
  59. )
  60. # Run borgmatic to generate a backup archive including a database dump.
  61. subprocess.check_call('borgmatic create --config {} -v 2'.format(config_path).split(' '))
  62. # Get the created archive name.
  63. output = subprocess.check_output(
  64. 'borgmatic --config {} list --json'.format(config_path).split(' ')
  65. ).decode(sys.stdout.encoding)
  66. parsed_output = json.loads(output)
  67. assert len(parsed_output) == 1
  68. assert len(parsed_output[0]['archives']) == 1
  69. archive_name = parsed_output[0]['archives'][0]['archive']
  70. # Restore the database from the archive.
  71. subprocess.check_call(
  72. 'borgmatic --config {} restore --archive {}'.format(config_path, archive_name).split(
  73. ' '
  74. )
  75. )
  76. finally:
  77. os.chdir(original_working_directory)
  78. shutil.rmtree(temporary_directory)
  79. def test_database_dump_with_error_causes_borgmatic_to_exit():
  80. # Create a Borg repository.
  81. temporary_directory = tempfile.mkdtemp()
  82. repository_path = os.path.join(temporary_directory, 'test.borg')
  83. borgmatic_source_directory = os.path.join(temporary_directory, '.borgmatic')
  84. original_working_directory = os.getcwd()
  85. try:
  86. config_path = os.path.join(temporary_directory, 'test.yaml')
  87. write_configuration(config_path, repository_path, borgmatic_source_directory)
  88. subprocess.check_call(
  89. 'borgmatic -v 2 --config {} init --encryption repokey'.format(config_path).split(' ')
  90. )
  91. # Run borgmatic with a config override such that the database dump fails.
  92. with pytest.raises(subprocess.CalledProcessError):
  93. subprocess.check_call(
  94. [
  95. 'borgmatic',
  96. 'create',
  97. '--config',
  98. config_path,
  99. '-v',
  100. '2',
  101. '--override',
  102. "hooks.postgresql_databases=[{'name': 'nope'}]",
  103. ]
  104. )
  105. finally:
  106. os.chdir(original_working_directory)
  107. shutil.rmtree(temporary_directory)