test_database.py 5.2 KB

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