forked from borgmatic-collective/borgmatic
Fix for a regression in the ZFS, LVM, and Btrfs hooks in which partial excludes of snapshot paths were ignored (#1169).
This commit is contained in:
2
NEWS
2
NEWS
@@ -3,6 +3,8 @@
|
||||
contain multiple paths.
|
||||
* #1168: Fix for the "list", "info", and "delete" options in "extra_borg_options" being ignored
|
||||
when "--archive" is omitted with Borg 1.x.
|
||||
* #1169: Fix for a regression in the ZFS, LVM, and Btrfs hooks in which partial excludes of
|
||||
snapshot paths were ignored.
|
||||
* Add a "rename" option to "extra_borg_options" to support passing arbitrary flags to "borg
|
||||
rename".
|
||||
|
||||
|
||||
@@ -329,9 +329,15 @@ def dump_data_sources(
|
||||
|
||||
snapshot_subvolume(btrfs_command, subvolume.path, snapshot_path)
|
||||
|
||||
last_contained_pattern_index = borgmatic.hooks.data_source.config.get_last_pattern_index(
|
||||
patterns, subvolume.contained_patterns
|
||||
)
|
||||
|
||||
for pattern in subvolume.contained_patterns:
|
||||
snapshot_pattern = make_borg_snapshot_pattern(subvolume.path, pattern)
|
||||
borgmatic.hooks.data_source.config.replace_pattern(patterns, pattern, snapshot_pattern)
|
||||
borgmatic.hooks.data_source.config.replace_pattern(
|
||||
patterns, pattern, snapshot_pattern, last_contained_pattern_index
|
||||
)
|
||||
|
||||
borgmatic.hooks.data_source.config.inject_pattern(
|
||||
patterns, make_snapshot_exclude_pattern(subvolume.path)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import contextlib
|
||||
import json
|
||||
import logging
|
||||
import shutil
|
||||
@@ -131,7 +132,23 @@ def inject_pattern(patterns, data_source_pattern):
|
||||
patterns.insert(0, data_source_pattern)
|
||||
|
||||
|
||||
def replace_pattern(patterns, pattern_to_replace, data_source_pattern):
|
||||
def get_last_pattern_index(patterns, patterns_subset):
|
||||
'''
|
||||
Given a sequence of all patterns and a subset of those patterns, find each subset pattern in the
|
||||
all patterns sequence and return the highest (last) index.
|
||||
'''
|
||||
last_pattern_index = 0
|
||||
|
||||
for pattern in patterns_subset:
|
||||
with contextlib.suppress(ValueError):
|
||||
last_pattern_index = max(patterns.index(pattern), last_pattern_index)
|
||||
|
||||
return last_pattern_index
|
||||
|
||||
|
||||
def replace_pattern(
|
||||
patterns, pattern_to_replace, data_source_pattern, last_contained_pattern_index
|
||||
):
|
||||
'''
|
||||
Given a list of borgmatic.borg.pattern.Pattern instances representing the configured patterns,
|
||||
replace the given pattern with the given data source pattern. The idea is that borgmatic is
|
||||
@@ -139,8 +156,32 @@ def replace_pattern(patterns, pattern_to_replace, data_source_pattern):
|
||||
that the hook's data gets included in the backup.
|
||||
|
||||
As part of this replacement, if the data source pattern is a root pattern, also insert an
|
||||
"include" version of the given root pattern right after the replaced pattern, in an attempt to
|
||||
preempt any of the user's configured exclude patterns that may follow.
|
||||
"include" version of the given root pattern right after the given last contained pattern index
|
||||
in an attempt to preempt any of the user's configured global exclude patterns that may follow.
|
||||
But we don't want to preempt any intentional partial excludes of the data source pattern itself,
|
||||
which is why the include goes after the last contained pattern index.
|
||||
|
||||
For instance, let's say that the patterns are effectively:
|
||||
|
||||
R /foo
|
||||
R /bar
|
||||
- /bar/.cache
|
||||
R /baz
|
||||
- **
|
||||
|
||||
... and "R /bar" is the pattern to replace, data source pattern is "R /bar/snapshot", and the
|
||||
last contained pattern index is 2 (corresponding to "- /bar/.cache"). The resulting patterns
|
||||
after calling this function would be:
|
||||
|
||||
R /foo
|
||||
R /bar/snapshot
|
||||
- /bar/snapshot/.cache
|
||||
+ /bar/snapshot
|
||||
R /baz
|
||||
- **
|
||||
|
||||
Note that the positioning of "+ /bar/snapshot" means that it overrides the "- **" global exclude
|
||||
but not the "- /bar/snapshot/.cache" contained pattern exclude.
|
||||
|
||||
If the pattern to replace can't be found in the given patterns, then just inject the data source
|
||||
pattern at the start of the list.
|
||||
@@ -156,7 +197,7 @@ def replace_pattern(patterns, pattern_to_replace, data_source_pattern):
|
||||
|
||||
if data_source_pattern.type == borgmatic.borg.pattern.Pattern_type.ROOT:
|
||||
patterns.insert(
|
||||
index + 1,
|
||||
last_contained_pattern_index + 1,
|
||||
borgmatic.borg.pattern.Pattern(
|
||||
path=data_source_pattern.path,
|
||||
type=borgmatic.borg.pattern.Pattern_type.INCLUDE,
|
||||
|
||||
@@ -269,6 +269,10 @@ def dump_data_sources(
|
||||
snapshot_mount_path,
|
||||
)
|
||||
|
||||
last_contained_pattern_index = borgmatic.hooks.data_source.config.get_last_pattern_index(
|
||||
patterns, logical_volume.contained_patterns
|
||||
)
|
||||
|
||||
for pattern in logical_volume.contained_patterns:
|
||||
snapshot_pattern = make_borg_snapshot_pattern(
|
||||
pattern,
|
||||
@@ -276,7 +280,9 @@ def dump_data_sources(
|
||||
normalized_runtime_directory,
|
||||
)
|
||||
|
||||
borgmatic.hooks.data_source.config.replace_pattern(patterns, pattern, snapshot_pattern)
|
||||
borgmatic.hooks.data_source.config.replace_pattern(
|
||||
patterns, pattern, snapshot_pattern, last_contained_pattern_index
|
||||
)
|
||||
|
||||
return []
|
||||
|
||||
|
||||
@@ -300,6 +300,10 @@ def dump_data_sources(
|
||||
snapshot_mount_path,
|
||||
)
|
||||
|
||||
last_contained_pattern_index = borgmatic.hooks.data_source.config.get_last_pattern_index(
|
||||
patterns, dataset.contained_patterns
|
||||
)
|
||||
|
||||
for pattern in dataset.contained_patterns:
|
||||
snapshot_pattern = make_borg_snapshot_pattern(
|
||||
pattern,
|
||||
@@ -307,7 +311,9 @@ def dump_data_sources(
|
||||
normalized_runtime_directory,
|
||||
)
|
||||
|
||||
borgmatic.hooks.data_source.config.replace_pattern(patterns, pattern, snapshot_pattern)
|
||||
borgmatic.hooks.data_source.config.replace_pattern(
|
||||
patterns, pattern, snapshot_pattern, last_contained_pattern_index
|
||||
)
|
||||
|
||||
return []
|
||||
|
||||
|
||||
@@ -5,11 +5,22 @@ from borgmatic.hooks.data_source import btrfs as module
|
||||
|
||||
|
||||
def test_dump_data_sources_snapshots_each_subvolume_and_updates_patterns():
|
||||
patterns = [Pattern('/foo'), Pattern('/mnt/subvol1'), Pattern('/mnt/subvol2')]
|
||||
patterns = [
|
||||
Pattern('/foo'),
|
||||
Pattern('/mnt/subvol1'),
|
||||
Pattern('/mnt/subvol1/.cache', Pattern_type.EXCLUDE),
|
||||
Pattern('/mnt/subvol2'),
|
||||
]
|
||||
config = {'btrfs': {}}
|
||||
flexmock(module).should_receive('get_subvolumes').and_return(
|
||||
(
|
||||
module.Subvolume('/mnt/subvol1', contained_patterns=(Pattern('/mnt/subvol1'),)),
|
||||
module.Subvolume(
|
||||
'/mnt/subvol1',
|
||||
contained_patterns=(
|
||||
Pattern('/mnt/subvol1'),
|
||||
Pattern('/mnt/subvol1/.cache', Pattern_type.EXCLUDE),
|
||||
),
|
||||
),
|
||||
module.Subvolume('/mnt/subvol2', contained_patterns=(Pattern('/mnt/subvol2'),)),
|
||||
),
|
||||
)
|
||||
@@ -50,6 +61,7 @@ def test_dump_data_sources_snapshots_each_subvolume_and_updates_patterns():
|
||||
),
|
||||
Pattern('/foo'),
|
||||
Pattern('/mnt/subvol1/.borgmatic-snapshot-1234/./mnt/subvol1'),
|
||||
Pattern('/mnt/subvol1/.borgmatic-snapshot-1234/./mnt/subvol1/.cache', Pattern_type.EXCLUDE),
|
||||
Pattern('/mnt/subvol1/.borgmatic-snapshot-1234/./mnt/subvol1', Pattern_type.INCLUDE),
|
||||
Pattern('/mnt/subvol2/.borgmatic-snapshot-1234/./mnt/subvol2'),
|
||||
Pattern('/mnt/subvol2/.borgmatic-snapshot-1234/./mnt/subvol2', Pattern_type.INCLUDE),
|
||||
|
||||
@@ -6,13 +6,20 @@ from borgmatic.hooks.data_source import lvm as module
|
||||
|
||||
def test_dump_data_sources_snapshots_and_mounts_and_updates_patterns():
|
||||
config = {'lvm': {}}
|
||||
patterns = [Pattern('/mnt/lvolume1/subdir'), Pattern('/mnt/lvolume2')]
|
||||
patterns = [
|
||||
Pattern('/mnt/lvolume1/subdir'),
|
||||
Pattern('/mnt/lvolume1/subdir/.cache', Pattern_type.EXCLUDE),
|
||||
Pattern('/mnt/lvolume2'),
|
||||
]
|
||||
logical_volumes = (
|
||||
module.Logical_volume(
|
||||
name='lvolume1',
|
||||
device_path='/dev/lvolume1',
|
||||
mount_point='/mnt/lvolume1',
|
||||
contained_patterns=(Pattern('/mnt/lvolume1/subdir'),),
|
||||
contained_patterns=(
|
||||
Pattern('/mnt/lvolume1/subdir'),
|
||||
Pattern('/mnt/lvolume1/subdir/.cache', Pattern_type.EXCLUDE),
|
||||
),
|
||||
),
|
||||
module.Logical_volume(
|
||||
name='lvolume2',
|
||||
@@ -75,6 +82,9 @@ def test_dump_data_sources_snapshots_and_mounts_and_updates_patterns():
|
||||
|
||||
assert patterns == [
|
||||
Pattern('/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume1/subdir'),
|
||||
Pattern(
|
||||
'/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume1/subdir/.cache', Pattern_type.EXCLUDE
|
||||
),
|
||||
Pattern('/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume1/subdir', Pattern_type.INCLUDE),
|
||||
Pattern('/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume2'),
|
||||
Pattern('/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume2', Pattern_type.INCLUDE),
|
||||
|
||||
@@ -450,6 +450,9 @@ def test_dump_data_sources_snapshots_each_subvolume_and_replaces_patterns():
|
||||
'/mnt/subvol2',
|
||||
object,
|
||||
).and_return(Pattern('/mnt/subvol2/.borgmatic-snapshot-1234/mnt/subvol2'))
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).and_return(0)
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').with_args(
|
||||
object,
|
||||
Pattern('/mnt/subvol1'),
|
||||
@@ -457,6 +460,7 @@ def test_dump_data_sources_snapshots_each_subvolume_and_replaces_patterns():
|
||||
'/mnt/subvol1/.borgmatic-snapshot-1234/mnt/subvol1',
|
||||
source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
|
||||
),
|
||||
0,
|
||||
).once()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').with_args(
|
||||
object,
|
||||
@@ -465,6 +469,7 @@ def test_dump_data_sources_snapshots_each_subvolume_and_replaces_patterns():
|
||||
'/mnt/subvol2/.borgmatic-snapshot-1234/mnt/subvol2',
|
||||
source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
|
||||
),
|
||||
0,
|
||||
).once()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('inject_pattern').with_args(
|
||||
object,
|
||||
@@ -527,6 +532,9 @@ def test_dump_data_sources_uses_custom_btrfs_command_in_commands():
|
||||
'/mnt/subvol1',
|
||||
object,
|
||||
).and_return(Pattern('/mnt/subvol1/.borgmatic-snapshot-1234/mnt/subvol1'))
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).and_return(0)
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').with_args(
|
||||
object,
|
||||
Pattern('/mnt/subvol1'),
|
||||
@@ -534,6 +542,7 @@ def test_dump_data_sources_uses_custom_btrfs_command_in_commands():
|
||||
'/mnt/subvol1/.borgmatic-snapshot-1234/mnt/subvol1',
|
||||
source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
|
||||
),
|
||||
0,
|
||||
).once()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('inject_pattern').with_args(
|
||||
object,
|
||||
@@ -594,6 +603,9 @@ def test_dump_data_sources_with_findmnt_command_warns():
|
||||
'/mnt/subvol1',
|
||||
object,
|
||||
).and_return(Pattern('/mnt/subvol1/.borgmatic-snapshot-1234/mnt/subvol1'))
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).and_return(0)
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').with_args(
|
||||
object,
|
||||
Pattern('/mnt/subvol1'),
|
||||
@@ -601,6 +613,7 @@ def test_dump_data_sources_with_findmnt_command_warns():
|
||||
'/mnt/subvol1/.borgmatic-snapshot-1234/mnt/subvol1',
|
||||
source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
|
||||
),
|
||||
0,
|
||||
).once()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('inject_pattern').with_args(
|
||||
object,
|
||||
@@ -641,6 +654,9 @@ def test_dump_data_sources_with_dry_run_skips_snapshot_and_patterns_update():
|
||||
)
|
||||
flexmock(module).should_receive('snapshot_subvolume').never()
|
||||
flexmock(module).should_receive('make_snapshot_exclude_pattern').never()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).never()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').never()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('inject_pattern').never()
|
||||
|
||||
@@ -666,6 +682,9 @@ def test_dump_data_sources_without_matching_subvolumes_skips_snapshot_and_patter
|
||||
flexmock(module).should_receive('make_snapshot_path').never()
|
||||
flexmock(module).should_receive('snapshot_subvolume').never()
|
||||
flexmock(module).should_receive('make_snapshot_exclude_pattern').never()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).never()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').never()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('inject_pattern').never()
|
||||
|
||||
|
||||
@@ -203,6 +203,52 @@ def test_inject_pattern_with_root_pattern_prepends_it_along_with_corresponding_i
|
||||
]
|
||||
|
||||
|
||||
def test_get_last_pattern_index_with_ordered_subset_patterns_finds_last_one():
|
||||
patterns = [
|
||||
module.borgmatic.borg.pattern.Pattern('/foo'),
|
||||
module.borgmatic.borg.pattern.Pattern('/bar'),
|
||||
module.borgmatic.borg.pattern.Pattern('/baz'),
|
||||
module.borgmatic.borg.pattern.Pattern('/quux'),
|
||||
]
|
||||
patterns_subset = [
|
||||
module.borgmatic.borg.pattern.Pattern('/bar'),
|
||||
module.borgmatic.borg.pattern.Pattern('/baz'),
|
||||
]
|
||||
|
||||
assert module.get_last_pattern_index(patterns, patterns_subset) == 2
|
||||
|
||||
|
||||
def test_get_last_pattern_index_with_unordered_subset_patterns_finds_last_one():
|
||||
patterns = [
|
||||
module.borgmatic.borg.pattern.Pattern('/foo'),
|
||||
module.borgmatic.borg.pattern.Pattern('/bar'),
|
||||
module.borgmatic.borg.pattern.Pattern('/baz'),
|
||||
module.borgmatic.borg.pattern.Pattern('/quux'),
|
||||
]
|
||||
patterns_subset = [
|
||||
module.borgmatic.borg.pattern.Pattern('/baz'),
|
||||
module.borgmatic.borg.pattern.Pattern('/bar'),
|
||||
]
|
||||
|
||||
assert module.get_last_pattern_index(patterns, patterns_subset) == 2
|
||||
|
||||
|
||||
def test_get_last_pattern_index_with_unknown_subset_patterns_skips_it():
|
||||
patterns = [
|
||||
module.borgmatic.borg.pattern.Pattern('/foo'),
|
||||
module.borgmatic.borg.pattern.Pattern('/bar'),
|
||||
module.borgmatic.borg.pattern.Pattern('/baz'),
|
||||
module.borgmatic.borg.pattern.Pattern('/quux'),
|
||||
]
|
||||
patterns_subset = [
|
||||
module.borgmatic.borg.pattern.Pattern('/baz'),
|
||||
module.borgmatic.borg.pattern.Pattern('/unknown'),
|
||||
module.borgmatic.borg.pattern.Pattern('/bar'),
|
||||
]
|
||||
|
||||
assert module.get_last_pattern_index(patterns, patterns_subset) == 2
|
||||
|
||||
|
||||
def test_replace_pattern_swaps_out_pattern_in_place():
|
||||
patterns = [
|
||||
module.borgmatic.borg.pattern.Pattern('/etc'),
|
||||
@@ -217,6 +263,7 @@ def test_replace_pattern_swaps_out_pattern_in_place():
|
||||
'/foo/bar',
|
||||
type=module.borgmatic.borg.pattern.Pattern_type.EXCLUDE,
|
||||
),
|
||||
0,
|
||||
)
|
||||
|
||||
assert patterns == [
|
||||
@@ -243,6 +290,7 @@ def test_replace_pattern_with_unknown_pattern_falls_back_to_injecting():
|
||||
patterns,
|
||||
module.borgmatic.borg.pattern.Pattern('/unknown'),
|
||||
module.borgmatic.borg.pattern.Pattern('/foo/bar'),
|
||||
0,
|
||||
)
|
||||
|
||||
|
||||
@@ -251,20 +299,23 @@ def test_replace_pattern_with_root_pattern_swaps_it_in_along_with_corresponding_
|
||||
module.borgmatic.borg.pattern.Pattern('/etc'),
|
||||
module.borgmatic.borg.pattern.Pattern('/var'),
|
||||
module.borgmatic.borg.pattern.Pattern('/lib'),
|
||||
module.borgmatic.borg.pattern.Pattern('/run'),
|
||||
]
|
||||
|
||||
module.replace_pattern(
|
||||
patterns,
|
||||
module.borgmatic.borg.pattern.Pattern('/var'),
|
||||
module.borgmatic.borg.pattern.Pattern('/foo/bar'),
|
||||
2,
|
||||
)
|
||||
|
||||
assert patterns == [
|
||||
module.borgmatic.borg.pattern.Pattern('/etc'),
|
||||
module.borgmatic.borg.pattern.Pattern('/foo/bar'),
|
||||
module.borgmatic.borg.pattern.Pattern('/lib'),
|
||||
module.borgmatic.borg.pattern.Pattern(
|
||||
'/foo/bar',
|
||||
type=module.borgmatic.borg.pattern.Pattern_type.INCLUDE,
|
||||
),
|
||||
module.borgmatic.borg.pattern.Pattern('/lib'),
|
||||
module.borgmatic.borg.pattern.Pattern('/run'),
|
||||
]
|
||||
|
||||
@@ -360,6 +360,9 @@ def test_dump_data_sources_snapshots_and_mounts_and_replaces_patterns():
|
||||
logical_volumes[1],
|
||||
'/run/borgmatic',
|
||||
).and_return(Pattern('/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume2'))
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).and_return(0)
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').with_args(
|
||||
object,
|
||||
Pattern('/mnt/lvolume1/subdir'),
|
||||
@@ -367,6 +370,7 @@ def test_dump_data_sources_snapshots_and_mounts_and_replaces_patterns():
|
||||
'/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume1/subdir',
|
||||
source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
|
||||
),
|
||||
0,
|
||||
).once()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').with_args(
|
||||
object,
|
||||
@@ -375,6 +379,7 @@ def test_dump_data_sources_snapshots_and_mounts_and_replaces_patterns():
|
||||
'/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume2',
|
||||
source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
|
||||
),
|
||||
0,
|
||||
).once()
|
||||
|
||||
assert (
|
||||
@@ -396,6 +401,9 @@ def test_dump_data_sources_with_no_logical_volumes_skips_snapshots():
|
||||
flexmock(module).should_receive('get_logical_volumes').and_return(())
|
||||
flexmock(module).should_receive('snapshot_logical_volume').never()
|
||||
flexmock(module).should_receive('mount_snapshot').never()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).and_return(0)
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').never()
|
||||
|
||||
assert (
|
||||
@@ -477,6 +485,9 @@ def test_dump_data_sources_uses_snapshot_size_for_snapshot():
|
||||
logical_volumes[1],
|
||||
'/run/borgmatic',
|
||||
).and_return(Pattern('/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume2'))
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).and_return(0)
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').with_args(
|
||||
object,
|
||||
Pattern('/mnt/lvolume1/subdir'),
|
||||
@@ -484,6 +495,7 @@ def test_dump_data_sources_uses_snapshot_size_for_snapshot():
|
||||
'/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume1/subdir',
|
||||
source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
|
||||
),
|
||||
0,
|
||||
).once()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').with_args(
|
||||
object,
|
||||
@@ -492,6 +504,7 @@ def test_dump_data_sources_uses_snapshot_size_for_snapshot():
|
||||
'/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume2',
|
||||
source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
|
||||
),
|
||||
0,
|
||||
).once()
|
||||
|
||||
assert (
|
||||
@@ -580,6 +593,9 @@ def test_dump_data_sources_uses_custom_commands():
|
||||
logical_volumes[1],
|
||||
'/run/borgmatic',
|
||||
).and_return(Pattern('/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume2'))
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).and_return(0)
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').with_args(
|
||||
object,
|
||||
Pattern('/mnt/lvolume1/subdir'),
|
||||
@@ -587,6 +603,7 @@ def test_dump_data_sources_uses_custom_commands():
|
||||
'/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume1/subdir',
|
||||
source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
|
||||
),
|
||||
0,
|
||||
).once()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').with_args(
|
||||
object,
|
||||
@@ -595,6 +612,7 @@ def test_dump_data_sources_uses_custom_commands():
|
||||
'/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume2',
|
||||
source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
|
||||
),
|
||||
0,
|
||||
).once()
|
||||
|
||||
assert (
|
||||
@@ -633,6 +651,9 @@ def test_dump_data_sources_with_dry_run_skips_snapshots_and_does_not_touch_patte
|
||||
flexmock(module).should_receive('snapshot_logical_volume').never()
|
||||
flexmock(module).should_receive('get_snapshots').never()
|
||||
flexmock(module).should_receive('mount_snapshot').never()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).never()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').never()
|
||||
|
||||
assert (
|
||||
@@ -714,6 +735,9 @@ def test_dump_data_sources_ignores_mismatch_between_given_patterns_and_contained
|
||||
logical_volumes[1],
|
||||
'/run/borgmatic',
|
||||
).and_return(Pattern('/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume2'))
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).and_return(0)
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').with_args(
|
||||
object,
|
||||
Pattern('/mnt/lvolume1/subdir'),
|
||||
@@ -721,6 +745,7 @@ def test_dump_data_sources_ignores_mismatch_between_given_patterns_and_contained
|
||||
'/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume1/subdir',
|
||||
source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
|
||||
),
|
||||
0,
|
||||
).once()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').with_args(
|
||||
object,
|
||||
@@ -729,6 +754,7 @@ def test_dump_data_sources_ignores_mismatch_between_given_patterns_and_contained
|
||||
'/run/borgmatic/lvm_snapshots/b33f/./mnt/lvolume2',
|
||||
source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
|
||||
),
|
||||
0,
|
||||
).once()
|
||||
|
||||
assert (
|
||||
@@ -785,6 +811,9 @@ def test_dump_data_sources_with_missing_snapshot_errors():
|
||||
snapshot_name='lvolume2_borgmatic-1234',
|
||||
).never()
|
||||
flexmock(module).should_receive('mount_snapshot').never()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).never()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').never()
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
|
||||
@@ -328,6 +328,9 @@ def test_dump_data_sources_snapshots_and_mounts_and_replaces_patterns():
|
||||
'/run/borgmatic',
|
||||
).and_return(Pattern('/run/borgmatic/zfs_snapshots/b33f/./mnt/dataset/subdir'))
|
||||
patterns = [Pattern('/mnt/dataset/subdir')]
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).and_return(0)
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').with_args(
|
||||
object,
|
||||
Pattern('/mnt/dataset/subdir'),
|
||||
@@ -335,6 +338,7 @@ def test_dump_data_sources_snapshots_and_mounts_and_replaces_patterns():
|
||||
'/run/borgmatic/zfs_snapshots/b33f/./mnt/dataset/subdir',
|
||||
source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
|
||||
),
|
||||
0,
|
||||
).once()
|
||||
|
||||
assert (
|
||||
@@ -355,6 +359,9 @@ def test_dump_data_sources_with_no_datasets_skips_snapshots():
|
||||
flexmock(module.os).should_receive('getpid').and_return(1234)
|
||||
flexmock(module).should_receive('snapshot_dataset').never()
|
||||
flexmock(module).should_receive('mount_snapshot').never()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).never()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').never()
|
||||
patterns = [Pattern('/mnt/dataset')]
|
||||
|
||||
@@ -400,6 +407,9 @@ def test_dump_data_sources_uses_custom_commands():
|
||||
dataset,
|
||||
'/run/borgmatic',
|
||||
).and_return(Pattern('/run/borgmatic/zfs_snapshots/b33f/./mnt/dataset/subdir'))
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).and_return(0)
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').with_args(
|
||||
object,
|
||||
Pattern('/mnt/dataset/subdir'),
|
||||
@@ -407,6 +417,7 @@ def test_dump_data_sources_uses_custom_commands():
|
||||
'/run/borgmatic/zfs_snapshots/b33f/./mnt/dataset/subdir',
|
||||
source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
|
||||
),
|
||||
0,
|
||||
).once()
|
||||
patterns = [Pattern('/mnt/dataset/subdir')]
|
||||
hook_config = {
|
||||
@@ -437,6 +448,9 @@ def test_dump_data_sources_with_dry_run_skips_commands_and_does_not_touch_patter
|
||||
flexmock(module.os).should_receive('getpid').and_return(1234)
|
||||
flexmock(module).should_receive('snapshot_dataset').never()
|
||||
flexmock(module).should_receive('mount_snapshot').never()
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).and_return(0)
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').never()
|
||||
patterns = [Pattern('/mnt/dataset')]
|
||||
|
||||
@@ -480,6 +494,9 @@ def test_dump_data_sources_ignores_mismatch_between_given_patterns_and_contained
|
||||
dataset,
|
||||
'/run/borgmatic',
|
||||
).and_return(Pattern('/run/borgmatic/zfs_snapshots/b33f/./mnt/dataset/subdir'))
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive(
|
||||
'get_last_pattern_index'
|
||||
).and_return(0)
|
||||
flexmock(module.borgmatic.hooks.data_source.config).should_receive('replace_pattern').with_args(
|
||||
object,
|
||||
Pattern('/mnt/dataset/subdir'),
|
||||
@@ -487,6 +504,7 @@ def test_dump_data_sources_ignores_mismatch_between_given_patterns_and_contained
|
||||
'/run/borgmatic/zfs_snapshots/b33f/./mnt/dataset/subdir',
|
||||
source=module.borgmatic.borg.pattern.Pattern_source.HOOK,
|
||||
),
|
||||
0,
|
||||
).once()
|
||||
patterns = [Pattern('/hmm')]
|
||||
|
||||
|
||||
Reference in New Issue
Block a user