Move bootstrap manifest file creation into a hook so it can actually clean up after itself.
This commit is contained in:
parent
b45b62cd38
commit
689643e5fa
5
NEWS
5
NEWS
@ -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).
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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'],
|
||||
|
@ -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):
|
||||
|
@ -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:
|
||||
|
@ -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,
|
||||
|
@ -6,6 +6,7 @@ import shutil
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
DATA_SOURCE_HOOK_NAMES = (
|
||||
'bootstrap',
|
||||
'mariadb_databases',
|
||||
'mysql_databases',
|
||||
'mongodb_databases',
|
||||
|
@ -126,6 +126,7 @@ def dump_data_sources(
|
||||
databases,
|
||||
config,
|
||||
log_prefix,
|
||||
config_paths,
|
||||
borgmatic_runtime_directory,
|
||||
source_directories,
|
||||
dry_run,
|
||||
|
@ -28,6 +28,7 @@ def dump_data_sources(
|
||||
databases,
|
||||
config,
|
||||
log_prefix,
|
||||
config_paths,
|
||||
borgmatic_runtime_directory,
|
||||
source_directories,
|
||||
dry_run,
|
||||
|
@ -125,6 +125,7 @@ def dump_data_sources(
|
||||
databases,
|
||||
config,
|
||||
log_prefix,
|
||||
config_paths,
|
||||
borgmatic_runtime_directory,
|
||||
source_directories,
|
||||
dry_run,
|
||||
|
@ -108,6 +108,7 @@ def dump_data_sources(
|
||||
databases,
|
||||
config,
|
||||
log_prefix,
|
||||
config_paths,
|
||||
borgmatic_runtime_directory,
|
||||
source_directories,
|
||||
dry_run,
|
||||
|
@ -28,6 +28,7 @@ def dump_data_sources(
|
||||
databases,
|
||||
config,
|
||||
log_prefix,
|
||||
config_paths,
|
||||
borgmatic_runtime_directory,
|
||||
source_directories,
|
||||
dry_run,
|
||||
|
@ -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".
|
||||
|
@ -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.
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
@ -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
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
@ -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,
|
||||
|
Loading…
x
Reference in New Issue
Block a user