diff --git a/borgmatic/actions/bootstrap.py b/borgmatic/actions/bootstrap.py new file mode 100644 index 000000000..d51cafc66 --- /dev/null +++ b/borgmatic/actions/bootstrap.py @@ -0,0 +1,73 @@ +import logging +import os +import json + +import borgmatic.borg.extract +import borgmatic.borg.rlist +import borgmatic.config.validate +import borgmatic.hooks.command + +from borgmatic.borg.state import DEFAULT_BORGMATIC_SOURCE_DIRECTORY + +logger = logging.getLogger(__name__) + +def get_config_paths(bootstrap_arguments, global_arguments, local_borg_version): + borgmatic_source_directory = DEFAULT_BORGMATIC_SOURCE_DIRECTORY + borgmatic_manifest_path = os.path.expanduser( + os.path.join(borgmatic_source_directory, 'bootstrap', 'configs-list.json') + ) + extract_process = borgmatic.borg.extract.extract_archive( + global_arguments.dry_run, + bootstrap_arguments.repository, + borgmatic.borg.rlist.resolve_archive_name( + bootstrap_arguments.repository, + bootstrap_arguments.archive or 'latest', + {}, + local_borg_version, + global_arguments + ), + [borgmatic_manifest_path], + {}, + {}, + local_borg_version, + global_arguments, + extract_to_stdout=True, + ) + + manifest_data = json.loads(extract_process.stdout.read()) + + return manifest_data['config_paths'] + + + + +def run_bootstrap(bootstrap_arguments, global_arguments, local_borg_version): + ''' + Run the "bootstrap" action for the given repository. + ''' + manifest_config_paths = get_config_paths(bootstrap_arguments, global_arguments, local_borg_version) + + for config_path in manifest_config_paths: + logger.info('Bootstrapping config path %s', config_path) + + borgmatic.borg.extract.extract_archive( + global_arguments.dry_run, + bootstrap_arguments.repository, + borgmatic.borg.rlist.resolve_archive_name( + bootstrap_arguments.repository, + bootstrap_arguments.archive or 'latest', + {}, + local_borg_version, + global_arguments + ), + [config_path], + {}, + {}, + local_borg_version, + global_arguments, + extract_to_stdout=False, + ) + + + + diff --git a/borgmatic/commands/borgmatic.py b/borgmatic/commands/borgmatic.py index 4271fa8f3..ccc6ccf2f 100644 --- a/borgmatic/commands/borgmatic.py +++ b/borgmatic/commands/borgmatic.py @@ -21,6 +21,7 @@ import borgmatic.actions.compact import borgmatic.actions.create import borgmatic.actions.export_tar import borgmatic.actions.extract +import borgmatic.actions.bootstrap import borgmatic.actions.info import borgmatic.actions.list import borgmatic.actions.mount @@ -621,6 +622,19 @@ def collect_configuration_run_summary_logs(configs, arguments): except ValueError as error: yield from log_error_records(str(error)) return + + if 'bootstrap' in arguments: + # no configuration file is needed for bootstrap + local_borg_version = borg_version.local_borg_version({}, 'borg') + borgmatic.actions.bootstrap.run_bootstrap(arguments['bootstrap'], arguments['global'], local_borg_version) + yield logging.makeLogRecord( + dict( + levelno=logging.INFO, + levelname='INFO', + msg='Bootstrap successful', + ) + ) + return if not configs: yield from log_error_records(