bootstrap.py 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  1. import contextlib
  2. import glob
  3. import importlib
  4. import json
  5. import logging
  6. import os
  7. import borgmatic.borg.pattern
  8. import borgmatic.config.paths
  9. logger = logging.getLogger(__name__)
  10. def use_streaming(hook_config, config): # pragma: no cover
  11. '''
  12. Return whether dump streaming is used for this hook. (Spoiler: It isn't.)
  13. '''
  14. return False
  15. def dump_data_sources(
  16. hook_config,
  17. config,
  18. config_paths,
  19. borgmatic_runtime_directory,
  20. patterns,
  21. dry_run,
  22. ):
  23. '''
  24. Given a bootstrap configuration dict, a configuration dict, the borgmatic configuration file
  25. paths, the borgmatic runtime directory, the configured patterns, and whether this is a dry run,
  26. create a borgmatic manifest file to store the paths of the configuration files used to create
  27. the archive. But skip this if the bootstrap store_config_files option is False or if this is a
  28. dry run.
  29. Return an empty sequence, since there are no ongoing dump processes from this hook.
  30. '''
  31. if hook_config and hook_config.get('store_config_files') is False:
  32. return []
  33. borgmatic_manifest_path = os.path.join(
  34. borgmatic_runtime_directory,
  35. 'bootstrap',
  36. 'manifest.json',
  37. )
  38. if dry_run:
  39. return []
  40. os.makedirs(os.path.dirname(borgmatic_manifest_path), exist_ok=True)
  41. with open(borgmatic_manifest_path, 'w', encoding='utf-8') as manifest_file:
  42. json.dump(
  43. {
  44. 'borgmatic_version': importlib.metadata.version('borgmatic'),
  45. 'config_paths': config_paths,
  46. },
  47. manifest_file,
  48. )
  49. patterns.extend(
  50. borgmatic.borg.pattern.Pattern(
  51. config_path,
  52. source=borgmatic.borg.pattern.Pattern_source.HOOK,
  53. )
  54. for config_path in config_paths
  55. )
  56. patterns.append(
  57. borgmatic.borg.pattern.Pattern(
  58. os.path.join(borgmatic_runtime_directory, 'bootstrap'),
  59. source=borgmatic.borg.pattern.Pattern_source.HOOK,
  60. ),
  61. )
  62. return []
  63. def remove_data_source_dumps(hook_config, config, borgmatic_runtime_directory, patterns, dry_run):
  64. '''
  65. Given a bootstrap configuration dict, a configuration dict, the borgmatic runtime directory, the
  66. configured patterns, and whether this is a dry run, then remove the manifest file created above.
  67. If this is a dry run, then don't actually remove anything.
  68. '''
  69. dry_run_label = ' (dry run; not actually removing anything)' if dry_run else ''
  70. manifest_glob = os.path.join(
  71. borgmatic.config.paths.replace_temporary_subdirectory_with_glob(
  72. os.path.normpath(borgmatic_runtime_directory),
  73. ),
  74. 'bootstrap',
  75. )
  76. logger.debug(
  77. f'Looking for bootstrap manifest files to remove in {manifest_glob}{dry_run_label}',
  78. )
  79. for manifest_directory in glob.glob(manifest_glob):
  80. manifest_file_path = os.path.join(manifest_directory, 'manifest.json')
  81. logger.debug(f'Removing bootstrap manifest at {manifest_file_path}{dry_run_label}')
  82. if dry_run:
  83. continue
  84. with contextlib.suppress(FileNotFoundError):
  85. os.remove(manifest_file_path)
  86. with contextlib.suppress(FileNotFoundError):
  87. os.rmdir(manifest_directory)
  88. def make_data_source_dump_patterns(
  89. hook_config,
  90. config,
  91. borgmatic_runtime_directory,
  92. name=None,
  93. ): # pragma: no cover
  94. '''
  95. Restores are implemented via the separate, purpose-specific "bootstrap" action rather than the
  96. generic "restore".
  97. '''
  98. return ()
  99. def restore_data_source_dump(
  100. hook_config,
  101. config,
  102. data_source,
  103. dry_run,
  104. extract_process,
  105. connection_params,
  106. borgmatic_runtime_directory,
  107. ): # pragma: no cover
  108. '''
  109. Restores are implemented via the separate, purpose-specific "bootstrap" action rather than the
  110. generic "restore".
  111. '''
  112. raise NotImplementedError()