Add support for a database backup label instead of host:port (#1116)

This commit is contained in:
Florian Apolloner
2025-09-15 20:02:31 +02:00
parent 000d633590
commit c084f10fe2
10 changed files with 64 additions and 21 deletions
+1
View File
@@ -1,4 +1,5 @@
2.0.8.dev0
* #1116: Add support for database backup labels.
* #1114: Document systemd configuration changes for the ZFS filesystem hook.
* #1118: Fix a bug in which Borg hangs during database backup when different filesystems are in
use.
+25
View File
@@ -1323,6 +1323,11 @@ properties:
implicitly enables read_special (see above) to support
dump and restore streaming.
example: users
label:
type: string
description: |
Label to identify the database dump in the backup.
example: my_backup_label
hostname:
type: string
description: |
@@ -1524,6 +1529,11 @@ properties:
database hook implicitly enables read_special (see
above) to support dump and restore streaming.
example: users
label:
type: string
description: |
Label to identify the database dump in the backup.
example: my_backup_label
hostname:
type: string
description: |
@@ -1689,6 +1699,11 @@ properties:
database hook implicitly enables read_special (see
above) to support dump and restore streaming.
example: users
label:
type: string
description: |
Label to identify the database dump in the backup.
example: my_backup_label
hostname:
type: string
description: |
@@ -1862,6 +1877,11 @@ properties:
read_special (see above) to support dump and restore
streaming.
example: /var/lib/sqlite/users.db
label:
type: string
description: |
Label to identify the database dump in the backup.
example: my_backup_label
restore_path:
type: string
description: |
@@ -1910,6 +1930,11 @@ properties:
database hook implicitly enables read_special (see
above) to support dump and restore streaming.
example: users
label:
type: string
description: |
Label to identify the database dump in the backup.
example: my_backup_label
hostname:
type: string
description: |
+5 -5
View File
@@ -19,7 +19,7 @@ def make_data_source_dump_path(borgmatic_runtime_directory, data_source_hook_nam
return os.path.join(borgmatic_runtime_directory, data_source_hook_name)
def make_data_source_dump_filename(dump_path, name, hostname=None, port=None):
def make_data_source_dump_filename(dump_path, name, hostname=None, port=None, label=None):
'''
Based on the given dump directory path, data source name, hostname, and port, return a filename
to use for the data source dump. The hostname defaults to localhost.
@@ -29,12 +29,12 @@ def make_data_source_dump_filename(dump_path, name, hostname=None, port=None):
if os.path.sep in name:
raise ValueError(f'Invalid data source name {name}')
return os.path.join(
dump_path,
(hostname or 'localhost') + ('' if port is None else f':{port}'),
name,
identifier = (
label if label else (hostname or 'localhost') + ('' if port is None else f':{port}')
)
return os.path.join(dump_path, identifier, name)
def write_data_source_dumps_metadata(borgmatic_runtime_directory, hook_name, dumps_metadata):
'''
+4 -3
View File
@@ -178,6 +178,7 @@ def execute_dump_command(
database['name'],
database.get('hostname'),
database.get('port'),
database.get('label'),
)
if os.path.exists(dump_filename):
@@ -384,16 +385,16 @@ def make_data_source_dump_patterns(
borgmatic_source_directory = borgmatic.config.paths.get_borgmatic_source_directory(config)
return (
dump.make_data_source_dump_filename(make_dump_path('borgmatic'), name, hostname='*'),
dump.make_data_source_dump_filename(make_dump_path('borgmatic'), name, label='*'),
dump.make_data_source_dump_filename(
make_dump_path(borgmatic_runtime_directory),
name,
hostname='*',
label='*',
),
dump.make_data_source_dump_filename(
make_dump_path(borgmatic_source_directory),
name,
hostname='*',
label='*',
),
)
+5 -3
View File
@@ -71,6 +71,7 @@ def dump_data_sources(
name,
database.get('hostname'),
database.get('port'),
database.get('label'),
)
dump_format = database.get('format', 'archive')
@@ -200,16 +201,16 @@ def make_data_source_dump_patterns(
borgmatic_source_directory = borgmatic.config.paths.get_borgmatic_source_directory(config)
return (
dump.make_data_source_dump_filename(make_dump_path('borgmatic'), name, hostname='*'),
dump.make_data_source_dump_filename(make_dump_path('borgmatic'), name, label='*'),
dump.make_data_source_dump_filename(
make_dump_path(borgmatic_runtime_directory),
name,
hostname='*',
label='*',
),
dump.make_data_source_dump_filename(
make_dump_path(borgmatic_source_directory),
name,
hostname='*',
label='*',
),
)
@@ -238,6 +239,7 @@ def restore_data_source_dump(
make_dump_path(borgmatic_runtime_directory),
data_source['name'],
data_source.get('hostname'),
data_source.get('label'),
)
restore_command = build_restore_command(
extract_process,
+4 -3
View File
@@ -104,6 +104,7 @@ def execute_dump_command(
database['name'],
database.get('hostname'),
database.get('port'),
database.get('label'),
)
if os.path.exists(dump_filename):
@@ -315,16 +316,16 @@ def make_data_source_dump_patterns(
borgmatic_source_directory = borgmatic.config.paths.get_borgmatic_source_directory(config)
return (
dump.make_data_source_dump_filename(make_dump_path('borgmatic'), name, hostname='*'),
dump.make_data_source_dump_filename(make_dump_path('borgmatic'), name, label='*'),
dump.make_data_source_dump_filename(
make_dump_path(borgmatic_runtime_directory),
name,
hostname='*',
label='*',
),
dump.make_data_source_dump_filename(
make_dump_path(borgmatic_source_directory),
name,
hostname='*',
label='*',
),
)
+5 -3
View File
@@ -186,6 +186,7 @@ def dump_data_sources(
database_name,
database.get('hostname'),
database.get('port'),
database.get('label'),
)
if os.path.exists(dump_filename):
@@ -302,16 +303,16 @@ def make_data_source_dump_patterns(
borgmatic_source_directory = borgmatic.config.paths.get_borgmatic_source_directory(config)
return (
dump.make_data_source_dump_filename(make_dump_path('borgmatic'), name, hostname='*'),
dump.make_data_source_dump_filename(make_dump_path('borgmatic'), name, label='*'),
dump.make_data_source_dump_filename(
make_dump_path(borgmatic_runtime_directory),
name,
hostname='*',
label='*',
),
dump.make_data_source_dump_filename(
make_dump_path(borgmatic_source_directory),
name,
hostname='*',
label='*',
),
)
@@ -359,6 +360,7 @@ def restore_data_source_dump(
make_dump_path(borgmatic_runtime_directory),
data_source['name'],
data_source.get('hostname'),
data_source.get('label'),
)
psql_command = tuple(
shlex.quote(part) for part in shlex.split(data_source.get('psql_command') or 'psql')
+6 -4
View File
@@ -71,7 +71,9 @@ def dump_data_sources(
)
dump_path = make_dump_path(borgmatic_runtime_directory)
dump_filename = dump.make_data_source_dump_filename(dump_path, database['name'])
dump_filename = dump.make_data_source_dump_filename(
dump_path, database['name'], label=database.get('label')
)
if os.path.exists(dump_filename):
logger.warning(
@@ -143,16 +145,16 @@ def make_data_source_dump_patterns(
borgmatic_source_directory = borgmatic.config.paths.get_borgmatic_source_directory(config)
return (
dump.make_data_source_dump_filename(make_dump_path('borgmatic'), name, hostname='*'),
dump.make_data_source_dump_filename(make_dump_path('borgmatic'), name, label='*'),
dump.make_data_source_dump_filename(
make_dump_path(borgmatic_runtime_directory),
name,
hostname='*',
label='*',
),
dump.make_data_source_dump_filename(
make_dump_path(borgmatic_source_directory),
name,
hostname='*',
label='*',
),
)
+2
View File
@@ -72,8 +72,10 @@ Here's a more involved example that connects to remote databases:
```yaml
postgresql_databases:
- name: users
label: database_server1
hostname: database1.example.org
- name: orders
label: database_server2
hostname: database2.example.org
port: 5433
username: postgres
@@ -25,6 +25,13 @@ def test_make_data_source_dump_filename_uses_name_and_hostname_and_port():
)
def test_make_data_source_dump_filename_users_label():
assert (
module.make_data_source_dump_filename('databases', 'test', 'hostname', 1234, 'custom_label')
== 'databases/custom_label/test'
)
def test_make_data_source_dump_filename_without_hostname_defaults_to_localhost():
assert module.make_data_source_dump_filename('databases', 'test') == 'databases/localhost/test'