Move bootstrap manifest file creation into a hook so it can actually clean up after itself.
Some checks failed
build / test (push) Failing after 1m9s
build / docs (push) Has been skipped

This commit is contained in:
Dan Helfman 2024-11-24 16:00:33 -08:00
parent b45b62cd38
commit 689643e5fa
23 changed files with 148 additions and 194 deletions

5
NEWS
View File

@ -1,6 +1,11 @@
1.9.3.dev0
* #261 (beta): Add a ZFS hook for snapshotting and backing up ZFS datasets. See the documentation
for more information: https://torsion.org/borgmatic/docs/how-to/snapshot-your-filesystems/
* After it's stored in a Borg archive, remove the manifest file created in support of
the "bootstrap" action.
* Deprecate the "store_config_files" option at the global scope and move it under the "bootstrap"
hook. See the documentation for more information:
https://torsion.org/borgmatic/docs/how-to/extract-a-backup/#extract-the-configuration-files-used-to-create-an-archive
* Add a "--deleted" flag to the "repo-list" action for listing deleted archives that haven't
yet been compacted (Borg 2 only).

View File

@ -374,7 +374,7 @@ def collect_spot_check_source_paths(
repository_path=repository['path'],
config=config,
source_directories=borgmatic.actions.create.process_source_directories(
config, config_paths=()
config,
),
local_borg_version=local_borg_version,
global_arguments=global_arguments,

View File

@ -1,7 +1,5 @@
import glob
import importlib.metadata
import itertools
import json
import logging
import os
import pathlib
@ -17,32 +15,6 @@ import borgmatic.hooks.dump
logger = logging.getLogger(__name__)
def create_borgmatic_manifest(config, config_paths, borgmatic_runtime_directory, dry_run):
'''
Given a configuration dict, a sequence of config file paths, the borgmatic runtime directory,
and whether this is a dry run, create a borgmatic manifest file to store the paths to the
configuration files used to create the archive.
'''
if dry_run:
return
borgmatic_manifest_path = os.path.join(
borgmatic_runtime_directory, 'bootstrap', 'manifest.json'
)
if not os.path.exists(borgmatic_manifest_path):
os.makedirs(os.path.dirname(borgmatic_manifest_path), exist_ok=True)
with open(borgmatic_manifest_path, 'w') as config_list_file:
json.dump(
{
'borgmatic_version': importlib.metadata.version('borgmatic'),
'config_paths': config_paths,
},
config_list_file,
)
def expand_directory(directory, working_directory):
'''
Given a directory path, expand any tilde (representing a user's home directory) and any globs
@ -146,18 +118,15 @@ def pattern_root_directories(patterns=None):
]
def process_source_directories(config, config_paths, source_directories=None):
def process_source_directories(config, source_directories=None):
'''
Given a sequence of source directories (either in the source_directories argument or, lacking
that, from config) and a sequence of config paths to append, expand and deduplicate the source
directories, returning the result.
that, from config), expand and deduplicate the source directories, returning the result.
'''
working_directory = borgmatic.config.paths.get_working_directory(config)
if source_directories is None:
source_directories = tuple(config.get('source_directories', ())) + (
tuple(config_paths) if config.get('store_config_files', True) else ()
)
source_directories = tuple(config.get('source_directories', ()))
return deduplicate_directories(
map_directories_to_devices(
@ -221,12 +190,13 @@ def run_create(
borgmatic_runtime_directory,
global_arguments.dry_run,
)
source_directories = process_source_directories(config, config_paths)
source_directories = process_source_directories(config)
active_dumps = borgmatic.hooks.dispatch.call_hooks(
'dump_data_sources',
config,
repository['path'],
borgmatic.hooks.dump.DATA_SOURCE_HOOK_NAMES,
config_paths,
borgmatic_runtime_directory,
source_directories,
global_arguments.dry_run,
@ -235,19 +205,9 @@ def run_create(
# Process source directories again in case any data source hooks updated them. Without this
# step, we could end up with duplicate paths that cause Borg to hang when it tries to read
# from the same named pipe twice.
source_directories = process_source_directories(config, config_paths, source_directories)
source_directories = process_source_directories(config, source_directories)
stream_processes = [process for processes in active_dumps.values() for process in processes]
if config.get('store_config_files', True):
create_borgmatic_manifest(
config,
config_paths,
borgmatic_runtime_directory,
global_arguments.dry_run,
)
if not global_arguments.dry_run:
source_directories.append(os.path.join(borgmatic_runtime_directory, 'bootstrap'))
json_output = borgmatic.borg.create.create_archive(
global_arguments.dry_run,
repository['path'],

View File

@ -93,6 +93,25 @@ def normalize(config_filename, config):
)
config['exclude_if_present'] = [exclude_if_present]
# Unconditionally set the bootstrap hook so that it's enabled by default and config files get
# stored in each Borg archive.
config.setdefault('bootstrap', {})
# Move store_config_files from the global scope to the bootstrap hook.
store_config_files = config.get('store_config_files')
if store_config_files is not None:
logs.append(
logging.makeLogRecord(
dict(
levelno=logging.WARNING,
levelname='WARNING',
msg=f'{config_filename}: The store_config_files option has moved under the bootstrap hook. Specifying store_config_files at the global scope is deprecated and support will be removed from a future release.',
)
)
)
del config['store_config_files']
config['bootstrap']['store_config_files'] = store_config_files
# Upgrade various monitoring hooks from a string to a dict.
healthchecks = config.get('healthchecks')
if isinstance(healthchecks, str):

View File

@ -229,13 +229,6 @@ properties:
create the check records again (and therefore re-run checks).
Defaults to $XDG_STATE_HOME or ~/.local/state.
example: /var/lib/borgmatic
store_config_files:
type: boolean
description: |
Store configuration files used to create a backup in the backup
itself. Defaults to true. Changing this to false prevents "borgmatic
bootstrap" from extracting configuration files from the backup.
example: false
source_directories_must_exist:
type: boolean
description: |
@ -942,6 +935,20 @@ properties:
of them (after any action).
example:
- "echo Completed actions."
bootstrap:
type: object
properties:
store_config_files:
type: boolean
description: |
Store configuration files used to create a backup inside the
backup itself. Defaults to true. Changing this to false
prevents "borgmatic bootstrap" from extracting configuration
files from the backup.
example: false
description: |
Support for the "borgmatic bootstrap" action, used to extract
borgmatic configuration files from a backup archive.
postgresql_databases:
type: array
items:

View File

@ -2,6 +2,7 @@ import logging
from borgmatic.hooks import (
apprise,
bootstrap,
cronhub,
cronitor,
healthchecks,
@ -23,6 +24,7 @@ logger = logging.getLogger(__name__)
HOOK_NAME_TO_MODULE = {
'apprise': apprise,
'bootstrap': bootstrap,
'cronhub': cronhub,
'cronitor': cronitor,
'healthchecks': healthchecks,

View File

@ -6,6 +6,7 @@ import shutil
logger = logging.getLogger(__name__)
DATA_SOURCE_HOOK_NAMES = (
'bootstrap',
'mariadb_databases',
'mysql_databases',
'mongodb_databases',

View File

@ -126,6 +126,7 @@ def dump_data_sources(
databases,
config,
log_prefix,
config_paths,
borgmatic_runtime_directory,
source_directories,
dry_run,

View File

@ -28,6 +28,7 @@ def dump_data_sources(
databases,
config,
log_prefix,
config_paths,
borgmatic_runtime_directory,
source_directories,
dry_run,

View File

@ -125,6 +125,7 @@ def dump_data_sources(
databases,
config,
log_prefix,
config_paths,
borgmatic_runtime_directory,
source_directories,
dry_run,

View File

@ -108,6 +108,7 @@ def dump_data_sources(
databases,
config,
log_prefix,
config_paths,
borgmatic_runtime_directory,
source_directories,
dry_run,

View File

@ -28,6 +28,7 @@ def dump_data_sources(
databases,
config,
log_prefix,
config_paths,
borgmatic_runtime_directory,
source_directories,
dry_run,

View File

@ -120,17 +120,19 @@ def dump_data_sources(
hook_config,
config,
log_prefix,
config_paths,
borgmatic_runtime_directory,
source_directories,
dry_run,
):
'''
Given a ZFS configuration dict, a configuration dict, a log prefix, the borgmatic runtime
directory, the configured source directories, and whether this is a dry run, auto-detect and
snapshot any ZFS dataset mount points listed in the given source directories and any dataset
with a borgmatic-specific user property. Also update those source directories, replacing dataset
mount points with corresponding snapshot directories so they get stored in the Borg archive
instead of the dataset mount points. Use the log prefix in any log entries.
Given a ZFS configuration dict, a configuration dict, a log prefix, the borgmatic configuration
file paths, the borgmatic runtime directory, the configured source directories, and whether this
is a dry run, auto-detect and snapshot any ZFS dataset mount points listed in the given source
directories and any dataset with a borgmatic-specific user property. Also update those source
directories, replacing dataset mount points with corresponding snapshot directories so they get
stored in the Borg archive instead of the dataset mount points. Use the log prefix in any log
entries.
Return an empty sequence, since there are no ongoing dump processes from this hook.
@ -306,15 +308,24 @@ def remove_data_source_dumps(hook_config, config, log_prefix, borgmatic_runtime_
destroy_snapshot(zfs_command, full_snapshot_name)
def make_data_source_dump_patterns(hook_config, config, log_prefix, name=None): # pragma: no cover
def make_data_source_dump_patterns(
hook_config, config, log_prefix, borgmatic_runtime_directory, name=None
): # pragma: no cover
'''
Restores aren't implemented, because stored files can be extracted directly with "extract".
'''
raise NotImplementedError()
return ()
def restore_data_source_dump(
hook_config, config, log_prefix, data_source, dry_run, extract_process, connection_params
hook_config,
config,
log_prefix,
data_source,
dry_run,
extract_process,
connection_params,
borgmatic_runtime_directory,
): # pragma: no cover
'''
Restores aren't implemented, because stored files can be extracted directly with "extract".

View File

@ -202,13 +202,25 @@ borgmatic config bootstrap --repository repo.borg --archive host-2023-01-02T04:0
See the output of `config bootstrap --help` for additional flags you may need
for bootstrapping.
<span class="minilink minilink-addedin">New in version 1.8.1</span> Set the
`store_config_files` option to `false` to disable the automatic backup of
borgmatic configuration files, for instance if they contain sensitive
information you don't want to store even inside your encrypted backups. If you
do this though, the `config bootstrap` action will no longer work.
<span class="minilink minilink-addedin">New in version 1.9.3</span>
If your borgmatic configuration files contain sensitive information you don't
want to store even inside your encrypted backups, you can disable the
automatic backup of the configuration files. To do this, set the
`store_config_files` option under the `bootstrap` hook to `false`. For
instance:
<span class="minilink minilink-addedin">New in version 1.8.7</span> Included
configuration files are stored in each backup archive. This means that the
`config bootstrap` action not only extracts the top-level configuration files
but also the includes they depend upon.
```yaml
bootstrap:
store_config_files: false
```
If you do this though, the `config bootstrap` action will no longer work.
<span class="minilink minilink-addedin">In version 1.8.1 through 1.9.2</span>
The `store_config_files` option was at the global scope instead of under the
`bootstrap` hook.
<span class="minilink minilink-addedin">New in version 1.8.7</span>
Configuration file includes are stored in each backup archive. This means that
the `config bootstrap` action not only extracts the top-level configuration
files but also the includes they depend upon.

View File

@ -67,6 +67,7 @@ def test_parse_configuration_transforms_file_into_mapping():
'keep_hourly': 24,
'keep_minutely': 60,
'checks': [{'name': 'repository'}, {'name': 'archives'}],
'bootstrap': {},
}
assert config_paths == {'/tmp/config.yaml'}
assert logs == []
@ -90,6 +91,7 @@ def test_parse_configuration_passes_through_quoted_punctuation():
assert config == {
'source_directories': [f'/home/{string.punctuation}'],
'repositories': [{'path': 'test.borg'}],
'bootstrap': {},
}
assert config_paths == {'/tmp/config.yaml'}
assert logs == []
@ -150,6 +152,7 @@ def test_parse_configuration_inlines_include_inside_deprecated_section():
'repositories': [{'path': 'hostname.borg'}],
'keep_daily': 7,
'keep_hourly': 24,
'bootstrap': {},
}
assert config_paths == {'/tmp/include.yaml', '/tmp/config.yaml'}
assert len(logs) == 1
@ -185,6 +188,7 @@ def test_parse_configuration_merges_include():
'repositories': [{'path': 'hostname.borg'}],
'keep_daily': 1,
'keep_hourly': 24,
'bootstrap': {},
}
assert config_paths == {'/tmp/include.yaml', '/tmp/config.yaml'}
assert logs == []
@ -248,6 +252,7 @@ def test_parse_configuration_applies_overrides():
'source_directories': ['/home'],
'repositories': [{'path': 'hostname.borg'}],
'local_path': 'borg2',
'bootstrap': {},
}
assert config_paths == {'/tmp/config.yaml'}
assert logs == []
@ -274,6 +279,7 @@ def test_parse_configuration_applies_normalization_after_environment_variable_in
'source_directories': ['/home'],
'repositories': [{'path': 'ssh://user@hostname/./repo'}],
'exclude_if_present': ['.nobackup'],
'bootstrap': {},
}
assert config_paths == {'/tmp/config.yaml'}
assert logs

View File

@ -1,61 +1,9 @@
import sys
import pytest
from flexmock import flexmock
from borgmatic.actions import create as module
def test_create_borgmatic_manifest_creates_manifest_file():
flexmock(module.os.path).should_receive('join').with_args(
'/run/borgmatic', 'bootstrap', 'manifest.json'
).and_return('/run/borgmatic/bootstrap/manifest.json')
flexmock(module.os.path).should_receive('exists').and_return(False)
flexmock(module.os).should_receive('makedirs').and_return(True)
flexmock(module.importlib.metadata).should_receive('version').and_return('1.0.0')
flexmock(sys.modules['builtins']).should_receive('open').with_args(
'/run/borgmatic/bootstrap/manifest.json', 'w'
).and_return(
flexmock(
__enter__=lambda *args: flexmock(write=lambda *args: None, close=lambda *args: None),
__exit__=lambda *args: None,
)
)
flexmock(module.json).should_receive('dump').and_return(True).once()
module.create_borgmatic_manifest({}, 'test.yaml', '/run/borgmatic', False)
def test_create_borgmatic_manifest_creates_manifest_file_with_custom_borgmatic_runtime_directory():
flexmock(module.os.path).should_receive('join').with_args(
'/run/borgmatic', 'bootstrap', 'manifest.json'
).and_return('/run/borgmatic/bootstrap/manifest.json')
flexmock(module.os.path).should_receive('exists').and_return(False)
flexmock(module.os).should_receive('makedirs').and_return(True)
flexmock(module.importlib.metadata).should_receive('version').and_return('1.0.0')
flexmock(sys.modules['builtins']).should_receive('open').with_args(
'/run/borgmatic/bootstrap/manifest.json', 'w'
).and_return(
flexmock(
__enter__=lambda *args: flexmock(write=lambda *args: None, close=lambda *args: None),
__exit__=lambda *args: None,
)
)
flexmock(module.json).should_receive('dump').and_return(True).once()
module.create_borgmatic_manifest(
{'borgmatic_runtime_directory': '/borgmatic'}, 'test.yaml', '/run/borgmatic', False
)
def test_create_borgmatic_manifest_does_not_create_manifest_file_on_dry_run():
flexmock(module.json).should_receive('dump').never()
module.create_borgmatic_manifest({}, 'test.yaml', '/run/borgmatic', True)
def test_expand_directory_with_basic_path_passes_it_through():
flexmock(module.os.path).should_receive('expanduser').and_return('foo')
flexmock(module.glob).should_receive('glob').and_return([])
@ -207,28 +155,7 @@ def test_pattern_root_directories_parses_roots_and_ignores_others():
) == ['/root', '/baz']
def test_process_source_directories_includes_source_directories_and_config_paths():
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
'/working'
)
flexmock(module).should_receive('deduplicate_directories').and_return(
('foo', 'bar', 'test.yaml')
)
flexmock(module).should_receive('map_directories_to_devices').and_return({})
flexmock(module).should_receive('expand_directories').with_args(
('foo', 'bar', 'test.yaml'), working_directory='/working'
).and_return(()).once()
flexmock(module).should_receive('pattern_root_directories').and_return(())
flexmock(module).should_receive('expand_directories').with_args(
(), working_directory='/working'
).and_return(())
assert module.process_source_directories(
config={'source_directories': ['foo', 'bar']}, config_paths=('test.yaml',)
) == ('foo', 'bar', 'test.yaml')
def test_process_source_directories_does_not_include_config_paths_when_store_config_files_is_false():
def test_process_source_directories_includes_source_directories():
flexmock(module.borgmatic.config.paths).should_receive('get_working_directory').and_return(
'/working'
)
@ -243,8 +170,7 @@ def test_process_source_directories_does_not_include_config_paths_when_store_con
).and_return(())
assert module.process_source_directories(
config={'source_directories': ['foo', 'bar'], 'store_config_files': False},
config_paths=('test.yaml',),
config={'source_directories': ['foo', 'bar']},
) == ('foo', 'bar')
@ -264,7 +190,6 @@ def test_process_source_directories_prefers_source_directory_argument_to_config(
assert module.process_source_directories(
config={'source_directories': ['nope']},
config_paths=('test.yaml',),
source_directories=['foo', 'bar'],
) == ('foo', 'bar')
@ -276,7 +201,6 @@ def test_run_create_executes_and_calls_hooks_for_configured_repository():
flexmock()
)
flexmock(module.borgmatic.borg.create).should_receive('create_archive').once()
flexmock(module).should_receive('create_borgmatic_manifest').once()
flexmock(module.borgmatic.hooks.command).should_receive('execute_hook').times(2)
flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks').and_return({})
flexmock(module.borgmatic.hooks.dispatch).should_receive(
@ -310,47 +234,6 @@ def test_run_create_executes_and_calls_hooks_for_configured_repository():
)
def test_run_create_with_store_config_files_false_does_not_create_borgmatic_manifest():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.config.validate).should_receive('repositories_match').never()
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').and_return(
flexmock()
)
flexmock(module.borgmatic.borg.create).should_receive('create_archive').once()
flexmock(module).should_receive('create_borgmatic_manifest').never()
flexmock(module.borgmatic.hooks.command).should_receive('execute_hook').times(2)
flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks').and_return({})
flexmock(module.borgmatic.hooks.dispatch).should_receive(
'call_hooks_even_if_unconfigured'
).and_return({})
flexmock(module).should_receive('process_source_directories').and_return([])
flexmock(module.os.path).should_receive('join').and_return('/run/borgmatic/bootstrap')
create_arguments = flexmock(
repository=None,
progress=flexmock(),
stats=flexmock(),
json=False,
list_files=flexmock(),
)
global_arguments = flexmock(monitoring_verbosity=1, dry_run=False)
list(
module.run_create(
config_filename='test.yaml',
repository={'path': 'repo'},
config={'store_config_files': False},
config_paths=['/tmp/test.yaml'],
hook_context={},
local_borg_version=None,
create_arguments=create_arguments,
global_arguments=global_arguments,
dry_run_label='',
local_path=None,
remote_path=None,
)
)
def test_run_create_runs_with_selected_repository():
flexmock(module.logger).answer = lambda message: None
flexmock(module.borgmatic.config.validate).should_receive(
@ -360,7 +243,6 @@ def test_run_create_runs_with_selected_repository():
flexmock()
)
flexmock(module.borgmatic.borg.create).should_receive('create_archive').once()
flexmock(module).should_receive('create_borgmatic_manifest').once()
flexmock(module.borgmatic.hooks.command).should_receive('execute_hook').times(2)
flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks').and_return({})
flexmock(module.borgmatic.hooks.dispatch).should_receive(
@ -401,7 +283,6 @@ def test_run_create_bails_if_repository_does_not_match():
).once().and_return(False)
flexmock(module.borgmatic.config.paths).should_receive('Runtime_directory').never()
flexmock(module.borgmatic.borg.create).should_receive('create_archive').never()
flexmock(module).should_receive('create_borgmatic_manifest').never()
create_arguments = flexmock(
repository=flexmock(),
progress=flexmock(),
@ -441,7 +322,6 @@ def test_run_create_produces_json():
)
parsed_json = flexmock()
flexmock(module.borgmatic.actions.json).should_receive('parse_json').and_return(parsed_json)
flexmock(module).should_receive('create_borgmatic_manifest').once()
flexmock(module.borgmatic.hooks.command).should_receive('execute_hook').times(2)
flexmock(module.borgmatic.hooks.dispatch).should_receive('call_hooks').and_return({})
flexmock(module.borgmatic.hooks.dispatch).should_receive(

View File

@ -136,6 +136,11 @@ def test_normalize_sections_with_only_scalar_raises():
{'exclude_if_present': ['.nobackup']},
False,
),
(
{'store_config_files': False},
{'bootstrap': {'store_config_files': False}},
True,
),
(
{'source_directories': ['foo', 'bar']},
{'source_directories': ['foo', 'bar']},
@ -259,6 +264,7 @@ def test_normalize_applies_hard_coded_normalization_to_config(
flexmock(module).should_receive('normalize_sections').and_return([])
logs = module.normalize('test.yaml', config)
expected_config.setdefault('bootstrap', {})
assert config == expected_config

View File

@ -78,6 +78,7 @@ def test_dump_data_sources_dumps_each_database():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -108,6 +109,7 @@ def test_dump_data_sources_dumps_with_password():
[database],
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -133,6 +135,7 @@ def test_dump_data_sources_dumps_all_databases_at_once():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -161,6 +164,7 @@ def test_dump_data_sources_dumps_all_databases_separately_when_format_configured
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -472,6 +476,7 @@ def test_dump_data_sources_errors_for_missing_all_databases():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -491,6 +496,7 @@ def test_dump_data_sources_does_not_error_for_missing_all_databases_with_dry_run
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=True,

View File

@ -46,6 +46,7 @@ def test_dump_data_sources_runs_mongodump_for_each_database():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -68,6 +69,7 @@ def test_dump_data_sources_with_dry_run_skips_mongodump():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=True,
@ -106,6 +108,7 @@ def test_dump_data_sources_runs_mongodump_with_hostname_and_port():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -151,6 +154,7 @@ def test_dump_data_sources_runs_mongodump_with_username_and_password():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -176,6 +180,7 @@ def test_dump_data_sources_runs_mongodump_with_directory_format():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -211,6 +216,7 @@ def test_dump_data_sources_runs_mongodump_with_options():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -236,6 +242,7 @@ def test_dump_data_sources_runs_mongodumpall_for_all_databases():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,

View File

@ -78,6 +78,7 @@ def test_dump_data_sources_dumps_each_database():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -108,6 +109,7 @@ def test_dump_data_sources_dumps_with_password():
[database],
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -133,6 +135,7 @@ def test_dump_data_sources_dumps_all_databases_at_once():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -161,6 +164,7 @@ def test_dump_data_sources_dumps_all_databases_separately_when_format_configured
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -470,6 +474,7 @@ def test_dump_data_sources_errors_for_missing_all_databases():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -489,6 +494,7 @@ def test_dump_data_sources_does_not_error_for_missing_all_databases_with_dry_run
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=True,

View File

@ -256,6 +256,7 @@ def test_dump_data_sources_runs_pg_dump_for_each_database():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -275,6 +276,7 @@ def test_dump_data_sources_raises_when_no_database_names_to_dump():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -291,6 +293,7 @@ def test_dump_data_sources_does_not_raise_when_no_database_names_to_dump():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=True,
@ -316,6 +319,7 @@ def test_dump_data_sources_with_duplicate_dump_skips_pg_dump():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -343,6 +347,7 @@ def test_dump_data_sources_with_dry_run_skips_pg_dump():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=True,
@ -388,6 +393,7 @@ def test_dump_data_sources_runs_pg_dump_with_hostname_and_port():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -431,6 +437,7 @@ def test_dump_data_sources_runs_pg_dump_with_username_and_password():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -474,6 +481,7 @@ def test_dump_data_sources_with_username_injection_attack_gets_escaped():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -513,6 +521,7 @@ def test_dump_data_sources_runs_pg_dump_with_directory_format():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -555,6 +564,7 @@ def test_dump_data_sources_runs_pg_dump_with_options():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -584,6 +594,7 @@ def test_dump_data_sources_runs_pg_dumpall_for_all_databases():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -625,6 +636,7 @@ def test_dump_data_sources_runs_non_default_pg_dump():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,

View File

@ -31,6 +31,7 @@ def test_dump_data_sources_logs_and_skips_if_dump_already_exists():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -61,6 +62,7 @@ def test_dump_data_sources_dumps_each_database():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -98,6 +100,7 @@ def test_dump_data_sources_with_path_injection_attack_gets_escaped():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -126,6 +129,7 @@ def test_dump_data_sources_with_non_existent_path_warns_and_dumps_database():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -156,6 +160,7 @@ def test_dump_data_sources_with_name_all_warns_and_dumps_all_databases():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=False,
@ -180,6 +185,7 @@ def test_dump_data_sources_does_not_dump_if_dry_run():
databases,
{},
'test.yaml',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=[],
dry_run=True,

View File

@ -77,6 +77,7 @@ def test_dump_data_sources_snapshots_and_mounts_and_updates_source_directories()
hook_config={},
config={'source_directories': '/mnt/dataset', 'zfs': {}},
log_prefix='test',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=source_directories,
dry_run=False,
@ -117,6 +118,7 @@ def test_dump_data_sources_uses_custom_commands():
'zfs': hook_config,
},
log_prefix='test',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=source_directories,
dry_run=False,
@ -141,6 +143,7 @@ def test_dump_data_sources_with_dry_run_skips_commands_and_does_not_touch_source
hook_config={},
config={'source_directories': '/mnt/dataset', 'zfs': {}},
log_prefix='test',
config_paths=('test.yaml',),
borgmatic_runtime_directory='/run/borgmatic',
source_directories=source_directories,
dry_run=True,