Fix findmnt command error in the Btrfs hook by switching to parsing JSON output (#954).
This commit is contained in:
parent
cb7f98192c
commit
ebb3bca4b3
3
NEWS
3
NEWS
@ -1,3 +1,6 @@
|
||||
1.9.5.dev0
|
||||
* #954: Fix findmnt command error in the Btrfs hook by switching to parsing JSON output.
|
||||
|
||||
1.9.4
|
||||
* #80 (beta): Add an LVM hook for snapshotting and backing up LVM logical volumes. See the
|
||||
documentation for more information:
|
||||
|
@ -1,5 +1,6 @@
|
||||
import collections
|
||||
import glob
|
||||
import json
|
||||
import logging
|
||||
import os
|
||||
import shutil
|
||||
@ -26,13 +27,21 @@ def get_filesystem_mount_points(findmnt_command):
|
||||
findmnt_output = borgmatic.execute.execute_command_and_capture_output(
|
||||
tuple(findmnt_command.split(' '))
|
||||
+ (
|
||||
'-n', # No headings.
|
||||
'-t', # Filesystem type.
|
||||
'btrfs',
|
||||
'--json',
|
||||
'--list', # Request a flat list instead of a nested subvolume hierarchy.
|
||||
)
|
||||
)
|
||||
|
||||
return tuple(line.rstrip().split(' ')[0] for line in findmnt_output.splitlines())
|
||||
try:
|
||||
return tuple(
|
||||
filesystem['target'] for filesystem in json.loads(findmnt_output)['filesystems']
|
||||
)
|
||||
except json.JSONDecodeError as error:
|
||||
raise ValueError(f'Invalid {findmnt_command} JSON output: {error}')
|
||||
except KeyError as error:
|
||||
raise ValueError(f'Invalid {findmnt_command} output: Missing key "{error}"')
|
||||
|
||||
|
||||
def get_subvolumes_for_filesystem(btrfs_command, filesystem_mount_point):
|
||||
|
@ -1,6 +1,6 @@
|
||||
[project]
|
||||
name = "borgmatic"
|
||||
version = "1.9.4"
|
||||
version = "1.9.5.dev0"
|
||||
authors = [
|
||||
{ name="Dan Helfman", email="witten@torsion.org" },
|
||||
]
|
||||
|
@ -4,29 +4,38 @@ import sys
|
||||
|
||||
def parse_arguments(*unparsed_arguments):
|
||||
parser = argparse.ArgumentParser(add_help=False)
|
||||
parser.add_argument('-n', dest='headings', action='store_false', default=True)
|
||||
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_LINES = (
|
||||
'/mnt/subvolume /dev/loop1 btrfs rw,relatime,ssd,space_cache=v2,subvolid=5,subvol=/',
|
||||
)
|
||||
BUILTIN_FILESYSTEM_MOUNT_OUTPUT = '''{
|
||||
"filesystems": [
|
||||
{
|
||||
"target": "/mnt/subvolume",
|
||||
"source": "/dev/loop0",
|
||||
"fstype": "btrfs",
|
||||
"options": "rw,relatime,ssd,space_cache=v2,subvolid=5,subvol=/"
|
||||
}
|
||||
]
|
||||
}
|
||||
'''
|
||||
|
||||
|
||||
def print_filesystem_mounts(arguments):
|
||||
for line in BUILTIN_FILESYSTEM_MOUNT_LINES:
|
||||
print(line)
|
||||
def print_filesystem_mounts():
|
||||
print(BUILTIN_FILESYSTEM_MOUNT_OUTPUT)
|
||||
|
||||
|
||||
def main():
|
||||
arguments = parse_arguments(*sys.argv[1:])
|
||||
|
||||
assert not arguments.headings
|
||||
assert arguments.type == 'btrfs'
|
||||
assert arguments.json
|
||||
assert arguments.list
|
||||
|
||||
print_filesystem_mounts(arguments)
|
||||
print_filesystem_mounts()
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
@ -1,3 +1,4 @@
|
||||
import pytest
|
||||
from flexmock import flexmock
|
||||
|
||||
from borgmatic.hooks.data_source import btrfs as module
|
||||
@ -7,13 +8,46 @@ def test_get_filesystem_mount_points_parses_findmnt_output():
|
||||
flexmock(module.borgmatic.execute).should_receive(
|
||||
'execute_command_and_capture_output'
|
||||
).and_return(
|
||||
'/mnt0 /dev/loop0 btrfs rw,relatime,ssd,space_cache=v2,subvolid=5,subvol=/\n'
|
||||
'/mnt1 /dev/loop1 btrfs rw,relatime,ssd,space_cache=v2,subvolid=5,subvol=/\n'
|
||||
'''{
|
||||
"filesystems": [
|
||||
{
|
||||
"target": "/mnt0",
|
||||
"source": "/dev/loop0",
|
||||
"fstype": "btrfs",
|
||||
"options": "rw,relatime,ssd,space_cache=v2,subvolid=5,subvol=/"
|
||||
},
|
||||
{
|
||||
"target": "/mnt1",
|
||||
"source": "/dev/loop0",
|
||||
"fstype": "btrfs",
|
||||
"options": "rw,relatime,ssd,space_cache=v2,subvolid=5,subvol=/"
|
||||
}
|
||||
]
|
||||
}
|
||||
'''
|
||||
)
|
||||
|
||||
assert module.get_filesystem_mount_points('findmnt') == ('/mnt0', '/mnt1')
|
||||
|
||||
|
||||
def test_get_filesystem_mount_points_with_invalid_findmnt_json_errors():
|
||||
flexmock(module.borgmatic.execute).should_receive(
|
||||
'execute_command_and_capture_output'
|
||||
).and_return('{')
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.get_filesystem_mount_points('findmnt')
|
||||
|
||||
|
||||
def test_get_filesystem_mount_points_with_findmnt_json_missing_filesystems_errors():
|
||||
flexmock(module.borgmatic.execute).should_receive(
|
||||
'execute_command_and_capture_output'
|
||||
).and_return('{"wtf": "something is wrong here"}')
|
||||
|
||||
with pytest.raises(ValueError):
|
||||
module.get_filesystem_mount_points('findmnt')
|
||||
|
||||
|
||||
def test_get_subvolumes_for_filesystem_parses_subvolume_list_output():
|
||||
flexmock(module.borgmatic.execute).should_receive(
|
||||
'execute_command_and_capture_output'
|
||||
|
Loading…
x
Reference in New Issue
Block a user