mirror of
https://github.com/borgmatic-collective/borgmatic.git
synced 2026-08-07 00:23:20 +02:00
For the MariaDB and MySQL database hooks, add a "skip_names" option to ignore particular databases when dumping "all" (#973).
This commit is contained in:
@@ -1,6 +1,8 @@
|
||||
2.0.10.dev0
|
||||
* #942: Factor reference material out of the documentation how-to guides. This means there's now a
|
||||
whole reference section in the docs! Check it out: https://torsion.org/borgmatic/
|
||||
* #973: For the MariaDB and MySQL database hooks, add a "skip_names" option to ignore particular
|
||||
databases when dumping "all".
|
||||
* #1150: Fix for a runtime directory error when the "create" action is used with the "--log-json"
|
||||
flag.
|
||||
* #1161: Fix a traceback (TypeError) in the "check" action with Python 3.14.
|
||||
|
||||
@@ -1546,6 +1546,15 @@ properties:
|
||||
database hook implicitly enables read_special (see
|
||||
above) to support dump and restore streaming.
|
||||
example: users
|
||||
skip_names:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: |
|
||||
Database names to skip when dumping "all" databases.
|
||||
Ignored when the database name is not "all".
|
||||
example:
|
||||
- cache
|
||||
label:
|
||||
type: string
|
||||
description: |
|
||||
@@ -1728,6 +1737,15 @@ properties:
|
||||
database hook implicitly enables read_special (see
|
||||
above) to support dump and restore streaming.
|
||||
example: users
|
||||
skip_names:
|
||||
type: array
|
||||
items:
|
||||
type: string
|
||||
description: |
|
||||
Database names to skip when dumping "all" databases.
|
||||
Ignored when the database name is not "all".
|
||||
example:
|
||||
- cache
|
||||
label:
|
||||
type: string
|
||||
description: |
|
||||
|
||||
@@ -112,7 +112,14 @@ def database_names_to_dump(database, config, username, password, environment, dr
|
||||
names to dump. In the case of "all", query for the names of databases on the configured host and
|
||||
return them, excluding any system databases that will cause problems during restore.
|
||||
'''
|
||||
skip_names = database.get('skip_names')
|
||||
|
||||
if database['name'] != 'all':
|
||||
if skip_names:
|
||||
logger.warning(
|
||||
f'For MariaDB database {database["name"]}, ignoring the "skip_names" option, which is only supported for database "all"'
|
||||
)
|
||||
|
||||
return (database['name'],)
|
||||
|
||||
if dry_run:
|
||||
@@ -144,12 +151,16 @@ def database_names_to_dump(database, config, username, password, environment, dr
|
||||
|
||||
logger.debug('Querying for "all" MariaDB databases to dump')
|
||||
|
||||
if skip_names:
|
||||
logger.debug(f'Skipping database names: {", ".join(skip_names)}')
|
||||
|
||||
show_output = execute_command_and_capture_output(show_command, environment=environment)
|
||||
|
||||
return tuple(
|
||||
show_name
|
||||
for show_name in show_output.strip().splitlines()
|
||||
if show_name not in SYSTEM_DATABASE_NAMES
|
||||
if not skip_names or show_name not in skip_names
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -35,7 +35,14 @@ def database_names_to_dump(database, config, username, password, environment, dr
|
||||
names to dump. In the case of "all", query for the names of databases on the configured host and
|
||||
return them, excluding any system databases that will cause problems during restore.
|
||||
'''
|
||||
skip_names = database.get('skip_names')
|
||||
|
||||
if database['name'] != 'all':
|
||||
if skip_names:
|
||||
logger.warning(
|
||||
f'For MySQL database {database["name"]}, ignoring the "skip_names" option, which is only supported for database "all"'
|
||||
)
|
||||
|
||||
return (database['name'],)
|
||||
|
||||
if dry_run:
|
||||
@@ -73,12 +80,16 @@ def database_names_to_dump(database, config, username, password, environment, dr
|
||||
|
||||
logger.debug('Querying for "all" MySQL databases to dump')
|
||||
|
||||
if skip_names:
|
||||
logger.debug(f'Skipping database names: {", ".join(skip_names)}')
|
||||
|
||||
show_output = execute_command_and_capture_output(show_command, environment=environment)
|
||||
|
||||
return tuple(
|
||||
show_name
|
||||
for show_name in show_output.strip().splitlines()
|
||||
if show_name not in SYSTEM_DATABASE_NAMES
|
||||
if not skip_names or show_name not in skip_names
|
||||
)
|
||||
|
||||
|
||||
|
||||
@@ -142,6 +142,23 @@ def test_database_names_to_dump_passes_through_name():
|
||||
assert names == ('foo',)
|
||||
|
||||
|
||||
def test_database_names_to_dump_with_non_all_name_and_skip_names_warns():
|
||||
environment = flexmock()
|
||||
|
||||
flexmock(module.logger).should_receive('warning').once()
|
||||
|
||||
names = module.database_names_to_dump(
|
||||
{'name': 'foo', 'skip_names': ('foo', 'bar')},
|
||||
{},
|
||||
'root',
|
||||
'trustsome1',
|
||||
environment,
|
||||
dry_run=False,
|
||||
)
|
||||
|
||||
assert names == ('foo',)
|
||||
|
||||
|
||||
def test_database_names_to_dump_bails_for_dry_run():
|
||||
environment = flexmock()
|
||||
flexmock(module).should_receive('execute_command_and_capture_output').never()
|
||||
@@ -193,6 +210,41 @@ def test_database_names_to_dump_queries_mariadb_for_database_names():
|
||||
assert names == ('foo', 'bar')
|
||||
|
||||
|
||||
def test_database_names_to_dump_with_database_name_all_and_skip_names_filters_out_unwanted_databases():
|
||||
environment = flexmock()
|
||||
flexmock(module.borgmatic.hooks.credential.parse).should_receive(
|
||||
'resolve_credential',
|
||||
).replace_with(lambda value, config: value)
|
||||
flexmock(module).should_receive('parse_extra_options').and_return((), None)
|
||||
flexmock(module).should_receive('make_defaults_file_options').with_args(
|
||||
'root',
|
||||
'trustsome1',
|
||||
None,
|
||||
).and_return(('--defaults-extra-file=/dev/fd/99',))
|
||||
flexmock(module).should_receive('execute_command_and_capture_output').with_args(
|
||||
(
|
||||
'mariadb',
|
||||
'--defaults-extra-file=/dev/fd/99',
|
||||
'--skip-column-names',
|
||||
'--batch',
|
||||
'--execute',
|
||||
'show schemas',
|
||||
),
|
||||
environment=environment,
|
||||
).and_return('foo\nbar\nbaz\nmysql\n').once()
|
||||
|
||||
names = module.database_names_to_dump(
|
||||
{'name': 'all', 'skip_names': ('foo', 'bar')},
|
||||
{},
|
||||
'root',
|
||||
'trustsome1',
|
||||
environment,
|
||||
dry_run=False,
|
||||
)
|
||||
|
||||
assert names == ('baz',)
|
||||
|
||||
|
||||
def test_database_names_to_dump_with_environment_password_transport_skips_defaults_file_and_passes_user_flag():
|
||||
environment = flexmock()
|
||||
flexmock(module.borgmatic.hooks.credential.parse).should_receive(
|
||||
|
||||
@@ -21,6 +21,23 @@ def test_database_names_to_dump_passes_through_name():
|
||||
assert names == ('foo',)
|
||||
|
||||
|
||||
def test_database_names_to_dump_with_non_all_name_and_skip_names_warns():
|
||||
environment = flexmock()
|
||||
|
||||
flexmock(module.logger).should_receive('warning').once()
|
||||
|
||||
names = module.database_names_to_dump(
|
||||
{'name': 'foo', 'skip_names': ('foo', 'bar')},
|
||||
{},
|
||||
'root',
|
||||
'trustsome1',
|
||||
environment,
|
||||
dry_run=False,
|
||||
)
|
||||
|
||||
assert names == ('foo',)
|
||||
|
||||
|
||||
def test_database_names_to_dump_bails_for_dry_run():
|
||||
environment = flexmock()
|
||||
flexmock(module.borgmatic.hooks.credential.parse).should_receive(
|
||||
@@ -75,6 +92,45 @@ def test_database_names_to_dump_queries_mysql_for_database_names():
|
||||
assert names == ('foo', 'bar')
|
||||
|
||||
|
||||
def test_database_names_to_dump_with_database_name_all_and_skip_names_filters_out_unwanted_databases():
|
||||
environment = flexmock()
|
||||
flexmock(module.borgmatic.hooks.credential.parse).should_receive(
|
||||
'resolve_credential',
|
||||
).replace_with(lambda value, config: value)
|
||||
flexmock(module.borgmatic.hooks.data_source.mariadb).should_receive(
|
||||
'parse_extra_options'
|
||||
).and_return((), None)
|
||||
flexmock(module.borgmatic.hooks.data_source.mariadb).should_receive(
|
||||
'make_defaults_file_options'
|
||||
).with_args(
|
||||
'root',
|
||||
'trustsome1',
|
||||
None,
|
||||
).and_return(('--defaults-extra-file=/dev/fd/99',))
|
||||
flexmock(module).should_receive('execute_command_and_capture_output').with_args(
|
||||
(
|
||||
'mysql',
|
||||
'--defaults-extra-file=/dev/fd/99',
|
||||
'--skip-column-names',
|
||||
'--batch',
|
||||
'--execute',
|
||||
'show schemas',
|
||||
),
|
||||
environment=environment,
|
||||
).and_return('foo\nbar\nbaz\nmysql\n').once()
|
||||
|
||||
names = module.database_names_to_dump(
|
||||
{'name': 'all', 'skip_names': ('foo', 'bar')},
|
||||
{},
|
||||
'root',
|
||||
'trustsome1',
|
||||
environment,
|
||||
dry_run=False,
|
||||
)
|
||||
|
||||
assert names == ('baz',)
|
||||
|
||||
|
||||
def test_database_names_to_dump_with_environment_password_transport_skips_defaults_file_and_passes_user_flag():
|
||||
environment = flexmock()
|
||||
flexmock(module.borgmatic.hooks.credential.parse).should_receive(
|
||||
|
||||
Reference in New Issue
Block a user