mirror of
https://github.com/borgmatic-collective/borgmatic.git
synced 2026-07-30 05:13:01 +02:00
Fix restore and get end-to-end tests passing (#1105).
This commit is contained in:
@@ -5,6 +5,7 @@ import pathlib
|
||||
import shutil
|
||||
import tempfile
|
||||
|
||||
import borgmatic.actions.pattern
|
||||
import borgmatic.borg.extract
|
||||
import borgmatic.borg.list
|
||||
import borgmatic.borg.mount
|
||||
@@ -536,13 +537,20 @@ def run_restore(
|
||||
return
|
||||
|
||||
logger.info(f'Restoring data sources from archive {restore_arguments.archive}')
|
||||
working_directory = borgmatic.config.paths.get_working_directory(config)
|
||||
|
||||
with borgmatic.config.paths.Runtime_directory(config) as borgmatic_runtime_directory:
|
||||
patterns = borgmatic.actions.pattern.process_patterns(
|
||||
borgmatic.actions.pattern.collect_patterns(config),
|
||||
config,
|
||||
working_directory,
|
||||
)
|
||||
borgmatic.hooks.dispatch.call_hooks_even_if_unconfigured(
|
||||
'remove_data_source_dumps',
|
||||
config,
|
||||
borgmatic.hooks.dispatch.Hook_type.DATA_SOURCE,
|
||||
borgmatic_runtime_directory,
|
||||
patterns,
|
||||
global_arguments.dry_run,
|
||||
)
|
||||
|
||||
@@ -625,6 +633,7 @@ def run_restore(
|
||||
config,
|
||||
borgmatic.hooks.dispatch.Hook_type.DATA_SOURCE,
|
||||
borgmatic_runtime_directory,
|
||||
patterns,
|
||||
global_arguments.dry_run,
|
||||
)
|
||||
|
||||
|
||||
@@ -12,9 +12,8 @@ def parse_arguments(*unparsed_arguments):
|
||||
subvolume_parser = action_parsers.add_parser('subvolume')
|
||||
subvolume_subparser = subvolume_parser.add_subparsers(dest='subaction')
|
||||
|
||||
list_parser = subvolume_subparser.add_parser('list')
|
||||
list_parser.add_argument('-s', dest='snapshots_only', action='store_true')
|
||||
list_parser.add_argument('subvolume_path')
|
||||
show_parser = subvolume_subparser.add_parser('show')
|
||||
show_parser.add_argument('subvolume_path')
|
||||
|
||||
snapshot_parser = subvolume_subparser.add_parser('snapshot')
|
||||
snapshot_parser.add_argument('-r', dest='read_only', action='store_true')
|
||||
@@ -24,6 +23,9 @@ def parse_arguments(*unparsed_arguments):
|
||||
delete_parser = subvolume_subparser.add_parser('delete')
|
||||
delete_parser.add_argument('snapshot_path')
|
||||
|
||||
ensure_deleted_parser = subvolume_subparser.add_parser('ensure_deleted')
|
||||
ensure_deleted_parser.add_argument('snapshot_path')
|
||||
|
||||
property_parser = action_parsers.add_parser('property')
|
||||
property_subparser = property_parser.add_subparsers(dest='subaction')
|
||||
get_parser = property_subparser.add_parser('get')
|
||||
@@ -34,13 +36,6 @@ def parse_arguments(*unparsed_arguments):
|
||||
return (global_parser, global_parser.parse_args(unparsed_arguments))
|
||||
|
||||
|
||||
BUILTIN_SUBVOLUME_LIST_LINES = (
|
||||
'261 gen 29 top level 5 path sub',
|
||||
'262 gen 29 top level 5 path other',
|
||||
)
|
||||
SUBVOLUME_LIST_LINE_PREFIX = '263 gen 29 top level 5 path '
|
||||
|
||||
|
||||
def load_snapshots():
|
||||
try:
|
||||
return json.load(open('/tmp/fake_btrfs.json'))
|
||||
@@ -52,18 +47,12 @@ def save_snapshots(snapshot_paths):
|
||||
json.dump(snapshot_paths, open('/tmp/fake_btrfs.json', 'w'))
|
||||
|
||||
|
||||
def print_subvolume_list(arguments, snapshot_paths):
|
||||
def print_subvolume_show(arguments):
|
||||
assert arguments.subvolume_path == '/e2e/mnt/subvolume'
|
||||
|
||||
if not arguments.snapshots_only:
|
||||
for line in BUILTIN_SUBVOLUME_LIST_LINES:
|
||||
print(line)
|
||||
|
||||
for snapshot_path in snapshot_paths:
|
||||
print(
|
||||
SUBVOLUME_LIST_LINE_PREFIX
|
||||
+ snapshot_path[snapshot_path.index('.borgmatic-snapshot-') :],
|
||||
)
|
||||
# borgmatic doesn't currently parse the output of "btrfs subvolume show"—it's just checking the
|
||||
# exit code—so what we print in response doesn't matter in this test.
|
||||
print('Totally legit btrfs subvolume!')
|
||||
|
||||
|
||||
def main():
|
||||
@@ -74,8 +63,8 @@ def main():
|
||||
global_parser.print_help()
|
||||
sys.exit(1)
|
||||
|
||||
if arguments.subaction == 'list':
|
||||
print_subvolume_list(arguments, snapshot_paths)
|
||||
if arguments.subaction == 'show':
|
||||
print_subvolume_show(arguments)
|
||||
elif arguments.subaction == 'snapshot':
|
||||
snapshot_paths.append(arguments.snapshot_path)
|
||||
save_snapshots(snapshot_paths)
|
||||
@@ -95,6 +84,8 @@ def main():
|
||||
if snapshot_path.endswith('/' + arguments.snapshot_path)
|
||||
]
|
||||
save_snapshots(snapshot_paths)
|
||||
elif arguments.subaction == 'ensure_deleted':
|
||||
assert arguments.snapshot_path not in snapshot_paths
|
||||
elif arguments.action == 'property' and arguments.subaction == 'get':
|
||||
print(f'{arguments.property_name}=false')
|
||||
|
||||
|
||||
@@ -1,42 +0,0 @@
|
||||
import argparse
|
||||
import sys
|
||||
|
||||
|
||||
def parse_arguments(*unparsed_arguments):
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
parser.add_argument('-t', dest='type')
|
||||
parser.add_argument('--json', action='store_true')
|
||||
parser.add_argument('--list', action='store_true')
|
||||
|
||||
return parser.parse_args(unparsed_arguments)
|
||||
|
||||
|
||||
BUILTIN_FILESYSTEM_MOUNT_OUTPUT = '''{
|
||||
"filesystems": [
|
||||
{
|
||||
"target": "/e2e/mnt/subvolume",
|
||||
"source": "/dev/loop0",
|
||||
"fstype": "btrfs",
|
||||
"options": "rw,relatime,ssd,space_cache=v2,subvolid=5,subvol=/"
|
||||
}
|
||||
]
|
||||
}
|
||||
'''
|
||||
|
||||
|
||||
def print_filesystem_mounts():
|
||||
print(BUILTIN_FILESYSTEM_MOUNT_OUTPUT)
|
||||
|
||||
|
||||
def main():
|
||||
arguments = parse_arguments(*sys.argv[1:])
|
||||
|
||||
assert arguments.type == 'btrfs'
|
||||
assert arguments.json
|
||||
assert arguments.list
|
||||
|
||||
print_filesystem_mounts()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
main()
|
||||
@@ -24,7 +24,6 @@ def generate_configuration(config_path, repository_path):
|
||||
+ 'encryption_passphrase: "test"\n'
|
||||
+ 'btrfs:\n'
|
||||
+ ' btrfs_command: python3 /app/tests/end-to-end/commands/fake_btrfs.py\n'
|
||||
+ ' findmnt_command: python3 /app/tests/end-to-end/commands/fake_findmnt.py\n'
|
||||
)
|
||||
config_file = open(config_path, 'w')
|
||||
config_file.write(config)
|
||||
@@ -55,7 +54,7 @@ def test_btrfs_create_and_list():
|
||||
|
||||
# Assert that the snapshot has been deleted.
|
||||
assert not subprocess.check_output(
|
||||
'python3 /app/tests/end-to-end/commands/fake_btrfs.py subvolume list -s /e2e/mnt/subvolume'.split(
|
||||
'python3 /app/tests/end-to-end/commands/fake_btrfs.py subvolume ensure_deleted /e2e/mnt/subvolume'.split(
|
||||
' ',
|
||||
),
|
||||
)
|
||||
|
||||
@@ -18,6 +18,7 @@ def test_run_create_executes_and_calls_hooks_for_configured_repository():
|
||||
flexmock(module.borgmatic.hooks.dispatch).should_receive(
|
||||
'call_hooks_even_if_unconfigured',
|
||||
).and_return({})
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('collect_patterns').and_return(())
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('process_patterns').and_return([])
|
||||
flexmock(os.path).should_receive('join').and_return('/run/borgmatic/bootstrap')
|
||||
@@ -60,6 +61,7 @@ def test_run_create_runs_with_selected_repository():
|
||||
flexmock(module.borgmatic.hooks.dispatch).should_receive(
|
||||
'call_hooks_even_if_unconfigured',
|
||||
).and_return({})
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('collect_patterns').and_return(())
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('process_patterns').and_return([])
|
||||
flexmock(os.path).should_receive('join').and_return('/run/borgmatic/bootstrap')
|
||||
@@ -207,6 +209,7 @@ def test_run_create_produces_json():
|
||||
flexmock(module.borgmatic.hooks.dispatch).should_receive(
|
||||
'call_hooks_even_if_unconfigured',
|
||||
).and_return({})
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('collect_patterns').and_return(())
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('process_patterns').and_return([])
|
||||
flexmock(os.path).should_receive('join').and_return('/run/borgmatic/bootstrap')
|
||||
@@ -252,6 +255,7 @@ def test_run_create_with_active_dumps_roundtrips_via_checkpoint_archive():
|
||||
flexmock(module.borgmatic.hooks.dispatch).should_receive(
|
||||
'call_hooks_even_if_unconfigured',
|
||||
).and_return({})
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('collect_patterns').and_return(())
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('process_patterns').and_return([])
|
||||
flexmock(os.path).should_receive('join').and_return('/run/borgmatic/bootstrap')
|
||||
@@ -335,6 +339,7 @@ def test_run_create_with_active_dumps_json_updates_archive_info():
|
||||
flexmock(module.borgmatic.hooks.dispatch).should_receive(
|
||||
'call_hooks_even_if_unconfigured',
|
||||
).and_return({})
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('collect_patterns').and_return(())
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('process_patterns').and_return([])
|
||||
flexmock(os.path).should_receive('join').and_return('/run/borgmatic/bootstrap')
|
||||
|
||||
@@ -1176,6 +1176,9 @@ def test_run_restore_restores_each_data_source():
|
||||
flexmock(module.borgmatic.config.paths).should_receive(
|
||||
'make_runtime_directory_glob',
|
||||
).replace_with(lambda path: path)
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('collect_patterns').and_return(())
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('process_patterns').and_return([])
|
||||
flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks_even_if_unconfigured')
|
||||
flexmock(module.borgmatic.borg.repo_list).should_receive('resolve_archive_name').and_return(
|
||||
flexmock(),
|
||||
@@ -1245,6 +1248,9 @@ def test_run_restore_bails_for_non_matching_repository():
|
||||
flexmock(module.borgmatic.config.paths).should_receive(
|
||||
'make_runtime_directory_glob',
|
||||
).replace_with(lambda path: path)
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('collect_patterns').and_return(())
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('process_patterns').and_return([])
|
||||
flexmock(module.borgmatic.hooks.dispatch).should_receive(
|
||||
'call_hooks_even_if_unconfigured',
|
||||
).never()
|
||||
@@ -1274,6 +1280,9 @@ def test_run_restore_restores_data_source_by_falling_back_to_all_name():
|
||||
flexmock(module.borgmatic.config.paths).should_receive(
|
||||
'make_runtime_directory_glob',
|
||||
).replace_with(lambda path: path)
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('collect_patterns').and_return(())
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('process_patterns').and_return([])
|
||||
flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks_even_if_unconfigured')
|
||||
flexmock(module.borgmatic.borg.repo_list).should_receive('resolve_archive_name').and_return(
|
||||
flexmock(),
|
||||
@@ -1334,6 +1343,9 @@ def test_run_restore_restores_data_source_configured_with_all_name():
|
||||
flexmock(module.borgmatic.config.paths).should_receive(
|
||||
'make_runtime_directory_glob',
|
||||
).replace_with(lambda path: path)
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('collect_patterns').and_return(())
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('process_patterns').and_return([])
|
||||
flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks_even_if_unconfigured')
|
||||
flexmock(module.borgmatic.borg.repo_list).should_receive('resolve_archive_name').and_return(
|
||||
flexmock(),
|
||||
@@ -1416,6 +1428,9 @@ def test_run_restore_skips_missing_data_source():
|
||||
flexmock(module.borgmatic.config.paths).should_receive(
|
||||
'make_runtime_directory_glob',
|
||||
).replace_with(lambda path: path)
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('collect_patterns').and_return(())
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('process_patterns').and_return([])
|
||||
flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks_even_if_unconfigured')
|
||||
flexmock(module.borgmatic.borg.repo_list).should_receive('resolve_archive_name').and_return(
|
||||
flexmock(),
|
||||
@@ -1498,6 +1513,9 @@ def test_run_restore_restores_data_sources_from_different_hooks():
|
||||
flexmock(module.borgmatic.config.paths).should_receive(
|
||||
'make_runtime_directory_glob',
|
||||
).replace_with(lambda path: path)
|
||||
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(None)
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('collect_patterns').and_return(())
|
||||
flexmock(module.borgmatic.actions.pattern).should_receive('process_patterns').and_return([])
|
||||
flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks_even_if_unconfigured')
|
||||
flexmock(module.borgmatic.borg.repo_list).should_receive('resolve_archive_name').and_return(
|
||||
flexmock(),
|
||||
|
||||
Reference in New Issue
Block a user